/[rdesktop]/sourceforge.net/trunk/rdesktop/secure.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/secure.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 779 - (show annotations)
Mon Oct 4 03:21:58 2004 UTC (19 years, 7 months ago) by jsorg71
File MIME type: text/plain
File size: 21773 byte(s)
bring the channel packets through rdp_loop so the uiports can enjoy the channel data

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP encryption and licensing
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 #include <openssl/rc4.h>
24 #include <openssl/md5.h>
25 #include <openssl/sha.h>
26 #include <openssl/bn.h>
27 #include <openssl/x509v3.h>
28
29 extern char g_hostname[16];
30 extern int g_width;
31 extern int g_height;
32 extern int g_keylayout;
33 extern BOOL g_encryption;
34 extern BOOL g_licence_issued;
35 extern BOOL g_use_rdp5;
36 extern BOOL g_console_session;
37 extern int g_server_bpp;
38 extern uint16 mcs_userid;
39 extern VCHANNEL g_channels[];
40 extern unsigned int g_num_channels;
41
42 static int rc4_key_len;
43 static RC4_KEY rc4_decrypt_key;
44 static RC4_KEY rc4_encrypt_key;
45 static RSA *server_public_key;
46
47 static uint8 sec_sign_key[16];
48 static uint8 sec_decrypt_key[16];
49 static uint8 sec_encrypt_key[16];
50 static uint8 sec_decrypt_update_key[16];
51 static uint8 sec_encrypt_update_key[16];
52 static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
53
54 uint16 g_server_rdp_version = 0;
55
56 /*
57 * I believe this is based on SSLv3 with the following differences:
58 * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
59 * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
60 * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
61 * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
62 * encryption/decryption keys updated every 4096 packets
63 * See http://wp.netscape.com/eng/ssl3/draft302.txt
64 */
65
66 /*
67 * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
68 * Both SHA1 and MD5 algorithms are used.
69 */
70 void
71 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
72 {
73 uint8 shasig[20];
74 uint8 pad[4];
75 SHA_CTX sha;
76 MD5_CTX md5;
77 int i;
78
79 for (i = 0; i < 3; i++)
80 {
81 memset(pad, salt + i, i + 1);
82
83 SHA1_Init(&sha);
84 SHA1_Update(&sha, pad, i + 1);
85 SHA1_Update(&sha, in, 48);
86 SHA1_Update(&sha, salt1, 32);
87 SHA1_Update(&sha, salt2, 32);
88 SHA1_Final(shasig, &sha);
89
90 MD5_Init(&md5);
91 MD5_Update(&md5, in, 48);
92 MD5_Update(&md5, shasig, 20);
93 MD5_Final(&out[i * 16], &md5);
94 }
95 }
96
97 /*
98 * 16-byte transformation used to generate export keys (6.2.2).
99 */
100 void
101 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
102 {
103 MD5_CTX md5;
104
105 MD5_Init(&md5);
106 MD5_Update(&md5, in, 16);
107 MD5_Update(&md5, salt1, 32);
108 MD5_Update(&md5, salt2, 32);
109 MD5_Final(out, &md5);
110 }
111
112 /* Reduce key entropy from 64 to 40 bits */
113 static void
114 sec_make_40bit(uint8 * key)
115 {
116 key[0] = 0xd1;
117 key[1] = 0x26;
118 key[2] = 0x9e;
119 }
120
121 /* Generate encryption keys given client and server randoms */
122 static void
123 sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
124 {
125 uint8 pre_master_secret[48];
126 uint8 master_secret[48];
127 uint8 key_block[48];
128
129 /* Construct pre-master secret */
130 memcpy(pre_master_secret, client_random, 24);
131 memcpy(pre_master_secret + 24, server_random, 24);
132
133 /* Generate master secret and then key material */
134 sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
135 sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
136
137 /* First 16 bytes of key material is MAC secret */
138 memcpy(sec_sign_key, key_block, 16);
139
140 /* Generate export keys from next two blocks of 16 bytes */
141 sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
142 sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
143
144 if (rc4_key_size == 1)
145 {
146 DEBUG(("40-bit encryption enabled\n"));
147 sec_make_40bit(sec_sign_key);
148 sec_make_40bit(sec_decrypt_key);
149 sec_make_40bit(sec_encrypt_key);
150 rc4_key_len = 8;
151 }
152 else
153 {
154 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
155 rc4_key_len = 16;
156 }
157
158 /* Save initial RC4 keys as update keys */
159 memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
160 memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
161
162 /* Initialise RC4 state arrays */
163 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
164 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
165 }
166
167 static uint8 pad_54[40] = {
168 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
169 54, 54, 54,
170 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
171 54, 54, 54
172 };
173
174 static uint8 pad_92[48] = {
175 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
176 92, 92, 92, 92, 92, 92, 92,
177 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
178 92, 92, 92, 92, 92, 92, 92
179 };
180
181 /* Output a uint32 into a buffer (little-endian) */
182 void
183 buf_out_uint32(uint8 * buffer, uint32 value)
184 {
185 buffer[0] = (value) & 0xff;
186 buffer[1] = (value >> 8) & 0xff;
187 buffer[2] = (value >> 16) & 0xff;
188 buffer[3] = (value >> 24) & 0xff;
189 }
190
191 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
192 void
193 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
194 {
195 uint8 shasig[20];
196 uint8 md5sig[16];
197 uint8 lenhdr[4];
198 SHA_CTX sha;
199 MD5_CTX md5;
200
201 buf_out_uint32(lenhdr, datalen);
202
203 SHA1_Init(&sha);
204 SHA1_Update(&sha, session_key, keylen);
205 SHA1_Update(&sha, pad_54, 40);
206 SHA1_Update(&sha, lenhdr, 4);
207 SHA1_Update(&sha, data, datalen);
208 SHA1_Final(shasig, &sha);
209
210 MD5_Init(&md5);
211 MD5_Update(&md5, session_key, keylen);
212 MD5_Update(&md5, pad_92, 48);
213 MD5_Update(&md5, shasig, 20);
214 MD5_Final(md5sig, &md5);
215
216 memcpy(signature, md5sig, siglen);
217 }
218
219 /* Update an encryption key */
220 static void
221 sec_update(uint8 * key, uint8 * update_key)
222 {
223 uint8 shasig[20];
224 SHA_CTX sha;
225 MD5_CTX md5;
226 RC4_KEY update;
227
228 SHA1_Init(&sha);
229 SHA1_Update(&sha, update_key, rc4_key_len);
230 SHA1_Update(&sha, pad_54, 40);
231 SHA1_Update(&sha, key, rc4_key_len);
232 SHA1_Final(shasig, &sha);
233
234 MD5_Init(&md5);
235 MD5_Update(&md5, update_key, rc4_key_len);
236 MD5_Update(&md5, pad_92, 48);
237 MD5_Update(&md5, shasig, 20);
238 MD5_Final(key, &md5);
239
240 RC4_set_key(&update, rc4_key_len, key);
241 RC4(&update, rc4_key_len, key, key);
242
243 if (rc4_key_len == 8)
244 sec_make_40bit(key);
245 }
246
247 /* Encrypt data using RC4 */
248 static void
249 sec_encrypt(uint8 * data, int length)
250 {
251 static int use_count;
252
253 if (use_count == 4096)
254 {
255 sec_update(sec_encrypt_key, sec_encrypt_update_key);
256 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
257 use_count = 0;
258 }
259
260 RC4(&rc4_encrypt_key, length, data, data);
261 use_count++;
262 }
263
264 /* Decrypt data using RC4 */
265 void
266 sec_decrypt(uint8 * data, int length)
267 {
268 static int use_count;
269
270 if (use_count == 4096)
271 {
272 sec_update(sec_decrypt_key, sec_decrypt_update_key);
273 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
274 use_count = 0;
275 }
276
277 RC4(&rc4_decrypt_key, length, data, data);
278 use_count++;
279 }
280
281 static void
282 reverse(uint8 * p, int len)
283 {
284 int i, j;
285 uint8 temp;
286
287 for (i = 0, j = len - 1; i < j; i++, j--)
288 {
289 temp = p[i];
290 p[i] = p[j];
291 p[j] = temp;
292 }
293 }
294
295 /* Perform an RSA public key encryption operation */
296 static void
297 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
298 {
299 BN_CTX *ctx;
300 BIGNUM mod, exp, x, y;
301 uint8 inr[SEC_MODULUS_SIZE];
302 int outlen;
303
304 reverse(modulus, SEC_MODULUS_SIZE);
305 reverse(exponent, SEC_EXPONENT_SIZE);
306 memcpy(inr, in, len);
307 reverse(inr, len);
308
309 ctx = BN_CTX_new();
310 BN_init(&mod);
311 BN_init(&exp);
312 BN_init(&x);
313 BN_init(&y);
314
315 BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
316 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
317 BN_bin2bn(inr, len, &x);
318 BN_mod_exp(&y, &x, &exp, &mod, ctx);
319 outlen = BN_bn2bin(&y, out);
320 reverse(out, outlen);
321 if (outlen < SEC_MODULUS_SIZE)
322 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
323
324 BN_free(&y);
325 BN_clear_free(&x);
326 BN_free(&exp);
327 BN_free(&mod);
328 BN_CTX_free(ctx);
329 }
330
331 /* Initialise secure transport packet */
332 STREAM
333 sec_init(uint32 flags, int maxlen)
334 {
335 int hdrlen;
336 STREAM s;
337
338 if (!g_licence_issued)
339 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
340 else
341 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
342 s = mcs_init(maxlen + hdrlen);
343 s_push_layer(s, sec_hdr, hdrlen);
344
345 return s;
346 }
347
348 /* Transmit secure transport packet over specified channel */
349 void
350 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
351 {
352 int datalen;
353
354 s_pop_layer(s, sec_hdr);
355 if (!g_licence_issued || (flags & SEC_ENCRYPT))
356 out_uint32_le(s, flags);
357
358 if (flags & SEC_ENCRYPT)
359 {
360 flags &= ~SEC_ENCRYPT;
361 datalen = s->end - s->p - 8;
362
363 #if WITH_DEBUG
364 DEBUG(("Sending encrypted packet:\n"));
365 hexdump(s->p + 8, datalen);
366 #endif
367
368 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
369 sec_encrypt(s->p + 8, datalen);
370 }
371
372 mcs_send_to_channel(s, channel);
373 }
374
375 /* Transmit secure transport packet */
376
377 void
378 sec_send(STREAM s, uint32 flags)
379 {
380 sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
381 }
382
383
384 /* Transfer the client random to the server */
385 static void
386 sec_establish_key(void)
387 {
388 uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
389 uint32 flags = SEC_CLIENT_RANDOM;
390 STREAM s;
391
392 s = sec_init(flags, 76);
393
394 out_uint32_le(s, length);
395 out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
396 out_uint8s(s, SEC_PADDING_SIZE);
397
398 s_mark_end(s);
399 sec_send(s, flags);
400 }
401
402 /* Output connect initial data blob */
403 static void
404 sec_out_mcs_data(STREAM s)
405 {
406 int hostlen = 2 * strlen(g_hostname);
407 int length = 158 + 76 + 12 + 4;
408 unsigned int i;
409
410 if (g_num_channels > 0)
411 length += g_num_channels * 12 + 8;
412
413 if (hostlen > 30)
414 hostlen = 30;
415
416 /* Generic Conference Control (T.124) ConferenceCreateRequest */
417 out_uint16_be(s, 5);
418 out_uint16_be(s, 0x14);
419 out_uint8(s, 0x7c);
420 out_uint16_be(s, 1);
421
422 out_uint16_be(s, (length | 0x8000)); /* remaining length */
423
424 out_uint16_be(s, 8); /* length? */
425 out_uint16_be(s, 16);
426 out_uint8(s, 0);
427 out_uint16_le(s, 0xc001);
428 out_uint8(s, 0);
429
430 out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
431 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
432
433 /* Client information */
434 out_uint16_le(s, SEC_TAG_CLI_INFO);
435 out_uint16_le(s, 212); /* length */
436 out_uint16_le(s, g_use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
437 out_uint16_le(s, 8);
438 out_uint16_le(s, g_width);
439 out_uint16_le(s, g_height);
440 out_uint16_le(s, 0xca01);
441 out_uint16_le(s, 0xaa03);
442 out_uint32_le(s, g_keylayout);
443 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
444
445 /* Unicode name of client, padded to 32 bytes */
446 rdp_out_unistr(s, g_hostname, hostlen);
447 out_uint8s(s, 30 - hostlen);
448
449 out_uint32_le(s, 4);
450 out_uint32(s, 0);
451 out_uint32_le(s, 12);
452 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
453 out_uint16_le(s, 0xca01); /* colour depth? */
454 out_uint16_le(s, 1);
455
456 out_uint32(s, 0);
457 out_uint8(s, g_server_bpp);
458 out_uint16_le(s, 0x0700);
459 out_uint8(s, 0);
460 out_uint32_le(s, 1);
461 out_uint8s(s, 64); /* End of client info */
462
463 out_uint16_le(s, SEC_TAG_CLI_4);
464 out_uint16_le(s, 12);
465 out_uint32_le(s, g_console_session ? 0xb : 9);
466 out_uint32(s, 0);
467
468 /* Client encryption settings */
469 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
470 out_uint16_le(s, 12); /* length */
471 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
472 out_uint32(s, 0); /* Unknown */
473
474 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
475 if (g_num_channels > 0)
476 {
477 out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
478 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
479 out_uint32_le(s, g_num_channels); /* number of virtual channels */
480 for (i = 0; i < g_num_channels; i++)
481 {
482 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
483 out_uint8a(s, g_channels[i].name, 8);
484 out_uint32_be(s, g_channels[i].flags);
485 }
486 }
487
488 s_mark_end(s);
489 }
490
491 /* Parse a public key structure */
492 static BOOL
493 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
494 {
495 uint32 magic, modulus_len;
496
497 in_uint32_le(s, magic);
498 if (magic != SEC_RSA_MAGIC)
499 {
500 error("RSA magic 0x%x\n", magic);
501 return False;
502 }
503
504 in_uint32_le(s, modulus_len);
505 if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
506 {
507 error("modulus len 0x%x\n", modulus_len);
508 return False;
509 }
510
511 in_uint8s(s, 8); /* modulus_bits, unknown */
512 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
513 in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
514 in_uint8s(s, SEC_PADDING_SIZE);
515
516 return s_check(s);
517 }
518
519 static BOOL
520 sec_parse_x509_key(X509 * cert)
521 {
522 EVP_PKEY *epk = NULL;
523 /* By some reason, Microsoft sets the OID of the Public RSA key to
524 the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
525
526 Kudos to Richard Levitte for the following (. intiutive .)
527 lines of code that resets the OID and let's us extract the key. */
528 if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
529 {
530 DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
531 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
532 }
533 epk = X509_get_pubkey(cert);
534 if (NULL == epk)
535 {
536 error("Failed to extract public key from certificate\n");
537 return False;
538 }
539
540 server_public_key = (RSA *) epk->pkey.ptr;
541
542 return True;
543 }
544
545
546 /* Parse a crypto information structure */
547 static BOOL
548 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
549 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
550 {
551 uint32 crypt_level, random_len, rsa_info_len;
552 uint32 cacert_len, cert_len, flags;
553 X509 *cacert, *server_cert;
554 uint16 tag, length;
555 uint8 *next_tag, *end;
556
557 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
558 in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
559 if (crypt_level == 0) /* no encryption */
560 return False;
561 in_uint32_le(s, random_len);
562 in_uint32_le(s, rsa_info_len);
563
564 if (random_len != SEC_RANDOM_SIZE)
565 {
566 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
567 return False;
568 }
569
570 in_uint8p(s, *server_random, random_len);
571
572 /* RSA info */
573 end = s->p + rsa_info_len;
574 if (end > s->end)
575 return False;
576
577 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
578 if (flags & 1)
579 {
580 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
581 in_uint8s(s, 8); /* unknown */
582
583 while (s->p < end)
584 {
585 in_uint16_le(s, tag);
586 in_uint16_le(s, length);
587
588 next_tag = s->p + length;
589
590 switch (tag)
591 {
592 case SEC_TAG_PUBKEY:
593 if (!sec_parse_public_key(s, modulus, exponent))
594 return False;
595 DEBUG_RDP5(("Got Public key, RDP4-style\n"));
596
597 break;
598
599 case SEC_TAG_KEYSIG:
600 /* Is this a Microsoft key that we just got? */
601 /* Care factor: zero! */
602 /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
603 key as a known key of the hostname. This would prevent some MITM-attacks. */
604 break;
605
606 default:
607 unimpl("crypt tag 0x%x\n", tag);
608 }
609
610 s->p = next_tag;
611 }
612 }
613 else
614 {
615 uint32 certcount;
616
617 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
618 in_uint32_le(s, certcount); /* Number of certificates */
619
620 if (certcount < 2)
621 {
622 error("Server didn't send enough X509 certificates\n");
623 return False;
624 }
625
626 for (; certcount > 2; certcount--)
627 { /* ignore all the certificates between the root and the signing CA */
628 uint32 ignorelen;
629 X509 *ignorecert;
630
631 DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
632
633 in_uint32_le(s, ignorelen);
634 DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
635 ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
636
637 if (ignorecert == NULL)
638 { /* XXX: error out? */
639 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
640 }
641
642 #ifdef WITH_DEBUG_RDP5
643 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
644 X509_print_fp(stdout, ignorecert);
645 #endif
646 }
647
648 /* Do da funky X.509 stuffy
649
650 "How did I find out about this? I looked up and saw a
651 bright light and when I came to I had a scar on my forehead
652 and knew about X.500"
653 - Peter Gutman in a early version of
654 http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
655 */
656
657 in_uint32_le(s, cacert_len);
658 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
659 cacert = d2i_X509(NULL, &(s->p), cacert_len);
660 /* Note: We don't need to move s->p here - d2i_X509 is
661 "kind" enough to do it for us */
662 if (NULL == cacert)
663 {
664 error("Couldn't load CA Certificate from server\n");
665 return False;
666 }
667
668 /* Currently, we don't use the CA Certificate.
669 FIXME:
670 *) Verify the server certificate (server_cert) with the
671 CA certificate.
672 *) Store the CA Certificate with the hostname of the
673 server we are connecting to as key, and compare it
674 when we connect the next time, in order to prevent
675 MITM-attacks.
676 */
677
678 in_uint32_le(s, cert_len);
679 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
680 server_cert = d2i_X509(NULL, &(s->p), cert_len);
681 if (NULL == server_cert)
682 {
683 error("Couldn't load Certificate from server\n");
684 return False;
685 }
686
687 in_uint8s(s, 16); /* Padding */
688
689 /* Note: Verifying the server certificate must be done here,
690 before sec_parse_public_key since we'll have to apply
691 serious violence to the key after this */
692
693 if (!sec_parse_x509_key(server_cert))
694 {
695 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
696 return False;
697 }
698 return True; /* There's some garbage here we don't care about */
699 }
700 return s_check_end(s);
701 }
702
703 /* Process crypto information blob */
704 static void
705 sec_process_crypt_info(STREAM s)
706 {
707 uint8 *server_random, *modulus, *exponent;
708 uint8 client_random[SEC_RANDOM_SIZE];
709 uint32 rc4_key_size;
710 uint8 inr[SEC_MODULUS_SIZE];
711
712 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
713 {
714 DEBUG(("Failed to parse crypt info\n"));
715 return;
716 }
717
718 DEBUG(("Generating client random\n"));
719 /* Generate a client random, and hence determine encryption keys */
720 /* This is what the MS client do: */
721 memset(inr, 0, SEC_RANDOM_SIZE);
722 /* *ARIGL!* Plaintext attack, anyone?
723 I tried doing:
724 generate_random(inr);
725 ..but that generates connection errors now and then (yes,
726 "now and then". Something like 0 to 3 attempts needed before a
727 successful connection. Nice. Not!
728 */
729
730 generate_random(client_random);
731 if (NULL != server_public_key)
732 { /* Which means we should use
733 RDP5-style encryption */
734
735 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
736 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
737
738 RSA_public_encrypt(SEC_MODULUS_SIZE,
739 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
740
741 reverse(sec_crypted_random, SEC_MODULUS_SIZE);
742
743 }
744 else
745 { /* RDP4-style encryption */
746 sec_rsa_encrypt(sec_crypted_random,
747 client_random, SEC_RANDOM_SIZE, modulus, exponent);
748 }
749 sec_generate_keys(client_random, server_random, rc4_key_size);
750 }
751
752
753 /* Process SRV_INFO, find RDP version supported by server */
754 static void
755 sec_process_srv_info(STREAM s)
756 {
757 in_uint16_le(s, g_server_rdp_version);
758 DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
759 if (1 == g_server_rdp_version)
760 {
761 g_use_rdp5 = 0;
762 g_server_bpp = 8;
763 }
764 }
765
766
767 /* Process connect response data blob */
768 void
769 sec_process_mcs_data(STREAM s)
770 {
771 uint16 tag, length;
772 uint8 *next_tag;
773 uint8 len;
774
775 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
776 in_uint8(s, len);
777 if (len & 0x80)
778 in_uint8(s, len);
779
780 while (s->p < s->end)
781 {
782 in_uint16_le(s, tag);
783 in_uint16_le(s, length);
784
785 if (length <= 4)
786 return;
787
788 next_tag = s->p + length - 4;
789
790 switch (tag)
791 {
792 case SEC_TAG_SRV_INFO:
793 sec_process_srv_info(s);
794 break;
795
796 case SEC_TAG_SRV_CRYPT:
797 sec_process_crypt_info(s);
798 break;
799
800 case SEC_TAG_SRV_CHANNELS:
801 /* FIXME: We should parse this information and
802 use it to map RDP5 channels to MCS
803 channels */
804 break;
805
806 default:
807 unimpl("response tag 0x%x\n", tag);
808 }
809
810 s->p = next_tag;
811 }
812 }
813
814 /* Receive secure transport packet */
815 STREAM
816 sec_recv(uint8 * rdpver)
817 {
818 uint32 sec_flags;
819 uint16 channel;
820 STREAM s;
821
822 while ((s = mcs_recv(&channel, rdpver)) != NULL)
823 {
824 if (rdpver != NULL)
825 {
826 if (*rdpver != 3)
827 {
828 if (*rdpver & 0x80)
829 {
830 in_uint8s(s, 8); /* signature */
831 sec_decrypt(s->p, s->end - s->p);
832 }
833 return s;
834 }
835 }
836 if (g_encryption || !g_licence_issued)
837 {
838 in_uint32_le(s, sec_flags);
839
840 if (sec_flags & SEC_ENCRYPT)
841 {
842 in_uint8s(s, 8); /* signature */
843 sec_decrypt(s->p, s->end - s->p);
844 }
845
846 if (sec_flags & SEC_LICENCE_NEG)
847 {
848 licence_process(s);
849 continue;
850 }
851 }
852
853 if (channel != MCS_GLOBAL_CHANNEL)
854 {
855 channel_process(s, channel);
856 *rdpver = 0xff;
857 return s;
858 }
859
860 return s;
861 }
862
863 return NULL;
864 }
865
866 /* Establish a secure connection */
867 BOOL
868 sec_connect(char *server, char *username)
869 {
870 struct stream mcs_data;
871
872 /* We exchange some RDP data during the MCS-Connect */
873 mcs_data.size = 512;
874 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
875 sec_out_mcs_data(&mcs_data);
876
877 if (!mcs_connect(server, &mcs_data, username))
878 return False;
879
880 /* sec_process_mcs_data(&mcs_data); */
881 if (g_encryption)
882 sec_establish_key();
883 xfree(mcs_data.data);
884 return True;
885 }
886
887 /* Disconnect a connection */
888 void
889 sec_disconnect(void)
890 {
891 mcs_disconnect();
892 }

  ViewVC Help
Powered by ViewVC 1.1.26