/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 348 - (hide annotations)
Thu Mar 27 13:15:36 2003 UTC (21 years, 3 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 forsberg 348 /* -*- c-basic-offset: 8 -*-
2 matty 3 rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Multipoint Communications Service
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 matty 3
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 matty 10 #include "rdesktop.h"
22 matty 3
23 matty 10 uint16 mcs_userid;
24 forsberg 348 extern BOOL use_rdp5;
25 matty 10
26     /* Parse an ASN.1 BER header */
27 matty 25 static BOOL
28     ber_parse_header(STREAM s, int tagval, int *length)
29 matty 3 {
30 matty 10 int tag, len;
31 matty 3
32 matty 10 if (tagval > 0xff)
33 matty 3 {
34 matty 10 in_uint16_be(s, tag);
35 matty 3 }
36 matty 10 else
37 matty 3 {
38 matty 24 in_uint8(s, tag)}
39 matty 3
40 matty 10 if (tag != tagval)
41 matty 3 {
42 matty 30 error("expected tag %d, got %d\n", tagval, tag);
43 matty 10 return False;
44 matty 3 }
45    
46 matty 10 in_uint8(s, len);
47 matty 3
48 matty 10 if (len & 0x80)
49 matty 3 {
50 matty 10 len &= ~0x80;
51     *length = 0;
52     while (len--)
53     next_be(s, *length);
54 matty 3 }
55 matty 24 else
56     *length = len;
57 matty 3
58 matty 10 return s_check(s);
59 matty 3 }
60    
61 matty 10 /* Output an ASN.1 BER header */
62 matty 25 static void
63     ber_out_header(STREAM s, int tagval, int length)
64 matty 3 {
65 matty 10 if (tagval > 0xff)
66 matty 3 {
67 matty 10 out_uint16_be(s, tagval);
68 matty 3 }
69 matty 10 else
70     {
71     out_uint8(s, tagval);
72     }
73 matty 3
74 matty 10 if (length >= 0x80)
75 matty 3 {
76 matty 10 out_uint8(s, 0x82);
77     out_uint16_be(s, length);
78 matty 3 }
79 matty 24 else
80     out_uint8(s, length);
81 matty 3 }
82    
83 matty 10 /* Output an ASN.1 BER integer */
84 matty 25 static void
85     ber_out_integer(STREAM s, int value)
86 matty 3 {
87 matty 10 ber_out_header(s, BER_TAG_INTEGER, 2);
88     out_uint16_be(s, value);
89 matty 3 }
90    
91 matty 10 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
92 matty 25 static void
93 astrand 82 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
94 matty 3 {
95 matty 10 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 matty 24 ber_out_integer(s, 1); /* num_priorities */
100     ber_out_integer(s, 0); /* min_throughput */
101     ber_out_integer(s, 1); /* max_height */
102 matty 10 ber_out_integer(s, max_pdusize);
103 matty 24 ber_out_integer(s, 2); /* ver_protocol */
104 matty 3 }
105    
106 matty 10 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
107 matty 25 static BOOL
108     mcs_parse_domain_params(STREAM s)
109 matty 3 {
110 matty 10 int length;
111 matty 3
112 matty 10 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
113     in_uint8s(s, length);
114    
115     return s_check(s);
116 matty 3 }
117    
118 matty 10 /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
119 matty 25 static void
120     mcs_send_connect_initial(STREAM mcs_data)
121 matty 3 {
122 matty 10 int datalen = mcs_data->end - mcs_data->data;
123 forsberg 348 int length = 9 + 3 * 34 + 4 + datalen;
124 matty 10 STREAM s;
125 matty 3
126 matty 10 s = iso_init(length + 5);
127 matty 3
128 matty 10 ber_out_header(s, MCS_CONNECT_INITIAL, length);
129 forsberg 348 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 matty 3
134 matty 10 ber_out_header(s, BER_TAG_BOOLEAN, 1);
135 matty 24 out_uint8(s, 0xff); /* upward flag */
136 matty 3
137 forsberg 348 mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */
138 matty 24 mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */
139     mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
140 matty 3
141 matty 10 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
142     out_uint8p(s, mcs_data->data, datalen);
143 matty 3
144 matty 10 s_mark_end(s);
145     iso_send(s);
146 matty 3 }
147    
148 matty 10 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
149 matty 25 static BOOL
150     mcs_recv_connect_response(STREAM mcs_data)
151 matty 3 {
152 matty 10 uint8 result;
153     int length;
154     STREAM s;
155 matty 3
156 matty 10 s = iso_recv();
157     if (s == NULL)
158 matty 7 return False;
159    
160 matty 10 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
161 matty 3
162 matty 10 ber_parse_header(s, BER_TAG_RESULT, &length);
163     in_uint8(s, result);
164     if (result != 0)
165 matty 7 {
166 matty 30 error("MCS connect: %d\n", result);
167 matty 3 return False;
168     }
169    
170 matty 10 ber_parse_header(s, BER_TAG_INTEGER, &length);
171 matty 24 in_uint8s(s, length); /* connect id */
172 matty 10 mcs_parse_domain_params(s);
173    
174     ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
175 matty 3
176 forsberg 348 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 matty 3
185 forsberg 348 in_uint8a(s, mcs_data->data, length);
186     mcs_data->p = mcs_data->data;
187     mcs_data->end = mcs_data->data + length;
188     */
189 matty 10 return s_check_end(s);
190 matty 3 }
191    
192 matty 10 /* Send an EDrq message (ASN.1 PER) */
193 matty 25 static void
194 matthewc 192 mcs_send_edrq(void)
195 matty 3 {
196 matty 10 STREAM s;
197 matty 3
198 matty 10 s = iso_init(5);
199 matty 3
200 matty 10 out_uint8(s, (MCS_EDRQ << 2));
201 matty 24 out_uint16_be(s, 1); /* height */
202     out_uint16_be(s, 1); /* interval */
203 matty 3
204 matty 10 s_mark_end(s);
205     iso_send(s);
206 matty 3 }
207    
208 matty 10 /* Send an AUrq message (ASN.1 PER) */
209 matty 25 static void
210 matthewc 192 mcs_send_aurq(void)
211 matty 3 {
212 matty 10 STREAM s;
213 matty 3
214 matty 10 s = iso_init(1);
215 matty 3
216 matty 10 out_uint8(s, (MCS_AURQ << 2));
217 matty 3
218 matty 10 s_mark_end(s);
219     iso_send(s);
220 matty 3 }
221    
222 matty 10 /* Expect a AUcf message (ASN.1 PER) */
223 matty 25 static BOOL
224 astrand 64 mcs_recv_aucf(uint16 * mcs_userid)
225 matty 3 {
226 matty 10 uint8 opcode, result;
227     STREAM s;
228 matty 3
229 matty 10 s = iso_recv();
230     if (s == NULL)
231 matty 3 return False;
232    
233 matty 10 in_uint8(s, opcode);
234     if ((opcode >> 2) != MCS_AUCF)
235 matty 3 {
236 matty 30 error("expected AUcf, got %d\n", opcode);
237 matty 3 return False;
238     }
239    
240 matty 10 in_uint8(s, result);
241     if (result != 0)
242     {
243 matty 30 error("AUrq: %d\n", result);
244 matty 10 return False;
245     }
246 matty 3
247 matty 10 if (opcode & 2)
248     in_uint16_be(s, *mcs_userid);
249 matty 3
250 matty 10 return s_check_end(s);
251 matty 3 }
252    
253 matty 10 /* Send a CJrq message (ASN.1 PER) */
254 matty 25 static void
255     mcs_send_cjrq(uint16 chanid)
256 matty 3 {
257 matty 10 STREAM s;
258 matty 3
259 matty 10 s = iso_init(5);
260 matty 3
261 matty 10 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 matty 3 }
268    
269 matty 10 /* Expect a CJcf message (ASN.1 PER) */
270 matty 25 static BOOL
271 matthewc 192 mcs_recv_cjcf(void)
272 matty 3 {
273 matty 10 uint8 opcode, result;
274     STREAM s;
275 matty 3
276 matty 10 s = iso_recv();
277     if (s == NULL)
278     return False;
279 matty 3
280 matty 10 in_uint8(s, opcode);
281     if ((opcode >> 2) != MCS_CJCF)
282     {
283 matty 30 error("expected CJcf, got %d\n", opcode);
284 matty 10 return False;
285     }
286 matty 3
287 matty 10 in_uint8(s, result);
288     if (result != 0)
289 matty 3 {
290 matty 30 error("CJrq: %d\n", result);
291 matty 3 return False;
292     }
293    
294 matty 24 in_uint8s(s, 4); /* mcs_userid, req_chanid */
295 matty 10 if (opcode & 2)
296 matty 24 in_uint8s(s, 2); /* join_chanid */
297 matty 3
298 matty 10 return s_check_end(s);
299 matty 3 }
300    
301 matty 10 /* Initialise an MCS transport data packet */
302 matty 25 STREAM
303     mcs_init(int length)
304 matty 3 {
305 matty 10 STREAM s;
306 matty 3
307 matty 10 s = iso_init(length + 8);
308     s_push_layer(s, mcs_hdr, 8);
309 matty 3
310 matty 10 return s;
311 matty 3 }
312    
313 matty 10 /* Send an MCS transport data packet */
314 matty 25 void
315     mcs_send(STREAM s)
316 matty 3 {
317 matty 10 uint16 length;
318 matty 3
319 matty 10 s_pop_layer(s, mcs_hdr);
320     length = s->end - s->p - 8;
321     length |= 0x8000;
322 matty 3
323 matty 10 out_uint8(s, (MCS_SDRQ << 2));
324     out_uint16_be(s, mcs_userid);
325     out_uint16_be(s, MCS_GLOBAL_CHANNEL);
326 matty 24 out_uint8(s, 0x70); /* flags */
327 matty 10 out_uint16_be(s, length);
328 matty 3
329 matty 10 iso_send(s);
330 matty 3 }
331    
332 matty 10 /* Receive an MCS transport data packet */
333 matty 25 STREAM
334 forsberg 348 mcs_recv(uint16 * channel)
335 matty 3 {
336 matty 10 uint8 opcode, appid, length;
337     STREAM s;
338 matty 3
339 matty 10 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 matty 3 {
347 matty 10 if (appid != MCS_DPUM)
348     {
349 matty 30 error("expected data, got %d\n", opcode);
350 matty 10 }
351     return NULL;
352 matty 3 }
353    
354 forsberg 348 in_uint8s(s, 2); /* userid */
355     in_uint16_be(s, *channel);
356     in_uint8s(s, 1); /* flags */
357 matty 10 in_uint8(s, length);
358     if (length & 0x80)
359 matty 24 in_uint8s(s, 1); /* second byte of length */
360 matty 3
361 matty 10 return s;
362 matty 3 }
363    
364 matty 10 /* Establish a connection up to the MCS layer */
365 matty 25 BOOL
366 forsberg 348 mcs_connect(char *server, STREAM mcs_data, char *username)
367 matty 3 {
368 forsberg 348 if (!iso_connect(server, username))
369 matty 3 return False;
370    
371 matty 10 mcs_send_connect_initial(mcs_data);
372     if (!mcs_recv_connect_response(mcs_data))
373     goto error;
374 matty 3
375 matty 10 mcs_send_edrq();
376 matty 3
377 matty 10 mcs_send_aurq();
378     if (!mcs_recv_aucf(&mcs_userid))
379     goto error;
380 matty 3
381 matty 10 mcs_send_cjrq(mcs_userid + 1001);
382     if (!mcs_recv_cjcf())
383     goto error;
384 matty 3
385 matty 10 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
386     if (!mcs_recv_cjcf())
387     goto error;
388 matty 3
389 forsberg 348 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 matty 10 return True;
399 matty 7
400 matty 24 error:
401 matty 10 iso_disconnect();
402     return False;
403 matty 3 }
404 matty 7
405 matty 10 /* Disconnect from the MCS layer */
406 matty 25 void
407 matthewc 192 mcs_disconnect(void)
408 matty 10 {
409     iso_disconnect();
410     }

  ViewVC Help
Powered by ViewVC 1.1.26