/[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 1199 - (hide annotations)
Mon Mar 27 08:17:34 2006 UTC (18 years, 1 month ago) by astrand
File MIME type: text/plain
File size: 24091 byte(s)
Added SeamlessRDP support: Merged seamlessrdp-branch

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 astrand 1035 extern unsigned 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 astrand 1042 extern int g_server_depth;
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 astrand 977 /* These values must be available to reset state - Session Directory */
60     static int sec_encrypt_use_count = 0;
61     static int sec_decrypt_use_count = 0;
62    
63 matty 10 /*
64 matthewc 699 * I believe this is based on SSLv3 with the following differences:
65     * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
66     * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
67     * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
68     * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
69     * encryption/decryption keys updated every 4096 packets
70     * See http://wp.netscape.com/eng/ssl3/draft302.txt
71     */
72    
73     /*
74     * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
75 matty 10 * Both SHA1 and MD5 algorithms are used.
76     */
77 matty 25 void
78 astrand 64 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
79 matty 10 {
80     uint8 shasig[20];
81     uint8 pad[4];
82     SHA_CTX sha;
83     MD5_CTX md5;
84     int i;
85    
86     for (i = 0; i < 3; i++)
87     {
88 matty 24 memset(pad, salt + i, i + 1);
89 matty 10
90     SHA1_Init(&sha);
91 matty 24 SHA1_Update(&sha, pad, i + 1);
92 matty 10 SHA1_Update(&sha, in, 48);
93     SHA1_Update(&sha, salt1, 32);
94     SHA1_Update(&sha, salt2, 32);
95     SHA1_Final(shasig, &sha);
96    
97     MD5_Init(&md5);
98     MD5_Update(&md5, in, 48);
99     MD5_Update(&md5, shasig, 20);
100 matty 24 MD5_Final(&out[i * 16], &md5);
101 matty 10 }
102     }
103    
104     /*
105 matthewc 699 * 16-byte transformation used to generate export keys (6.2.2).
106 matty 10 */
107 matty 25 void
108 astrand 64 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
109 matty 10 {
110     MD5_CTX md5;
111    
112     MD5_Init(&md5);
113     MD5_Update(&md5, in, 16);
114     MD5_Update(&md5, salt1, 32);
115     MD5_Update(&md5, salt2, 32);
116     MD5_Final(out, &md5);
117     }
118    
119     /* Reduce key entropy from 64 to 40 bits */
120 matty 25 static void
121 astrand 64 sec_make_40bit(uint8 * key)
122 matty 10 {
123     key[0] = 0xd1;
124     key[1] = 0x26;
125     key[2] = 0x9e;
126     }
127    
128 matthewc 699 /* Generate encryption keys given client and server randoms */
129 matty 25 static void
130 matthewc 699 sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
131 matty 10 {
132 matthewc 699 uint8 pre_master_secret[48];
133     uint8 master_secret[48];
134     uint8 key_block[48];
135 matty 10
136 matthewc 699 /* Construct pre-master secret */
137 astrand 706 memcpy(pre_master_secret, client_random, 24);
138 matthewc 699 memcpy(pre_master_secret + 24, server_random, 24);
139 matty 10
140 matthewc 699 /* Generate master secret and then key material */
141     sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
142 astrand 706 sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
143 matty 10
144 matthewc 699 /* First 16 bytes of key material is MAC secret */
145     memcpy(sec_sign_key, key_block, 16);
146 matty 10
147 matthewc 699 /* Generate export keys from next two blocks of 16 bytes */
148     sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
149     sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
150 matty 10
151     if (rc4_key_size == 1)
152     {
153 matty 30 DEBUG(("40-bit encryption enabled\n"));
154 matty 10 sec_make_40bit(sec_sign_key);
155     sec_make_40bit(sec_decrypt_key);
156     sec_make_40bit(sec_encrypt_key);
157     rc4_key_len = 8;
158     }
159     else
160     {
161 forsberg 352 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
162 matty 10 rc4_key_len = 16;
163     }
164    
165 matthewc 57 /* Save initial RC4 keys as update keys */
166     memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
167     memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
168 matty 10
169     /* Initialise RC4 state arrays */
170     RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
171     RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
172     }
173    
174 matty 24 static uint8 pad_54[40] = {
175     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
176 matty 25 54, 54, 54,
177 matty 24 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
178 matty 25 54, 54, 54
179 matty 10 };
180    
181 matty 24 static uint8 pad_92[48] = {
182     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
183 matty 25 92, 92, 92, 92, 92, 92, 92,
184 matty 24 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
185 matty 25 92, 92, 92, 92, 92, 92, 92
186 matty 10 };
187    
188     /* Output a uint32 into a buffer (little-endian) */
189 matty 25 void
190 astrand 64 buf_out_uint32(uint8 * buffer, uint32 value)
191 matty 10 {
192     buffer[0] = (value) & 0xff;
193     buffer[1] = (value >> 8) & 0xff;
194     buffer[2] = (value >> 16) & 0xff;
195     buffer[3] = (value >> 24) & 0xff;
196     }
197    
198 matthewc 699 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
199 matty 25 void
200 astrand 82 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
201 matty 10 {
202     uint8 shasig[20];
203     uint8 md5sig[16];
204     uint8 lenhdr[4];
205     SHA_CTX sha;
206     MD5_CTX md5;
207    
208 matty 24 buf_out_uint32(lenhdr, datalen);
209 matty 10
210     SHA1_Init(&sha);
211 matthewc 61 SHA1_Update(&sha, session_key, keylen);
212 matty 10 SHA1_Update(&sha, pad_54, 40);
213     SHA1_Update(&sha, lenhdr, 4);
214     SHA1_Update(&sha, data, datalen);
215     SHA1_Final(shasig, &sha);
216    
217     MD5_Init(&md5);
218 matthewc 61 MD5_Update(&md5, session_key, keylen);
219 matty 10 MD5_Update(&md5, pad_92, 48);
220     MD5_Update(&md5, shasig, 20);
221     MD5_Final(md5sig, &md5);
222    
223 matthewc 61 memcpy(signature, md5sig, siglen);
224 matty 10 }
225    
226 matthewc 699 /* Update an encryption key */
227 matty 25 static void
228 astrand 64 sec_update(uint8 * key, uint8 * update_key)
229 matty 10 {
230     uint8 shasig[20];
231     SHA_CTX sha;
232     MD5_CTX md5;
233     RC4_KEY update;
234    
235     SHA1_Init(&sha);
236 matthewc 57 SHA1_Update(&sha, update_key, rc4_key_len);
237 matty 10 SHA1_Update(&sha, pad_54, 40);
238 matthewc 57 SHA1_Update(&sha, key, rc4_key_len);
239 matty 10 SHA1_Final(shasig, &sha);
240    
241     MD5_Init(&md5);
242 matthewc 57 MD5_Update(&md5, update_key, rc4_key_len);
243 matty 10 MD5_Update(&md5, pad_92, 48);
244     MD5_Update(&md5, shasig, 20);
245     MD5_Final(key, &md5);
246    
247     RC4_set_key(&update, rc4_key_len, key);
248     RC4(&update, rc4_key_len, key, key);
249    
250     if (rc4_key_len == 8)
251     sec_make_40bit(key);
252     }
253    
254     /* Encrypt data using RC4 */
255 matty 25 static void
256 astrand 64 sec_encrypt(uint8 * data, int length)
257 matty 10 {
258 astrand 977 if (sec_encrypt_use_count == 4096)
259 matty 10 {
260     sec_update(sec_encrypt_key, sec_encrypt_update_key);
261     RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
262 astrand 977 sec_encrypt_use_count = 0;
263 matty 10 }
264    
265     RC4(&rc4_encrypt_key, length, data, data);
266 astrand 977 sec_encrypt_use_count++;
267 matty 10 }
268    
269     /* Decrypt data using RC4 */
270 forsberg 352 void
271 astrand 64 sec_decrypt(uint8 * data, int length)
272 matty 10 {
273 astrand 977 if (sec_decrypt_use_count == 4096)
274 matty 10 {
275     sec_update(sec_decrypt_key, sec_decrypt_update_key);
276     RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
277 astrand 977 sec_decrypt_use_count = 0;
278 matty 10 }
279    
280     RC4(&rc4_decrypt_key, length, data, data);
281 astrand 977 sec_decrypt_use_count++;
282 matty 10 }
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 966 /* See
453     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
454 astrand 964 out_uint32_le(s, g_keyboard_type);
455     out_uint32_le(s, g_keyboard_subtype);
456     out_uint32_le(s, g_keyboard_functionkeys);
457 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
458 n-ki 677 out_uint16_le(s, 0xca01); /* colour depth? */
459 matthewc 365 out_uint16_le(s, 1);
460 matty 10
461 forsberg 352 out_uint32(s, 0);
462 astrand 1042 out_uint8(s, g_server_depth);
463 forsberg 357 out_uint16_le(s, 0x0700);
464     out_uint8(s, 0);
465 forsberg 352 out_uint32_le(s, 1);
466     out_uint8s(s, 64); /* End of client info */
467    
468     out_uint16_le(s, SEC_TAG_CLI_4);
469     out_uint16_le(s, 12);
470 matthewc 482 out_uint32_le(s, g_console_session ? 0xb : 9);
471 matthewc 365 out_uint32(s, 0);
472 forsberg 352
473 matty 10 /* Client encryption settings */
474     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
475 forsberg 352 out_uint16_le(s, 12); /* length */
476 jsorg71 437 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
477 matthewc 365 out_uint32(s, 0); /* Unknown */
478 forsberg 352
479 matthewc 432 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
480     if (g_num_channels > 0)
481 forsberg 412 {
482     out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
483 matthewc 432 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
484     out_uint32_le(s, g_num_channels); /* number of virtual channels */
485     for (i = 0; i < g_num_channels; i++)
486 forsberg 412 {
487 matthewc 432 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
488     out_uint8a(s, g_channels[i].name, 8);
489     out_uint32_be(s, g_channels[i].flags);
490 forsberg 412 }
491     }
492 forsberg 352
493 matty 10 s_mark_end(s);
494     }
495    
496     /* Parse a public key structure */
497 matty 25 static BOOL
498 astrand 64 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
499 matty 10 {
500     uint32 magic, modulus_len;
501    
502     in_uint32_le(s, magic);
503     if (magic != SEC_RSA_MAGIC)
504     {
505 matty 30 error("RSA magic 0x%x\n", magic);
506 matty 10 return False;
507     }
508    
509     in_uint32_le(s, modulus_len);
510     if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
511     {
512 matty 30 error("modulus len 0x%x\n", modulus_len);
513 matty 10 return False;
514     }
515    
516 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
517 matty 10 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
518     in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
519     in_uint8s(s, SEC_PADDING_SIZE);
520    
521     return s_check(s);
522     }
523    
524 forsberg 352 static BOOL
525     sec_parse_x509_key(X509 * cert)
526     {
527     EVP_PKEY *epk = NULL;
528     /* By some reason, Microsoft sets the OID of the Public RSA key to
529     the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
530    
531     Kudos to Richard Levitte for the following (. intiutive .)
532     lines of code that resets the OID and let's us extract the key. */
533     if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
534     {
535     DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
536 astrand 1199 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
537 forsberg 352 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
538     }
539     epk = X509_get_pubkey(cert);
540     if (NULL == epk)
541     {
542     error("Failed to extract public key from certificate\n");
543     return False;
544     }
545    
546 astrand 1199 server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
547 forsberg 352
548 astrand 1199 EVP_PKEY_free(epk);
549    
550 forsberg 352 return True;
551     }
552    
553    
554 matty 10 /* Parse a crypto information structure */
555 matty 25 static BOOL
556 astrand 64 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
557 astrand 82 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
558 matty 10 {
559     uint32 crypt_level, random_len, rsa_info_len;
560 matthewc 363 uint32 cacert_len, cert_len, flags;
561 forsberg 352 X509 *cacert, *server_cert;
562 matty 10 uint16 tag, length;
563     uint8 *next_tag, *end;
564    
565 matty 24 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
566     in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
567 forsberg 352 if (crypt_level == 0) /* no encryption */
568 jsorg71 89 return False;
569 matty 10 in_uint32_le(s, random_len);
570     in_uint32_le(s, rsa_info_len);
571    
572     if (random_len != SEC_RANDOM_SIZE)
573     {
574 forsberg 352 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
575 matty 10 return False;
576     }
577    
578     in_uint8p(s, *server_random, random_len);
579    
580     /* RSA info */
581     end = s->p + rsa_info_len;
582     if (end > s->end)
583     return False;
584    
585 forsberg 412 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
586 matthewc 363 if (flags & 1)
587 forsberg 352 {
588     DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
589 matthewc 363 in_uint8s(s, 8); /* unknown */
590 matty 10
591 forsberg 352 while (s->p < end)
592     {
593     in_uint16_le(s, tag);
594     in_uint16_le(s, length);
595    
596     next_tag = s->p + length;
597    
598     switch (tag)
599     {
600     case SEC_TAG_PUBKEY:
601     if (!sec_parse_public_key(s, modulus, exponent))
602     return False;
603     DEBUG_RDP5(("Got Public key, RDP4-style\n"));
604    
605     break;
606    
607     case SEC_TAG_KEYSIG:
608     /* Is this a Microsoft key that we just got? */
609     /* Care factor: zero! */
610     /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
611     key as a known key of the hostname. This would prevent some MITM-attacks. */
612     break;
613    
614     default:
615     unimpl("crypt tag 0x%x\n", tag);
616     }
617    
618     s->p = next_tag;
619     }
620     }
621 matthewc 363 else
622 matty 10 {
623 stargo 557 uint32 certcount;
624    
625 forsberg 352 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
626 astrand 580 in_uint32_le(s, certcount); /* Number of certificates */
627 matty 10
628 astrand 580 if (certcount < 2)
629 stargo 557 {
630     error("Server didn't send enough X509 certificates\n");
631     return False;
632     }
633    
634 astrand 580 for (; certcount > 2; certcount--)
635     { /* ignore all the certificates between the root and the signing CA */
636 stargo 557 uint32 ignorelen;
637     X509 *ignorecert;
638    
639     DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
640    
641     in_uint32_le(s, ignorelen);
642     DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
643     ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
644    
645 astrand 580 if (ignorecert == NULL)
646     { /* XXX: error out? */
647 stargo 557 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
648     }
649    
650     #ifdef WITH_DEBUG_RDP5
651 astrand 580 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
652 stargo 557 X509_print_fp(stdout, ignorecert);
653     #endif
654     }
655    
656 forsberg 352 /* Do da funky X.509 stuffy
657 matty 10
658 forsberg 352 "How did I find out about this? I looked up and saw a
659     bright light and when I came to I had a scar on my forehead
660     and knew about X.500"
661     - Peter Gutman in a early version of
662     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
663     */
664    
665     in_uint32_le(s, cacert_len);
666 forsberg 419 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
667 forsberg 352 cacert = d2i_X509(NULL, &(s->p), cacert_len);
668     /* Note: We don't need to move s->p here - d2i_X509 is
669     "kind" enough to do it for us */
670     if (NULL == cacert)
671 matty 10 {
672 forsberg 352 error("Couldn't load CA Certificate from server\n");
673     return False;
674     }
675 matty 10
676 forsberg 352 /* Currently, we don't use the CA Certificate.
677     FIXME:
678     *) Verify the server certificate (server_cert) with the
679     CA certificate.
680     *) Store the CA Certificate with the hostname of the
681     server we are connecting to as key, and compare it
682     when we connect the next time, in order to prevent
683     MITM-attacks.
684     */
685 matty 10
686 astrand 1199 X509_free(cacert);
687    
688 forsberg 352 in_uint32_le(s, cert_len);
689 forsberg 419 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
690 forsberg 352 server_cert = d2i_X509(NULL, &(s->p), cert_len);
691     if (NULL == server_cert)
692     {
693     error("Couldn't load Certificate from server\n");
694     return False;
695     }
696 matty 10
697 forsberg 352 in_uint8s(s, 16); /* Padding */
698    
699     /* Note: Verifying the server certificate must be done here,
700     before sec_parse_public_key since we'll have to apply
701     serious violence to the key after this */
702    
703     if (!sec_parse_x509_key(server_cert))
704     {
705     DEBUG_RDP5(("Didn't parse X509 correctly\n"));
706 astrand 1199 X509_free(server_cert);
707 forsberg 352 return False;
708 matty 10 }
709 astrand 1199 X509_free(server_cert);
710 forsberg 352 return True; /* There's some garbage here we don't care about */
711 matty 10 }
712     return s_check_end(s);
713     }
714    
715     /* Process crypto information blob */
716 matty 25 static void
717     sec_process_crypt_info(STREAM s)
718 matty 10 {
719     uint8 *server_random, *modulus, *exponent;
720     uint8 client_random[SEC_RANDOM_SIZE];
721     uint32 rc4_key_size;
722 forsberg 352 uint8 inr[SEC_MODULUS_SIZE];
723 matty 10
724 astrand 82 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
725 forsberg 352 {
726     DEBUG(("Failed to parse crypt info\n"));
727 matty 10 return;
728 forsberg 352 }
729 matty 10
730 forsberg 352 DEBUG(("Generating client random\n"));
731 forsberg 412 /* Generate a client random, and hence determine encryption keys */
732 astrand 540 /* This is what the MS client do: */
733 forsberg 377 memset(inr, 0, SEC_RANDOM_SIZE);
734     /* *ARIGL!* Plaintext attack, anyone?
735 forsberg 412 I tried doing:
736     generate_random(inr);
737     ..but that generates connection errors now and then (yes,
738     "now and then". Something like 0 to 3 attempts needed before a
739     successful connection. Nice. Not!
740     */
741 forsberg 377
742 matty 10 generate_random(client_random);
743 forsberg 352 if (NULL != server_public_key)
744     { /* Which means we should use
745     RDP5-style encryption */
746    
747     memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
748     reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
749    
750     RSA_public_encrypt(SEC_MODULUS_SIZE,
751     inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
752    
753     reverse(sec_crypted_random, SEC_MODULUS_SIZE);
754    
755 astrand 1199 RSA_free(server_public_key);
756     server_public_key = NULL;
757 forsberg 352 }
758     else
759     { /* RDP4-style encryption */
760     sec_rsa_encrypt(sec_crypted_random,
761     client_random, SEC_RANDOM_SIZE, modulus, exponent);
762     }
763 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
764     }
765    
766 forsberg 352
767     /* Process SRV_INFO, find RDP version supported by server */
768     static void
769     sec_process_srv_info(STREAM s)
770     {
771 jsorg71 438 in_uint16_le(s, g_server_rdp_version);
772     DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
773     if (1 == g_server_rdp_version)
774 n-ki 677 {
775 jsorg71 438 g_use_rdp5 = 0;
776 astrand 1042 g_server_depth = 8;
777 n-ki 677 }
778 forsberg 352 }
779    
780    
781 matty 10 /* Process connect response data blob */
782 forsberg 352 void
783 matty 25 sec_process_mcs_data(STREAM s)
784 matty 10 {
785     uint16 tag, length;
786     uint8 *next_tag;
787 jsorg71 90 uint8 len;
788 matty 10
789 matthewc 642 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
790 jsorg71 90 in_uint8(s, len);
791     if (len & 0x80)
792     in_uint8(s, len);
793 matty 10
794     while (s->p < s->end)
795     {
796     in_uint16_le(s, tag);
797     in_uint16_le(s, length);
798    
799     if (length <= 4)
800     return;
801    
802     next_tag = s->p + length - 4;
803    
804     switch (tag)
805     {
806     case SEC_TAG_SRV_INFO:
807 forsberg 352 sec_process_srv_info(s);
808     break;
809    
810 matthewc 432 case SEC_TAG_SRV_CRYPT:
811     sec_process_crypt_info(s);
812     break;
813    
814     case SEC_TAG_SRV_CHANNELS:
815 forsberg 419 /* FIXME: We should parse this information and
816     use it to map RDP5 channels to MCS
817 astrand 435 channels */
818 matty 10 break;
819    
820     default:
821 matty 30 unimpl("response tag 0x%x\n", tag);
822 matty 10 }
823    
824     s->p = next_tag;
825     }
826     }
827    
828     /* Receive secure transport packet */
829 matty 25 STREAM
830 jsorg71 733 sec_recv(uint8 * rdpver)
831 matty 10 {
832     uint32 sec_flags;
833 forsberg 352 uint16 channel;
834 matty 10 STREAM s;
835    
836 jsorg71 733 while ((s = mcs_recv(&channel, rdpver)) != NULL)
837 matty 10 {
838 jsorg71 733 if (rdpver != NULL)
839     {
840     if (*rdpver != 3)
841     {
842     if (*rdpver & 0x80)
843     {
844     in_uint8s(s, 8); /* signature */
845     sec_decrypt(s->p, s->end - s->p);
846     }
847     return s;
848     }
849     }
850 jsorg71 437 if (g_encryption || !g_licence_issued)
851 matty 10 {
852 matty 28 in_uint32_le(s, sec_flags);
853 matty 10
854 matthewc 432 if (sec_flags & SEC_ENCRYPT)
855     {
856     in_uint8s(s, 8); /* signature */
857     sec_decrypt(s->p, s->end - s->p);
858     }
859    
860 matty 28 if (sec_flags & SEC_LICENCE_NEG)
861     {
862     licence_process(s);
863     continue;
864     }
865 astrand 977
866     if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
867     {
868     uint8 swapbyte;
869    
870     in_uint8s(s, 8); /* signature */
871     sec_decrypt(s->p, s->end - s->p);
872    
873     /* Check for a redirect packet, starts with 00 04 */
874     if (s->p[0] == 0 && s->p[1] == 4)
875     {
876     /* for some reason the PDU and the length seem to be swapped.
877     This isn't good, but we're going to do a byte for byte
878     swap. So the first foure value appear as: 00 04 XX YY,
879     where XX YY is the little endian length. We're going to
880     use 04 00 as the PDU type, so after our swap this will look
881     like: XX YY 04 00 */
882     swapbyte = s->p[0];
883     s->p[0] = s->p[2];
884     s->p[2] = swapbyte;
885    
886     swapbyte = s->p[1];
887     s->p[1] = s->p[3];
888     s->p[3] = swapbyte;
889    
890     swapbyte = s->p[2];
891     s->p[2] = s->p[3];
892     s->p[3] = swapbyte;
893     }
894     #ifdef WITH_DEBUG
895     /* warning! this debug statement will show passwords in the clear! */
896     hexdump(s->p, s->end - s->p);
897     #endif
898     }
899    
900 matty 10 }
901    
902 matthewc 432 if (channel != MCS_GLOBAL_CHANNEL)
903 forsberg 352 {
904 matthewc 432 channel_process(s, channel);
905 jsorg71 779 *rdpver = 0xff;
906     return s;
907 forsberg 352 }
908    
909 matthewc 432 return s;
910 matty 10 }
911    
912     return NULL;
913     }
914    
915     /* Establish a secure connection */
916 matty 25 BOOL
917 forsberg 352 sec_connect(char *server, char *username)
918 matty 10 {
919     struct stream mcs_data;
920    
921     /* We exchange some RDP data during the MCS-Connect */
922     mcs_data.size = 512;
923 forsberg 412 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
924 matty 10 sec_out_mcs_data(&mcs_data);
925    
926 forsberg 352 if (!mcs_connect(server, &mcs_data, username))
927 matty 10 return False;
928    
929 astrand 540 /* sec_process_mcs_data(&mcs_data); */
930 jsorg71 437 if (g_encryption)
931 matty 28 sec_establish_key();
932 matthewc 218 xfree(mcs_data.data);
933 matty 10 return True;
934     }
935    
936 astrand 977 /* Establish a secure connection */
937     BOOL
938     sec_reconnect(char *server)
939     {
940     struct stream mcs_data;
941    
942     /* We exchange some RDP data during the MCS-Connect */
943     mcs_data.size = 512;
944     mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
945     sec_out_mcs_data(&mcs_data);
946    
947     if (!mcs_reconnect(server, &mcs_data))
948     return False;
949    
950     /* sec_process_mcs_data(&mcs_data); */
951     if (g_encryption)
952     sec_establish_key();
953     xfree(mcs_data.data);
954     return True;
955     }
956    
957 matty 10 /* Disconnect a connection */
958 matty 25 void
959 matthewc 192 sec_disconnect(void)
960 matty 10 {
961     mcs_disconnect();
962     }
963 astrand 977
964     /* reset the state of the sec layer */
965     void
966     sec_reset_state(void)
967     {
968     g_server_rdp_version = 0;
969     sec_encrypt_use_count = 0;
970     sec_decrypt_use_count = 0;
971     mcs_reset_state();
972     }

  ViewVC Help
Powered by ViewVC 1.1.26