VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/mcs.c@ 75093

Last change on this file since 75093 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 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 <[email protected]> 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 int length;
57
58 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
59 in_uint8s(s, length);
60
61 return s_check(s);
62}
63
64/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
65static void
66mcs_send_connect_initial(STREAM mcs_data)
67{
68 int datalen = mcs_data->end - mcs_data->data;
69 int length = 9 + 3 * 34 + 4 + datalen;
70 STREAM s;
71
72 s = iso_init(length + 5);
73
74 ber_out_header(s, MCS_CONNECT_INITIAL, length);
75 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */
76 out_uint8(s, 1);
77 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */
78 out_uint8(s, 1);
79
80 ber_out_header(s, BER_TAG_BOOLEAN, 1);
81 out_uint8(s, 0xff); /* upward flag */
82
83 mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */
84 mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */
85 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
86
87 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
88 out_uint8p(s, mcs_data->data, datalen);
89
90 s_mark_end(s);
91 iso_send(s);
92}
93
94/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
95static RD_BOOL
96mcs_recv_connect_response(STREAM mcs_data)
97{
98 uint8 result;
99 int length;
100 STREAM s;
101
102 s = iso_recv(NULL);
103 if (s == NULL)
104 return False;
105
106 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
107
108 ber_parse_header(s, BER_TAG_RESULT, &length);
109 in_uint8(s, result);
110 if (result != 0)
111 {
112 error("MCS connect: %d\n", result);
113 return False;
114 }
115
116 ber_parse_header(s, BER_TAG_INTEGER, &length);
117 in_uint8s(s, length); /* connect id */
118 mcs_parse_domain_params(s);
119
120 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
121
122 sec_process_mcs_data(s);
123 /*
124 if (length > mcs_data->size)
125 {
126 error("MCS data length %d, expected %d\n", length,
127 mcs_data->size);
128 length = mcs_data->size;
129 }
130
131 in_uint8a(s, mcs_data->data, length);
132 mcs_data->p = mcs_data->data;
133 mcs_data->end = mcs_data->data + length;
134 */
135 return s_check_end(s);
136}
137
138/* Send an EDrq message (ASN.1 PER) */
139static void
140mcs_send_edrq(void)
141{
142 STREAM s;
143
144 s = iso_init(5);
145
146 out_uint8(s, (MCS_EDRQ << 2));
147 out_uint16_be(s, 1); /* height */
148 out_uint16_be(s, 1); /* interval */
149
150 s_mark_end(s);
151 iso_send(s);
152}
153
154/* Send an AUrq message (ASN.1 PER) */
155static void
156mcs_send_aurq(void)
157{
158 STREAM s;
159
160 s = iso_init(1);
161
162 out_uint8(s, (MCS_AURQ << 2));
163
164 s_mark_end(s);
165 iso_send(s);
166}
167
168/* Expect a AUcf message (ASN.1 PER) */
169static RD_BOOL
170mcs_recv_aucf(uint16 * mcs_userid)
171{
172 uint8 opcode, result;
173 STREAM s;
174
175 s = iso_recv(NULL);
176 if (s == NULL)
177 return False;
178
179 in_uint8(s, opcode);
180 if ((opcode >> 2) != MCS_AUCF)
181 {
182 error("expected AUcf, got %d\n", opcode);
183 return False;
184 }
185
186 in_uint8(s, result);
187 if (result != 0)
188 {
189 error("AUrq: %d\n", result);
190 return False;
191 }
192
193 if (opcode & 2)
194 in_uint16_be(s, *mcs_userid);
195
196 return s_check_end(s);
197}
198
199/* Send a CJrq message (ASN.1 PER) */
200static void
201mcs_send_cjrq(uint16 chanid)
202{
203 STREAM s;
204
205 DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
206
207 s = iso_init(5);
208
209 out_uint8(s, (MCS_CJRQ << 2));
210 out_uint16_be(s, g_mcs_userid);
211 out_uint16_be(s, chanid);
212
213 s_mark_end(s);
214 iso_send(s);
215}
216
217/* Expect a CJcf message (ASN.1 PER) */
218static RD_BOOL
219mcs_recv_cjcf(void)
220{
221 uint8 opcode, result;
222 STREAM s;
223
224 s = iso_recv(NULL);
225 if (s == NULL)
226 return False;
227
228 in_uint8(s, opcode);
229 if ((opcode >> 2) != MCS_CJCF)
230 {
231 error("expected CJcf, got %d\n", opcode);
232 return False;
233 }
234
235 in_uint8(s, result);
236 if (result != 0)
237 {
238 error("CJrq: %d\n", result);
239 return False;
240 }
241
242 in_uint8s(s, 4); /* mcs_userid, req_chanid */
243 if (opcode & 2)
244 in_uint8s(s, 2); /* join_chanid */
245
246 return s_check_end(s);
247}
248
249/* Initialise an MCS transport data packet */
250STREAM
251mcs_init(int length)
252{
253 STREAM s;
254
255 s = iso_init(length + 8);
256 s_push_layer(s, mcs_hdr, 8);
257
258 return s;
259}
260
261/* Send an MCS transport data packet to a specific channel */
262void
263mcs_send_to_channel(STREAM s, uint16 channel)
264{
265 uint16 length;
266
267 s_pop_layer(s, mcs_hdr);
268 length = s->end - s->p - 8;
269 length |= 0x8000;
270
271 out_uint8(s, (MCS_SDRQ << 2));
272 out_uint16_be(s, g_mcs_userid);
273 out_uint16_be(s, channel);
274 out_uint8(s, 0x70); /* flags */
275 out_uint16_be(s, length);
276
277 iso_send(s);
278}
279
280/* Send an MCS transport data packet to the global channel */
281void
282mcs_send(STREAM s)
283{
284 mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
285}
286
287/* Receive an MCS transport data packet */
288STREAM
289mcs_recv(uint16 * channel, uint8 * rdpver)
290{
291 uint8 opcode, appid, length;
292 STREAM s;
293
294 s = iso_recv(rdpver);
295 if (s == NULL)
296 return NULL;
297 if (rdpver != NULL)
298 if (*rdpver != 3)
299 return s;
300 in_uint8(s, opcode);
301 appid = opcode >> 2;
302 if (appid != MCS_SDIN)
303 {
304 if (appid != MCS_DPUM)
305 {
306 error("expected data, got %d\n", opcode);
307 }
308 return NULL;
309 }
310 in_uint8s(s, 2); /* userid */
311 in_uint16_be(s, *channel);
312 in_uint8s(s, 1); /* flags */
313 in_uint8(s, length);
314 if (length & 0x80)
315 in_uint8s(s, 1); /* second byte of length */
316 return s;
317}
318
319RD_BOOL
320mcs_connect_start(char *server, char *username, char *domain, char *password,
321 RD_BOOL reconnect, uint32 * selected_protocol)
322{
323 return iso_connect(server, username, domain, password, reconnect, selected_protocol);
324}
325
326RD_BOOL
327mcs_connect_finalize(STREAM mcs_data)
328{
329 unsigned int i;
330
331 mcs_send_connect_initial(mcs_data);
332 if (!mcs_recv_connect_response(mcs_data))
333 goto error;
334
335 mcs_send_edrq();
336
337 mcs_send_aurq();
338 if (!mcs_recv_aucf(&g_mcs_userid))
339 goto error;
340
341 mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
342
343 if (!mcs_recv_cjcf())
344 goto error;
345
346 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
347 if (!mcs_recv_cjcf())
348 goto error;
349
350 for (i = 0; i < g_num_channels; i++)
351 {
352 mcs_send_cjrq(g_channels[i].mcs_id);
353 if (!mcs_recv_cjcf())
354 goto error;
355 }
356 return True;
357
358 error:
359 iso_disconnect();
360 return False;
361}
362
363/* Disconnect from the MCS layer */
364void
365mcs_disconnect(void)
366{
367 iso_disconnect();
368}
369
370/* reset the state of the mcs layer */
371void
372mcs_reset_state(void)
373{
374 g_mcs_userid = 0;
375 iso_reset_state();
376}
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