/[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 1035 - (show annotations)
Fri Dec 30 20:32:06 2005 UTC (18 years, 4 months ago) by astrand
File MIME type: text/plain
File size: 23851 byte(s)
Applied patch #1367109: prevent strtol overflow

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

  ViewVC Help
Powered by ViewVC 1.1.26