/[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 966 by astrand, Wed Aug 3 11:48:22 2005 UTC revision 1374 by jsorg71, Tue Jan 9 07:24:44 2007 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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-2005     Copyright (C) Matthew Chapman 1999-2007
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 19  Line 19 
19  */  */
20    
21  #include "rdesktop.h"  #include "rdesktop.h"
22    #include "ssl.h"
 #include <openssl/rc4.h>  
 #include <openssl/md5.h>  
 #include <openssl/sha.h>  
 #include <openssl/bn.h>  
 #include <openssl/x509v3.h>  
23    
24  extern char g_hostname[16];  extern char g_hostname[16];
25  extern int g_width;  extern int g_width;
26  extern int g_height;  extern int g_height;
27  extern int g_keylayout;  extern unsigned int g_keylayout;
28  extern int g_keyboard_type;  extern int g_keyboard_type;
29  extern int g_keyboard_subtype;  extern int g_keyboard_subtype;
30  extern int g_keyboard_functionkeys;  extern int g_keyboard_functionkeys;
31  extern BOOL g_encryption;  extern RD_BOOL g_encryption;
32  extern BOOL g_licence_issued;  extern RD_BOOL g_licence_issued;
33  extern BOOL g_use_rdp5;  extern RD_BOOL g_use_rdp5;
34  extern BOOL g_console_session;  extern RD_BOOL g_console_session;
35  extern int g_server_bpp;  extern int g_server_depth;
36  extern uint16 mcs_userid;  extern uint16 mcs_userid;
37  extern VCHANNEL g_channels[];  extern VCHANNEL g_channels[];
38  extern unsigned int g_num_channels;  extern unsigned int g_num_channels;
39    
40  static int rc4_key_len;  static int rc4_key_len;
41  static RC4_KEY rc4_decrypt_key;  static SSL_RC4 rc4_decrypt_key;
42  static RC4_KEY rc4_encrypt_key;  static SSL_RC4 rc4_encrypt_key;
43  static RSA *server_public_key;  static uint32 server_public_key_len;
44    
45  static uint8 sec_sign_key[16];  static uint8 sec_sign_key[16];
46  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
47  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
48  static uint8 sec_decrypt_update_key[16];  static uint8 sec_decrypt_update_key[16];
49  static uint8 sec_encrypt_update_key[16];  static uint8 sec_encrypt_update_key[16];
50  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 sec_crypted_random[SEC_MAX_MODULUS_SIZE];
51    
52  uint16 g_server_rdp_version = 0;  uint16 g_server_rdp_version = 0;
53    
54    /* These values must be available to reset state - Session Directory */
55    static int sec_encrypt_use_count = 0;
56    static int sec_decrypt_use_count = 0;
57    
58  /*  /*
59   * I believe this is based on SSLv3 with the following differences:   * I believe this is based on SSLv3 with the following differences:
60   *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields   *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
# Line 75  sec_hash_48(uint8 * out, uint8 * in, uin Line 74  sec_hash_48(uint8 * out, uint8 * in, uin
74  {  {
75          uint8 shasig[20];          uint8 shasig[20];
76          uint8 pad[4];          uint8 pad[4];
77          SHA_CTX sha;          SSL_SHA1 sha1;
78          MD5_CTX md5;          SSL_MD5 md5;
79          int i;          int i;
80    
81          for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
82          {          {
83                  memset(pad, salt + i, i + 1);                  memset(pad, salt + i, i + 1);
84    
85                  SHA1_Init(&sha);                  ssl_sha1_init(&sha1);
86                  SHA1_Update(&sha, pad, i + 1);                  ssl_sha1_update(&sha1, pad, i + 1);
87                  SHA1_Update(&sha, in, 48);                  ssl_sha1_update(&sha1, in, 48);
88                  SHA1_Update(&sha, salt1, 32);                  ssl_sha1_update(&sha1, salt1, 32);
89                  SHA1_Update(&sha, salt2, 32);                  ssl_sha1_update(&sha1, salt2, 32);
90                  SHA1_Final(shasig, &sha);                  ssl_sha1_final(&sha1, shasig);
91    
92                  MD5_Init(&md5);                  ssl_md5_init(&md5);
93                  MD5_Update(&md5, in, 48);                  ssl_md5_update(&md5, in, 48);
94                  MD5_Update(&md5, shasig, 20);                  ssl_md5_update(&md5, shasig, 20);
95                  MD5_Final(&out[i * 16], &md5);                  ssl_md5_final(&md5, &out[i * 16]);
96          }          }
97  }  }
98    
# Line 103  sec_hash_48(uint8 * out, uint8 * in, uin Line 102  sec_hash_48(uint8 * out, uint8 * in, uin
102  void  void
103  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
104  {  {
105          MD5_CTX md5;          SSL_MD5 md5;
106    
107          MD5_Init(&md5);          ssl_md5_init(&md5);
108          MD5_Update(&md5, in, 16);          ssl_md5_update(&md5, in, 16);
109          MD5_Update(&md5, salt1, 32);          ssl_md5_update(&md5, salt1, 32);
110          MD5_Update(&md5, salt2, 32);          ssl_md5_update(&md5, salt2, 32);
111          MD5_Final(out, &md5);          ssl_md5_final(&md5, out);
112  }  }
113    
114  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
# Line 198  sec_sign(uint8 * signature, int siglen, Line 197  sec_sign(uint8 * signature, int siglen,
197          uint8 shasig[20];          uint8 shasig[20];
198          uint8 md5sig[16];          uint8 md5sig[16];
199          uint8 lenhdr[4];          uint8 lenhdr[4];
200          SHA_CTX sha;          SSL_SHA1 sha1;
201          MD5_CTX md5;          SSL_MD5 md5;
202    
203          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
204    
205          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
206          SHA1_Update(&sha, session_key, keylen);          ssl_sha1_update(&sha1, session_key, keylen);
207          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
208          SHA1_Update(&sha, lenhdr, 4);          ssl_sha1_update(&sha1, lenhdr, 4);
209          SHA1_Update(&sha, data, datalen);          ssl_sha1_update(&sha1, data, datalen);
210          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
211    
212          MD5_Init(&md5);          ssl_md5_init(&md5);
213          MD5_Update(&md5, session_key, keylen);          ssl_md5_update(&md5, session_key, keylen);
214          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
215          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
216          MD5_Final(md5sig, &md5);          ssl_md5_final(&md5, md5sig);
217    
218          memcpy(signature, md5sig, siglen);          memcpy(signature, md5sig, siglen);
219  }  }
# Line 224  static void Line 223  static void
223  sec_update(uint8 * key, uint8 * update_key)  sec_update(uint8 * key, uint8 * update_key)
224  {  {
225          uint8 shasig[20];          uint8 shasig[20];
226          SHA_CTX sha;          SSL_SHA1 sha1;
227          MD5_CTX md5;          SSL_MD5 md5;
228          RC4_KEY update;          SSL_RC4 update;
229    
230          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
231          SHA1_Update(&sha, update_key, rc4_key_len);          ssl_sha1_update(&sha1, update_key, rc4_key_len);
232          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
233          SHA1_Update(&sha, key, rc4_key_len);          ssl_sha1_update(&sha1, key, rc4_key_len);
234          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
235    
236          MD5_Init(&md5);          ssl_md5_init(&md5);
237          MD5_Update(&md5, update_key, rc4_key_len);          ssl_md5_update(&md5, update_key, rc4_key_len);
238          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
239          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
240          MD5_Final(key, &md5);          ssl_md5_final(&md5, key);
241    
242          RC4_set_key(&update, rc4_key_len, key);          ssl_rc4_set_key(&update, key, rc4_key_len);
243          RC4(&update, rc4_key_len, key, key);          ssl_rc4_crypt(&update, key, key, rc4_key_len);
244    
245          if (rc4_key_len == 8)          if (rc4_key_len == 8)
246                  sec_make_40bit(key);                  sec_make_40bit(key);
# Line 251  sec_update(uint8 * key, uint8 * update_k Line 250  sec_update(uint8 * key, uint8 * update_k
250  static void  static void
251  sec_encrypt(uint8 * data, int length)  sec_encrypt(uint8 * data, int length)
252  {  {
253          static int use_count;          if (sec_encrypt_use_count == 4096)
   
         if (use_count == 4096)  
254          {          {
255                  sec_update(sec_encrypt_key, sec_encrypt_update_key);                  sec_update(sec_encrypt_key, sec_encrypt_update_key);
256                  RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);                  ssl_rc4_set_key(&rc4_encrypt_key, sec_encrypt_key, rc4_key_len);
257                  use_count = 0;                  sec_encrypt_use_count = 0;
258          }          }
259    
260          RC4(&rc4_encrypt_key, length, data, data);          ssl_rc4_crypt(&rc4_encrypt_key, data, data, length);
261          use_count++;          sec_encrypt_use_count++;
262  }  }
263    
264  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
265  void  void
266  sec_decrypt(uint8 * data, int length)  sec_decrypt(uint8 * data, int length)
267  {  {
268          static int use_count;          if (sec_decrypt_use_count == 4096)
   
         if (use_count == 4096)  
269          {          {
270                  sec_update(sec_decrypt_key, sec_decrypt_update_key);                  sec_update(sec_decrypt_key, sec_decrypt_update_key);
271                  RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);                  ssl_rc4_set_key(&rc4_decrypt_key, sec_decrypt_key, rc4_key_len);
272                  use_count = 0;                  sec_decrypt_use_count = 0;
273          }          }
274    
275          RC4(&rc4_decrypt_key, length, data, data);          ssl_rc4_crypt(&rc4_decrypt_key, data, data, length);
276          use_count++;          sec_decrypt_use_count++;
 }  
   
 static void  
 reverse(uint8 * p, int len)  
 {  
         int i, j;  
         uint8 temp;  
   
         for (i = 0, j = len - 1; i < j; i++, j--)  
         {  
                 temp = p[i];  
                 p[i] = p[j];  
                 p[j] = temp;  
         }  
277  }  }
278    
279  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
280  static void  static void
281  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,
282                    uint8 * exponent)
283  {  {
284          BN_CTX *ctx;          ssl_rsa_encrypt(out, in, len, modulus_size, modulus, exponent);
         BIGNUM mod, exp, x, y;  
         uint8 inr[SEC_MODULUS_SIZE];  
         int outlen;  
   
         reverse(modulus, SEC_MODULUS_SIZE);  
         reverse(exponent, SEC_EXPONENT_SIZE);  
         memcpy(inr, in, len);  
         reverse(inr, len);  
   
         ctx = BN_CTX_new();  
         BN_init(&mod);  
         BN_init(&exp);  
         BN_init(&x);  
         BN_init(&y);  
   
         BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);  
         BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);  
         BN_bin2bn(inr, len, &x);  
         BN_mod_exp(&y, &x, &exp, &mod, ctx);  
         outlen = BN_bn2bin(&y, out);  
         reverse(out, outlen);  
         if (outlen < SEC_MODULUS_SIZE)  
                 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);  
   
         BN_free(&y);  
         BN_clear_free(&x);  
         BN_free(&exp);  
         BN_free(&mod);  
         BN_CTX_free(ctx);  
285  }  }
286    
287  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 354  sec_send_to_channel(STREAM s, uint32 fla Line 307  sec_send_to_channel(STREAM s, uint32 fla
307  {  {
308          int datalen;          int datalen;
309    
310    #ifdef WITH_SCARD
311            scard_lock(SCARD_LOCK_SEC);
312    #endif
313    
314          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
315          if (!g_licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
316                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
# Line 373  sec_send_to_channel(STREAM s, uint32 fla Line 330  sec_send_to_channel(STREAM s, uint32 fla
330          }          }
331    
332          mcs_send_to_channel(s, channel);          mcs_send_to_channel(s, channel);
333    
334    #ifdef WITH_SCARD
335            scard_unlock(SCARD_LOCK_SEC);
336    #endif
337  }  }
338    
339  /* Transmit secure transport packet */  /* Transmit secure transport packet */
# Line 388  sec_send(STREAM s, uint32 flags) Line 349  sec_send(STREAM s, uint32 flags)
349  static void  static void
350  sec_establish_key(void)  sec_establish_key(void)
351  {  {
352          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = server_public_key_len + SEC_PADDING_SIZE;
353          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
354          STREAM s;          STREAM s;
355    
356          s = sec_init(flags, 76);          s = sec_init(flags, length + 4);
357    
358          out_uint32_le(s, length);          out_uint32_le(s, length);
359          out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);          out_uint8p(s, sec_crypted_random, server_public_key_len);
360          out_uint8s(s, SEC_PADDING_SIZE);          out_uint8s(s, SEC_PADDING_SIZE);
361    
362          s_mark_end(s);          s_mark_end(s);
# Line 459  sec_out_mcs_data(STREAM s) Line 420  sec_out_mcs_data(STREAM s)
420          out_uint16_le(s, 1);          out_uint16_le(s, 1);
421    
422          out_uint32(s, 0);          out_uint32(s, 0);
423          out_uint8(s, g_server_bpp);          out_uint8(s, g_server_depth);
424          out_uint16_le(s, 0x0700);          out_uint16_le(s, 0x0700);
425          out_uint8(s, 0);          out_uint8(s, 0);
426          out_uint32_le(s, 1);          out_uint32_le(s, 1);
# Line 494  sec_out_mcs_data(STREAM s) Line 455  sec_out_mcs_data(STREAM s)
455  }  }
456    
457  /* Parse a public key structure */  /* Parse a public key structure */
458  static BOOL  static RD_BOOL
459  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)  sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
460  {  {
461          uint32 magic, modulus_len;          uint32 magic, modulus_len;
462    
# Line 507  sec_parse_public_key(STREAM s, uint8 ** Line 468  sec_parse_public_key(STREAM s, uint8 **
468          }          }
469    
470          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
471          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          modulus_len -= SEC_PADDING_SIZE;
472            if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
473          {          {
474                  error("modulus len 0x%x\n", modulus_len);                  error("Bad server public key size (%u bits)\n", modulus_len * 8);
475                  return False;                  return False;
476          }          }
477    
478          in_uint8s(s, 8);        /* modulus_bits, unknown */          in_uint8s(s, 8);        /* modulus_bits, unknown */
479          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);          in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
480          in_uint8p(s, *modulus, SEC_MODULUS_SIZE);          in_uint8a(s, modulus, modulus_len);
481          in_uint8s(s, SEC_PADDING_SIZE);          in_uint8s(s, SEC_PADDING_SIZE);
482            server_public_key_len = modulus_len;
483    
484          return s_check(s);          return s_check(s);
485  }  }
486    
487  static BOOL  /* Parse a public signature structure */
488  sec_parse_x509_key(X509 * cert)  static RD_BOOL
489  {  sec_parse_public_sig(STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
490          EVP_PKEY *epk = NULL;  {
491          /* By some reason, Microsoft sets the OID of the Public RSA key to          uint8 signature[SEC_MAX_MODULUS_SIZE];
492             the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"          uint32 sig_len;
493    
494             Kudos to Richard Levitte for the following (. intiutive .)          if (len != 72)
495             lines of code that resets the OID and let's us extract the key. */          {
496          if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)                  return True;
497          {          }
498                  DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));          memset(signature, 0, sizeof(signature));
499                  cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);          sig_len = len - 8;
500          }          in_uint8a(s, signature, sig_len);
501          epk = X509_get_pubkey(cert);          return ssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, server_public_key_len,
502          if (NULL == epk)                            signature, sig_len);
         {  
                 error("Failed to extract public key from certificate\n");  
                 return False;  
         }  
   
         server_public_key = (RSA *) epk->pkey.ptr;  
   
         return True;  
