/[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 1240 - (show annotations)
Sun Jul 2 13:03:22 2006 UTC (17 years, 11 months ago) by stargo
File MIME type: text/plain
File size: 24547 byte(s)
fix some warnings

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,
302 uint8 * exponent)
303 {
304 BN_CTX *ctx;
305 BIGNUM mod, exp, x, y;
306 uint8 inr[SEC_MAX_MODULUS_SIZE];
307 int outlen;
308
309 reverse(modulus, modulus_size);
310 reverse(exponent, SEC_EXPONENT_SIZE);
311 memcpy(inr, in, len);
312 reverse(inr, len);
313
314 ctx = BN_CTX_new();
315 BN_init(&mod);
316 BN_init(&exp);
317 BN_init(&x);
318 BN_init(&y);
319
320 BN_bin2bn(modulus, modulus_size, &mod);
321 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
322 BN_bin2bn(inr, len, &x);
323 BN_mod_exp(&y, &x, &exp, &mod, ctx);
324 outlen = BN_bn2bin(&y, out);
325 reverse(out, outlen);
326 if (outlen < modulus_size)
327 memset(out + outlen, 0, modulus_size - outlen);
328
329 BN_free(&y);
330 BN_clear_free(&x);
331 BN_free(&exp);
332 BN_free(&mod);
333 BN_CTX_free(ctx);
334 }
335
336 /* Initialise secure transport packet */
337 STREAM
338 sec_init(uint32 flags, int maxlen)
339 {
340 int hdrlen;
341 STREAM s;
342
343 if (!g_licence_issued)
344 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
345 else
346 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
347 s = mcs_init(maxlen + hdrlen);
348 s_push_layer(s, sec_hdr, hdrlen);
349
350 return s;
351 }
352
353 /* Transmit secure transport packet over specified channel */
354 void
355 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
356 {
357 int datalen;
358
359 s_pop_layer(s, sec_hdr);
360 if (!g_licence_issued || (flags & SEC_ENCRYPT))
361 out_uint32_le(s, flags);
362
363 if (flags & SEC_ENCRYPT)
364 {
365 flags &= ~SEC_ENCRYPT;
366 datalen = s->end - s->p - 8;
367
368 #if WITH_DEBUG
369 DEBUG(("Sending encrypted packet:\n"));
370 hexdump(s->p + 8, datalen);
371 #endif
372
373 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
374 sec_encrypt(s->p + 8, datalen);
375 }
376
377 mcs_send_to_channel(s, channel);
378 }
379
380 /* Transmit secure transport packet */
381
382 void
383 sec_send(STREAM s, uint32 flags)
384 {
385 sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
386 }
387
388
389 /* Transfer the client random to the server */
390 static void
391 sec_establish_key(void)
392 {
393 uint32 length = server_public_key_len + SEC_PADDING_SIZE;
394 uint32 flags = SEC_CLIENT_RANDOM;
395 STREAM s;
396
397 s = sec_init(flags, length + 4);
398
399 out_uint32_le(s, length);
400 out_uint8p(s, sec_crypted_random, server_public_key_len);
401 out_uint8s(s, SEC_PADDING_SIZE);
402
403 s_mark_end(s);
404 sec_send(s, flags);
405 }
406
407 /* Output connect initial data blob */
408 static void
409 sec_out_mcs_data(STREAM s)
410 {
411 int hostlen = 2 * strlen(g_hostname);
412 int length = 158 + 76 + 12 + 4;
413 unsigned int i;
414
415 if (g_num_channels > 0)
416 length += g_num_channels * 12 + 8;
417
418 if (hostlen > 30)
419 hostlen = 30;
420
421 /* Generic Conference Control (T.124) ConferenceCreateRequest */
422 out_uint16_be(s, 5);
423 out_uint16_be(s, 0x14);
424 out_uint8(s, 0x7c);
425 out_uint16_be(s, 1);
426
427 out_uint16_be(s, (length | 0x8000)); /* remaining length */
428
429 out_uint16_be(s, 8); /* length? */
430 out_uint16_be(s, 16);
431 out_uint8(s, 0);
432 out_uint16_le(s, 0xc001);
433 out_uint8(s, 0);
434
435 out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
436 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
437
438 /* Client information */
439 out_uint16_le(s, SEC_TAG_CLI_INFO);
440 out_uint16_le(s, 212); /* length */
441 out_uint16_le(s, g_use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
442 out_uint16_le(s, 8);
443 out_uint16_le(s, g_width);
444 out_uint16_le(s, g_height);
445 out_uint16_le(s, 0xca01);
446 out_uint16_le(s, 0xaa03);
447 out_uint32_le(s, g_keylayout);
448 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
449
450 /* Unicode name of client, padded to 32 bytes */
451 rdp_out_unistr(s, g_hostname, hostlen);
452 out_uint8s(s, 30 - hostlen);
453
454 /* See
455 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
456 out_uint32_le(s, g_keyboard_type);
457 out_uint32_le(s, g_keyboard_subtype);
458 out_uint32_le(s, g_keyboard_functionkeys);
459 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
460 out_uint16_le(s, 0xca01); /* colour depth? */
461 out_uint16_le(s, 1);
462
463 out_uint32(s, 0);
464 out_uint8(s, g_server_depth);
465 out_uint16_le(s, 0x0700);
466 out_uint8(s, 0);
467 out_uint32_le(s, 1);
468 out_uint8s(s, 64); /* End of client info */
469
470 out_uint16_le(s, SEC_TAG_CLI_4);
471 out_uint16_le(s, 12);
472 out_uint32_le(s, g_console_session ? 0xb : 9);
473 out_uint32(s, 0);
474
475 /* Client encryption settings */
476 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
477 out_uint16_le(s, 12); /* length */
478 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
479 out_uint32(s, 0); /* Unknown */
480
481 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
482 if (g_num_channels > 0)
483 {
484 out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
485 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
486 out_uint32_le(s, g_num_channels); /* number of virtual channels */
487 for (i = 0; i < g_num_channels; i++)
488 {
489 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
490 out_uint8a(s, g_channels[i].name, 8);
491 out_uint32_be(s, g_channels[i].flags);
492 }
493 }
494
495 s_mark_end(s);
496 }
497
498 /* Parse a public key structure */
499 static BOOL
500 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
501 {
502 uint32 magic, modulus_len;
503
504 in_uint32_le(s, magic);
505 if (magic != SEC_RSA_MAGIC)
506 {
507 error("RSA magic 0x%x\n", magic);
508 return False;
509 }
510
511 in_uint32_le(s, modulus_len);
512 modulus_len -= SEC_PADDING_SIZE;
513 if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
514 {
515 error("Bad server public key size (%u bits)\n", modulus_len * 8);
516 return False;
517 }
518
519 in_uint8s(s, 8); /* modulus_bits, unknown */
520 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
521 in_uint8p(s, *modulus, modulus_len);
522 in_uint8s(s, SEC_PADDING_SIZE);
523 server_public_key_len = modulus_len;
524
525 return s_check(s);
526 }
527
528 static BOOL
529 sec_parse_x509_key(X509 * cert)
530 {
531 EVP_PKEY *epk = NULL;
532 /* By some reason, Microsoft sets the OID of the Public RSA key to
533 the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
534
535 Kudos to Richard Levitte for the following (. intiutive .)
536 lines of code that resets the OID and let's us extract the key. */
537 if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
538 {
539 DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
540 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
541 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
542 }
543 epk = X509_get_pubkey(cert);
544 if (NULL == epk)
545 {
546 error("Failed to extract public key from certificate\n");
547 return False;
548 }
549
550 server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
551 EVP_PKEY_free(epk);
552
553 server_public_key_len = RSA_size(server_public_key);
554 if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))
555 {
556 error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
557 return False;
558 }
559
560 return True;
561 }
562
563
564 /* Parse a crypto information structure */
565 static BOOL
566 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
567 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
568 {
569 uint32 crypt_level, random_len, rsa_info_len;
570 uint32 cacert_len, cert_len, flags;
571 X509 *cacert, *server_cert;
572 uint16 tag, length;
573 uint8 *next_tag, *end;
574
575 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
576 in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
577 if (crypt_level == 0) /* no encryption */
578 return False;
579 in_uint32_le(s, random_len);
580 in_uint32_le(s, rsa_info_len);
581
582 if (random_len != SEC_RANDOM_SIZE)
583 {
584 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
585 return False;
586 }
587
588 in_uint8p(s, *server_random, random_len);
589
590 /* RSA info */
591 end = s->p + rsa_info_len;
592 if (end > s->end)
593 return False;
594
595 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
596 if (flags & 1)
597 {
598 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
599 in_uint8s(s, 8); /* unknown */
600
601 while (s->p < end)
602 {
603 in_uint16_le(s, tag);
604 in_uint16_le(s, length);
605
606 next_tag = s->p + length;
607
608 switch (tag)
609 {
610 case SEC_TAG_PUBKEY:
611 if (!sec_parse_public_key(s, modulus, exponent))
612 return False;
613 DEBUG_RDP5(("Got Public key, RDP4-style\n"));
614
615 break;
616
617 case SEC_TAG_KEYSIG:
618 /* Is this a Microsoft key that we just got? */
619 /* Care factor: zero! */
620 /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
621 key as a known key of the hostname. This would prevent some MITM-attacks. */
622 break;
623
624 default:
625 unimpl("crypt tag 0x%x\n", tag);
626 }
627
628 s->p = next_tag;
629 }
630 }
631 else
632 {
633 uint32 certcount;
634
635 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
636 in_uint32_le(s, certcount); /* Number of certificates */
637
638 if (certcount < 2)
639 {
640 error("Server didn't send enough X509 certificates\n");
641 return False;
642 }
643
644 for (; certcount > 2; certcount--)
645 { /* ignore all the certificates between the root and the signing CA */
646 uint32 ignorelen;
647 X509 *ignorecert;
648
649 DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
650
651 in_uint32_le(s, ignorelen);
652 DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
653 ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
654
655 if (ignorecert == NULL)
656 { /* XXX: error out? */
657 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
658 }
659
660 #ifdef WITH_DEBUG_RDP5
661 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
662 X509_print_fp(stdout, ignorecert);
663 #endif
664 }
665
666 /* Do da funky X.509 stuffy
667
668 "How did I find out about this? I looked up and saw a
669 bright light and when I came to I had a scar on my forehead
670 and knew about X.500"
671 - Peter Gutman in a early version of
672 http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
673 */
674
675 in_uint32_le(s, cacert_len);
676 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
677 cacert = d2i_X509(NULL, &(s->p), cacert_len);
678 /* Note: We don't need to move s->p here - d2i_X509 is
679 "kind" enough to do it for us */
680 if (NULL == cacert)
681 {
682 error("Couldn't load CA Certificate from server\n");
683 return False;
684 }
685
686 /* Currently, we don't use the CA Certificate.
687 FIXME:
688 *) Verify the server certificate (server_cert) with the
689 CA certificate.
690 *) Store the CA Certificate with the hostname of the
691 server we are connecting to as key, and compare it
692 when we connect the next time, in order to prevent
693 MITM-attacks.
694 */
695
696 X509_free(cacert);
697
698 in_uint32_le(s, cert_len);
699 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
700 server_cert = d2i_X509(NULL, &(s->p), cert_len);
701 if (NULL == server_cert)
702 {
703 error("Couldn't load Certificate from server\n");
704 return False;
705 }
706
707 in_uint8s(s, 16); /* Padding */
708
709 /* Note: Verifying the server certificate must be done here,
710 before sec_parse_public_key since we'll have to apply
711 serious violence to the key after this */
712
713 if (!sec_parse_x509_key(server_cert))
714 {
715 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
716 X509_free(server_cert);
717 return False;
718 }
719 X509_free(server_cert);
720 return True; /* There's some garbage here we don't care about */
721 }
722 return s_check_end(s);
723 }
724
725 /* Process crypto information blob */
726 static void
727 sec_process_crypt_info(STREAM s)
728 {
729 uint8 *server_random, *modulus = NULL, *exponent = NULL;
730 uint8 client_random[SEC_RANDOM_SIZE];
731 uint32 rc4_key_size;
732
733 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
734 {
735 DEBUG(("Failed to parse crypt info\n"));
736 return;
737 }
738
739 DEBUG(("Generating client random\n"));
740 generate_random(client_random);
741
742 if (NULL != server_public_key)
743 { /* Which means we should use
744 RDP5-style encryption */
745 uint8 inr[SEC_MAX_MODULUS_SIZE];
746 uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;
747
748 /* This is what the MS client do: */
749 memset(inr, 0, padding_len);
750 /* *ARIGL!* Plaintext attack, anyone?
751 I tried doing:
752 generate_random(inr);
753 ..but that generates connection errors now and then (yes,
754 "now and then". Something like 0 to 3 attempts needed before a
755 successful connection. Nice. Not!
756 */
757 memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
758 reverse(inr + padding_len, SEC_RANDOM_SIZE);
759
760 RSA_public_encrypt(server_public_key_len,
761 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
762
763 reverse(sec_crypted_random, server_public_key_len);
764
765 RSA_free(server_public_key);
766 server_public_key = NULL;
767 }
768 else
769 { /* RDP4-style encryption */
770 sec_rsa_encrypt(sec_crypted_random,
771 client_random, SEC_RANDOM_SIZE, server_public_key_len, modulus,
772 exponent);
773 }
774 sec_generate_keys(client_random, server_random, rc4_key_size);
775 }
776
777
778 /* Process SRV_INFO, find RDP version supported by server */
779 static void
780 sec_process_srv_info(STREAM s)
781 {
782 in_uint16_le(s, g_server_rdp_version);
783 DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
784 if (1 == g_server_rdp_version)
785 {
786 g_use_rdp5 = 0;
787 g_server_depth = 8;
788 }
789 }
790
791
792 /* Process connect response data blob */
793 void
794 sec_process_mcs_data(STREAM s)
795 {
796 uint16 tag, length;
797 uint8 *next_tag;
798 uint8 len;
799
800 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
801 in_uint8(s, len);
802 if (len & 0x80)
803 in_uint8(s, len);
804
805 while (s->p < s->end)
806 {
807 in_uint16_le(s, tag);
808 in_uint16_le(s, length);
809
810 if (length <= 4)
811 return;
812
813 next_tag = s->p + length - 4;
814
815 switch (tag)
816 {
817 case SEC_TAG_SRV_INFO:
818 sec_process_srv_info(s);
819 break;
820
821 case SEC_TAG_SRV_CRYPT:
822 sec_process_crypt_info(s);
823 break;
824
825 case SEC_TAG_SRV_CHANNELS:
826 /* FIXME: We should parse this information and
827 use it to map RDP5 channels to MCS
828 channels */
829 break;
830
831 default:
832 unimpl("response tag 0x%x\n", tag);
833 }
834
835 s->p = next_tag;
836 }
837 }
838
839 /* Receive secure transport packet */
840 STREAM
841 sec_recv(uint8 * rdpver)
842 {
843 uint32 sec_flags;
844 uint16 channel;
845 STREAM s;
846
847 while ((s = mcs_recv(&channel, rdpver)) != NULL)
848 {
849 if (rdpver != NULL)
850 {
851 if (*rdpver != 3)
852 {
853 if (*rdpver & 0x80)
854 {
855 in_uint8s(s, 8); /* signature */
856 sec_decrypt(s->p, s->end - s->p);
857 }
858 return s;
859 }
860 }
861 if (g_encryption || !g_licence_issued)
862 {
863 in_uint32_le(s, sec_flags);
864
865 if (sec_flags & SEC_ENCRYPT)
866 {
867 in_uint8s(s, 8); /* signature */
868 sec_decrypt(s->p, s->end - s->p);
869 }
870
871 if (sec_flags & SEC_LICENCE_NEG)
872 {
873 licence_process(s);
874 continue;
875 }
876
877 if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
878 {
879 uint8 swapbyte;
880
881 in_uint8s(s, 8); /* signature */
882 sec_decrypt(s->p, s->end - s->p);
883
884 /* Check for a redirect packet, starts with 00 04 */
885 if (s->p[0] == 0 && s->p[1] == 4)
886 {
887 /* for some reason the PDU and the length seem to be swapped.
888 This isn't good, but we're going to do a byte for byte
889 swap. So the first foure value appear as: 00 04 XX YY,
890 where XX YY is the little endian length. We're going to
891 use 04 00 as the PDU type, so after our swap this will look
892 like: XX YY 04 00 */
893 swapbyte = s->p[0];
894 s->p[0] = s->p[2];
895 s->p[2] = swapbyte;
896
897 swapbyte = s->p[1];
898 s->p[1] = s->p[3];
899 s->p[3] = swapbyte;
900
901 swapbyte = s->p[2];
902 s->p[2] = s->p[3];
903 s->p[3] = swapbyte;
904 }
905 #ifdef WITH_DEBUG
906 /* warning! this debug statement will show passwords in the clear! */
907 hexdump(s->p, s->end - s->p);
908 #endif
909 }
910
911 }
912
913 if (channel != MCS_GLOBAL_CHANNEL)
914 {
915 channel_process(s, channel);
916 *rdpver = 0xff;
917 return s;
918 }
919
920 return s;
921 }
922
923 return NULL;
924 }
925
926 /* Establish a secure connection */
927 BOOL
928 sec_connect(char *server, char *username)
929 {
930 struct stream mcs_data;
931
932 /* We exchange some RDP data during the MCS-Connect */
933 mcs_data.size = 512;
934 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
935 sec_out_mcs_data(&mcs_data);
936
937 if (!mcs_connect(server, &mcs_data, username))
938 return False;
939
940 /* sec_process_mcs_data(&mcs_data); */
941 if (g_encryption)
942 sec_establish_key();
943 xfree(mcs_data.data);
944 return True;
945 }
946
947 /* Establish a secure connection */
948 BOOL
949 sec_reconnect(char *server)
950 {
951 struct stream mcs_data;
952
953 /* We exchange some RDP data during the MCS-Connect */
954 mcs_data.size = 512;
955 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
956 sec_out_mcs_data(&mcs_data);
957
958 if (!mcs_reconnect(server, &mcs_data))
959 return False;
960
961 /* sec_process_mcs_data(&mcs_data); */
962 if (g_encryption)
963 sec_establish_key();
964 xfree(mcs_data.data);
965 return True;
966 }
967
968 /* Disconnect a connection */
969 void
970 sec_disconnect(void)
971 {
972 mcs_disconnect();
973 }
974
975 /* reset the state of the sec layer */
976 void
977 sec_reset_state(void)
978 {
979 g_server_rdp_version = 0;
980 sec_encrypt_use_count = 0;
981 sec_decrypt_use_count = 0;
982 mcs_reset_state();
983 }

  ViewVC Help
Powered by ViewVC 1.1.26