/[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 706 - (show annotations)
Tue Jun 1 08:06:02 2004 UTC (19 years, 11 months ago) by astrand
File MIME type: text/plain
File size: 21666 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26