503  }  }
504    
   
505  /* Parse a crypto information structure */  /* Parse a crypto information structure */
506  static BOOL  static RD_BOOL
507  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
508                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 * modulus, uint8 * exponent)
509  {  {
510          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
511          uint32 cacert_len, cert_len, flags;          uint32 cacert_len, cert_len, flags;
512          X509 *cacert, *server_cert;          SSL_CERT *cacert, *server_cert;
513            SSL_RKEY *server_public_key;
514          uint16 tag, length;          uint16 tag, length;
515          uint8 *next_tag, *end;          uint8 *next_tag, *end;
516    
# Line 602  sec_parse_crypt_info(STREAM s, uint32 * Line 557  sec_parse_crypt_info(STREAM s, uint32 *
557                                          break;                                          break;
558    
559                                  case SEC_TAG_KEYSIG:                                  case SEC_TAG_KEYSIG:
560                                          /* Is this a Microsoft key that we just got? */                                          if (!sec_parse_public_sig(s, length, modulus, exponent))
561                                          /* Care factor: zero! */                                                  return False;
                                         /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this  
                                            key as a known key of the hostname. This would prevent some MITM-attacks. */  
562                                          break;                                          break;
563    
564                                  default:                                  default:
# Line 621  sec_parse_crypt_info(STREAM s, uint32 * Line 574  sec_parse_crypt_info(STREAM s, uint32 *
574    
575                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
576                  in_uint32_le(s, certcount);     /* Number of certificates */                  in_uint32_le(s, certcount);     /* Number of certificates */
   
577                  if (certcount < 2)                  if (certcount < 2)
578                  {                  {
579                          error("Server didn't send enough X509 certificates\n");                          error("Server didn't send enough X509 certificates\n");
580                          return False;                          return False;
581                  }                  }
   
582                  for (; certcount > 2; certcount--)                  for (; certcount > 2; certcount--)
583                  {               /* ignore all the certificates between the root and the signing CA */                  {               /* ignore all the certificates between the root and the signing CA */
584                          uint32 ignorelen;                          uint32 ignorelen;
585                          X509 *ignorecert;                          SSL_CERT *ignorecert;
586    
587                          DEBUG_RDP5(("Ignored certs left: %d\n", certcount));                          DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
   
588                          in_uint32_le(s, ignorelen);                          in_uint32_le(s, ignorelen);
589                          DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));                          DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
590                          ignorecert = d2i_X509(NULL, &(s->p), ignorelen);                          ignorecert = ssl_cert_read(s->p, ignorelen);
591                            in_uint8s(s, ignorelen);
592                          if (ignorecert == NULL)                          if (ignorecert == NULL)
593                          {       /* XXX: error out? */                          {       /* XXX: error out? */
594                                  DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));                                  DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
# Line 646  sec_parse_crypt_info(STREAM s, uint32 * Line 596  sec_parse_crypt_info(STREAM s, uint32 *
596    
597  #ifdef WITH_DEBUG_RDP5  #ifdef WITH_DEBUG_RDP5
598                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
599                          X509_print_fp(stdout, ignorecert);                          ssl_cert_print_fp(stdout, ignorecert);
600  #endif  #endif
601                  }                  }
602                    /* Do da funky X.509 stuffy
                 /* Do da funky X.509 stuffy  
603    
604                     "How did I find out about this?  I looked up and saw a                     "How did I find out about this?  I looked up and saw a
605                     bright light and when I came to I had a scar on my forehead                     bright light and when I came to I had a scar on my forehead
# Line 658  sec_parse_crypt_info(STREAM s, uint32 * Line 607  sec_parse_crypt_info(STREAM s, uint32 *
607                     - Peter Gutman in a early version of                     - Peter Gutman in a early version of
608                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
609                   */                   */
   
