/[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 357 - (hide annotations)
Fri Mar 28 12:55:25 2003 UTC (21 years, 1 month ago) by forsberg
File MIME type: text/plain
File size: 19462 byte(s)
Got colordepth > 8 bits to work again (apparently, another byte must be set in the client info
depending on the depth wanted).

I think we need to be a bit careful and check what depth the server is really giving us, or
we will have strange results sometimes.

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

  ViewVC Help
Powered by ViewVC 1.1.26