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
238 // copied verbatim from the protocol...
239 unsigned char my_signature[SEC_MODULUS_SIZE] = {
240 0x49, 0x54, 0x1b, 0xbe, 0x23, 0x8b, 0xbe, 0x1f, 0x77, 0xfa, 0x5d, 0xd0, 0x57, 0xee, 0x55, 0xd2,
241 0x9e, 0x38, 0x7b, 0x82, 0x82, 0x8d, 0x25, 0x2a, 0xaa, 0xa0, 0xe6, 0xbe, 0x1b, 0xa6, 0x4e, 0xe2,
242 0x9b, 0x55, 0x39, 0xb2, 0x38, 0xd2, 0x11, 0x64, 0x06, 0x64, 0x87, 0xb6, 0x3a, 0xce, 0xc6, 0x9a,
243 0xc7, 0x85, 0xbd, 0xc7, 0xe3, 0x2b, 0x10, 0x9f, 0xdc, 0x38, 0x5a, 0x05, 0x86, 0xb3, 0x5c, 0x1a
247 mcs_send_connect_response()
253 printf("INITLEN: %u\n", s->p - s->iso_hdr);
255 ber_out_header(s, MCS_CONNECT_RESPONSE, 245 + 72);
256 ber_out_header(s, BER_TAG_RESULT, 1);
259 ber_out_header(s, BER_TAG_INTEGER, 1);
260 out_uint8(s, 0); // connect id
262 mcs_out_domain_params(s, 34, 2, 0, 0xffff); // dumdidum?
264 ber_out_header(s, BER_TAG_OCTET_STRING, 207 + 72);
266 // some unknown header of sorts
291 // two bytes of length
292 out_uint8(s, 0x80 | (length >> 8));
293 out_uint8(s, length & 0xff);
295 // server info -- we claim to support RDP5
296 out_uint16_le(s, SEC_TAG_SRV_INFO);
297 out_uint16_le(s, 8); // length
298 out_uint16_le(s, 4); // version
299 out_uint16_le(s, 8); // unknown
301 // channel info -- open a few channels
302 out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
303 out_uint16_le(s, 16); // length
304 out_uint16_le(s, 1003);
306 out_uint16_le(s, 1004);
307 out_uint16_le(s, 1005);
308 out_uint16_le(s, 1006);
312 out_uint16_le(s, SEC_TAG_SRV_CRYPT);
313 out_uint16_le(s, 232); // length
314 out_uint32_le(s, 2); // 128-bit
315 out_uint32_le(s, 3); // high
317 out_uint32_le(s, SEC_RANDOM_SIZE); // random_len
318 out_uint32_le(s, 180); // rsa_info_len
319 out_uint8s(s, SEC_RANDOM_SIZE); // server_random
320 out_uint32_le(s, 1); // RDP4-style
325 out_uint16_le(s, SEC_TAG_PUBKEY);
326 out_uint16_le(s, 92);
327 out_uint32_le(s, SEC_RSA_MAGIC);
328 out_uint32_le(s, SEC_MODULUS_SIZE + SEC_PADDING_SIZE); // modulus_len
329 out_uint32_le(s, SEC_MODULUS_SIZE * 8); // modulus_bits
330 out_uint32_le(s, 0x3f); // unknown
331 out_uint8p(s, my_exponent, SEC_EXPONENT_SIZE);
332 out_uint8p(s, my_modulus, SEC_MODULUS_SIZE);
333 out_uint8s(s, SEC_PADDING_SIZE);
335 // just copied verbatim...
336 out_uint16_le(s, SEC_TAG_KEYSIG);
337 out_uint16_le(s, 72);
338 out_uint8p(s, my_signature, 64); // 512 bits
339 out_uint8s(s, 4); // padding
346 /* Send an EDrq message (ASN.1 PER) */
354 out_uint8(s, (MCS_EDRQ << 2));
355 out_uint16_be(s, 1); /* height */
356 out_uint16_be(s, 1); /* interval */
362 /* Send an AUrq message (ASN.1 PER) */
370 out_uint8(s, (MCS_AURQ << 2));
376 /* Send a AUcf message (ASN.1 PER) */
378 mcs_send_aucf(uint16 mcs_userid)
384 out_uint8(s, (MCS_AUCF << 2) | 2); // | 2 = send user ID
385 out_uint8(s, 0); // success
392 /* Send a CJrq message (ASN.1 PER) */
394 mcs_send_cjrq(uint16 chanid)
398 DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
402 out_uint8(s, (MCS_CJRQ << 2));
403 out_uint16_be(s, g_mcs_userid);
404 out_uint16_be(s, chanid);
410 /* Expect a CJcf message (ASN.1 PER) */
412 mcs_send_cjcf(uint16 userid, uint16 chanid)
418 out_uint8(s, (MCS_CJCF << 2) | 2);
419 out_uint8(s, 0); // success
421 out_uint16_be(s, chanid);
422 out_uint16_be(s, chanid);
428 /* Initialise an MCS transport data packet */
434 s = iso_init(length + 8);
435 s_push_layer(s, mcs_hdr, 8);
440 /* Send an MCS transport data packet to a specific channel */
442 mcs_send_to_channel(STREAM s, uint16 channel)
446 s_pop_layer(s, mcs_hdr);
447 length = s->end - s->p - 8;
450 out_uint8(s, (MCS_SDIN << 2));
451 out_uint16_be(s, g_mcs_userid);
452 out_uint16_be(s, channel);
453 out_uint8(s, 0x70); /* flags */
454 out_uint16_be(s, length);
459 /* Send an MCS transport data packet to the global channel */
463 mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
466 /* Receive an MCS transport data packet */
468 mcs_recv(uint16 * channel)
470 uint8 opcode, appid, length, userid;
482 in_uint8s(s, 2); /* userid */
483 in_uint16_be(s, *channel);
484 in_uint8s(s, 1); /* flags */
487 in_uint8s(s, 1); /* second byte of length */
491 printf("Received DPUM (?)\n");
494 // Erect Domain (ignore)
495 printf("Received EDrq\n");
498 // Attach User Request, respond with AUcf (Attach User Confirm)
499 printf("Received AUrq, sending AUcf\n");
503 // Channel Join Request, respond with CJcf (Channel Join Confirm);
504 in_uint16_be(s, userid);
505 in_uint16_be(s, *channel);
506 printf("Received CJrq for channel %hu, sending CJcf\n", *channel);
507 mcs_send_cjcf(userid, *channel);
510 error("expected data, got %d\n", opcode);
516 /* Disconnect from the MCS layer */