610                  in_uint32_le(s, cacert_len);                  in_uint32_le(s, cacert_len);
611                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
612                  cacert = d2i_X509(NULL, &(s->p), cacert_len);                  cacert = ssl_cert_read(s->p, cacert_len);
613                  /* Note: We don't need to move s->p here - d2i_X509 is                  in_uint8s(s, cacert_len);
                    "kind" enough to do it for us */  
614                  if (NULL == cacert)                  if (NULL == cacert)
615                  {                  {
616                          error("Couldn't load CA Certificate from server\n");                          error("Couldn't load CA Certificate from server\n");
617                          return False;                          return False;
618                  }                  }
   
                 /* Currently, we don't use the CA Certificate.  
                    FIXME:  
                    *) Verify the server certificate (server_cert) with the  
                    CA certificate.  
                    *) Store the CA Certificate with the hostname of the  
                    server we are connecting to as key, and compare it  
                    when we connect the next time, in order to prevent  
                    MITM-attacks.  
                  */  
   
619                  in_uint32_le(s, cert_len);                  in_uint32_le(s, cert_len);
620                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));
621                  server_cert = d2i_X509(NULL, &(s->p), cert_len);                  server_cert = ssl_cert_read(s->p, cert_len);
622                    in_uint8s(s, cert_len);
623                  if (NULL == server_cert)                  if (NULL == server_cert)
624                  {                  {
625                            ssl_cert_free(cacert);
626                          error("Couldn't load Certificate from server\n");                          error("Couldn't load Certificate from server\n");
627                          return False;                          return False;
628                  }                  }
629                    if (!ssl_certs_ok(server_cert, cacert))
630                    {
631                            ssl_cert_free(server_cert);
632                            ssl_cert_free(cacert);
633                            error("Security error CA Certificate invalid\n");
634                            return False;
635                    }
636                    ssl_cert_free(cacert);
637                  in_uint8s(s, 16);       /* Padding */                  in_uint8s(s, 16);       /* Padding */
638                    server_public_key = ssl_cert_to_rkey(server_cert, &server_public_key_len);
639                  /* Note: Verifying the server certificate must be done here,                  if (NULL == server_public_key)
                    before sec_parse_public_key since we'll have to apply  
                    serious violence to the key after this */  
   
                 if (!sec_parse_x509_key(server_cert))  
