]> git.sesse.net Git - rdpsrv/blob - mcs.c
Include an (invalid) SEC_TAG_KEYSIG, and fix reading of VNC clipboard.
[rdpsrv] / mcs.c
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
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 g_mcs_userid;
24 extern VCHANNEL g_channels[];
25 extern unsigned int g_num_channels;
26
27 /* Parse an ASN.1 BER header */
28 static BOOL
29 ber_parse_header(STREAM s, int tagval, int *length)
30 {
31         int tag, len;
32
33         if (tagval > 0xff)
34         {
35                 in_uint16_be(s, tag);
36         }
37         else
38         {
39         in_uint8(s, tag)}
40
41         if (tag != tagval)
42         {
43                 error("expected tag %d, got %d\n", tagval, tag);
44                 return False;
45         }
46
47         in_uint8(s, len);
48
49         if (len & 0x80)
50         {
51                 len &= ~0x80;
52                 *length = 0;
53                 while (len--)
54                         next_be(s, *length);
55         }
56         else
57                 *length = len;
58
59         return s_check(s);
60 }
61
62 /* Output an ASN.1 BER header */
63 static void
64 ber_out_header(STREAM s, int tagval, int length)
65 {
66         if (tagval > 0xff)
67         {
68                 out_uint16_be(s, tagval);
69         }
70         else
71         {
72                 out_uint8(s, tagval);
73         }
74
75         if (length >= 0x80)
76         {
77                 out_uint8(s, 0x82);
78                 out_uint16_be(s, length);
79         }
80         else
81                 out_uint8(s, length);
82 }
83
84 /* Output an ASN.1 BER integer */
85 static void
86 ber_out_integer(STREAM s, int value)
87 {
88         ber_out_header(s, BER_TAG_INTEGER, 2);
89         out_uint16_be(s, value);
90 }
91
92 static void
93 ber_out_uint8(STREAM s, uint8 value)
94 {
95         ber_out_header(s, BER_TAG_INTEGER, 1);
96         out_uint8(s, value);
97 }
98
99 static void
100 ber_in_integer(STREAM s, int *value)
101 {
102         int length;
103         ber_parse_header(s, BER_TAG_INTEGER, &length);
104         in_uint16_be(s, *value);
105 }
106
107 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
108 static void
109 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
110 {
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
119         out_uint8(s, 0x00);
120         out_uint8(s, 0xff);
121         out_uint8(s, 0xf8);
122         ber_out_uint8(s, 2);  // ver_protocol
123 }
124
125 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
126 static BOOL
127 mcs_parse_domain_params(STREAM s)
128 {
129         int length;
130         int max_channels, max_users, max_tokens, max_pdusize;
131         int num_priorities, min_throughput, max_height;
132         int ver_protocol;
133
134         ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
135         printf("MCS_TAG_DOMAIN_PARAMS, len %u (expected 32)\n", length);
136         if (length == 32) {
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);
145
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);
153         } else {
154                 hexdump(s->p, length);
155                 in_uint8s(s, length);
156         }
157         
158         return s_check(s);
159 }
160
161 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
162 BOOL
163 mcs_recv_connect_initial()
164 {
165         uint8 result;
166         int length;
167         STREAM s;
168         char *buf;
169
170         s = iso_recv();
171         if (s == NULL)
172                 return False;
173
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 */
177         in_uint8(s, result);
178         ber_parse_header(s, BER_TAG_OCTET_STRING, &length);   /* called domain */
179         in_uint8(s, result);
180         
181         ber_parse_header(s, BER_TAG_BOOLEAN, &length);
182         in_uint8(s, result);
183
184         mcs_parse_domain_params(s);
185         mcs_parse_domain_params(s);
186         mcs_parse_domain_params(s);
187
188         ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
189         in_uint8p(s, buf, length);
190
191         printf("Data from MCS connect: '%*s'\n", length, buf);
192         
193         return s_check_end(s);
194 }
195
196 /* key generated with "openssl genrsa 512 | openssl rsa -text":
197  
198 modulus:
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:
203     51:bf:fe:f8:e5
204 publicExponent: 65537 (0x10001)
205 privateExponent:
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:
210     f8:28:72:99:41
211 prime1:
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:
214     a1:7c:ad
215 prime2:
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:
218     ee:7c:19
219 */
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
226 };
227 unsigned char my_exponent[SEC_EXPONENT_SIZE] = {
228         0x01, 0x00, 0x01, 0x00
229 };
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
236 };
237
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
244 };
245  
246 void
247 mcs_send_connect_response()
248 {
249         STREAM s;
250         int i, length;
251
252         s = iso_init(250);
253         printf("INITLEN: %u\n", s->p - s->iso_hdr);
254
255         ber_out_header(s, MCS_CONNECT_RESPONSE, 245 + 72);
256         ber_out_header(s, BER_TAG_RESULT, 1);
257         out_uint8(s, 0);
258
259         ber_out_header(s, BER_TAG_INTEGER, 1);
260         out_uint8(s, 0);  // connect id
261         
262         mcs_out_domain_params(s, 34, 2, 0, 0xffff);  // dumdidum?
263
264         ber_out_header(s, BER_TAG_OCTET_STRING, 207 + 72);
265
266         // some unknown header of sorts
267         out_uint8(s, 0x00);
268         out_uint8(s, 0x05);
269         out_uint8(s, 0x00);
270         out_uint8(s, 0x14);
271         out_uint8(s, 0x7c);
272         out_uint8(s, 0x00);
273         out_uint8(s, 0x01);
274         out_uint8(s, 0x2a);
275         out_uint8(s, 0x14);
276         out_uint8(s, 0x76);
277         out_uint8(s, 0x0a); 
278         out_uint8(s, 0x01);
279         out_uint8(s, 0x01);
280         out_uint8(s, 0x00);
281         out_uint8(s, 0x01);
282         out_uint8(s, 0xc0);
283         out_uint8(s, 0x00);
284         out_uint8(s, 0x4d);
285         out_uint8(s, 0x63);
286         out_uint8(s, 0x44);
287         out_uint8(s, 0x6e);
288
289         length = 184 + 72;
290         
291         // two bytes of length
292         out_uint8(s, 0x80 | (length >> 8));
293         out_uint8(s, length & 0xff);
294
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
300
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);
305         out_uint16_le(s, 3);
306         out_uint16_le(s, 1004);
307         out_uint16_le(s, 1005);
308         out_uint16_le(s, 1006);
309         out_uint16_le(s, 0);
310         
311         // crypto info
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
316
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
321         // unknown
322         out_uint32_le(s, 1);            
323         out_uint32_le(s, 1);
324
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);
334         
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
340         
341         s_mark_end(s);
342         iso_send(s);
343
344 }
345
346 /* Send an EDrq message (ASN.1 PER) */
347 static void
348 mcs_send_edrq(void)
349 {
350         STREAM s;
351
352         s = iso_init(5);
353
354         out_uint8(s, (MCS_EDRQ << 2));
355         out_uint16_be(s, 1);    /* height */
356         out_uint16_be(s, 1);    /* interval */
357
358         s_mark_end(s);
359         iso_send(s);
360 }
361
362 /* Send an AUrq message (ASN.1 PER) */
363 static void
364 mcs_send_aurq(void)
365 {
366         STREAM s;
367
368         s = iso_init(1);
369
370         out_uint8(s, (MCS_AURQ << 2));
371
372         s_mark_end(s);
373         iso_send(s);
374 }
375
376 /* Send a AUcf message (ASN.1 PER) */
377 static void
378 mcs_send_aucf(uint16 mcs_userid)
379 {
380         STREAM s;
381
382         s = iso_init(4);
383
384         out_uint8(s, (MCS_AUCF << 2) | 2);  // | 2 = send user ID
385         out_uint8(s, 0);  // success
386         out_uint16_be(s, 6);
387         
388         s_mark_end(s);
389         iso_send(s);
390 }
391
392 /* Send a CJrq message (ASN.1 PER) */
393 static void
394 mcs_send_cjrq(uint16 chanid)
395 {
396         STREAM s;
397
398         DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
399
400         s = iso_init(5);
401
402         out_uint8(s, (MCS_CJRQ << 2));
403         out_uint16_be(s, g_mcs_userid);
404         out_uint16_be(s, chanid);
405
406         s_mark_end(s);
407         iso_send(s);
408 }
409
410 /* Expect a CJcf message (ASN.1 PER) */
411 static void
412 mcs_send_cjcf(uint16 userid, uint16 chanid)
413 {
414         STREAM s;
415
416         s = iso_init(8);
417
418         out_uint8(s, (MCS_CJCF << 2) | 2);
419         out_uint8(s, 0); // success
420         out_uint16_be(s, 6);
421         out_uint16_be(s, chanid);
422         out_uint16_be(s, chanid);
423
424         s_mark_end(s);
425         iso_send(s);
426 }
427
428 /* Initialise an MCS transport data packet */
429 STREAM
430 mcs_init(int length)
431 {
432         STREAM s;
433
434         s = iso_init(length + 8);
435         s_push_layer(s, mcs_hdr, 8);
436
437         return s;
438 }
439
440 /* Send an MCS transport data packet to a specific channel */
441 void
442 mcs_send_to_channel(STREAM s, uint16 channel)
443 {
444         uint16 length;
445
446         s_pop_layer(s, mcs_hdr);
447         length = s->end - s->p - 8;
448         length |= 0x8000;
449
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);
455
456         iso_send(s);
457 }
458
459 /* Send an MCS transport data packet to the global channel */
460 void
461 mcs_send(STREAM s)
462 {
463         mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
464 }
465
466 /* Receive an MCS transport data packet */
467 STREAM
468 mcs_recv(uint16 * channel)
469 {
470         uint8 opcode, appid, length, userid;
471         STREAM s;
472
473         s = iso_recv();
474         if (s == NULL)
475                 return NULL;
476
477         in_uint8(s, opcode);
478         appid = opcode >> 2;
479
480         switch (appid) {
481         case MCS_SDRQ:
482                 in_uint8s(s, 2);        /* userid */
483                 in_uint16_be(s, *channel);
484                 in_uint8s(s, 1);        /* flags */
485                 in_uint8(s, length);
486                 if (length & 0x80)
487                         in_uint8s(s, 1);        /* second byte of length */
488
489                 return s;
490         case MCS_DPUM:
491                 printf("Received DPUM (?)\n");
492                 return NULL;
493         case MCS_EDRQ:
494                 // Erect Domain (ignore)
495                 printf("Received EDrq\n");
496                 return NULL;
497         case MCS_AURQ:
498                 // Attach User Request, respond with AUcf (Attach User Confirm)
499                 printf("Received AUrq, sending AUcf\n");
500                 mcs_send_aucf(0);
501                 return NULL;
502         case MCS_CJRQ:
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);
508                 return NULL;
509         default:
510                 error("expected data, got %d\n", opcode);
511                 return NULL;
512         }
513
514 }
515
516 /* Disconnect from the MCS layer */
517 void
518 mcs_disconnect(void)
519 {
520         iso_disconnect();
521 }