/[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 677 - (hide annotations)
Mon Apr 26 13:48:39 2004 UTC (20 years, 1 month ago) by n-ki
File MIME type: text/plain
File size: 21168 byte(s)
new: ui_resize_window() and related, which is used when resizing while shadowing. And fallback for color when connecting to a session with fewer colors than you have set in your session. Jeroen Meijer jeroen@oldambt7.com

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

  ViewVC Help
Powered by ViewVC 1.1.26