/[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 964 - (show annotations)
Wed Aug 3 11:30:53 2005 UTC (18 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 21923 byte(s)
It is now possible to specify keyboard type, subtype and number of functionskeys. From patch #974509, by Dekaino.

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

  ViewVC Help
Powered by ViewVC 1.1.26