/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/secure.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1237 by matthewc, Wed Jun 14 08:26:00 2006 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;
# Line 33  extern unsigned int g_keylayout; Line 28  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_depth;  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;
 static RSA *server_public_key;  
43  static uint32 server_public_key_len;  static uint32 server_public_key_len;
44    
45  static uint8 sec_sign_key[16];  static uint8 sec_sign_key[16];
# Line 80  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 108  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 203  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 229  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 259  sec_encrypt(uint8 * data, int length) Line 253  sec_encrypt(uint8 * data, int length)
253          if (sec_encrypt_use_count == 4096)          if (sec_encrypt_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                  sec_encrypt_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          sec_encrypt_use_count++;          sec_encrypt_use_count++;
262  }  }
263    
# Line 274  sec_decrypt(uint8 * data, int length) Line 268  sec_decrypt(uint8 * data, int length)
268          if (sec_decrypt_use_count == 4096)          if (sec_decrypt_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                  sec_decrypt_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          sec_decrypt_use_count++;          sec_decrypt_use_count++;
277  }  }
278    
 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;  
         }  
 }  
   
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, uint32 modulus_size, 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_MAX_MODULUS_SIZE];  
         int outlen;  
   
         reverse(modulus, 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, 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 < modulus_size)  
                 memset(out + outlen, 0, 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 355  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 374  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 393  sec_establish_key(void) Line 353  sec_establish_key(void)
353          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
354          STREAM s;          STREAM s;
355    
356          s = sec_init(flags, length+4);          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, server_public_key_len);          out_uint8p(s, sec_crypted_random, server_public_key_len);
# Line 495  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 509  sec_parse_public_key(STREAM s, uint8 ** Line 469  sec_parse_public_key(STREAM s, uint8 **
469    
470          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
471          modulus_len -= SEC_PADDING_SIZE;          modulus_len -= SEC_PADDING_SIZE;
472          if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))          if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
473          {          {
474                  error("Bad server public key size (%u bits)\n", modulus_len*8);                  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, modulus_len);          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;          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                  ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);          sig_len = len - 8;
500                  cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);          in_uint8a(s, signature, sig_len);
501          }          return ssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, server_public_key_len,
502          epk = X509_get_pubkey(cert);                            signature, sig_len);
         if (NULL == epk)  
         {  
                 error("Failed to extract public key from certificate\n");  
                 return False;  
         }  
   
         server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);  
         EVP_PKEY_free(epk);  
   
         server_public_key_len = RSA_size(server_public_key);  
         if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))  
         {  
                 error("Bad server public key size (%u bits)\n", server_public_key_len*8);  
                 return False;  
         }  
   
         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 614  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 633  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 658  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 670  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.  
                  */  
   
                 X509_free(cacert);  
   
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                          X509_free(server_cert);                          ssl_cert_free(server_cert);
643                          return False;                          return False;
644                  }                  }
645                  X509_free(server_cert);                  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;
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 725  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;
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"));
684          generate_random(client_random);          generate_random(client_random);
685            sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE,
686          if (NULL != server_public_key)                          server_public_key_len, modulus, exponent);
         {                       /* Which means we should use  
                                    RDP5-style encryption */  
                 uint8 inr[SEC_MAX_MODULUS_SIZE];  
                 uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;  
   
                 /* This is what the MS client do: */  
                 memset(inr, 0, padding_len);  
                 /*  *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!  
                  */  
                 memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);  
                 reverse(inr + padding_len, SEC_RANDOM_SIZE);  
   
                 RSA_public_encrypt(server_public_key_len,  
                                    inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);  
   
                 reverse(sec_crypted_random, server_public_key_len);  
   
                 RSA_free(server_public_key);  
                 server_public_key = NULL;  
         }  
         else  
         {                       /* RDP4-style encryption */  
                 sec_rsa_encrypt(sec_crypted_random,  
                                 client_random, SEC_RANDOM_SIZE, server_public_key_len, 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 922  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 943  sec_connect(char *server, char *username Line 858  sec_connect(char *server, char *username
858  }  }
859    
860  /* Establish a secure connection */  /* Establish a secure connection */
861  BOOL  RD_BOOL
862  sec_reconnect(char *server)  sec_reconnect(char *server)
863  {  {
864          struct stream mcs_data;          struct stream mcs_data;

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

  ViewVC Help
Powered by ViewVC 1.1.26