/[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 352 - (hide annotations)
Thu Mar 27 13:29:36 2003 UTC (21 years, 3 months ago) by forsberg
File MIME type: text/plain
File size: 19326 byte(s)
Send a "4" instead of a "1" in the correct place if we try to support RDP5.

Updated client build. We now aim at being 2600 compatible :-).

Set up the clipboard redirector at this protocol level as well (see also
mcs.c)

Do the new-style encryption setup using RSA and X.509 routines from
OpenSSL. That sounds easier than it is (!).

Added some comments and debug output.

Process RDP5 channel data (for channels != MCS_GLOBAL_CHANNEL).

Send the username to mcs_connect.

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     out_uint32_le(s, 0x070008);
454     out_uint32_le(s, 1);
455     out_uint8s(s, 64); /* End of client info */
456    
457     out_uint16_le(s, SEC_TAG_CLI_4);
458     out_uint16_le(s, 12);
459     out_uint32_le(s, 9);
460     out_uint32_le(s, 0);
461    
462 matty 10 /* Client encryption settings */
463     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
464 forsberg 352 out_uint16_le(s, 12); /* length */
465 matthewc 57 out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
466 forsberg 352 out_uint32_le(s, 0); /* Unknown */
467    
468     out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
469     out_uint16_le(s, 20); /* length */
470     out_uint32_le(s, 1); /* number of virtual channels */
471     out_uint8p(s, "cliprdr", 8); /* name padded to 8(?) */
472     out_uint16(s, 0);
473     out_uint16_le(s, 0xc0a0); /* Flags. Rumours tell this is documented in MSDN. */
474    
475 matty 10 s_mark_end(s);
476     }
477    
478     /* Parse a public key structure */
479 matty 25 static BOOL
480 astrand 64 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
481 matty 10 {
482     uint32 magic, modulus_len;
483    
484     in_uint32_le(s, magic);
485     if (magic != SEC_RSA_MAGIC)
486     {
487 matty 30 error("RSA magic 0x%x\n", magic);
488 matty 10 return False;
489     }
490    
491     in_uint32_le(s, modulus_len);
492     if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
493     {
494 matty 30 error("modulus len 0x%x\n", modulus_len);
495 matty 10 return False;
496     }
497    
498 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
499 matty 10 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
500     in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
501     in_uint8s(s, SEC_PADDING_SIZE);
502    
503     return s_check(s);
504     }
505    
506 forsberg 352 static BOOL
507     sec_parse_x509_key(X509 * cert)
508     {
509     EVP_PKEY *epk = NULL;
510     /* By some reason, Microsoft sets the OID of the Public RSA key to
511     the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
512    
513     Kudos to Richard Levitte for the following (. intiutive .)
514     lines of code that resets the OID and let's us extract the key. */
515     if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
516     {
517     DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
518     cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
519     }
520     epk = X509_get_pubkey(cert);
521     if (NULL == epk)
522     {
523     error("Failed to extract public key from certificate\n");
524     return False;
525     }
526    
527     server_public_key = (RSA *) epk->pkey.ptr;
528    
529     return True;
530     }
531    
532    
533 matty 10 /* Parse a crypto information structure */
534 matty 25 static BOOL
535 astrand 64 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
536 astrand 82 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
537 matty 10 {
538     uint32 crypt_level, random_len, rsa_info_len;
539 forsberg 352 uint32 cacert_len, cert_len;
540     X509 *cacert, *server_cert;
541 matty 10 uint16 tag, length;
542     uint8 *next_tag, *end;
543    
544 matty 24 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
545     in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
546 forsberg 352 if (crypt_level == 0) /* no encryption */
547 jsorg71 89 return False;
548 matty 10 in_uint32_le(s, random_len);
549     in_uint32_le(s, rsa_info_len);
550    
551     if (random_len != SEC_RANDOM_SIZE)
552     {
553 forsberg 352 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
554 matty 10 return False;
555     }
556    
557     in_uint8p(s, *server_random, random_len);
558    
559     /* RSA info */
560     end = s->p + rsa_info_len;
561     if (end > s->end)
562     return False;
563    
564 forsberg 352 if (!use_rdp5 || 1 == server_rdp_version)
565     {
566     DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
567     in_uint8s(s, 12); /* unknown */
568 matty 10
569 forsberg 352 while (s->p < end)
570     {
571     in_uint16_le(s, tag);
572     in_uint16_le(s, length);
573    
574     next_tag = s->p + length;
575    
576     switch (tag)
577     {
578     case SEC_TAG_PUBKEY:
579     if (!sec_parse_public_key(s, modulus, exponent))
580     return False;
581     DEBUG_RDP5(("Got Public key, RDP4-style\n"));
582    
583     break;
584    
585     case SEC_TAG_KEYSIG:
586     /* Is this a Microsoft key that we just got? */
587     /* Care factor: zero! */
588     /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
589     key as a known key of the hostname. This would prevent some MITM-attacks. */
590     break;
591    
592     default:
593     unimpl("crypt tag 0x%x\n", tag);
594     }
595    
596     s->p = next_tag;
597     }
598     }
599     else if (4 == server_rdp_version)
600 matty 10 {
601 forsberg 352 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
602     in_uint8s(s, 8); /* Unknown */
603 matty 10
604 forsberg 352 /* Do da funky X.509 stuffy
605 matty 10
606 forsberg 352 "How did I find out about this? I looked up and saw a
607     bright light and when I came to I had a scar on my forehead
608     and knew about X.500"
609     - Peter Gutman in a early version of
610     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
611     */
612    
613     in_uint32_le(s, cacert_len);
614     cacert = d2i_X509(NULL, &(s->p), cacert_len);
615     /* Note: We don't need to move s->p here - d2i_X509 is
616     "kind" enough to do it for us */
617     if (NULL == cacert)
618 matty 10 {
619 forsberg 352 error("Couldn't load CA Certificate from server\n");
620     return False;
621     }
622 matty 10
623 forsberg 352 /* Currently, we don't use the CA Certificate.
624     FIXME:
625     *) Verify the server certificate (server_cert) with the
626     CA certificate.
627     *) Store the CA Certificate with the hostname of the
628     server we are connecting to as key, and compare it
629     when we connect the next time, in order to prevent
630     MITM-attacks.
631     */
632 matty 10
633 forsberg 352 in_uint32_le(s, cert_len);
634     server_cert = d2i_X509(NULL, &(s->p), cert_len);
635     if (NULL == server_cert)
636     {
637     error("Couldn't load Certificate from server\n");
638     return False;
639     }
640 matty 10
641 forsberg 352 in_uint8s(s, 16); /* Padding */
642    
643     /* Note: Verifying the server certificate must be done here,
644     before sec_parse_public_key since we'll have to apply
645     serious violence to the key after this */
646    
647     if (!sec_parse_x509_key(server_cert))
648     {
649     DEBUG_RDP5(("Didn't parse X509 correctly\n"));
650     return False;
651 matty 10 }
652 forsberg 352 return True; /* There's some garbage here we don't care about */
653 matty 10 }
654 forsberg 352 else
655     {
656     error("Unknown Server RDP version %d", server_rdp_version);
657     return False;
658     }
659 matty 10 return s_check_end(s);
660     }
661    
662     /* Process crypto information blob */
663 matty 25 static void
664     sec_process_crypt_info(STREAM s)
665 matty 10 {
666     uint8 *server_random, *modulus, *exponent;
667     uint8 client_random[SEC_RANDOM_SIZE];
668     uint32 rc4_key_size;
669 forsberg 352 uint8 inr[SEC_MODULUS_SIZE];
670 matty 10
671 astrand 82 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
672 forsberg 352 {
673     DEBUG(("Failed to parse crypt info\n"));
674 matty 10 return;
675 forsberg 352 }
676 matty 10
677 forsberg 352 DEBUG(("Generating client random\n"));
678 matty 10 /* Generate a client random, and hence determine encryption keys */
679 forsberg 352 generate_random(inr);
680     // This is what the MS client do:
681     // memset(inr, 0, SEC_RANDOM_SIZE);
682     // *ARIGL!*
683 matty 10 generate_random(client_random);
684 forsberg 352 if (NULL != server_public_key)
685     { /* Which means we should use
686     RDP5-style encryption */
687    
688     memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
689     reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
690    
691     RSA_public_encrypt(SEC_MODULUS_SIZE,
692     inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
693    
694     reverse(sec_crypted_random, SEC_MODULUS_SIZE);
695    
696     }
697     else
698     { /* RDP4-style encryption */
699     sec_rsa_encrypt(sec_crypted_random,
700     client_random, SEC_RANDOM_SIZE, modulus, exponent);
701     }
702 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
703     }
704    
705 forsberg 352
706     /* Process SRV_INFO, find RDP version supported by server */
707     static void
708     sec_process_srv_info(STREAM s)
709     {
710     in_uint16_le(s, server_rdp_version);
711     DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
712     }
713    
714    
715 matty 10 /* Process connect response data blob */
716 forsberg 352 void
717 matty 25 sec_process_mcs_data(STREAM s)
718 matty 10 {
719     uint16 tag, length;
720     uint8 *next_tag;
721 jsorg71 90 uint8 len;
722 matty 10
723 forsberg 352 in_uint8s(s, 21); /* header (T.124 stuff, probably) */
724 jsorg71 90 in_uint8(s, len);
725     if (len & 0x80)
726     in_uint8(s, len);
727 matty 10
728     while (s->p < s->end)
729     {
730     in_uint16_le(s, tag);
731     in_uint16_le(s, length);
732    
733     if (length <= 4)
734     return;
735    
736     next_tag = s->p + length - 4;
737    
738     switch (tag)
739     {
740     case SEC_TAG_SRV_INFO:
741 forsberg 352 sec_process_srv_info(s);
742     break;
743    
744 matty 10 case SEC_TAG_SRV_3:
745     break;
746    
747     case SEC_TAG_SRV_CRYPT:
748     sec_process_crypt_info(s);
749     break;
750    
751     default:
752 matty 30 unimpl("response tag 0x%x\n", tag);
753 matty 10 }
754    
755     s->p = next_tag;
756     }
757     }
758    
759     /* Receive secure transport packet */
760 matty 25 STREAM
761 matthewc 192 sec_recv(void)
762 matty 10 {
763     uint32 sec_flags;
764 forsberg 352 uint16 channel;
765 matty 10 STREAM s;
766    
767 forsberg 352 while ((s = mcs_recv(&channel)) != NULL)
768 matty 10 {
769 matty 30 if (encryption || !licence_issued)
770 matty 10 {
771 matty 28 in_uint32_le(s, sec_flags);
772 matty 10
773 matty 28 if (sec_flags & SEC_LICENCE_NEG)
774     {
775     licence_process(s);
776     continue;
777     }
778    
779     if (sec_flags & SEC_ENCRYPT)
780     {
781     in_uint8s(s, 8); /* signature */
782     sec_decrypt(s->p, s->end - s->p);
783     }
784 matty 10 }
785    
786 forsberg 352 if (MCS_GLOBAL_CHANNEL == channel)
787     {
788     return s;
789     }
790     else
791     rdp5_process_channel(s, channel);
792    
793 matty 10 }
794    
795     return NULL;
796     }
797    
798     /* Establish a secure connection */
799 matty 25 BOOL
800 forsberg 352 sec_connect(char *server, char *username)
801 matty 10 {
802     struct stream mcs_data;
803    
804     /* We exchange some RDP data during the MCS-Connect */
805     mcs_data.size = 512;
806     mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);
807     sec_out_mcs_data(&mcs_data);
808    
809 forsberg 352 if (!mcs_connect(server, &mcs_data, username))
810 matty 10 return False;
811    
812 forsberg 352 // sec_process_mcs_data(&mcs_data);
813 matty 30 if (encryption)
814 matty 28 sec_establish_key();
815 matthewc 218 xfree(mcs_data.data);
816 matty 10 return True;
817     }
818    
819     /* Disconnect a connection */
820 matty 25 void
821 matthewc 192 sec_disconnect(void)
822 matty 10 {
823     mcs_disconnect();
824     }

  ViewVC Help
Powered by ViewVC 1.1.26