/[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 1237 - (show annotations)
Wed Jun 14 08:26:00 2006 UTC (17 years, 10 months ago) by matthewc
File MIME type: text/plain
File size: 24533 byte(s)
Allow server public key to be anywhere from 512 bits to 2048 bits.
(Vista Beta 2 uses a 2048 bit key)

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

  ViewVC Help
Powered by ViewVC 1.1.26