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

Legend:
Removed from v.88  
changed lines
  Added in v.1199

  ViewVC Help
Powered by ViewVC 1.1.26