/[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

Diff of /sourceforge.net/trunk/rdesktop/secure.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 57 by matthewc, Sat Jul 13 02:30:49 2002 UTC revision 1327 by stargo, Fri Nov 3 19:56:42 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing     Protocol services - RDP encryption and licensing
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20    
21  #include "rdesktop.h"  #include "rdesktop.h"
22    
 #ifdef WITH_OPENSSL  
23  #include <openssl/rc4.h>  #include <openssl/rc4.h>
24  #include <openssl/md5.h>  #include <openssl/md5.h>
25  #include <openssl/sha.h>  #include <openssl/sha.h>
26  #include <openssl/bn.h>  #include <openssl/bn.h>
27    #include <openssl/x509v3.h>
28    
29    #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
30    #define D2I_X509_CONST const
31  #else  #else
32  #include "crypto/rc4.h"  #define D2I_X509_CONST
 #include "crypto/md5.h"  
 #include "crypto/sha.h"  
 #include "crypto/bn.h"  
33  #endif  #endif
34    
35  extern char hostname[16];  extern char g_hostname[16];
36  extern int width;  extern int g_width;
37  extern int height;  extern int g_height;
38  extern int keylayout;  extern unsigned int g_keylayout;
39  extern BOOL encryption;  extern int g_keyboard_type;
40  extern BOOL licence_issued;  extern int g_keyboard_subtype;
41    extern int g_keyboard_functionkeys;
42    extern BOOL g_encryption;
43    extern BOOL g_licence_issued;
44    extern BOOL g_use_rdp5;
45    extern BOOL g_console_session;
46    extern int g_server_depth;
47    extern uint16 mcs_userid;
48    extern VCHANNEL g_channels[];
49    extern unsigned int g_num_channels;
50    
51  static int rc4_key_len;  static int rc4_key_len;
52  static RC4_KEY rc4_decrypt_key;  static RC4_KEY rc4_decrypt_key;
53  static RC4_KEY rc4_encrypt_key;  static RC4_KEY rc4_encrypt_key;
54    static RSA *server_public_key;
55    static uint32 server_public_key_len;
56    
57  static uint8 sec_sign_key[16];  static uint8 sec_sign_key[16];
58  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
59  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
60  static uint8 sec_decrypt_update_key[16];  static uint8 sec_decrypt_update_key[16];
61  static uint8 sec_encrypt_update_key[16];  static uint8 sec_encrypt_update_key[16];
62  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 sec_crypted_random[SEC_MAX_MODULUS_SIZE];
63    
64    uint16 g_server_rdp_version = 0;
65    
66    /* These values must be available to reset state - Session Directory */
67    static int sec_encrypt_use_count = 0;
68    static int sec_decrypt_use_count = 0;
69    
70    /*
71     * I believe this is based on SSLv3 with the following differences:
72     *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
73     *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
74     *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
75     *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
76     *  encryption/decryption keys updated every 4096 packets
77     * See http://wp.netscape.com/eng/ssl3/draft302.txt
78     */
79    
80  /*  /*
81   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
  * a client and server salt) and a global salt value used for padding.  
82   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
83   */   */
84  void  void
85  sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)  sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
86  {  {
87          uint8 shasig[20];          uint8 shasig[20];
88          uint8 pad[4];          uint8 pad[4];
# Line 83  sec_hash_48(uint8 *out, uint8 *in, uint8 Line 109  sec_hash_48(uint8 *out, uint8 *in, uint8
109  }  }
110    
111  /*  /*
112   * Weaker 16-byte transformation, also using two 32-byte salts, but   * 16-byte transformation used to generate export keys (6.2.2).
  * only using a single round of MD5.  
113   */   */
114  void  void
115  sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
116  {  {
117          MD5_CTX md5;          MD5_CTX md5;
118    
# Line 100  sec_hash_16(uint8 *out, uint8 *in, uint8 Line 125  sec_hash_16(uint8 *out, uint8 *in, uint8
125    
126  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
127  static void  static void
128  sec_make_40bit(uint8 *key)  sec_make_40bit(uint8 * key)
129  {  {
130          key[0] = 0xd1;          key[0] = 0xd1;
131          key[1] = 0x26;          key[1] = 0x26;
132          key[2] = 0x9e;          key[2] = 0x9e;
133  }  }
134    
135  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate encryption keys given client and server randoms */
136  static void  static void
137  sec_generate_keys(uint8 *client_key, uint8 *server_key, int rc4_key_size)  sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
138  {  {
139          uint8 session_key[48];          uint8 pre_master_secret[48];
140          uint8 temp_hash[48];          uint8 master_secret[48];
141          uint8 input[48];          uint8 key_block[48];
142    
143          /* Construct input data to hash */          /* Construct pre-master secret */
144          memcpy(input, client_key, 24);          memcpy(pre_master_secret, client_random, 24);
145          memcpy(input + 24, server_key, 24);          memcpy(pre_master_secret + 24, server_random, 24);
146    
147          /* Generate session key - two rounds of sec_hash_48 */          /* Generate master secret and then key material */
148          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
149          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
150    
151          /* Store first 16 bytes of session key, for generating signatures */          /* First 16 bytes of key material is MAC secret */
152          memcpy(sec_sign_key, session_key, 16);          memcpy(sec_sign_key, key_block, 16);
153    
154          /* Generate RC4 keys */          /* Generate export keys from next two blocks of 16 bytes */
155          sec_hash_16(sec_decrypt_key, &session_key[16], client_key,          sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
156                      server_key);          sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
         sec_hash_16(sec_encrypt_key, &session_key[32], client_key,  
                     server_key);  
157    
158          if (rc4_key_size == 1)          if (rc4_key_size == 1)
159          {          {
# Line 142  sec_generate_keys(uint8 *client_key, uin Line 165  sec_generate_keys(uint8 *client_key, uin
165          }          }
166          else          else
167          {          {
168                  DEBUG(("128-bit encryption enabled\n"));                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
169                  rc4_key_len = 16;                  rc4_key_len = 16;
170          }          }
171    
# Line 171  static uint8 pad_92[48] = { Line 194  static uint8 pad_92[48] = {
194    
195  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
196  void  void
197  buf_out_uint32(uint8 *buffer, uint32 value)  buf_out_uint32(uint8 * buffer, uint32 value)
198  {  {
199          buffer[0] = (value) & 0xff;          buffer[0] = (value) & 0xff;
200          buffer[1] = (value >> 8) & 0xff;          buffer[1] = (value >> 8) & 0xff;
# Line 179  buf_out_uint32(uint8 *buffer, uint32 val Line 202  buf_out_uint32(uint8 *buffer, uint32 val
202          buffer[3] = (value >> 24) & 0xff;          buffer[3] = (value >> 24) & 0xff;
203  }  }
204    
205  /* Generate a signature hash, using a combination of SHA1 and MD5 */  /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
206  void  void
207  sec_sign(uint8 *signature, uint8 *session_key, int length,  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
          uint8 *data, int datalen)  
208  {  {
209          uint8 shasig[20];          uint8 shasig[20];
210          uint8 md5sig[16];          uint8 md5sig[16];
# Line 193  sec_sign(uint8 *signature, uint8 *sessio Line 215  sec_sign(uint8 *signature, uint8 *sessio
215          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
216    
217          SHA1_Init(&sha);          SHA1_Init(&sha);
218          SHA1_Update(&sha, session_key, rc4_key_len);          SHA1_Update(&sha, session_key, keylen);
219          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
220          SHA1_Update(&sha, lenhdr, 4);          SHA1_Update(&sha, lenhdr, 4);
221          SHA1_Update(&sha, data, datalen);          SHA1_Update(&sha, data, datalen);
222          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
223    
224          MD5_Init(&md5);          MD5_Init(&md5);
225          MD5_Update(&md5, session_key, rc4_key_len);          MD5_Update(&md5, session_key, keylen);
226          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
227          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
228          MD5_Final(md5sig, &md5);          MD5_Final(md5sig, &md5);
229    
230          memcpy(signature, md5sig, length);          memcpy(signature, md5sig, siglen);
231  }  }
232    
233  /* Update an encryption key - similar to the signing process */  /* Update an encryption key */
234  static void  static void
235  sec_update(uint8 *key, uint8 *update_key)  sec_update(uint8 * key, uint8 * update_key)
236  {  {
237          uint8 shasig[20];          uint8 shasig[20];
238          SHA_CTX sha;          SHA_CTX sha;
# Line 238  sec_update(uint8 *key, uint8 *update_key Line 260  sec_update(uint8 *key, uint8 *update_key
260    
261  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
262  static void  static void
263  sec_encrypt(uint8 *data, int length)  sec_encrypt(uint8 * data, int length)
264  {  {
265          static int use_count;          if (sec_encrypt_use_count == 4096)
   
         if (use_count == 4096)  
266          {          {
267                  sec_update(sec_encrypt_key, sec_encrypt_update_key);                  sec_update(sec_encrypt_key, sec_encrypt_update_key);
268                  RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);                  RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
269                  use_count = 0;                  sec_encrypt_use_count = 0;
270          }          }
271    
272          RC4(&rc4_encrypt_key, length, data, data);          RC4(&rc4_encrypt_key, length, data, data);
273          use_count++;          sec_encrypt_use_count++;
274  }  }
275    
276  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
277  static void  void
278  sec_decrypt(uint8 *data, int length)  sec_decrypt(uint8 * data, int length)
279  {  {
280          static int use_count;          if (sec_decrypt_use_count == 4096)
   
         if (use_count == 4096)  
281          {          {
282                  sec_update(sec_decrypt_key, sec_decrypt_update_key);                  sec_update(sec_decrypt_key, sec_decrypt_update_key);
283                  RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);                  RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
284                  use_count = 0;                  sec_decrypt_use_count = 0;
285          }          }
286    
287          RC4(&rc4_decrypt_key, length, data, data);          RC4(&rc4_decrypt_key, length, data, data);
288          use_count++;          sec_decrypt_use_count++;
289  }  }
290    
291  static void  static void
292  reverse(uint8 *p, int len)  reverse(uint8 * p, int len)
293  {  {
294          int i, j;          int i, j;
295          uint8 temp;          uint8 temp;
296    
297          for (i = 0, j = len-1; i < j; i++, j--)          for (i = 0, j = len - 1; i < j; i++, j--)
298          {          {
299                  temp = p[i];                  temp = p[i];
300                  p[i] = p[j];                  p[i] = p[j];
# Line 286  reverse(uint8 *p, int len) Line 304  reverse(uint8 *p, int len)
304    
305  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
306  static void  static void
307  sec_rsa_encrypt(uint8 *out, uint8 *in, int len,  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
308                  uint8 *modulus, uint8 *exponent)                  uint8 * exponent)
309  {  {
310          BN_CTX ctx;          BN_CTX *ctx;
311          BIGNUM mod, exp, x, y;          BIGNUM mod, exp, x, y;
312          uint8 inr[SEC_MODULUS_SIZE];          uint8 inr[SEC_MAX_MODULUS_SIZE];
313          int outlen;          int outlen;
314    
315          reverse(modulus, SEC_MODULUS_SIZE);          reverse(modulus, modulus_size);
316          reverse(exponent, SEC_EXPONENT_SIZE);          reverse(exponent, SEC_EXPONENT_SIZE);
317          memcpy(inr, in, len);          memcpy(inr, in, len);
318          reverse(inr, len);          reverse(inr, len);
319    
320          BN_CTX_init(&ctx);          ctx = BN_CTX_new();
321          BN_init(&mod);          BN_init(&mod);
322          BN_init(&exp);          BN_init(&exp);
323          BN_init(&x);          BN_init(&x);
324          BN_init(&y);          BN_init(&y);
325    
326          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);          BN_bin2bn(modulus, modulus_size, &mod);
327          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
328          BN_bin2bn(inr, len, &x);          BN_bin2bn(inr, len, &x);
329          BN_mod_exp(&y, &x, &exp, &mod, &ctx);          BN_mod_exp(&y, &x, &exp, &mod, ctx);
330          outlen = BN_bn2bin(&y, out);          outlen = BN_bn2bin(&y, out);
331          reverse(out, outlen);          reverse(out, outlen);
332          if (outlen < SEC_MODULUS_SIZE)          if (outlen < modulus_size)
333                  memset(out+outlen, 0, SEC_MODULUS_SIZE-outlen);                  memset(out + outlen, 0, modulus_size - outlen);
334    
335          BN_free(&y);          BN_free(&y);
336          BN_clear_free(&x);          BN_clear_free(&x);
337          BN_free(&exp);          BN_free(&exp);
338          BN_free(&mod);          BN_free(&mod);
339          BN_CTX_free(&ctx);          BN_CTX_free(ctx);
340  }  }
341    
342  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 328  sec_init(uint32 flags, int maxlen) Line 346  sec_init(uint32 flags, int maxlen)
346          int hdrlen;          int hdrlen;
347          STREAM s;          STREAM s;
348    
349          if (!licence_issued)          if (!g_licence_issued)
350                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
351          else          else
352                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
# Line 338  sec_init(uint32 flags, int maxlen) Line 356  sec_init(uint32 flags, int maxlen)
356          return s;          return s;
357  }  }
358    
359  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
360  void  void
361  sec_send(STREAM s, uint32 flags)  sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
362  {  {
363          int datalen;          int datalen;
364    
365    #ifdef WITH_SCARD
366            scard_sec_lock();
367    #endif
368    
369          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
370          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
371                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
372    
373          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
# Line 358  sec_send(STREAM s, uint32 flags) Line 380  sec_send(STREAM s, uint32 flags)
380                  hexdump(s->p + 8, datalen);                  hexdump(s->p + 8, datalen);
381  #endif  #endif
382    
383                  sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);                  sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
384                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
385          }          }
386    
387          mcs_send(s);          mcs_send_to_channel(s, channel);
388    
389    #ifdef WITH_SCARD
390            scard_sec_unlock();
391    #endif
392    }
393    
394    /* Transmit secure transport packet */
395    
396    void
397    sec_send(STREAM s, uint32 flags)
398    {
399            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
400  }  }
401    
402    
403  /* Transfer the client random to the server */  /* Transfer the client random to the server */
404  static void  static void
405  sec_establish_key()  sec_establish_key(void)
406  {  {
407          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = server_public_key_len + SEC_PADDING_SIZE;
408          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
409          STREAM s;          STREAM s;
410    
411          s = sec_init(flags, 76);          s = sec_init(flags, length + 4);
412    
413          out_uint32_le(s, length);          out_uint32_le(s, length);
414          out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);          out_uint8p(s, sec_crypted_random, server_public_key_len);
415          out_uint8s(s, SEC_PADDING_SIZE);          out_uint8s(s, SEC_PADDING_SIZE);
416    
417          s_mark_end(s);          s_mark_end(s);
# Line 387  sec_establish_key() Line 422  sec_establish_key()
422  static void  static void
423  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
424  {  {
425          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(g_hostname);
426            int length = 158 + 76 + 12 + 4;
427            unsigned int i;
428    
429          out_uint16_be(s, 5);    /* unknown */          if (g_num_channels > 0)
430                    length += g_num_channels * 12 + 8;
431    
432            if (hostlen > 30)
433                    hostlen = 30;
434    
435            /* Generic Conference Control (T.124) ConferenceCreateRequest */
436            out_uint16_be(s, 5);
437          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
438          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
439          out_uint16_be(s, 1);          out_uint16_be(s, 1);
440    
441          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
442    
443          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
444          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 402  sec_out_mcs_data(STREAM s) Line 446  sec_out_mcs_data(STREAM s)
446          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
447          out_uint8(s, 0);          out_uint8(s, 0);
448    
449          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
450          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
451    
452          /* Client information */          /* Client information */
453          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
454          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
455          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
456          out_uint16_le(s, 8);          out_uint16_le(s, 8);
457          out_uint16_le(s, width);          out_uint16_le(s, g_width);
458          out_uint16_le(s, height);          out_uint16_le(s, g_height);
459          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
460          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
461          out_uint32_le(s, keylayout);          out_uint32_le(s, g_keylayout);
462          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
463    
464          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
465          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, g_hostname, hostlen);
466          out_uint8s(s, 30 - hostlen);          out_uint8s(s, 30 - hostlen);
467    
468          out_uint32_le(s, 4);          /* See
469          out_uint32(s, 0);             http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
470          out_uint32_le(s, 12);          out_uint32_le(s, g_keyboard_type);
471            out_uint32_le(s, g_keyboard_subtype);
472            out_uint32_le(s, g_keyboard_functionkeys);
473          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
474            out_uint16_le(s, 0xca01);       /* colour depth? */
475            out_uint16_le(s, 1);
476    
477          out_uint16(s, 0xca01);          out_uint32(s, 0);
478          out_uint16(s, 0);          out_uint8(s, g_server_depth);
479            out_uint16_le(s, 0x0700);
480            out_uint8(s, 0);
481            out_uint32_le(s, 1);
482            out_uint8s(s, 64);      /* End of client info */
483    
484            out_uint16_le(s, SEC_TAG_CLI_4);
485            out_uint16_le(s, 12);
486            out_uint32_le(s, g_console_session ? 0xb : 9);
487            out_uint32(s, 0);
488    
489          /* Client encryption settings */          /* Client encryption settings */
490          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
491          out_uint16(s, 8);       /* length */          out_uint16_le(s, 12);   /* length */
492          out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */          out_uint32_le(s, g_encryption ? 0x3 : 0);       /* encryption supported, 128-bit supported */
493            out_uint32(s, 0);       /* Unknown */
494    
495            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
496            if (g_num_channels > 0)
497            {
498                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
499                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
500                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
501                    for (i = 0; i < g_num_channels; i++)
502                    {
503                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
504                            out_uint8a(s, g_channels[i].name, 8);
505                            out_uint32_be(s, g_channels[i].flags);
506                    }
507            }
508    
509          s_mark_end(s);          s_mark_end(s);
510  }  }
511    
512  /* Parse a public key structure */  /* Parse a public key structure */
513  static BOOL  static BOOL
514  sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
515  {  {
516          uint32 magic, modulus_len;          uint32 magic, modulus_len;
517    
# Line 450  sec_parse_public_key(STREAM s, uint8 **m Line 523  sec_parse_public_key(STREAM s, uint8 **m
523          }          }
524    
525          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
526          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          modulus_len -= SEC_PADDING_SIZE;
527            if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
528          {          {
529                  error("modulus len 0x%x\n", modulus_len);                  error("Bad server public key size (%u bits)\n", modulus_len * 8);
530                  return False;                  return False;
531          }          }
532    
533          in_uint8s(s, 8);        /* modulus_bits, unknown */          in_uint8s(s, 8);        /* modulus_bits, unknown */
534          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
535          in_uint8p(s, *modulus, SEC_MODULUS_SIZE);          in_uint8p(s, *modulus, modulus_len);
536          in_uint8s(s, SEC_PADDING_SIZE);          in_uint8s(s, SEC_PADDING_SIZE);
537            server_public_key_len = modulus_len;
538    
539          return s_check(s);          return s_check(s);
540  }  }
541    
542    static BOOL
543    sec_parse_x509_key(X509 * cert)
544    {
545            EVP_PKEY *epk = NULL;
546            /* By some reason, Microsoft sets the OID of the Public RSA key to
547               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
548    
549               Kudos to Richard Levitte for the following (. intiutive .)
550               lines of code that resets the OID and let's us extract the key. */
551            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
552            {
553                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
554                    ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
555                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
556            }
557            epk = X509_get_pubkey(cert);
558            if (NULL == epk)
559            {
560                    error("Failed to extract public key from certificate\n");
561                    return False;
562            }
563    
564            server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
565            EVP_PKEY_free(epk);
566    
567            server_public_key_len = RSA_size(server_public_key);
568            if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))
569            {
570                    error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
571                    return False;
572            }
573    
574            return True;
575    }
576    
577    
578  /* Parse a crypto information structure */  /* Parse a crypto information structure */
579  static BOOL  static BOOL
580  sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
581                       uint8 **server_random, uint8 **modulus, uint8 **exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
582  {  {
583          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
584            uint32 cacert_len, cert_len, flags;
585            X509 *cacert, *server_cert;
586          uint16 tag, length;          uint16 tag, length;
587          uint8 *next_tag, *end;          uint8 *next_tag, *end;
588    
589          in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */          in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
590          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
591            if (crypt_level == 0)   /* no encryption */
592                    return False;
593          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
594          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
595    
596          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
597          {          {
598                  error("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
599                  return False;                  return False;
600          }          }
601    
# Line 491  sec_parse_crypt_info(STREAM s, uint32 *r Line 606  sec_parse_crypt_info(STREAM s, uint32 *r
606          if (end > s->end)          if (end > s->end)
607                  return False;                  return False;
608    
609          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
610            if (flags & 1)
611            {
612                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
613                    in_uint8s(s, 8);        /* unknown */
614    
615                    while (s->p < end)
616                    {
617                            in_uint16_le(s, tag);
618                            in_uint16_le(s, length);
619    
620                            next_tag = s->p + length;
621    
622                            switch (tag)
623                            {
624                                    case SEC_TAG_PUBKEY:
625                                            if (!sec_parse_public_key(s, modulus, exponent))
626                                                    return False;
627                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
628    
629                                            break;
630    
631                                    case SEC_TAG_KEYSIG:
632                                            /* Is this a Microsoft key that we just got? */
633                                            /* Care factor: zero! */
634                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
635                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
636                                            break;
637    
638          while (s->p < end)                                  default:
639                                            unimpl("crypt tag 0x%x\n", tag);
640                            }
641    
642                            s->p = next_tag;
643                    }
644            }
645            else
646          {          {
647                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
648    
649                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
650                    in_uint32_le(s, certcount);     /* Number of certificates */
651    
652                  switch (tag)                  if (certcount < 2)
653                  {                  {
654                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
655                                  if (!sec_parse_public_key                          return False;
656                                      (s, modulus, exponent))                  }
                                         return False;  
657    
658                                  break;                  for (; certcount > 2; certcount--)
659                    {               /* ignore all the certificates between the root and the signing CA */
660                            uint32 ignorelen;
661                            X509 *ignorecert;
662    
663                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
664    
665                            in_uint32_le(s, ignorelen);
666                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
667                            ignorecert =
668                                    d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p),
669                                             ignorelen);
670    
671                            if (ignorecert == NULL)
672                            {       /* XXX: error out? */
673                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
674                            }
675    
676                          case SEC_TAG_KEYSIG:  #ifdef WITH_DEBUG_RDP5
677                                  /* Is this a Microsoft key that we just got? */                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
678                                  /* Care factor: zero! */                          X509_print_fp(stdout, ignorecert);
679                                  break;  #endif
680                    }
681    
682                          default:                  /* Do da funky X.509 stuffy
683                                  unimpl("crypt tag 0x%x\n", tag);  
684                       "How did I find out about this?  I looked up and saw a
685                       bright light and when I came to I had a scar on my forehead
686                       and knew about X.500"
687                       - Peter Gutman in a early version of
688                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
689                     */
690    
691                    in_uint32_le(s, cacert_len);
692                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
693                    cacert = d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p), cacert_len);
694                    /* Note: We don't need to move s->p here - d2i_X509 is
695                       "kind" enough to do it for us */
696                    if (NULL == cacert)
697                    {
698                            error("Couldn't load CA Certificate from server\n");
699                            return False;
700                  }                  }
701    
702                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
703          }                     FIXME:
704                       *) Verify the server certificate (server_cert) with the
705                       CA certificate.
706                       *) Store the CA Certificate with the hostname of the
707                       server we are connecting to as key, and compare it
708                       when we connect the next time, in order to prevent
709                       MITM-attacks.
710                     */
711    
712                    X509_free(cacert);
713    
714                    in_uint32_le(s, cert_len);
715                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
716                    server_cert = d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p), cert_len);
717                    if (NULL == server_cert)
718                    {
719                            error("Couldn't load Certificate from server\n");
720                            return False;
721                    }
722    
723                    in_uint8s(s, 16);       /* Padding */
724    
725                    /* Note: Verifying the server certificate must be done here,
726                       before sec_parse_public_key since we'll have to apply
727                       serious violence to the key after this */
728    
729                    if (!sec_parse_x509_key(server_cert))
730                    {
731                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
732                            X509_free(server_cert);
733                            return False;
734                    }
735                    X509_free(server_cert);
736                    return True;    /* There's some garbage here we don't care about */
737            }
738          return s_check_end(s);          return s_check_end(s);
739  }  }
740    
# Line 528  sec_parse_crypt_info(STREAM s, uint32 *r Line 742  sec_parse_crypt_info(STREAM s, uint32 *r
742  static void  static void
743  sec_process_crypt_info(STREAM s)  sec_process_crypt_info(STREAM s)
744  {  {
745          uint8 *server_random, *modulus, *exponent;          uint8 *server_random = NULL, *modulus = NULL, *exponent = NULL;
746          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
747          uint32 rc4_key_size;          uint32 rc4_key_size;
748    
749          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
750                                    &modulus, &exponent))          {
751                    DEBUG(("Failed to parse crypt info\n"));
752                  return;                  return;
753            }
754    
755          /* Generate a client random, and hence determine encryption keys */          DEBUG(("Generating client random\n"));
756          generate_random(client_random);          generate_random(client_random);
757          sec_rsa_encrypt(sec_crypted_random, client_random,  
758                          SEC_RANDOM_SIZE, modulus, exponent);          if (NULL != server_public_key)
759            {                       /* Which means we should use
760                                       RDP5-style encryption */
761                    uint8 inr[SEC_MAX_MODULUS_SIZE];
762                    uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;
763    
764                    /* This is what the MS client do: */
765                    memset(inr, 0, padding_len);
766                    /*  *ARIGL!* Plaintext attack, anyone?
767                       I tried doing:
768                       generate_random(inr);
769                       ..but that generates connection errors now and then (yes,
770                       "now and then". Something like 0 to 3 attempts needed before a
771                       successful connection. Nice. Not!
772                     */
773                    memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
774                    reverse(inr + padding_len, SEC_RANDOM_SIZE);
775    
776                    RSA_public_encrypt(server_public_key_len,
777                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
778    
779                    reverse(sec_crypted_random, server_public_key_len);
780    
781                    RSA_free(server_public_key);
782                    server_public_key = NULL;
783            }
784            else
785            {                       /* RDP4-style encryption */
786                    sec_rsa_encrypt(sec_crypted_random,
787                                    client_random, SEC_RANDOM_SIZE, server_public_key_len, modulus,
788                                    exponent);
789            }
790          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
791  }  }
792    
793  /* Process connect response data blob */  
794    /* Process SRV_INFO, find RDP version supported by server */
795  static void  static void
796    sec_process_srv_info(STREAM s)
797    {
798            in_uint16_le(s, g_server_rdp_version);
799            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
800            if (1 == g_server_rdp_version)
801            {
802                    g_use_rdp5 = 0;
803                    g_server_depth = 8;
804            }
805    }
806    
807    
808    /* Process connect response data blob */
809    void
810  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
811  {  {
812          uint16 tag, length;          uint16 tag, length;
813          uint8 *next_tag;          uint8 *next_tag;
814            uint8 len;
815    
816          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
817            in_uint8(s, len);
818            if (len & 0x80)
819                    in_uint8(s, len);
820    
821          while (s->p < s->end)          while (s->p < s->end)
822          {          {
# Line 565  sec_process_mcs_data(STREAM s) Line 831  sec_process_mcs_data(STREAM s)
831                  switch (tag)                  switch (tag)
832                  {                  {
833                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
834                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
835                                  break;                                  break;
836    
837                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
838                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
839                                  break;                                  break;
840    
841                            case SEC_TAG_SRV_CHANNELS:
842                                    /* FIXME: We should parse this information and
843                                       use it to map RDP5 channels to MCS
844                                       channels */
845                                    break;
846    
847                          default:                          default:
848                                  unimpl("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
849                  }                  }
# Line 582  sec_process_mcs_data(STREAM s) Line 854  sec_process_mcs_data(STREAM s)
854    
855  /* Receive secure transport packet */  /* Receive secure transport packet */
856  STREAM  STREAM
857  sec_recv()  sec_recv(uint8 * rdpver)
858  {  {
859          uint32 sec_flags;          uint32 sec_flags;
860            uint16 channel;
861          STREAM s;          STREAM s;
862    
863          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel, rdpver)) != NULL)
864          {          {
865                  if (encryption || !licence_issued)                  if (rdpver != NULL)
866                    {
867                            if (*rdpver != 3)
868                            {
869                                    if (*rdpver & 0x80)
870                                    {
871                                            in_uint8s(s, 8);        /* signature */
872                                            sec_decrypt(s->p, s->end - s->p);
873                                    }
874                                    return s;
875                            }
876                    }
877                    if (g_encryption || !g_licence_issued)
878                  {                  {
879                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
880    
881                            if (sec_flags & SEC_ENCRYPT)
882                            {
883                                    in_uint8s(s, 8);        /* signature */
884                                    sec_decrypt(s->p, s->end - s->p);
885                            }
886    
887                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
888                          {                          {
889                                  licence_process(s);                                  licence_process(s);
890                                  continue;                                  continue;
891                          }                          }
892    
893                          if (sec_flags & SEC_ENCRYPT)                          if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
894                          {                          {
895                                    uint8 swapbyte;
896    
897                                  in_uint8s(s, 8);        /* signature */                                  in_uint8s(s, 8);        /* signature */
898                                  sec_decrypt(s->p, s->end - s->p);                                  sec_decrypt(s->p, s->end - s->p);
899    
900                                    /* Check for a redirect packet, starts with 00 04 */
901                                    if (s->p[0] == 0 && s->p[1] == 4)
902                                    {
903                                            /* for some reason the PDU and the length seem to be swapped.
904                                               This isn't good, but we're going to do a byte for byte
905                                               swap.  So the first foure value appear as: 00 04 XX YY,
906                                               where XX YY is the little endian length. We're going to
907                                               use 04 00 as the PDU type, so after our swap this will look
908                                               like: XX YY 04 00 */
909                                            swapbyte = s->p[0];
910                                            s->p[0] = s->p[2];
911                                            s->p[2] = swapbyte;
912    
913                                            swapbyte = s->p[1];
914                                            s->p[1] = s->p[3];
915                                            s->p[3] = swapbyte;
916    
917                                            swapbyte = s->p[2];
918                                            s->p[2] = s->p[3];
919                                            s->p[3] = swapbyte;
920                                    }
921    #ifdef WITH_DEBUG
922                                    /* warning!  this debug statement will show passwords in the clear! */
923                                    hexdump(s->p, s->end - s->p);
924    #endif
925                          }                          }
926    
927                    }
928    
929                    if (channel != MCS_GLOBAL_CHANNEL)
930                    {
931                            channel_process(s, channel);
932                            *rdpver = 0xff;
933                            return s;
934                  }                  }
935    
936                  return s;                  return s;
# Line 614  sec_recv() Line 941  sec_recv()
941    
942  /* Establish a secure connection */  /* Establish a secure connection */
943  BOOL  BOOL
944  sec_connect(char *server)  sec_connect(char *server, char *username)
945  {  {
946          struct stream mcs_data;          struct stream mcs_data;
947    
948          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
949          mcs_data.size = 512;          mcs_data.size = 512;
950          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
951          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
952    
953          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
954                  return False;                  return False;
955    
956          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
957          if (encryption)          if (g_encryption)
958                  sec_establish_key();                  sec_establish_key();
959            xfree(mcs_data.data);
960            return True;
961    }
962    
963    /* Establish a secure connection */
964    BOOL
965    sec_reconnect(char *server)
966    {
967            struct stream mcs_data;
968    
969            /* We exchange some RDP data during the MCS-Connect */
970            mcs_data.size = 512;
971            mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
972            sec_out_mcs_data(&mcs_data);
973    
974            if (!mcs_reconnect(server, &mcs_data))
975                    return False;
976    
977            /*      sec_process_mcs_data(&mcs_data); */
978            if (g_encryption)
979                    sec_establish_key();
980            xfree(mcs_data.data);
981          return True;          return True;
982  }  }
983    
984  /* Disconnect a connection */  /* Disconnect a connection */
985  void  void
986  sec_disconnect()  sec_disconnect(void)
987  {  {
988          mcs_disconnect();          mcs_disconnect();
989  }  }
990    
991    /* reset the state of the sec layer */
992    void
993    sec_reset_state(void)
994    {
995            g_server_rdp_version = 0;
996            sec_encrypt_use_count = 0;
997            sec_decrypt_use_count = 0;
998            mcs_reset_state();
999    }

Legend:
Removed from v.57  
changed lines
  Added in v.1327

  ViewVC Help
Powered by ViewVC 1.1.26