/[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 1315 - (show annotations)
Wed Nov 1 22:12:27 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 24810 byte(s)
warnings on newer openssl-versions

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

  ViewVC Help
Powered by ViewVC 1.1.26