/[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 435 - (show annotations)
Wed Jul 9 09:18:20 2003 UTC (20 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 20361 byte(s)
Indent fixes

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