/[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 642 - (show annotations)
Thu Mar 18 02:32:00 2004 UTC (20 years, 2 months ago) by matthewc
File MIME type: text/plain
File size: 21324 byte(s)
Annotate the T.124 bits.

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

  ViewVC Help
Powered by ViewVC 1.1.26