/[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 419 - (show annotations)
Wed Jun 11 07:12:18 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 20466 byte(s)
Added comment about TAG_SRV_SRV_3. And some debug output.

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

  ViewVC Help
Powered by ViewVC 1.1.26