/[rdesktop]/sourceforge.net/trunk/rdesktop/mcs.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/mcs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 348 - (show annotations)
Thu Mar 27 13:15:36 2003 UTC (21 years, 2 months ago) by forsberg
File MIME type: text/plain
File size: 7916 byte(s)
Changed some of the data sent from mcs_send_connection_initial - the
number of channels being the most important.

Don't assume the length of the data coming back from the server is
of the same length that the data we sent was.

Record the channel id of incoming MCS packets.

Send username to iso_connect, in order for it to be able to send the
mstshash.

Open the clipboard channel if we are speaking RDP5.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Multipoint Communications Service
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "rdesktop.h"
22
23 uint16 mcs_userid;
24 extern BOOL use_rdp5;
25
26 /* Parse an ASN.1 BER header */
27 static BOOL
28 ber_parse_header(STREAM s, int tagval, int *length)
29 {
30 int tag, len;
31
32 if (tagval > 0xff)
33 {
34 in_uint16_be(s, tag);
35 }
36 else
37 {
38 in_uint8(s, tag)}
39
40 if (tag != tagval)
41 {
42 error("expected tag %d, got %d\n", tagval, tag);
43 return False;
44 }
45
46 in_uint8(s, len);
47
48 if (len & 0x80)
49 {
50 len &= ~0x80;
51 *length = 0;
52 while (len--)
53 next_be(s, *length);
54 }
55 else
56 *length = len;
57
58 return s_check(s);
59 }
60
61 /* Output an ASN.1 BER header */
62 static void
63 ber_out_header(STREAM s, int tagval, int length)
64 {
65 if (tagval > 0xff)
66 {
67 out_uint16_be(s, tagval);
68 }
69 else
70 {
71 out_uint8(s, tagval);
72 }
73
74 if (length >= 0x80)
75 {
76 out_uint8(s, 0x82);
77 out_uint16_be(s, length);
78 }
79 else
80 out_uint8(s, length);
81 }
82
83 /* Output an ASN.1 BER integer */
84 static void
85 ber_out_integer(STREAM s, int value)
86 {
87 ber_out_header(s, BER_TAG_INTEGER, 2);
88 out_uint16_be(s, value);
89 }
90
91 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
92 static void
93 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
94 {
95 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
96 ber_out_integer(s, max_channels);
97 ber_out_integer(s, max_users);
98 ber_out_integer(s, max_tokens);
99 ber_out_integer(s, 1); /* num_priorities */
100 ber_out_integer(s, 0); /* min_throughput */
101 ber_out_integer(s, 1); /* max_height */
102 ber_out_integer(s, max_pdusize);
103 ber_out_integer(s, 2); /* ver_protocol */
104 }
105
106 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
107 static BOOL
108 mcs_parse_domain_params(STREAM s)
109 {
110 int length;
111
112 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
113 in_uint8s(s, length);
114
115 return s_check(s);
116 }
117
118 /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
119 static void
120 mcs_send_connect_initial(STREAM mcs_data)
121 {
122 int datalen = mcs_data->end - mcs_data->data;
123 int length = 9 + 3 * 34 + 4 + datalen;
124 STREAM s;
125
126 s = iso_init(length + 5);
127
128 ber_out_header(s, MCS_CONNECT_INITIAL, length);
129 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */
130 out_uint8(s, 1);
131 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */
132 out_uint8(s, 1);
133
134 ber_out_header(s, BER_TAG_BOOLEAN, 1);
135 out_uint8(s, 0xff); /* upward flag */
136
137 mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */
138 mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */
139 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
140
141 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
142 out_uint8p(s, mcs_data->data, datalen);
143
144 s_mark_end(s);
145 iso_send(s);
146 }
147
148 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
149 static BOOL
150 mcs_recv_connect_response(STREAM mcs_data)
151 {
152 uint8 result;
153 int length;
154 STREAM s;
155
156 s = iso_recv();
157 if (s == NULL)
158 return False;
159
160 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
161
162 ber_parse_header(s, BER_TAG_RESULT, &length);
163 in_uint8(s, result);
164 if (result != 0)
165 {
166 error("MCS connect: %d\n", result);
167 return False;
168 }
169
170 ber_parse_header(s, BER_TAG_INTEGER, &length);
171 in_uint8s(s, length); /* connect id */
172 mcs_parse_domain_params(s);
173
174 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
175
176 sec_process_mcs_data(s);
177 /*
178 if (length > mcs_data->size)
179 {
180 error("MCS data length %d, expected %d\n", length,
181 mcs_data->size);
182 length = mcs_data->size;
183 }
184
185 in_uint8a(s, mcs_data->data, length);
186 mcs_data->p = mcs_data->data;
187 mcs_data->end = mcs_data->data + length;
188 */
189 return s_check_end(s);
190 }
191
192 /* Send an EDrq message (ASN.1 PER) */
193 static void
194 mcs_send_edrq(void)
195 {
196 STREAM s;
197
198 s = iso_init(5);
199
200 out_uint8(s, (MCS_EDRQ << 2));
201 out_uint16_be(s, 1); /* height */
202 out_uint16_be(s, 1); /* interval */
203
204 s_mark_end(s);
205 iso_send(s);
206 }
207
208 /* Send an AUrq message (ASN.1 PER) */
209 static void
210 mcs_send_aurq(void)
211 {
212 STREAM s;
213
214 s = iso_init(1);
215
216 out_uint8(s, (MCS_AURQ << 2));
217
218 s_mark_end(s);
219 iso_send(s);
220 }
221
222 /* Expect a AUcf message (ASN.1 PER) */
223 static BOOL
224 mcs_recv_aucf(uint16 * mcs_userid)
225 {
226 uint8 opcode, result;
227 STREAM s;
228
229 s = iso_recv();
230 if (s == NULL)
231 return False;
232
233 in_uint8(s, opcode);
234 if ((opcode >> 2) != MCS_AUCF)
235 {
236 error("expected AUcf, got %d\n", opcode);
237 return False;
238 }
239
240 in_uint8(s, result);
241 if (result != 0)
242 {
243 error("AUrq: %d\n", result);
244 return False;
245 }
246
247 if (opcode & 2)
248 in_uint16_be(s, *mcs_userid);
249
250 return s_check_end(s);
251 }
252
253 /* Send a CJrq message (ASN.1 PER) */
254 static void
255 mcs_send_cjrq(uint16 chanid)
256 {
257 STREAM s;
258
259 s = iso_init(5);
260
261 out_uint8(s, (MCS_CJRQ << 2));
262 out_uint16_be(s, mcs_userid);
263 out_uint16_be(s, chanid);
264
265 s_mark_end(s);
266 iso_send(s);
267 }
268
269 /* Expect a CJcf message (ASN.1 PER) */
270 static BOOL
271 mcs_recv_cjcf(void)
272 {
273 uint8 opcode, result;
274 STREAM s;
275
276 s = iso_recv();
277 if (s == NULL)
278 return False;
279
280 in_uint8(s, opcode);
281 if ((opcode >> 2) != MCS_CJCF)
282 {
283 error("expected CJcf, got %d\n", opcode);
284 return False;
285 }
286
287 in_uint8(s, result);
288 if (result != 0)
289 {
290 error("CJrq: %d\n", result);
291 return False;
292 }
293
294 in_uint8s(s, 4); /* mcs_userid, req_chanid */
295 if (opcode & 2)
296 in_uint8s(s, 2); /* join_chanid */
297
298 return s_check_end(s);
299 }
300
301 /* Initialise an MCS transport data packet */
302 STREAM
303 mcs_init(int length)
304 {
305 STREAM s;
306
307 s = iso_init(length + 8);
308 s_push_layer(s, mcs_hdr, 8);
309
310 return s;
311 }
312
313 /* Send an MCS transport data packet */
314 void
315 mcs_send(STREAM s)
316 {
317 uint16 length;
318
319 s_pop_layer(s, mcs_hdr);
320 length = s->end - s->p - 8;
321 length |= 0x8000;
322
323 out_uint8(s, (MCS_SDRQ << 2));
324 out_uint16_be(s, mcs_userid);
325 out_uint16_be(s, MCS_GLOBAL_CHANNEL);
326 out_uint8(s, 0x70); /* flags */
327 out_uint16_be(s, length);
328
329 iso_send(s);
330 }
331
332 /* Receive an MCS transport data packet */
333 STREAM
334 mcs_recv(uint16 * channel)
335 {
336 uint8 opcode, appid, length;
337 STREAM s;
338
339 s = iso_recv();
340 if (s == NULL)
341 return NULL;
342
343 in_uint8(s, opcode);
344 appid = opcode >> 2;
345 if (appid != MCS_SDIN)
346 {
347 if (appid != MCS_DPUM)
348 {
349 error("expected data, got %d\n", opcode);
350 }
351 return NULL;
352 }
353
354 in_uint8s(s, 2); /* userid */
355 in_uint16_be(s, *channel);
356 in_uint8s(s, 1); /* flags */
357 in_uint8(s, length);
358 if (length & 0x80)
359 in_uint8s(s, 1); /* second byte of length */
360
361 return s;
362 }
363
364 /* Establish a connection up to the MCS layer */
365 BOOL
366 mcs_connect(char *server, STREAM mcs_data, char *username)
367 {
368 if (!iso_connect(server, username))
369 return False;
370
371 mcs_send_connect_initial(mcs_data);
372 if (!mcs_recv_connect_response(mcs_data))
373 goto error;
374
375 mcs_send_edrq();
376
377 mcs_send_aurq();
378 if (!mcs_recv_aucf(&mcs_userid))
379 goto error;
380
381 mcs_send_cjrq(mcs_userid + 1001);
382 if (!mcs_recv_cjcf())
383 goto error;
384
385 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
386 if (!mcs_recv_cjcf())
387 goto error;
388
389 if (use_rdp5)
390 {
391 /* Note: If we send this cjrq after telling the server we support RDP4 only,
392 the server won't respond with a cjcf and we will hang. */
393 mcs_send_cjrq(MCS_GLOBAL_CHANNEL + 1); /* hack - clipboard */
394 if (!mcs_recv_cjcf())
395 goto error;
396 }
397
398 return True;
399
400 error:
401 iso_disconnect();
402 return False;
403 }
404
405 /* Disconnect from the MCS layer */
406 void
407 mcs_disconnect(void)
408 {
409 iso_disconnect();
410 }

  ViewVC Help
Powered by ViewVC 1.1.26