/[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 10 - (show annotations)
Tue Aug 15 10:23:24 2000 UTC (23 years, 8 months ago) by matty
File MIME type: text/plain
File size: 7367 byte(s)
Major commit of work from laptop - done in various free moments.
Implemented encryption layer and some basic licensing negotiation.
Reorganised code somewhat. While this is not quite as clean, it is
a lot faster - our parser speed was becoming a bottle-neck.

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

  ViewVC Help
Powered by ViewVC 1.1.26