640                  {                  {
641                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));
642                            ssl_cert_free(server_cert);
643                            return False;
644                    }
645                    ssl_cert_free(server_cert);
646                    if ((server_public_key_len < SEC_MODULUS_SIZE) ||
647                        (server_public_key_len > SEC_MAX_MODULUS_SIZE))
648                    {
649                            error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
650                            ssl_rkey_free(server_public_key);
651                          return False;                          return False;
652                  }                  }
653                    if (ssl_rkey_get_exp_mod(server_public_key, exponent, SEC_EXPONENT_SIZE,
654                                             modulus, SEC_MAX_MODULUS_SIZE) != 0)
655                    {
656                            error("Problem extracting RSA exponent, modulus");
657                            ssl_rkey_free(server_public_key);
658                            return False;
659                    }
660                    ssl_rkey_free(server_public_key);
661                  return True;    /* There's some garbage here we don't care about */                  return True;    /* There's some garbage here we don't care about */
662          }          }
663          return s_check_end(s);          return s_check_end(s);
# Line 709  sec_parse_crypt_info(STREAM s, uint32 * Line 667  sec_parse_crypt_info(STREAM s, uint32 *
667  static void  static void
668  sec_process_crypt_info(STREAM s)  sec_process_crypt_info(STREAM s)
669  {  {
670          uint8 *server_random, *modulus, *exponent;          uint8 *server_random = NULL;
671          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
672            uint8 modulus[SEC_MAX_MODULUS_SIZE];
673            uint8 exponent[SEC_EXPONENT_SIZE];
674          uint32 rc4_key_size;          uint32 rc4_key_size;
         uint8 inr[SEC_MODULUS_SIZE];  
675    
676          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))          memset(modulus, 0, sizeof(modulus));
677            memset(exponent, 0, sizeof(exponent));
678            if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, modulus, exponent))
679          {          {
680                  DEBUG(("Failed to parse crypt info\n"));                  DEBUG(("Failed to parse crypt info\n"));
681                  return;                  return;
682          }          }
   
