/[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

Annotation of /sourceforge.net/trunk/rdesktop/secure.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 964 - (hide annotations)
Wed Aug 3 11:30:53 2005 UTC (18 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 21923 byte(s)
It is now possible to specify keyboard type, subtype and number of functionskeys. From patch #974509, by Dekaino.

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

  ViewVC Help
Powered by ViewVC 1.1.26