/[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 1199 - (show annotations)
Mon Mar 27 08:17:34 2006 UTC (18 years, 1 month ago) by astrand
File MIME type: text/plain
File size: 24091 byte(s)
Added SeamlessRDP support: Merged seamlessrdp-branch

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 unsigned 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_depth;
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 /* These values must be available to reset state - Session Directory */
60 static int sec_encrypt_use_count = 0;
61 static int sec_decrypt_use_count = 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 if (sec_encrypt_use_count == 4096)
259 {
260 sec_update(sec_encrypt_key, sec_encrypt_update_key);
261 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
262 sec_encrypt_use_count = 0;
263 }
264
265 RC4(&rc4_encrypt_key, length, data, data);
266 sec_encrypt_use_count++;
267 }
268
269 /* Decrypt data using RC4 */
270 void
271 sec_decrypt(uint8 * data, int length)
272 {
273 if (sec_decrypt_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 sec_decrypt_use_count = 0;
278 }
279
280 RC4(&rc4_decrypt_key, length, data, data);
281 sec_decrypt_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 /* See
453 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
454 out_uint32_le(s, g_keyboard_type);
455 out_uint32_le(s, g_keyboard_subtype);
456 out_uint32_le(s, g_keyboard_functionkeys);
457 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
458 out_uint16_le(s, 0xca01); /* colour depth? */
459 out_uint16_le(s, 1);
460
461 out_uint32(s, 0);
462 out_uint8(s, g_server_depth);
463 out_uint16_le(s, 0x0700);
464 out_uint8(s, 0);
465 out_uint32_le(s, 1);
466 out_uint8s(s, 64); /* End of client info */
467
468 out_uint16_le(s, SEC_TAG_CLI_4);
469 out_uint16_le(s, 12);
470 out_uint32_le(s, g_console_session ? 0xb : 9);
471 out_uint32(s, 0);
472
473 /* Client encryption settings */
474 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
475 out_uint16_le(s, 12); /* length */
476 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
477 out_uint32(s, 0); /* Unknown */
478
479 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
480 if (g_num_channels > 0)
481 {
482 out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
483 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
484 out_uint32_le(s, g_num_channels); /* number of virtual channels */
485 for (i = 0; i < g_num_channels; i++)
486 {
487 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
488 out_uint8a(s, g_channels[i].name, 8);
489 out_uint32_be(s, g_channels[i].flags);
490 }
491 }
492
493 s_mark_end(s);
494 }
495
496 /* Parse a public key structure */
497 static BOOL
498 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
499 {
500 uint32 magic, modulus_len;
501
502 in_uint32_le(s, magic);
503 if (magic != SEC_RSA_MAGIC)
504 {
505 error("RSA magic 0x%x\n", magic);
506 return False;
507 }
508
509 in_uint32_le(s, modulus_len);
510 if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
511 {
512 error("modulus len 0x%x\n", modulus_len);
513 return False;
514 }
515
516 in_uint8s(s, 8); /* modulus_bits, unknown */
517 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
518 in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
519 in_uint8s(s, SEC_PADDING_SIZE);
520
521 return s_check(s);
522 }
523
524 static BOOL
525 sec_parse_x509_key(X509 * cert)
526 {
527 EVP_PKEY *epk = NULL;
528 /* By some reason, Microsoft sets the OID of the Public RSA key to
529 the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
530
531 Kudos to Richard Levitte for the following (. intiutive .)
532 lines of code that resets the OID and let's us extract the key. */
533 if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
534 {
535 DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
536 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
537 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
538 }
539 epk = X509_get_pubkey(cert);
540 if (NULL == epk)
541 {
542 error("Failed to extract public key from certificate\n");
543 return False;
544 }
545
546 server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
547
548 EVP_PKEY_free(epk);
549
550 return True;
551 }
552
553
554 /* Parse a crypto information structure */
555 static BOOL
556 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
557 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
558 {
559 uint32 crypt_level, random_len, rsa_info_len;
560 uint32 cacert_len, cert_len, flags;
561 X509 *cacert, *server_cert;
562 uint16 tag, length;
563 uint8 *next_tag, *end;
564
565 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
566 in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
567 if (crypt_level == 0) /* no encryption */
568 return False;
569 in_uint32_le(s, random_len);
570 in_uint32_le(s, rsa_info_len);
571
572 if (random_len != SEC_RANDOM_SIZE)
573 {
574 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
575 return False;
576 }
577
578 in_uint8p(s, *server_random, random_len);
579
580 /* RSA info */
581 end = s->p + rsa_info_len;
582 if (end > s->end)
583 return False;
584
585 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
586 if (flags & 1)
587 {
588 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
589 in_uint8s(s, 8); /* unknown */
590
591 while (s->p < end)
592 {
593 in_uint16_le(s, tag);
594 in_uint16_le(s, length);
595
596 next_tag = s->p + length;
597
598 switch (tag)
599 {
600 case SEC_TAG_PUBKEY:
601 if (!sec_parse_public_key(s, modulus, exponent))
602 return False;
603 DEBUG_RDP5(("Got Public key, RDP4-style\n"));
604
605 break;
606
607 case SEC_TAG_KEYSIG:
608 /* Is this a Microsoft key that we just got? */
609 /* Care factor: zero! */
610 /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
611 key as a known key of the hostname. This would prevent some MITM-attacks. */
612 break;
613
614 default:
615 unimpl("crypt tag 0x%x\n", tag);
616 }
617
618 s->p = next_tag;
619 }
620 }
621 else
622 {
623 uint32 certcount;
624
625 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
626 in_uint32_le(s, certcount); /* Number of certificates */
627
628 if (certcount < 2)
629 {
630 error("Server didn't send enough X509 certificates\n");
631 return False;
632 }
633
634 for (; certcount > 2; certcount--)
635 { /* ignore all the certificates between the root and the signing CA */
636 uint32 ignorelen;
637 X509 *ignorecert;
638
639 DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
640
641 in_uint32_le(s, ignorelen);
642 DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
643 ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
644
645 if (ignorecert == NULL)
646 { /* XXX: error out? */
647 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
648 }
649
650 #ifdef WITH_DEBUG_RDP5
651 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
652 X509_print_fp(stdout, ignorecert);
653 #endif
654 }
655
656 /* Do da funky X.509 stuffy
657
658 "How did I find out about this? I looked up and saw a
659 bright light and when I came to I had a scar on my forehead
660 and knew about X.500"
661 - Peter Gutman in a early version of
662 http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
663 */
664
665 in_uint32_le(s, cacert_len);
666 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
667 cacert = d2i_X509(NULL, &(s->p), cacert_len);
668 /* Note: We don't need to move s->p here - d2i_X509 is
669 "kind" enough to do it for us */
670 if (NULL == cacert)
671 {
672 error("Couldn't load CA Certificate from server\n");
673 return False;
674 }
675
676 /* Currently, we don't use the CA Certificate.
677 FIXME:
678 *) Verify the server certificate (server_cert) with the
679 CA certificate.
680 *) Store the CA Certificate with the hostname of the
681 server we are connecting to as key, and compare it
682 when we connect the next time, in order to prevent
683 MITM-attacks.
684 */
685
686 X509_free(cacert);
687
688 in_uint32_le(s, cert_len);
689 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
690 server_cert = d2i_X509(NULL, &(s->p), cert_len);
691 if (NULL == server_cert)
692 {
693 error("Couldn't load Certificate from server\n");
694 return False;
695 }
696
697 in_uint8s(s, 16); /* Padding */
698
699 /* Note: Verifying the server certificate must be done here,
700 before sec_parse_public_key since we'll have to apply
701 serious violence to the key after this */
702
703 if (!sec_parse_x509_key(server_cert))
704 {
705 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
706 X509_free(server_cert);
707 return False;
708 }
709 X509_free(server_cert);
710 return True; /* There's some garbage here we don't care about */
711 }
712 return s_check_end(s);
713 }
714
715 /* Process crypto information blob */
716 static void
717 sec_process_crypt_info(STREAM s)
718 {
719 uint8 *server_random, *modulus, *exponent;
720 uint8 client_random[SEC_RANDOM_SIZE];
721 uint32 rc4_key_size;
722 uint8 inr[SEC_MODULUS_SIZE];
723
724 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
725 {
726 DEBUG(("Failed to parse crypt info\n"));
727 return;
728 }
729
730 DEBUG(("Generating client random\n"));
731 /* Generate a client random, and hence determine encryption keys */
732 /* This is what the MS client do: */
733 memset(inr, 0, SEC_RANDOM_SIZE);
734 /* *ARIGL!* Plaintext attack, anyone?
735 I tried doing:
736 generate_random(inr);
737 ..but that generates connection errors now and then (yes,
738 "now and then". Something like 0 to 3 attempts needed before a
739 successful connection. Nice. Not!
740 */
741
742 generate_random(client_random);
743 if (NULL != server_public_key)
744 { /* Which means we should use
745 RDP5-style encryption */
746
747 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
748 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
749
750 RSA_public_encrypt(SEC_MODULUS_SIZE,
751 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
752
753 reverse(sec_crypted_random, SEC_MODULUS_SIZE);
754
755 RSA_free(server_public_key);
756 server_public_key = NULL;
757 }
758 else
759 { /* RDP4-style encryption */
760 sec_rsa_encrypt(sec_crypted_random,
761 client_random, SEC_RANDOM_SIZE, modulus, exponent);
762 }
763 sec_generate_keys(client_random, server_random, rc4_key_size);
764 }
765
766
767 /* Process SRV_INFO, find RDP version supported by server */
768 static void
769 sec_process_srv_info(STREAM s)
770 {
771 in_uint16_le(s, g_server_rdp_version);
772 DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
773 if (1 == g_server_rdp_version)
774 {
775 g_use_rdp5 = 0;
776 g_server_depth = 8;
777 }
778 }
779
780
781 /* Process connect response data blob */
782 void
783 sec_process_mcs_data(STREAM s)
784 {
785 uint16 tag, length;
786 uint8 *next_tag;
787 uint8 len;
788
789 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
790 in_uint8(s, len);
791 if (len & 0x80)
792 in_uint8(s, len);
793
794 while (s->p < s->end)
795 {
796 in_uint16_le(s, tag);
797 in_uint16_le(s, length);
798
799 if (length <= 4)
800 return;
801
802 next_tag = s->p + length - 4;
803
804 switch (tag)
805 {
806 case SEC_TAG_SRV_INFO:
807 sec_process_srv_info(s);
808 break;
809
810 case SEC_TAG_SRV_CRYPT:
811 sec_process_crypt_info(s);
812 break;
813
814 case SEC_TAG_SRV_CHANNELS:
815 /* FIXME: We should parse this information and
816 use it to map RDP5 channels to MCS
817 channels */
818 break;
819
820 default:
821 unimpl("response tag 0x%x\n", tag);
822 }
823
824 s->p = next_tag;
825 }
826 }
827
828 /* Receive secure transport packet */
829 STREAM
830 sec_recv(uint8 * rdpver)
831 {
832 uint32 sec_flags;
833 uint16 channel;
834 STREAM s;
835
836 while ((s = mcs_recv(&channel, rdpver)) != NULL)
837 {
838 if (rdpver != NULL)
839 {
840 if (*rdpver != 3)
841 {
842 if (*rdpver & 0x80)
843 {
844 in_uint8s(s, 8); /* signature */
845 sec_decrypt(s->p, s->end - s->p);
846 }
847 return s;
848 }
849 }
850 if (g_encryption || !g_licence_issued)
851 {
852 in_uint32_le(s, sec_flags);
853
854 if (sec_flags & SEC_ENCRYPT)
855 {
856 in_uint8s(s, 8); /* signature */
857 sec_decrypt(s->p, s->end - s->p);
858 }
859
860 if (sec_flags & SEC_LICENCE_NEG)
861 {
862 licence_process(s);
863 continue;
864 }
865
866 if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
867 {
868 uint8 swapbyte;
869
870 in_uint8s(s, 8); /* signature */
871 sec_decrypt(s->p, s->end - s->p);
872
873 /* Check for a redirect packet, starts with 00 04 */
874 if (s->p[0] == 0 && s->p[1] == 4)
875 {
876 /* for some reason the PDU and the length seem to be swapped.
877 This isn't good, but we're going to do a byte for byte
878 swap. So the first foure value appear as: 00 04 XX YY,
879 where XX YY is the little endian length. We're going to
880 use 04 00 as the PDU type, so after our swap this will look
881 like: XX YY 04 00 */
882 swapbyte = s->p[0];
883 s->p[0] = s->p[2];
884 s->p[2] = swapbyte;
885
886 swapbyte = s->p[1];
887 s->p[1] = s->p[3];
888 s->p[3] = swapbyte;
889
890 swapbyte = s->p[2];
891 s->p[2] = s->p[3];
892 s->p[3] = swapbyte;
893 }
894 #ifdef WITH_DEBUG
895 /* warning! this debug statement will show passwords in the clear! */
896 hexdump(s->p, s->end - s->p);
897 #endif
898 }
899
900 }
901
902 if (channel != MCS_GLOBAL_CHANNEL)
903 {
904 channel_process(s, channel);
905 *rdpver = 0xff;
906 return s;
907 }
908
909 return s;
910 }
911
912 return NULL;
913 }
914
915 /* Establish a secure connection */
916 BOOL
917 sec_connect(char *server, char *username)
918 {
919 struct stream mcs_data;
920
921 /* We exchange some RDP data during the MCS-Connect */
922 mcs_data.size = 512;
923 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
924 sec_out_mcs_data(&mcs_data);
925
926 if (!mcs_connect(server, &mcs_data, username))
927 return False;
928
929 /* sec_process_mcs_data(&mcs_data); */
930 if (g_encryption)
931 sec_establish_key();
932 xfree(mcs_data.data);
933 return True;
934 }
935
936 /* Establish a secure connection */
937 BOOL
938 sec_reconnect(char *server)
939 {
940 struct stream mcs_data;
941
942 /* We exchange some RDP data during the MCS-Connect */
943 mcs_data.size = 512;
944 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
945 sec_out_mcs_data(&mcs_data);
946
947 if (!mcs_reconnect(server, &mcs_data))
948 return False;
949
950 /* sec_process_mcs_data(&mcs_data); */
951 if (g_encryption)
952 sec_establish_key();
953 xfree(mcs_data.data);
954 return True;
955 }
956
957 /* Disconnect a connection */
958 void
959 sec_disconnect(void)
960 {
961 mcs_disconnect();
962 }
963
964 /* reset the state of the sec layer */
965 void
966 sec_reset_state(void)
967 {
968 g_server_rdp_version = 0;
969 sec_encrypt_use_count = 0;
970 sec_decrypt_use_count = 0;
971 mcs_reset_state();
972 }

  ViewVC Help
Powered by ViewVC 1.1.26