/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/mcs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show annotations)
Sat Jan 6 03:12:10 2001 UTC (23 years, 4 months ago) by matty
Original Path: sourceforge.net/trunk/rdesktop/mcs.c
File MIME type: text/plain
File size: 7375 byte(s)
ran indent (-bli0 -i8 -cli8 -npcs -npsl)

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

  ViewVC Help
Powered by ViewVC 1.1.26