VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/mcs.c@ 94377

Last change on this file since 94377 was 76779, checked in by vboxsync, 6 years ago

RDP: add client-1.8.4.
bugref:9356: Update rdesktop-vrdp to 1.8.4
client-1.8.4 is a Subversion copy of 1.8.3 with the upstream 1.8.3 to 1.8.4
patch applied and a couple of fixes and changes after review, namely:

  • Stopped disabling the new pointer data format for our build, as this is no

longer needed.

  • Adjusted some snprintf buffers to make GCC happy.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.2 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Multipoint Communications Service
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21/*
22 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
24 * the General Public License version 2 (GPLv2) at this time for any software where
25 * a choice of GPL license versions is made available with the language indicating
26 * that GPLv2 or any later version may be used, or where a choice of which version
27 * of the GPL is applied is otherwise unspecified.
28 */
29
30#include "rdesktop.h"
31
32uint16 g_mcs_userid;
33extern VCHANNEL g_channels[];
34extern unsigned int g_num_channels;
35
36
37/* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
38static void
39mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
40{
41 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
42 ber_out_integer(s, max_channels);
43 ber_out_integer(s, max_users);
44 ber_out_integer(s, max_tokens);
45 ber_out_integer(s, 1); /* num_priorities */
46 ber_out_integer(s, 0); /* min_throughput */
47 ber_out_integer(s, 1); /* max_height */
48 ber_out_integer(s, max_pdusize);
49 ber_out_integer(s, 2); /* ver_protocol */
50}
51
52/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
53static RD_BOOL
54mcs_parse_domain_params(STREAM s)
55{
56 uint32 length;
57 struct stream packet = *s;
58
59 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
60
61 if (!s_check_rem(s, length))
62 {
63 rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
64 }
65
66 in_uint8s(s, length);
67
68 return s_check(s);
69}
70
71/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
72static void
73mcs_send_connect_initial(STREAM mcs_data)
74{
75 int datalen = mcs_data->end - mcs_data->data;
76 int length = 9 + 3 * 34 + 4 + datalen;
77 STREAM s;
78
79 s = iso_init(length + 5);
80
81 ber_out_header(s, MCS_CONNECT_INITIAL, length);
82 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */
83 out_uint8(s, 1);
84 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */
85 out_uint8(s, 1);
86
87 ber_out_header(s, BER_TAG_BOOLEAN, 1);
88 out_uint8(s, 0xff); /* upward flag */
89
90 mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */
91 mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */
92 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
93
94 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
95 out_uint8p(s, mcs_data->data, datalen);
96
97 s_mark_end(s);
98 iso_send(s);
99}
100
101/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
102static RD_BOOL
103mcs_recv_connect_response(STREAM mcs_data)
104{
105 uint8 result;
106 uint32 length;
107 STREAM s;
108 struct stream packet;
109 s = iso_recv(NULL);
110 if (s == NULL)
111 return False;
112
113 packet = *s;
114
115 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
116
117 ber_parse_header(s, BER_TAG_RESULT, &length);
118 in_uint8(s, result);
119 if (result != 0)
120 {
121 error("MCS connect: %d\n", result);
122 return False;
123 }
124
125 ber_parse_header(s, BER_TAG_INTEGER, &length);
126 in_uint8s(s, length); /* connect id */
127
128 if (!s_check_rem(s, length))
129 {
130 rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
131 }
132
133 mcs_parse_domain_params(s);
134
135 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
136
137 sec_process_mcs_data(s);
138 /*
139 if (length > mcs_data->size)
140 {
141 error("MCS data length %d, expected %d\n", length,
142 mcs_data->size);
143 length = mcs_data->size;
144 }
145
146 in_uint8a(s, mcs_data->data, length);
147 mcs_data->p = mcs_data->data;
148 mcs_data->end = mcs_data->data + length;
149 */
150 return s_check_end(s);
151}
152
153/* Send an EDrq message (ASN.1 PER) */
154static void
155mcs_send_edrq(void)
156{
157 STREAM s;
158
159 s = iso_init(5);
160
161 out_uint8(s, (MCS_EDRQ << 2));
162 out_uint16_be(s, 1); /* height */
163 out_uint16_be(s, 1); /* interval */
164
165 s_mark_end(s);
166 iso_send(s);
167}
168
169/* Send an AUrq message (ASN.1 PER) */
170static void
171mcs_send_aurq(void)
172{
173 STREAM s;
174
175 s = iso_init(1);
176
177 out_uint8(s, (MCS_AURQ << 2));
178
179 s_mark_end(s);
180 iso_send(s);
181}
182
183/* Expect a AUcf message (ASN.1 PER) */
184static RD_BOOL
185mcs_recv_aucf(uint16 * mcs_userid)
186{
187 uint8 opcode, result;
188 STREAM s;
189
190 s = iso_recv(NULL);
191 if (s == NULL)
192 return False;
193
194 in_uint8(s, opcode);
195 if ((opcode >> 2) != MCS_AUCF)
196 {
197 error("expected AUcf, got %d\n", opcode);
198 return False;
199 }
200
201 in_uint8(s, result);
202 if (result != 0)
203 {
204 error("AUrq: %d\n", result);
205 return False;
206 }
207
208 if (opcode & 2)
209 in_uint16_be(s, *mcs_userid);
210
211 return s_check_end(s);
212}
213
214/* Send a CJrq message (ASN.1 PER) */
215static void
216mcs_send_cjrq(uint16 chanid)
217{
218 STREAM s;
219
220 DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
221
222 s = iso_init(5);
223
224 out_uint8(s, (MCS_CJRQ << 2));
225 out_uint16_be(s, g_mcs_userid);
226 out_uint16_be(s, chanid);
227
228 s_mark_end(s);
229 iso_send(s);
230}
231
232/* Expect a CJcf message (ASN.1 PER) */
233static RD_BOOL
234mcs_recv_cjcf(void)
235{
236 uint8 opcode, result;
237 STREAM s;
238
239 s = iso_recv(NULL);
240 if (s == NULL)
241 return False;
242
243 in_uint8(s, opcode);
244 if ((opcode >> 2) != MCS_CJCF)
245 {
246 error("expected CJcf, got %d\n", opcode);
247 return False;
248 }
249
250 in_uint8(s, result);
251 if (result != 0)
252 {
253 error("CJrq: %d\n", result);
254 return False;
255 }
256
257 in_uint8s(s, 4); /* mcs_userid, req_chanid */
258 if (opcode & 2)
259 in_uint8s(s, 2); /* join_chanid */
260
261 return s_check_end(s);
262}
263
264/* Initialise an MCS transport data packet */
265STREAM
266mcs_init(int length)
267{
268 STREAM s;
269
270 s = iso_init(length + 8);
271 s_push_layer(s, mcs_hdr, 8);
272
273 return s;
274}
275
276/* Send an MCS transport data packet to a specific channel */
277void
278mcs_send_to_channel(STREAM s, uint16 channel)
279{
280 uint16 length;
281
282 s_pop_layer(s, mcs_hdr);
283 length = s->end - s->p - 8;
284 length |= 0x8000;
285
286 out_uint8(s, (MCS_SDRQ << 2));
287 out_uint16_be(s, g_mcs_userid);
288 out_uint16_be(s, channel);
289 out_uint8(s, 0x70); /* flags */
290 out_uint16_be(s, length);
291
292 iso_send(s);
293}
294
295/* Send an MCS transport data packet to the global channel */
296void
297mcs_send(STREAM s)
298{
299 mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
300}
301
302/* Receive an MCS transport data packet */
303STREAM
304mcs_recv(uint16 * channel, uint8 * rdpver)
305{
306 uint8 opcode, appid, length;
307 STREAM s;
308
309 s = iso_recv(rdpver);
310 if (s == NULL)
311 return NULL;
312 if (rdpver != NULL)
313 if (*rdpver != 3)
314 return s;
315 in_uint8(s, opcode);
316 appid = opcode >> 2;
317 if (appid != MCS_SDIN)
318 {
319 if (appid != MCS_DPUM)
320 {
321 error("expected data, got %d\n", opcode);
322 }
323 return NULL;
324 }
325 in_uint8s(s, 2); /* userid */
326 in_uint16_be(s, *channel);
327 in_uint8s(s, 1); /* flags */
328 in_uint8(s, length);
329 if (length & 0x80)
330 in_uint8s(s, 1); /* second byte of length */
331 return s;
332}
333
334RD_BOOL
335mcs_connect_start(char *server, char *username, char *domain, char *password,
336 RD_BOOL reconnect, uint32 * selected_protocol)
337{
338 return iso_connect(server, username, domain, password, reconnect, selected_protocol);
339}
340
341RD_BOOL
342mcs_connect_finalize(STREAM mcs_data)
343{
344 unsigned int i;
345
346 mcs_send_connect_initial(mcs_data);
347 if (!mcs_recv_connect_response(mcs_data))
348 goto error;
349
350 mcs_send_edrq();
351
352 mcs_send_aurq();
353 if (!mcs_recv_aucf(&g_mcs_userid))
354 goto error;
355
356 mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
357
358 if (!mcs_recv_cjcf())
359 goto error;
360
361 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
362 if (!mcs_recv_cjcf())
363 goto error;
364
365 for (i = 0; i < g_num_channels; i++)
366 {
367 mcs_send_cjrq(g_channels[i].mcs_id);
368 if (!mcs_recv_cjcf())
369 goto error;
370 }
371 return True;
372
373 error:
374 iso_disconnect();
375 return False;
376}
377
378/* Disconnect from the MCS layer */
379void
380mcs_disconnect(void)
381{
382 iso_disconnect();
383}
384
385/* reset the state of the mcs layer */
386void
387mcs_reset_state(void)
388{
389 g_mcs_userid = 0;
390 iso_reset_state();
391}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette