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
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.
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.
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.
24 extern VCHANNEL g_channels[];
25 extern unsigned int g_num_channels;
27 /* Parse an ASN.1 BER header */
29 ber_parse_header(STREAM s, int tagval, int *length)
43 error("expected tag %d, got %d\n", tagval, tag);
62 /* Output an ASN.1 BER header */
64 ber_out_header(STREAM s, int tagval, int length)
68 out_uint16_be(s, tagval);
78 out_uint16_be(s, length);
84 /* Output an ASN.1 BER integer */
86 ber_out_integer(STREAM s, int value)
88 ber_out_header(s, BER_TAG_INTEGER, 2);
89 out_uint16_be(s, value);
93 ber_out_uint8(STREAM s, uint8 value)
95 ber_out_header(s, BER_TAG_INTEGER, 1);
100 ber_in_integer(STREAM s, int *value)
103 ber_parse_header(s, BER_TAG_INTEGER, &length);
104 in_uint16_be(s, *value);
107 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
109 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
111 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 26);
112 ber_out_uint8(s, 34); // max_channels
113 ber_out_uint8(s, 3); // max_users
114 ber_out_uint8(s, 0); // max_tokens
115 ber_out_uint8(s, 1); // num_priorities
116 ber_out_uint8(s, 0); // min_throughput
117 ber_out_uint8(s, 1); // max_height
118 ber_out_header(s, BER_TAG_INTEGER, 3); // pdu size
122 ber_out_uint8(s, 2); // ver_protocol
125 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
127 mcs_parse_domain_params(STREAM s)
130 int max_channels, max_users, max_tokens, max_pdusize;
131 int num_priorities, min_throughput, max_height;
134 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
135 printf("MCS_TAG_DOMAIN_PARAMS, len %u (expected 32)\n", length);
137 ber_in_integer(s, &max_channels);
138 ber_in_integer(s, &max_users);
139 ber_in_integer(s, &max_tokens);
140 ber_in_integer(s, &num_priorities);
141 ber_in_integer(s, &min_throughput);
142 ber_in_integer(s, &max_height);
143 ber_in_integer(s, &max_pdusize);
144 ber_in_integer(s, &ver_protocol);
146 printf("max_channels=%u\n", max_channels);
147 printf("max_users=%u\n", max_users);
148 printf("max_tokens=%u\n", max_tokens);
149 printf("num_priorities=%u\n", num_priorities);
150 printf("min_throughput=%u\n", min_throughput);
151 printf("max_pdusize=%u\n", max_pdusize);
152 printf("ver_protocol=%u\n", ver_protocol);
154 hexdump(s->p, length);
155 in_uint8s(s, length);
161 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
163 mcs_recv_connect_initial()
174 ber_parse_header(s, MCS_CONNECT_INITIAL, &length);
175 printf("parsing MCS_CONNECT_INITIAL (len=%u)\n", length);
176 ber_parse_header(s, BER_TAG_OCTET_STRING, &length); /* calling domain */
178 ber_parse_header(s, BER_TAG_OCTET_STRING, &length); /* called domain */
181 ber_parse_header(s, BER_TAG_BOOLEAN, &length);
184 mcs_parse_domain_params(s);
185 mcs_parse_domain_params(s);
186 mcs_parse_domain_params(s);
188 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
189 in_uint8p(s, buf, length);
191 printf("Data from MCS connect: '%*s'\n", length, buf);
193 return s_check_end(s);
196 /* key generated with "openssl genrsa 512 | openssl rsa -text":
199 00:b1:e0:36:2f:fd:dd:8b:d6:64:e9:2b:14:f8:b9:
200 0b:ba:3b:b7:0a:f1:f3:97:56:93:38:01:2f:d1:31:
201 2d:70:59:de:97:6a:61:3f:cb:a4:b4:12:05:89:14:
202 d9:b0:8a:70:03:b6:f1:ad:c5:b9:19:9b:b9:8f:03:
204 publicExponent: 65537 (0x10001)
206 00:a4:86:68:58:97:8d:f6:2c:06:06:8d:ac:c6:2a:
207 12:a8:dd:56:ff:2e:b0:4b:08:ee:fe:dc:4a:28:4a:
208 3e:67:2d:8e:08:6b:5f:87:69:a4:c5:a0:e7:50:1a:
209 f0:71:03:46:f2:52:7c:e6:09:40:40:61:51:76:32:
212 00:db:46:d9:34:10:ce:0d:f6:f7:48:30:0f:2b:f6:
213 4d:66:40:27:00:97:db:48:77:cd:96:b5:a6:51:81:
216 00:cf:aa:5c:d3:8a:0d:d4:91:a6:40:92:ff:2c:31:
217 d6:f9:08:8d:e8:d2:a8:2f:89:a6:88:2c:61:68:8e:
220 unsigned char my_modulus[SEC_MODULUS_SIZE] = {
221 0xe5, 0xf8, 0xfe, 0xbf, 0x51,
222 0x03, 0x8f, 0xb9, 0x9b, 0x19, 0xb9, 0xc5, 0xad, 0xf1, 0xb6, 0x03, 0x70, 0x8a, 0xb0, 0xd9,
223 0x14, 0x89, 0x05, 0x12, 0xb4, 0xa4, 0xcb, 0x3f, 0x61, 0x6a, 0x97, 0xde, 0x59, 0x70, 0x2d,
224 0x31, 0xd1, 0x2f, 0x01, 0x38, 0x93, 0x56, 0x97, 0xf3, 0xf1, 0x0a, 0xb7, 0x3b, 0xba, 0x0b,
225 0xb9, 0xf8, 0x14, 0x2b, 0xe9, 0x64, 0xd6, 0x8b, 0xdd, 0xfd, 0x2f, 0x36, 0xe0, 0xb1
227 unsigned char my_exponent[SEC_EXPONENT_SIZE] = {
228 0x01, 0x00, 0x01, 0x00
230 unsigned char my_private_exponent[] = {
231 0x41, 0x99, 0x72, 0x28, 0xf8,
232 0x32, 0x76, 0x51, 0x61, 0x40, 0x40, 0x09, 0xe6, 0x7c, 0x52, 0xf2, 0x46, 0x03, 0x71, 0xf0,
233 0x1a, 0x50, 0xe7, 0xa0, 0xc5, 0xa4, 0x69, 0x87, 0x5f, 0x6b, 0x08, 0x8e, 0x2d, 0x67, 0x3e,
234 0x4a, 0x28, 0x4a, 0xdc, 0xfe, 0xee, 0x08, 0x4b, 0xb0, 0x2e, 0xff, 0x56, 0xdd, 0xa8, 0x12,
235 0x2a, 0xc6, 0xac, 0x8d, 0x06, 0x06, 0x2c, 0xf6, 0x8d, 0x97, 0x58, 0x68, 0x86, 0xa4
240 mcs_send_connect_response()
246 printf("INITLEN: %u\n", s->p - s->iso_hdr);
248 ber_out_header(s, MCS_CONNECT_RESPONSE, 245);
249 ber_out_header(s, BER_TAG_RESULT, 1);
252 ber_out_header(s, BER_TAG_INTEGER, 1);
253 out_uint8(s, 0); // connect id
255 mcs_out_domain_params(s, 34, 2, 0, 0xffff); // dumdidum?
257 ber_out_header(s, BER_TAG_OCTET_STRING, 207);
259 // some unknown header of sorts
284 // two bytes of length
285 out_uint8(s, 0x80 | (length >> 8));
286 out_uint8(s, length & 0xff);
288 // server info -- we claim to support RDP5
289 out_uint16_le(s, SEC_TAG_SRV_INFO);
290 out_uint16_le(s, 8); // length
291 out_uint16_le(s, 4); // version
292 out_uint16_le(s, 8); // unknown
294 // channel info -- open a few channels
295 out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
296 out_uint16_le(s, 16); // length
297 out_uint16_le(s, 1003);
299 out_uint16_le(s, 1004);
300 out_uint16_le(s, 1005);
301 out_uint16_le(s, 1006);
305 out_uint16_le(s, SEC_TAG_SRV_CRYPT);
306 out_uint16_le(s, 160); // length
307 out_uint32_le(s, 2); // 128-bit
308 out_uint32_le(s, 3); // high
310 out_uint32_le(s, SEC_RANDOM_SIZE); // random_len
311 out_uint32_le(s, 108); // rsa_info_len
312 out_uint8s(s, SEC_RANDOM_SIZE); // server_random
313 out_uint32_le(s, 1); // RDP4-style
318 out_uint16_le(s, SEC_TAG_PUBKEY);
319 out_uint16_le(s, 92);
320 out_uint32_le(s, SEC_RSA_MAGIC);
321 out_uint32_le(s, SEC_MODULUS_SIZE + SEC_PADDING_SIZE); // modulus_len
322 out_uint32_le(s, SEC_MODULUS_SIZE * 8); // modulus_bits
323 out_uint32_le(s, 0x3f); // unknown
324 out_uint8p(s, my_exponent, SEC_EXPONENT_SIZE);
325 out_uint8p(s, my_modulus, SEC_MODULUS_SIZE);
326 out_uint8s(s, SEC_PADDING_SIZE);
333 /* Send an EDrq message (ASN.1 PER) */
341 out_uint8(s, (MCS_EDRQ << 2));
342 out_uint16_be(s, 1); /* height */
343 out_uint16_be(s, 1); /* interval */
349 /* Send an AUrq message (ASN.1 PER) */
357 out_uint8(s, (MCS_AURQ << 2));
363 /* Send a AUcf message (ASN.1 PER) */
365 mcs_send_aucf(uint16 mcs_userid)
371 out_uint8(s, (MCS_AUCF << 2) | 2); // | 2 = send user ID
372 out_uint8(s, 0); // success
379 /* Send a CJrq message (ASN.1 PER) */
381 mcs_send_cjrq(uint16 chanid)
385 DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
389 out_uint8(s, (MCS_CJRQ << 2));
390 out_uint16_be(s, g_mcs_userid);
391 out_uint16_be(s, chanid);
397 /* Expect a CJcf message (ASN.1 PER) */
399 mcs_send_cjcf(uint16 userid, uint16 chanid)
405 out_uint8(s, (MCS_CJCF << 2) | 2);
406 out_uint8(s, 0); // success
408 out_uint16_be(s, chanid);
409 out_uint16_be(s, chanid);
415 /* Initialise an MCS transport data packet */
421 s = iso_init(length + 8);
422 s_push_layer(s, mcs_hdr, 8);
427 /* Send an MCS transport data packet to a specific channel */
429 mcs_send_to_channel(STREAM s, uint16 channel)
433 s_pop_layer(s, mcs_hdr);
434 length = s->end - s->p - 8;
437 out_uint8(s, (MCS_SDIN << 2));
438 out_uint16_be(s, g_mcs_userid);
439 out_uint16_be(s, channel);
440 out_uint8(s, 0x70); /* flags */
441 out_uint16_be(s, length);
446 /* Send an MCS transport data packet to the global channel */
450 mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
453 /* Receive an MCS transport data packet */
455 mcs_recv(uint16 * channel)
457 uint8 opcode, appid, length, userid;
469 in_uint8s(s, 2); /* userid */
470 in_uint16_be(s, *channel);
471 in_uint8s(s, 1); /* flags */
474 in_uint8s(s, 1); /* second byte of length */
478 printf("Received DPUM (?)\n");
481 // Erect Domain (ignore)
482 printf("Received EDrq\n");
485 // Attach User Request, respond with AUcf (Attach User Confirm)
486 printf("Received AUrq, sending AUcf\n");
490 // Channel Join Request, respond with CJcf (Channel Join Confirm);
491 in_uint16_be(s, userid);
492 in_uint16_be(s, *channel);
493 printf("Received CJrq for channel %hu, sending CJcf\n", *channel);
494 mcs_send_cjcf(userid, *channel);
497 error("expected data, got %d\n", opcode);
503 /* Disconnect from the MCS layer */