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

Legend:
Removed from v.90  
changed lines
  Added in v.1239

  ViewVC Help
Powered by ViewVC 1.1.26