683          DEBUG(("Generating client random\n"));          DEBUG(("Generating client random\n"));
         /* Generate a client random, and hence determine encryption keys */  
         /* This is what the MS client do: */  
         memset(inr, 0, SEC_RANDOM_SIZE);  
         /*  *ARIGL!* Plaintext attack, anyone?  
            I tried doing:  
            generate_random(inr);  
            ..but that generates connection errors now and then (yes,  
            "now and then". Something like 0 to 3 attempts needed before a  
            successful connection. Nice. Not!  
          */  
   
684          generate_random(client_random);          generate_random(client_random);
685          if (NULL != server_public_key)          sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE,
686          {                       /* Which means we should use                          server_public_key_len, modulus, exponent);
                                    RDP5-style encryption */  
   
                 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);  
                 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);  
   
                 RSA_public_encrypt(SEC_MODULUS_SIZE,  
                                    inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);  
   
                 reverse(sec_crypted_random, SEC_MODULUS_SIZE);  
   
         }  
         else  
         {                       /* RDP4-style encryption */  
                 sec_rsa_encrypt(sec_crypted_random,  
                                 client_random, SEC_RANDOM_SIZE, modulus, exponent);  
         }  
687          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
688  }  }
689    
# Line 764  sec_process_srv_info(STREAM s) Line 697  sec_process_srv_info(STREAM s)
697          if (1 == g_server_rdp_version)          if (1 == g_server_rdp_version)
698          {          {
699                  g_use_rdp5 = 0;                  g_use_rdp5 = 0;
700                  g_server_bpp = 8;                  g_server_depth = 8;
701          }          }
702  }  }
703    
# Line 853  sec_recv(uint8 * rdpver) Line 786  sec_recv(uint8 * rdpver)
786                                  licence_process(s);                                  licence_process(s);
787                                  continue;                                  continue;
788                          }                          }
789    
790                            if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
791                            {
792                                    uint8 swapbyte;
793    
794                                    in_uint8s(s, 8);        /* signature */
795                                    sec_decrypt(s->p, s->end - s->p);
796    
797                                    /* Check for a redirect packet, starts with 00 04 */
798                                    if (s->p[0] == 0 && s->p[1] == 4)
799                                    {
800                                            /* for some reason the PDU and the length seem to be swapped.
801                                               This isn't good, but we're going to do a byte for byte
802                                               swap.  So the first foure value appear as: 00 04 XX YY,
803                                               where XX YY is the little endian length. We're going to
804                                               use 04 00 as the PDU type, so after our swap this will look
805                                               like: XX YY 04 00 */
806                                            swapbyte = s->p[0];
807                                            s->p[0] = s->p[2];
808                                            s->p[2] = swapbyte;
809    
810                                            swapbyte = s->p[1];
811                                            s->p[1] = s->p[3];
812                                            s->p[3] = swapbyte;
813    
814                                            swapbyte = s->p[2];
815                                            s->p[2] = s->p[3];
816                                            s->p[3] = swapbyte;
817                                    }
818    #ifdef WITH_DEBUG
819                                    /* warning!  this debug statement will show passwords in the clear! */
820                                    hexdump(s->p, s->end - s->p);
821    #endif
822                            }
823    
824                  }                  }
825    
826                  if (channel != MCS_GLOBAL_CHANNEL)                  if (channel != MCS_GLOBAL_CHANNEL)
# Line 869  sec_recv(uint8 * rdpver) Line 837  sec_recv(uint8 * rdpver)
837  }  }
838    
839  /* Establish a secure connection */  /* Establish a secure connection */
840  BOOL  RD_BOOL
841  sec_connect(char *server, char *username)  sec_connect(char *server, char *username)
842  {  {
843          struct stream mcs_data;          struct stream mcs_data;
# Line 889  sec_connect(char *server, char *username Line 857  sec_connect(char *server, char *username
857          return True;          return True;
858  }  }
859    
860    /* Establish a secure connection */
861    RD_BOOL
862    sec_reconnect(char *server)
863    {
864            struct stream mcs_data;
865    
866            /* We exchange some RDP data during the MCS-Connect */
867            mcs_data.size = 512;
868            mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
869            sec_out_mcs_data(&mcs_data);
870    
871            if (!mcs_reconnect(server, &mcs_data))
872                    return False;
873    
874            /*      sec_process_mcs_data(&mcs_data); */
875            if (g_encryption)
876                    sec_establish_key();
877            xfree(mcs_data.data);
878            return True;
879    }
880    
881  /* Disconnect a connection */  /* Disconnect a connection */
882  void  void
883  sec_disconnect(void)  sec_disconnect(void)
884  {  {
885          mcs_disconnect();          mcs_disconnect();
886  }  }
887    
888    /* reset the state of the sec layer */
889    void
890    sec_reset_state(void)
891    {
892            g_server_rdp_version = 0;
893            sec_encrypt_use_count = 0;
894            sec_decrypt_use_count = 0;
895            mcs_reset_state();
896    }

Legend:
Removed from v.966  
changed lines
  Added in v.1374

  ViewVC Help
Powered by ViewVC 1.1.26