/[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 207 by matthewc, Thu Sep 26 14:26:46 2002 UTC revision 1315 by stargo, Wed Nov 1 22:12:27 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-2002     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
# Line 83  sec_hash_48(uint8 * out, uint8 * in, uin Line 109  sec_hash_48(uint8 * out, uint8 * in, uin
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)
# Line 107  sec_make_40bit(uint8 * key) Line 132  sec_make_40bit(uint8 * key)
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, server_key);          sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
156          sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);          sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
157    
158          if (rc4_key_size == 1)          if (rc4_key_size == 1)
159          {          {
# Line 140  sec_generate_keys(uint8 * client_key, ui Line 165  sec_generate_keys(uint8 * client_key, ui
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 177  buf_out_uint32(uint8 * buffer, uint32 va Line 202  buf_out_uint32(uint8 * buffer, uint32 va
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, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
208  {  {
# Line 205  sec_sign(uint8 * signature, int siglen, Line 230  sec_sign(uint8 * signature, int siglen,
230          memcpy(signature, md5sig, siglen);          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  {  {
# Line 237  sec_update(uint8 * key, uint8 * update_k Line 262  sec_update(uint8 * key, uint8 * update_k
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
# Line 283  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, uint8 * modulus, uint8 * exponent)  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
308                    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 324  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 334  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          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
366          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
367                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
368    
369          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                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
381          }          }
382    
383          mcs_send(s);          mcs_send_to_channel(s, channel);
384  }  }
385    
386    /* Transmit secure transport packet */
387    
388    void
389    sec_send(STREAM s, uint32 flags)
390    {
391            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
392    }
393    
394    
395  /* Transfer the client random to the server */  /* Transfer the client random to the server */
396  static void  static void
397  sec_establish_key(void)  sec_establish_key(void)
398  {  {
399          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = server_public_key_len + SEC_PADDING_SIZE;
400          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
401          STREAM s;          STREAM s;
402    
403          s = sec_init(flags, 76);          s = sec_init(flags, length + 4);
404    
405          out_uint32_le(s, length);          out_uint32_le(s, length);
406          out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);          out_uint8p(s, sec_crypted_random, server_public_key_len);
407          out_uint8s(s, SEC_PADDING_SIZE);          out_uint8s(s, SEC_PADDING_SIZE);
408    
409          s_mark_end(s);          s_mark_end(s);
# Line 383  sec_establish_key(void) Line 414  sec_establish_key(void)
414  static void  static void
415  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
416  {  {
417          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(g_hostname);
418            int length = 158 + 76 + 12 + 4;
419            unsigned int i;
420    
421            if (g_num_channels > 0)
422                    length += g_num_channels * 12 + 8;
423    
424          if (hostlen > 30)          if (hostlen > 30)
425                  hostlen = 30;                  hostlen = 30;
426    
427          out_uint16_be(s, 5);    /* unknown */          /* Generic Conference Control (T.124) ConferenceCreateRequest */
428            out_uint16_be(s, 5);
429          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
430          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
431          out_uint16_be(s, 1);          out_uint16_be(s, 1);
432    
433          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
434    
435          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
436          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 401  sec_out_mcs_data(STREAM s) Line 438  sec_out_mcs_data(STREAM s)
438          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
439          out_uint8(s, 0);          out_uint8(s, 0);
440    
441          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
442          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
443    
444          /* Client information */          /* Client information */
445          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
446          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
447          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
448          out_uint16_le(s, 8);          out_uint16_le(s, 8);
449          out_uint16_le(s, width);          out_uint16_le(s, g_width);
450          out_uint16_le(s, height);          out_uint16_le(s, g_height);
451          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
452          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
453          out_uint32_le(s, keylayout);          out_uint32_le(s, g_keylayout);
454          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
455    
456          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
457          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, g_hostname, hostlen);
458          out_uint8s(s, 30 - hostlen);          out_uint8s(s, 30 - hostlen);
459    
460          out_uint32_le(s, 4);          /* See
461          out_uint32(s, 0);             http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
462          out_uint32_le(s, 12);          out_uint32_le(s, g_keyboard_type);
463            out_uint32_le(s, g_keyboard_subtype);
464            out_uint32_le(s, g_keyboard_functionkeys);
465          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
466            out_uint16_le(s, 0xca01);       /* colour depth? */
467            out_uint16_le(s, 1);
468    
469          out_uint16_le(s, 0xca01);          out_uint32(s, 0);
470          out_uint16(s, 0);          out_uint8(s, g_server_depth);
471            out_uint16_le(s, 0x0700);
472            out_uint8(s, 0);
473            out_uint32_le(s, 1);
474            out_uint8s(s, 64);      /* End of client info */
475    
476            out_uint16_le(s, SEC_TAG_CLI_4);
477            out_uint16_le(s, 12);
478            out_uint32_le(s, g_console_session ? 0xb : 9);
479            out_uint32(s, 0);
480    
481          /* Client encryption settings */          /* Client encryption settings */
482          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
483          out_uint16_le(s, 8);    /* length */          out_uint16_le(s, 12);   /* length */
484          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 */
485            out_uint32(s, 0);       /* Unknown */
486    
487            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
488            if (g_num_channels > 0)
489            {
490                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
491                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
492                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
493                    for (i = 0; i < g_num_channels; i++)
494                    {
495                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
496                            out_uint8a(s, g_channels[i].name, 8);
497                            out_uint32_be(s, g_channels[i].flags);
498                    }
499            }
500    
501          s_mark_end(s);          s_mark_end(s);
502  }  }
503    
# Line 449  sec_parse_public_key(STREAM s, uint8 ** Line 515  sec_parse_public_key(STREAM s, uint8 **
515          }          }
516    
517          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
518          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          modulus_len -= SEC_PADDING_SIZE;
519            if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
520          {          {
521                  error("modulus len 0x%x\n", modulus_len);                  error("Bad server public key size (%u bits)\n", modulus_len * 8);
522                  return False;                  return False;
523          }          }
524    
525          in_uint8s(s, 8);        /* modulus_bits, unknown */          in_uint8s(s, 8);        /* modulus_bits, unknown */
526          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
527          in_uint8p(s, *modulus, SEC_MODULUS_SIZE);          in_uint8p(s, *modulus, modulus_len);
528          in_uint8s(s, SEC_PADDING_SIZE);          in_uint8s(s, SEC_PADDING_SIZE);
529            server_public_key_len = modulus_len;
530    
531          return s_check(s);          return s_check(s);
532  }  }
533    
534    static BOOL
535    sec_parse_x509_key(X509 * cert)
536    {
537            EVP_PKEY *epk = NULL;
538            /* By some reason, Microsoft sets the OID of the Public RSA key to
539               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
540    
541               Kudos to Richard Levitte for the following (. intiutive .)
542               lines of code that resets the OID and let's us extract the key. */
543            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
544            {
545                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
546                    ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
547                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
548            }
549            epk = X509_get_pubkey(cert);
550            if (NULL == epk)
551            {
552                    error("Failed to extract public key from certificate\n");
553                    return False;
554            }
555    
556            server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
557            EVP_PKEY_free(epk);
558    
559            server_public_key_len = RSA_size(server_public_key);
560            if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))
561            {
562                    error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
563                    return False;
564            }
565    
566            return True;
567    }
568    
569    
570  /* Parse a crypto information structure */  /* Parse a crypto information structure */
571  static BOOL  static BOOL
572  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
573                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
574  {  {
575          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
576            uint32 cacert_len, cert_len, flags;
577            X509 *cacert, *server_cert;
578          uint16 tag, length;          uint16 tag, length;
579          uint8 *next_tag, *end;          uint8 *next_tag, *end;
580    
581          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 */
582          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
583          if (crypt_level == 0)   /* no encryptation */          if (crypt_level == 0)   /* no encryption */
584                  return False;                  return False;
585          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
586          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
587    
588          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
589          {          {
590                  error("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
591                  return False;                  return False;
592          }          }
593    
# Line 492  sec_parse_crypt_info(STREAM s, uint32 * Line 598  sec_parse_crypt_info(STREAM s, uint32 *
598          if (end > s->end)          if (end > s->end)
599                  return False;                  return False;
600    
601          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
602            if (flags & 1)
603            {
604                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
605                    in_uint8s(s, 8);        /* unknown */
606    
607                    while (s->p < end)
608                    {
609                            in_uint16_le(s, tag);
610                            in_uint16_le(s, length);
611    
612                            next_tag = s->p + length;
613    
614                            switch (tag)
615                            {
616                                    case SEC_TAG_PUBKEY:
617                                            if (!sec_parse_public_key(s, modulus, exponent))
618                                                    return False;
619                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
620    
621                                            break;
622    
623                                    case SEC_TAG_KEYSIG:
624                                            /* Is this a Microsoft key that we just got? */
625                                            /* Care factor: zero! */
626                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
627                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
628                                            break;
629    
630                                    default:
631                                            unimpl("crypt tag 0x%x\n", tag);
632                            }
633    
634          while (s->p < end)                          s->p = next_tag;
635                    }
636            }
637            else
638          {          {
639                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
640    
641                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
642                    in_uint32_le(s, certcount);     /* Number of certificates */
643    
644                  switch (tag)                  if (certcount < 2)
645                  {                  {
646                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
647                                  if (!sec_parse_public_key(s, modulus, exponent))                          return False;
648                                          return False;                  }
649    
650                                  break;                  for (; certcount > 2; certcount--)
651                    {               /* ignore all the certificates between the root and the signing CA */
652                            uint32 ignorelen;
653                            X509 *ignorecert;
654    
655                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
656    
657                            in_uint32_le(s, ignorelen);
658                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
659                            ignorecert =
660                                    d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p),
661                                             ignorelen);
662    
663                            if (ignorecert == NULL)
664                            {       /* XXX: error out? */
665                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
666                            }
667    
668                          case SEC_TAG_KEYSIG:  #ifdef WITH_DEBUG_RDP5
669                                  /* Is this a Microsoft key that we just got? */                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
670                                  /* Care factor: zero! */                          X509_print_fp(stdout, ignorecert);
671                                  break;  #endif
672                    }
673    
674                          default:                  /* Do da funky X.509 stuffy
675                                  unimpl("crypt tag 0x%x\n", tag);  
676                       "How did I find out about this?  I looked up and saw a
677                       bright light and when I came to I had a scar on my forehead
678                       and knew about X.500"
679                       - Peter Gutman in a early version of
680                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
681                     */
682    
683                    in_uint32_le(s, cacert_len);
684                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
685                    cacert = d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p), cacert_len);
686                    /* Note: We don't need to move s->p here - d2i_X509 is
687                       "kind" enough to do it for us */
688                    if (NULL == cacert)
689                    {
690                            error("Couldn't load CA Certificate from server\n");
691                            return False;
692                  }                  }
693    
694                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
695          }                     FIXME:
696                       *) Verify the server certificate (server_cert) with the
697                       CA certificate.
698                       *) Store the CA Certificate with the hostname of the
699                       server we are connecting to as key, and compare it
700                       when we connect the next time, in order to prevent
701                       MITM-attacks.
702                     */
703    
704                    X509_free(cacert);
705    
706                    in_uint32_le(s, cert_len);
707                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
708                    server_cert = d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &(s->p), cert_len);
709                    if (NULL == server_cert)
710                    {
711                            error("Couldn't load Certificate from server\n");
712                            return False;
713                    }
714    
715                    in_uint8s(s, 16);       /* Padding */
716    
717                    /* Note: Verifying the server certificate must be done here,
718                       before sec_parse_public_key since we'll have to apply
719                       serious violence to the key after this */
720    
721                    if (!sec_parse_x509_key(server_cert))
722                    {
723                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
724                            X509_free(server_cert);
725                            return False;
726                    }
727                    X509_free(server_cert);
728                    return True;    /* There's some garbage here we don't care about */
729            }
730          return s_check_end(s);          return s_check_end(s);
731  }  }
732    
# Line 528  sec_parse_crypt_info(STREAM s, uint32 * Line 734  sec_parse_crypt_info(STREAM s, uint32 *
734  static void  static void
735  sec_process_crypt_info(STREAM s)  sec_process_crypt_info(STREAM s)
736  {  {
737          uint8 *server_random, *modulus, *exponent;          uint8 *server_random = NULL, *modulus = NULL, *exponent = NULL;
738          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
739          uint32 rc4_key_size;          uint32 rc4_key_size;
740    
741          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
742            {
743                    DEBUG(("Failed to parse crypt info\n"));
744                  return;                  return;
745            }
746    
747          /* Generate a client random, and hence determine encryption keys */          DEBUG(("Generating client random\n"));
748          generate_random(client_random);          generate_random(client_random);
749          sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);  
750            if (NULL != server_public_key)
751            {                       /* Which means we should use
752                                       RDP5-style encryption */
753                    uint8 inr[SEC_MAX_MODULUS_SIZE];
754                    uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;
755    
756                    /* This is what the MS client do: */
757                    memset(inr, 0, padding_len);
758                    /*  *ARIGL!* Plaintext attack, anyone?
759                       I tried doing:
760                       generate_random(inr);
761                       ..but that generates connection errors now and then (yes,
762                       "now and then". Something like 0 to 3 attempts needed before a
763                       successful connection. Nice. Not!
764                     */
765                    memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
766                    reverse(inr + padding_len, SEC_RANDOM_SIZE);
767    
768                    RSA_public_encrypt(server_public_key_len,
769                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
770    
771                    reverse(sec_crypted_random, server_public_key_len);
772    
773                    RSA_free(server_public_key);
774                    server_public_key = NULL;
775            }
776            else
777            {                       /* RDP4-style encryption */
778                    sec_rsa_encrypt(sec_crypted_random,
779                                    client_random, SEC_RANDOM_SIZE, server_public_key_len, modulus,
780                                    exponent);
781            }
782          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
783  }  }
784    
785  /* Process connect response data blob */  
786    /* Process SRV_INFO, find RDP version supported by server */
787  static void  static void
788    sec_process_srv_info(STREAM s)
789    {
790            in_uint16_le(s, g_server_rdp_version);
791            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
792            if (1 == g_server_rdp_version)
793            {
794                    g_use_rdp5 = 0;
795                    g_server_depth = 8;
796            }
797    }
798    
799    
800    /* Process connect response data blob */
801    void
802  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
803  {  {
804          uint16 tag, length;          uint16 tag, length;
805          uint8 *next_tag;          uint8 *next_tag;
806          uint8 len;          uint8 len;
807    
808          in_uint8s(s, 21);       /* header */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
809          in_uint8(s, len);          in_uint8(s, len);
810          if (len & 0x80)          if (len & 0x80)
811                  in_uint8(s, len);                  in_uint8(s, len);
# Line 567  sec_process_mcs_data(STREAM s) Line 823  sec_process_mcs_data(STREAM s)
823                  switch (tag)                  switch (tag)
824                  {                  {
825                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
826                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
827                                  break;                                  break;
828    
829                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
830                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
831                                  break;                                  break;
832    
833                            case SEC_TAG_SRV_CHANNELS:
834                                    /* FIXME: We should parse this information and
835                                       use it to map RDP5 channels to MCS
836                                       channels */
837                                    break;
838    
839                          default:                          default:
840                                  unimpl("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
841                  }                  }
# Line 584  sec_process_mcs_data(STREAM s) Line 846  sec_process_mcs_data(STREAM s)
846    
847  /* Receive secure transport packet */  /* Receive secure transport packet */
848  STREAM  STREAM
849  sec_recv(void)  sec_recv(uint8 * rdpver)
850  {  {
851          uint32 sec_flags;          uint32 sec_flags;
852            uint16 channel;
853          STREAM s;          STREAM s;
854    
855          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel, rdpver)) != NULL)
856          {          {
857                  if (encryption || !licence_issued)                  if (rdpver != NULL)
858                    {
859                            if (*rdpver != 3)
860                            {
861                                    if (*rdpver & 0x80)
862                                    {
863                                            in_uint8s(s, 8);        /* signature */
864                                            sec_decrypt(s->p, s->end - s->p);
865                                    }
866                                    return s;
867                            }
868                    }
869                    if (g_encryption || !g_licence_issued)
870                  {                  {
871                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
872    
873                            if (sec_flags & SEC_ENCRYPT)
874                            {
875                                    in_uint8s(s, 8);        /* signature */
876                                    sec_decrypt(s->p, s->end - s->p);
877                            }
878    
879                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
880                          {                          {
881                                  licence_process(s);                                  licence_process(s);
882                                  continue;                                  continue;
883                          }                          }
884    
885                          if (sec_flags & SEC_ENCRYPT)                          if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
886                          {                          {
887                                    uint8 swapbyte;
888    
889                                  in_uint8s(s, 8);        /* signature */                                  in_uint8s(s, 8);        /* signature */
890                                  sec_decrypt(s->p, s->end - s->p);                                  sec_decrypt(s->p, s->end - s->p);
891    
892                                    /* Check for a redirect packet, starts with 00 04 */
893                                    if (s->p[0] == 0 && s->p[1] == 4)
894                                    {
895                                            /* for some reason the PDU and the length seem to be swapped.
896                                               This isn't good, but we're going to do a byte for byte
897                                               swap.  So the first foure value appear as: 00 04 XX YY,
898                                               where XX YY is the little endian length. We're going to
899                                               use 04 00 as the PDU type, so after our swap this will look
900                                               like: XX YY 04 00 */
901                                            swapbyte = s->p[0];
902                                            s->p[0] = s->p[2];
903                                            s->p[2] = swapbyte;
904    
905                                            swapbyte = s->p[1];
906                                            s->p[1] = s->p[3];
907                                            s->p[3] = swapbyte;
908    
909                                            swapbyte = s->p[2];
910                                            s->p[2] = s->p[3];
911                                            s->p[3] = swapbyte;
912                                    }
913    #ifdef WITH_DEBUG
914                                    /* warning!  this debug statement will show passwords in the clear! */
915                                    hexdump(s->p, s->end - s->p);
916    #endif
917                          }                          }
918    
919                    }
920    
921                    if (channel != MCS_GLOBAL_CHANNEL)
922                    {
923                            channel_process(s, channel);
924                            *rdpver = 0xff;
925                            return s;
926                  }                  }
927    
928                  return s;                  return s;
# Line 616  sec_recv(void) Line 933  sec_recv(void)
933    
934  /* Establish a secure connection */  /* Establish a secure connection */
935  BOOL  BOOL
936  sec_connect(char *server)  sec_connect(char *server, char *username)
937    {
938            struct stream mcs_data;
939    
940            /* We exchange some RDP data during the MCS-Connect */
941            mcs_data.size = 512;
942            mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
943            sec_out_mcs_data(&mcs_data);
944    
945            if (!mcs_connect(server, &mcs_data, username))
946                    return False;
947    
948            /*      sec_process_mcs_data(&mcs_data); */
949            if (g_encryption)
950                    sec_establish_key();
951            xfree(mcs_data.data);
952            return True;
953    }
954    
955    /* Establish a secure connection */
956    BOOL
957    sec_reconnect(char *server)
958  {  {
959          struct stream mcs_data;          struct stream mcs_data;
960    
961          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
962          mcs_data.size = 512;          mcs_data.size = 512;
963          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
964          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
965    
966          if (!mcs_connect(server, &mcs_data))          if (!mcs_reconnect(server, &mcs_data))
967                  return False;                  return False;
968    
969          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
970          if (encryption)          if (g_encryption)
971                  sec_establish_key();                  sec_establish_key();
972            xfree(mcs_data.data);
973          return True;          return True;
974  }  }
975    
# Line 640  sec_disconnect(void) Line 979  sec_disconnect(void)
979  {  {
980          mcs_disconnect();          mcs_disconnect();
981  }  }
982    
983    /* reset the state of the sec layer */
984    void
985    sec_reset_state(void)
986    {
987            g_server_rdp_version = 0;
988            sec_encrypt_use_count = 0;
989            sec_decrypt_use_count = 0;
990            mcs_reset_state();
991    }

Legend:
Removed from v.207  
changed lines
  Added in v.1315

  ViewVC Help
Powered by ViewVC 1.1.26