/[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 412 - (show annotations)
Fri Jun 6 11:07:46 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 20235 byte(s)
Request channels in an orderly way :).
Allow transmission on a certain channel (still retaining old interface).
Indentation changes.

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 cacert = d2i_X509(NULL, &(s->p), cacert_len);
644 /* Note: We don't need to move s->p here - d2i_X509 is
645 "kind" enough to do it for us */
646 if (NULL == cacert)
647 {
648 error("Couldn't load CA Certificate from server\n");
649 return False;
650 }
651
652 /* Currently, we don't use the CA Certificate.
653 FIXME:
654 *) Verify the server certificate (server_cert) with the
655 CA certificate.
656 *) Store the CA Certificate with the hostname of the
657 server we are connecting to as key, and compare it
658 when we connect the next time, in order to prevent
659 MITM-attacks.
660 */
661
662 in_uint32_le(s, cert_len);
663 server_cert = d2i_X509(NULL, &(s->p), cert_len);
664 if (NULL == server_cert)
665 {
666 error("Couldn't load Certificate from server\n");
667 return False;
668 }
669
670 in_uint8s(s, 16); /* Padding */
671
672 /* Note: Verifying the server certificate must be done here,
673 before sec_parse_public_key since we'll have to apply
674 serious violence to the key after this */
675
676 if (!sec_parse_x509_key(server_cert))
677 {
678 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
679 return False;
680 }
681 return True; /* There's some garbage here we don't care about */
682 }
683 return s_check_end(s);
684 }
685
686 /* Process crypto information blob */
687 static void
688 sec_process_crypt_info(STREAM s)
689 {
690 uint8 *server_random, *modulus, *exponent;
691 uint8 client_random[SEC_RANDOM_SIZE];
692 uint32 rc4_key_size;
693 uint8 inr[SEC_MODULUS_SIZE];
694
695 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
696 {
697 DEBUG(("Failed to parse crypt info\n"));
698 return;
699 }
700
701 DEBUG(("Generating client random\n"));
702 /* Generate a client random, and hence determine encryption keys */
703 // This is what the MS client do:
704 memset(inr, 0, SEC_RANDOM_SIZE);
705 /* *ARIGL!* Plaintext attack, anyone?
706 I tried doing:
707 generate_random(inr);
708 ..but that generates connection errors now and then (yes,
709 "now and then". Something like 0 to 3 attempts needed before a
710 successful connection. Nice. Not!
711 */
712
713 generate_random(client_random);
714 if (NULL != server_public_key)
715 { /* Which means we should use
716 RDP5-style encryption */
717
718 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
719 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
720
721 RSA_public_encrypt(SEC_MODULUS_SIZE,
722 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
723
724 reverse(sec_crypted_random, SEC_MODULUS_SIZE);
725
726 }
727 else
728 { /* RDP4-style encryption */
729 sec_rsa_encrypt(sec_crypted_random,
730 client_random, SEC_RANDOM_SIZE, modulus, exponent);
731 }
732 sec_generate_keys(client_random, server_random, rc4_key_size);
733 }
734
735
736 /* Process SRV_INFO, find RDP version supported by server */
737 static void
738 sec_process_srv_info(STREAM s)
739 {
740 in_uint16_le(s, server_rdp_version);
741 DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
742 }
743
744
745 /* Process connect response data blob */
746 void
747 sec_process_mcs_data(STREAM s)
748 {
749 uint16 tag, length;
750 uint8 *next_tag;
751 uint8 len;
752
753 in_uint8s(s, 21); /* header (T.124 stuff, probably) */
754 in_uint8(s, len);
755 if (len & 0x80)
756 in_uint8(s, len);
757
758 while (s->p < s->end)
759 {
760 in_uint16_le(s, tag);
761 in_uint16_le(s, length);
762
763 if (length <= 4)
764 return;
765
766 next_tag = s->p + length - 4;
767
768 switch (tag)
769 {
770 case SEC_TAG_SRV_INFO:
771 sec_process_srv_info(s);
772 break;
773
774 case SEC_TAG_SRV_3:
775 break;
776
777 case SEC_TAG_SRV_CRYPT:
778 sec_process_crypt_info(s);
779 break;
780
781 default:
782 unimpl("response tag 0x%x\n", tag);
783 }
784
785 s->p = next_tag;
786 }
787 }
788
789 /* Receive secure transport packet */
790 STREAM
791 sec_recv(void)
792 {
793 uint32 sec_flags;
794 uint16 channel;
795 STREAM s;
796
797 while ((s = mcs_recv(&channel)) != NULL)
798 {
799 if (encryption || !g_licence_issued)
800 {
801 in_uint32_le(s, sec_flags);
802
803 if (sec_flags & SEC_LICENCE_NEG)
804 {
805 if (sec_flags & SEC_ENCRYPT)
806 {
807 DEBUG_RDP5(("Encrypted license detected\n"));
808 }
809 licence_process(s);
810 continue;
811 }
812
813 if (sec_flags & SEC_ENCRYPT)
814 {
815 in_uint8s(s, 8); /* signature */
816 sec_decrypt(s->p, s->end - s->p);
817 }
818 }
819
820 if (MCS_GLOBAL_CHANNEL == channel)
821 {
822 return s;
823 }
824 else
825 rdp5_process_channel(s, channel);
826
827 }
828
829 return NULL;
830 }
831
832 /* Establish a secure connection */
833 BOOL
834 sec_connect(char *server, char *username)
835 {
836 struct stream mcs_data;
837
838 /* We exchange some RDP data during the MCS-Connect */
839 mcs_data.size = 512;
840 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
841 sec_out_mcs_data(&mcs_data);
842
843 if (!mcs_connect(server, &mcs_data, username))
844 return False;
845
846 // sec_process_mcs_data(&mcs_data);
847 if (encryption)
848 sec_establish_key();
849 xfree(mcs_data.data);
850 return True;
851 }
852
853 /* Disconnect a connection */
854 void
855 sec_disconnect(void)
856 {
857 mcs_disconnect();
858 }

  ViewVC Help
Powered by ViewVC 1.1.26