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

1 forsberg 352 /* -*- c-basic-offset: 8 -*-
2 matty 10 rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
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     #ifdef WITH_OPENSSL
24     #include <openssl/rc4.h>
25     #include <openssl/md5.h>
26     #include <openssl/sha.h>
27     #include <openssl/bn.h>
28 forsberg 352 #include <openssl/x509v3.h>
29 matty 32 #else
30 matty 10 #include "crypto/rc4.h"
31     #include "crypto/md5.h"
32     #include "crypto/sha.h"
33 matty 32 #include "crypto/bn.h"
34     #endif
35 matty 10
36     extern char hostname[16];
37     extern int width;
38     extern int height;
39     extern int keylayout;
40 matty 30 extern BOOL encryption;
41 jsorg71 380 extern BOOL g_licence_issued;
42 forsberg 352 extern BOOL use_rdp5;
43 jsorg71 309 extern int server_bpp;
44 forsberg 412 extern uint16 mcs_userid;
45 matty 10
46     static int rc4_key_len;
47     static RC4_KEY rc4_decrypt_key;
48     static RC4_KEY rc4_encrypt_key;
49 forsberg 352 static RSA *server_public_key;
50 matty 10
51 matthewc 57 static uint8 sec_sign_key[16];
52 matty 10 static uint8 sec_decrypt_key[16];
53     static uint8 sec_encrypt_key[16];
54 matthewc 57 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 matty 10
58 forsberg 352 uint16 server_rdp_version = 0;
59    
60 matty 10 /*
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 matty 25 void
66 astrand 64 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
67 matty 10 {
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 matty 24 memset(pad, salt + i, i + 1);
77 matty 10
78     SHA1_Init(&sha);
79 matty 24 SHA1_Update(&sha, pad, i + 1);
80 matty 10 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 matty 24 MD5_Final(&out[i * 16], &md5);
89 matty 10 }
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 matty 25 void
97 astrand 64 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
98 matty 10 {
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 matty 25 static void
110 astrand 64 sec_make_40bit(uint8 * key)
111 matty 10 {
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 matty 25 static void
119 astrand 64 sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
120 matty 10 {
121     uint8 session_key[48];
122     uint8 temp_hash[48];
123     uint8 input[48];
124    
125     /* Construct input data to hash */
126 matty 24 memcpy(input, client_key, 24);
127     memcpy(input + 24, server_key, 24);
128 matty 10
129     /* Generate session key - two rounds of sec_hash_48 */
130 matty 24 sec_hash_48(temp_hash, input, client_key, server_key, 65);
131 matty 10 sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
132    
133 matthewc 57 /* Store first 16 bytes of session key, for generating signatures */
134     memcpy(sec_sign_key, session_key, 16);
135 matty 10
136     /* Generate RC4 keys */
137 astrand 82 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 matty 10
140     if (rc4_key_size == 1)
141     {
142 matty 30 DEBUG(("40-bit encryption enabled\n"));
143 matty 10 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 forsberg 352 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
151 matty 10 rc4_key_len = 16;
152     }
153    
154 matthewc 57 /* 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 matty 10
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 matty 24 static uint8 pad_54[40] = {
164     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
165 matty 25 54, 54, 54,
166 matty 24 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
167 matty 25 54, 54, 54
168 matty 10 };
169    
170 matty 24 static uint8 pad_92[48] = {
171     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
172 matty 25 92, 92, 92, 92, 92, 92, 92,
173 matty 24 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
174 matty 25 92, 92, 92, 92, 92, 92, 92
175 matty 10 };
176    
177     /* Output a uint32 into a buffer (little-endian) */
178 matty 25 void
179 astrand 64 buf_out_uint32(uint8 * buffer, uint32 value)
180 matty 10 {
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 matty 25 void
189 astrand 82 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
190 matty 10 {
191     uint8 shasig[20];
192     uint8 md5sig[16];
193     uint8 lenhdr[4];
194     SHA_CTX sha;
195     MD5_CTX md5;
196    
197 matty 24 buf_out_uint32(lenhdr, datalen);
198 matty 10
199     SHA1_Init(&sha);
200 matthewc 61 SHA1_Update(&sha, session_key, keylen);
201 matty 10 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 matthewc 61 MD5_Update(&md5, session_key, keylen);
208 matty 10 MD5_Update(&md5, pad_92, 48);
209     MD5_Update(&md5, shasig, 20);
210     MD5_Final(md5sig, &md5);
211    
212 matthewc 61 memcpy(signature, md5sig, siglen);
213 matty 10 }
214    
215     /* Update an encryption key - similar to the signing process */
216 matty 25 static void
217 astrand 64 sec_update(uint8 * key, uint8 * update_key)
218 matty 10 {
219     uint8 shasig[20];
220     SHA_CTX sha;
221     MD5_CTX md5;
222     RC4_KEY update;
223    
224     SHA1_Init(&sha);
225 matthewc 57 SHA1_Update(&sha, update_key, rc4_key_len);
226 matty 10 SHA1_Update(&sha, pad_54, 40);
227 matthewc 57 SHA1_Update(&sha, key, rc4_key_len);
228 matty 10 SHA1_Final(shasig, &sha);
229    
230     MD5_Init(&md5);
231 matthewc 57 MD5_Update(&md5, update_key, rc4_key_len);
232 matty 10 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 matty 25 static void
245 astrand 64 sec_encrypt(uint8 * data, int length)
246 matty 10 {
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 forsberg 352 void
262 astrand 64 sec_decrypt(uint8 * data, int length)
263 matty 10 {
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 matty 25 static void
278 astrand 64 reverse(uint8 * p, int len)
279 matty 10 {
280     int i, j;
281 matty 32 uint8 temp;
282 matty 10
283 astrand 64 for (i = 0, j = len - 1; i < j; i++, j--)
284 matty 10 {
285 matty 32 temp = p[i];
286     p[i] = p[j];
287     p[j] = temp;
288 matty 10 }
289     }
290    
291     /* Perform an RSA public key encryption operation */
292 matty 25 static void
293 astrand 82 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
294 matty 10 {
295 matthewc 295 BN_CTX *ctx;
296 matty 32 BIGNUM mod, exp, x, y;
297     uint8 inr[SEC_MODULUS_SIZE];
298     int outlen;
299 matty 10
300 matty 32 reverse(modulus, SEC_MODULUS_SIZE);
301     reverse(exponent, SEC_EXPONENT_SIZE);
302     memcpy(inr, in, len);
303     reverse(inr, len);
304 matty 10
305 matthewc 295 ctx = BN_CTX_new();
306 matty 32 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 matthewc 295 BN_mod_exp(&y, &x, &exp, &mod, ctx);
315 matty 32 outlen = BN_bn2bin(&y, out);
316     reverse(out, outlen);
317     if (outlen < SEC_MODULUS_SIZE)
318 astrand 64 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
319 matty 32
320     BN_free(&y);
321     BN_clear_free(&x);
322     BN_free(&exp);
323     BN_free(&mod);
324 matthewc 295 BN_CTX_free(ctx);
325 matty 10 }
326    
327     /* Initialise secure transport packet */
328 matty 25 STREAM
329     sec_init(uint32 flags, int maxlen)
330 matty 10 {
331     int hdrlen;
332     STREAM s;
333    
334 jsorg71 380 if (!g_licence_issued)
335 matty 28 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
336     else
337     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
338 matty 24 s = mcs_init(maxlen + hdrlen);
339 matty 10 s_push_layer(s, sec_hdr, hdrlen);
340    
341     return s;
342     }
343    
344 forsberg 412 /* Transmit secure transport packet over specified channel */
345 matty 25 void
346 forsberg 412 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
347 matty 10 {
348     int datalen;
349    
350     s_pop_layer(s, sec_hdr);
351 jsorg71 380 if (!g_licence_issued || (flags & SEC_ENCRYPT))
352 matty 28 out_uint32_le(s, flags);
353 matty 10
354     if (flags & SEC_ENCRYPT)
355     {
356     flags &= ~SEC_ENCRYPT;
357     datalen = s->end - s->p - 8;
358    
359 matty 30 #if WITH_DEBUG
360     DEBUG(("Sending encrypted packet:\n"));
361 matty 24 hexdump(s->p + 8, datalen);
362 matty 10 #endif
363    
364 astrand 82 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
365 matty 24 sec_encrypt(s->p + 8, datalen);
366 matty 10 }
367    
368 forsberg 412 mcs_send_to_channel(s, channel);
369 matty 10 }
370    
371 forsberg 412 /* 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 matty 10 /* Transfer the client random to the server */
381 matty 25 static void
382 matthewc 192 sec_establish_key(void)
383 matty 10 {
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 matty 25 static void
400     sec_out_mcs_data(STREAM s)
401 matty 10 {
402 forsberg 412 uint16 num_channels = get_num_channels();
403 matty 10 int hostlen = 2 * strlen(hostname);
404 forsberg 412 int length = 158 + 76 + 12 + 4 + (CHANNEL_TAGDATA_SIZE * num_channels);
405     uint16 i;
406     rdp5_channel *channel;
407 astrand 101
408 forsberg 412 if (0 < num_channels)
409     {
410     length += +4 + 4;
411     }
412    
413 jsorg71 88 if (hostlen > 30)
414     hostlen = 30;
415 matty 10
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 forsberg 352 out_uint16_be(s, (length | 0x8000)); /* remaining length */
422 matty 10
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 matty 24 out_uint32_le(s, 0x61637544); /* "Duca" ?! */
430 forsberg 352 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
431 matty 10
432     /* Client information */
433     out_uint16_le(s, SEC_TAG_CLI_INFO);
434 forsberg 352 out_uint16_le(s, 212); /* length */
435     out_uint16_le(s, use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
436 matty 10 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 forsberg 352 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
443 matty 10
444     /* Unicode name of client, padded to 32 bytes */
445     rdp_out_unistr(s, hostname, hostlen);
446 matty 24 out_uint8s(s, 30 - hostlen);
447 matty 10
448     out_uint32_le(s, 4);
449     out_uint32(s, 0);
450     out_uint32_le(s, 12);
451 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
452 matty 10
453 jsorg71 315 switch (server_bpp)
454 jsorg71 309 {
455 jsorg71 315 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 jsorg71 309 }
468 matthewc 365 out_uint16_le(s, 1);
469 matty 10
470 forsberg 352 out_uint32(s, 0);
471 forsberg 357 out_uint8(s, server_bpp);
472     out_uint16_le(s, 0x0700);
473     out_uint8(s, 0);
474 forsberg 352 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 matthewc 365 out_uint32(s, 0);
481 forsberg 352
482 matty 10 /* Client encryption settings */
483     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
484 forsberg 352 out_uint16_le(s, 12); /* length */
485 matthewc 57 out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
486 matthewc 365 out_uint32(s, 0); /* Unknown */
487 forsberg 352
488 forsberg 412 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 forsberg 352
503 matty 10 s_mark_end(s);
504     }
505    
506     /* Parse a public key structure */
507 matty 25 static BOOL
508 astrand 64 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
509 matty 10 {
510     uint32 magic, modulus_len;
511    
512     in_uint32_le(s, magic);
513     if (magic != SEC_RSA_MAGIC)
514     {
515 matty 30 error("RSA magic 0x%x\n", magic);
516 matty 10 return False;
517     }
518    
519     in_uint32_le(s, modulus_len);
520     if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
521     {
522 matty 30 error("modulus len 0x%x\n", modulus_len);
523 matty 10 return False;
524     }
525    
526 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
527 matty 10 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 forsberg 352 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 matty 10 /* Parse a crypto information structure */
562 matty 25 static BOOL
563 astrand 64 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
564 astrand 82 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
565 matty 10 {
566     uint32 crypt_level, random_len, rsa_info_len;
567 matthewc 363 uint32 cacert_len, cert_len, flags;
568 forsberg 352 X509 *cacert, *server_cert;
569 matty 10 uint16 tag, length;
570     uint8 *next_tag, *end;
571    
572 matty 24 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 forsberg 352 if (crypt_level == 0) /* no encryption */
575 jsorg71 89 return False;
576 matty 10 in_uint32_le(s, random_len);
577     in_uint32_le(s, rsa_info_len);
578    
579     if (random_len != SEC_RANDOM_SIZE)
580     {
581 forsberg 352 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
582 matty 10 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 forsberg 412 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
593 matthewc 363 if (flags & 1)
594 forsberg 352 {
595     DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
596 matthewc 363 in_uint8s(s, 8); /* unknown */
597 matty 10
598 forsberg 352 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 matthewc 363 else
629 matty 10 {
630 forsberg 352 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
631 matthewc 363 in_uint8s(s, 4); /* Number of certificates */
632 matty 10
633 forsberg 352 /* Do da funky X.509 stuffy
634 matty 10
635 forsberg 352 "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 forsberg 419 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
644 forsberg 352 cacert = d2i_X509(NULL, &(s->p), cacert_len);
645     /* Note: We don't need to move s->p here - d2i_X509 is
646     "kind" enough to do it for us */
647     if (NULL == cacert)
648 matty 10 {
649 forsberg 352 error("Couldn't load CA Certificate from server\n");
650     return False;
651     }
652 matty 10
653 forsberg 352 /* Currently, we don't use the CA Certificate.
654     FIXME:
655     *) Verify the server certificate (server_cert) with the
656     CA certificate.
657     *) Store the CA Certificate with the hostname of the
658     server we are connecting to as key, and compare it
659     when we connect the next time, in order to prevent
660     MITM-attacks.
661     */
662 matty 10
663 forsberg 352 in_uint32_le(s, cert_len);
664 forsberg 419 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
665 forsberg 352 server_cert = d2i_X509(NULL, &(s->p), cert_len);
666     if (NULL == server_cert)
667     {
668     error("Couldn't load Certificate from server\n");
669     return False;
670     }
671 matty 10
672 forsberg 352 in_uint8s(s, 16); /* Padding */
673    
674     /* Note: Verifying the server certificate must be done here,
675     before sec_parse_public_key since we'll have to apply
676     serious violence to the key after this */
677    
678     if (!sec_parse_x509_key(server_cert))
679     {
680     DEBUG_RDP5(("Didn't parse X509 correctly\n"));
681     return False;
682 matty 10 }
683 forsberg 352 return True; /* There's some garbage here we don't care about */
684 matty 10 }
685     return s_check_end(s);
686     }
687    
688     /* Process crypto information blob */
689 matty 25 static void
690     sec_process_crypt_info(STREAM s)
691 matty 10 {
692     uint8 *server_random, *modulus, *exponent;
693     uint8 client_random[SEC_RANDOM_SIZE];
694     uint32 rc4_key_size;
695 forsberg 352 uint8 inr[SEC_MODULUS_SIZE];
696 matty 10
697 astrand 82 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
698 forsberg 352 {
699     DEBUG(("Failed to parse crypt info\n"));
700 matty 10 return;
701 forsberg 352 }
702 matty 10
703 forsberg 352 DEBUG(("Generating client random\n"));
704 forsberg 412 /* Generate a client random, and hence determine encryption keys */
705 forsberg 352 // This is what the MS client do:
706 forsberg 377 memset(inr, 0, SEC_RANDOM_SIZE);
707     /* *ARIGL!* Plaintext attack, anyone?
708 forsberg 412 I tried doing:
709     generate_random(inr);
710     ..but that generates connection errors now and then (yes,
711     "now and then". Something like 0 to 3 attempts needed before a
712     successful connection. Nice. Not!
713     */
714 forsberg 377
715 matty 10 generate_random(client_random);
716 forsberg 352 if (NULL != server_public_key)
717     { /* Which means we should use
718     RDP5-style encryption */
719    
720     memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
721     reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
722    
723     RSA_public_encrypt(SEC_MODULUS_SIZE,
724     inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
725    
726     reverse(sec_crypted_random, SEC_MODULUS_SIZE);
727    
728     }
729     else
730     { /* RDP4-style encryption */
731     sec_rsa_encrypt(sec_crypted_random,
732     client_random, SEC_RANDOM_SIZE, modulus, exponent);
733     }
734 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
735     }
736    
737 forsberg 352
738     /* Process SRV_INFO, find RDP version supported by server */
739     static void
740     sec_process_srv_info(STREAM s)
741     {
742     in_uint16_le(s, server_rdp_version);
743     DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
744     }
745    
746    
747 matty 10 /* Process connect response data blob */
748 forsberg 352 void
749 matty 25 sec_process_mcs_data(STREAM s)
750 matty 10 {
751     uint16 tag, length;
752     uint8 *next_tag;
753 jsorg71 90 uint8 len;
754 matty 10
755 forsberg 352 in_uint8s(s, 21); /* header (T.124 stuff, probably) */
756 jsorg71 90 in_uint8(s, len);
757     if (len & 0x80)
758     in_uint8(s, len);
759 matty 10
760     while (s->p < s->end)
761     {
762     in_uint16_le(s, tag);
763     in_uint16_le(s, length);
764    
765     if (length <= 4)
766     return;
767    
768     next_tag = s->p + length - 4;
769    
770     switch (tag)
771     {
772     case SEC_TAG_SRV_INFO:
773 forsberg 352 sec_process_srv_info(s);
774     break;
775    
776 matty 10 case SEC_TAG_SRV_3:
777 forsberg 419 /* FIXME: We should parse this information and
778     use it to map RDP5 channels to MCS
779     channels */
780 matty 10 break;
781    
782     case SEC_TAG_SRV_CRYPT:
783     sec_process_crypt_info(s);
784     break;
785    
786     default:
787 matty 30 unimpl("response tag 0x%x\n", tag);
788 matty 10 }
789    
790     s->p = next_tag;
791     }
792     }
793    
794     /* Receive secure transport packet */
795 matty 25 STREAM
796 matthewc 192 sec_recv(void)
797 matty 10 {
798     uint32 sec_flags;
799 forsberg 352 uint16 channel;
800 matty 10 STREAM s;
801    
802 forsberg 352 while ((s = mcs_recv(&channel)) != NULL)
803 matty 10 {
804 jsorg71 380 if (encryption || !g_licence_issued)
805 matty 10 {
806 matty 28 in_uint32_le(s, sec_flags);
807 matty 10
808 matty 28 if (sec_flags & SEC_LICENCE_NEG)
809     {
810 forsberg 412 if (sec_flags & SEC_ENCRYPT)
811     {
812 forsberg 357 DEBUG_RDP5(("Encrypted license detected\n"));
813 jsorg71 380 }
814 matty 28 licence_process(s);
815     continue;
816     }
817    
818     if (sec_flags & SEC_ENCRYPT)
819     {
820     in_uint8s(s, 8); /* signature */
821     sec_decrypt(s->p, s->end - s->p);
822     }
823 matty 10 }
824    
825 forsberg 352 if (MCS_GLOBAL_CHANNEL == channel)
826     {
827     return s;
828     }
829     else
830     rdp5_process_channel(s, channel);
831    
832 matty 10 }
833    
834     return NULL;
835     }
836    
837     /* Establish a secure connection */
838 matty 25 BOOL
839 forsberg 352 sec_connect(char *server, char *username)
840 matty 10 {
841     struct stream mcs_data;
842    
843     /* We exchange some RDP data during the MCS-Connect */
844     mcs_data.size = 512;
845 forsberg 412 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
846 matty 10 sec_out_mcs_data(&mcs_data);
847    
848 forsberg 352 if (!mcs_connect(server, &mcs_data, username))
849 matty 10 return False;
850    
851 forsberg 352 // sec_process_mcs_data(&mcs_data);
852 matty 30 if (encryption)
853 matty 28 sec_establish_key();
854 matthewc 218 xfree(mcs_data.data);
855 matty 10 return True;
856     }
857    
858     /* Disconnect a connection */
859 matty 25 void
860 matthewc 192 sec_disconnect(void)
861 matty 10 {
862     mcs_disconnect();
863     }

  ViewVC Help
Powered by ViewVC 1.1.26