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

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

  ViewVC Help
Powered by ViewVC 1.1.26