/[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 28 by matty, Wed Jun 20 13:54:48 2001 UTC revision 352 by forsberg, Thu Mar 27 13:29:36 2003 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-2000     Copyright (C) Matthew Chapman 1999-2002
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    
23    #ifdef WITH_OPENSSL
24    #include <openssl/rc4.h>
25    #include <openssl/md5.h>
26    #include <openssl/sha.h>
27    #include <openssl/bn.h>
28    #include <openssl/x509v3.h>
29    #else
30  #include "crypto/rc4.h"  #include "crypto/rc4.h"
31  #include "crypto/md5.h"  #include "crypto/md5.h"
32  #include "crypto/sha.h"  #include "crypto/sha.h"
33  #include "crypto/arith.h"  #include "crypto/bn.h"
34    #endif
35    
36  extern char hostname[16];  extern char hostname[16];
37  extern int width;  extern int width;
38  extern int height;  extern int height;
39  extern int keylayout;  extern int keylayout;
40  extern BOOL use_encryption;  extern BOOL encryption;
41  extern BOOL licence_issued;  extern BOOL licence_issued;
42    extern BOOL use_rdp5;
43    extern int server_bpp;
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[8];  static uint8 sec_sign_key[16];
51  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
52  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
53  static uint8 sec_decrypt_update_key[8];  static uint8 sec_decrypt_update_key[16];
54  static uint8 sec_encrypt_update_key[8];  static uint8 sec_encrypt_update_key[16];
55  static uint8 sec_crypted_random[64];  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
56    
57    uint16 server_rdp_version = 0;
58    
59  /*  /*
60   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * General purpose 48-byte transformation, using two 32-byte salts (generally,
# Line 48  static uint8 sec_crypted_random[64]; Line 62  static uint8 sec_crypted_random[64];
62   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
63   */   */
64  void  void
65  sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)  sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
66  {  {
67          uint8 shasig[20];          uint8 shasig[20];
68          uint8 pad[4];          uint8 pad[4];
# Line 79  sec_hash_48(uint8 *out, uint8 *in, uint8 Line 93  sec_hash_48(uint8 *out, uint8 *in, uint8
93   * only using a single round of MD5.   * only using a single round of MD5.
94   */   */
95  void  void
96  sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
97  {  {
98          MD5_CTX md5;          MD5_CTX md5;
99    
# Line 92  sec_hash_16(uint8 *out, uint8 *in, uint8 Line 106  sec_hash_16(uint8 *out, uint8 *in, uint8
106    
107  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
108  static void  static void
109  sec_make_40bit(uint8 *key)  sec_make_40bit(uint8 * key)
110  {  {
111          key[0] = 0xd1;          key[0] = 0xd1;
112          key[1] = 0x26;          key[1] = 0x26;
# Line 101  sec_make_40bit(uint8 *key) Line 115  sec_make_40bit(uint8 *key)
115    
116  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate a session key and RC4 keys, given client and server randoms */
117  static void  static void
118  sec_generate_keys(uint8 *client_key, uint8 *server_key, int rc4_key_size)  sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
119  {  {
120          uint8 session_key[48];          uint8 session_key[48];
121          uint8 temp_hash[48];          uint8 temp_hash[48];
# Line 115  sec_generate_keys(uint8 *client_key, uin Line 129  sec_generate_keys(uint8 *client_key, uin
129          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(temp_hash, input, client_key, server_key, 65);
130          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
131    
132          /* Store first 8 bytes of session key, for generating signatures */          /* Store first 16 bytes of session key, for generating signatures */
133          memcpy(sec_sign_key, session_key, 8);          memcpy(sec_sign_key, session_key, 16);
134    
135          /* Generate RC4 keys */          /* Generate RC4 keys */
136          sec_hash_16(sec_decrypt_key, &session_key[16], client_key,          sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
137                      server_key);          sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
         sec_hash_16(sec_encrypt_key, &session_key[32], client_key,  
                     server_key);  
138    
139          if (rc4_key_size == 1)          if (rc4_key_size == 1)
140          {          {
141                  DEBUG("40-bit encryption enabled\n");                  DEBUG(("40-bit encryption enabled\n"));
142                  sec_make_40bit(sec_sign_key);                  sec_make_40bit(sec_sign_key);
143                  sec_make_40bit(sec_decrypt_key);                  sec_make_40bit(sec_decrypt_key);
144                  sec_make_40bit(sec_encrypt_key);                  sec_make_40bit(sec_encrypt_key);
# Line 134  sec_generate_keys(uint8 *client_key, uin Line 146  sec_generate_keys(uint8 *client_key, uin
146          }          }
147          else          else
148          {          {
149                  DEBUG("128-bit encryption enabled\n");                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
150                  rc4_key_len = 16;                  rc4_key_len = 16;
151          }          }
152    
153          /* Store first 8 bytes of RC4 keys as update keys */          /* Save initial RC4 keys as update keys */
154          memcpy(sec_decrypt_update_key, sec_decrypt_key, 8);          memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
155          memcpy(sec_encrypt_update_key, sec_encrypt_key, 8);          memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
156    
157          /* Initialise RC4 state arrays */          /* Initialise RC4 state arrays */
158          RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);          RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
# Line 163  static uint8 pad_92[48] = { Line 175  static uint8 pad_92[48] = {
175    
176  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
177  void  void
178  buf_out_uint32(uint8 *buffer, uint32 value)  buf_out_uint32(uint8 * buffer, uint32 value)
179  {  {
180          buffer[0] = (value) & 0xff;          buffer[0] = (value) & 0xff;
181          buffer[1] = (value >> 8) & 0xff;          buffer[1] = (value >> 8) & 0xff;
# Line 173  buf_out_uint32(uint8 *buffer, uint32 val Line 185  buf_out_uint32(uint8 *buffer, uint32 val
185    
186  /* Generate a signature hash, using a combination of SHA1 and MD5 */  /* Generate a signature hash, using a combination of SHA1 and MD5 */
187  void  void
188  sec_sign(uint8 *signature, uint8 *session_key, int length,  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
          uint8 *data, int datalen)  
189  {  {
190          uint8 shasig[20];          uint8 shasig[20];
191          uint8 md5sig[16];          uint8 md5sig[16];
# Line 185  sec_sign(uint8 *signature, uint8 *sessio Line 196  sec_sign(uint8 *signature, uint8 *sessio
196          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
197    
198          SHA1_Init(&sha);          SHA1_Init(&sha);
199          SHA1_Update(&sha, session_key, length);          SHA1_Update(&sha, session_key, keylen);
200          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
201          SHA1_Update(&sha, lenhdr, 4);          SHA1_Update(&sha, lenhdr, 4);
202          SHA1_Update(&sha, data, datalen);          SHA1_Update(&sha, data, datalen);
203          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
204    
205          MD5_Init(&md5);          MD5_Init(&md5);
206          MD5_Update(&md5, session_key, length);          MD5_Update(&md5, session_key, keylen);
207          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
208          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
209          MD5_Final(md5sig, &md5);          MD5_Final(md5sig, &md5);
210    
211          memcpy(signature, md5sig, length);          memcpy(signature, md5sig, siglen);
212  }  }
213    
214  /* Update an encryption key - similar to the signing process */  /* Update an encryption key - similar to the signing process */
215  static void  static void
216  sec_update(uint8 *key, uint8 *update_key)  sec_update(uint8 * key, uint8 * update_key)
217  {  {
218          uint8 shasig[20];          uint8 shasig[20];
219          SHA_CTX sha;          SHA_CTX sha;
# Line 210  sec_update(uint8 *key, uint8 *update_key Line 221  sec_update(uint8 *key, uint8 *update_key
221          RC4_KEY update;          RC4_KEY update;
222    
223          SHA1_Init(&sha);          SHA1_Init(&sha);
224          SHA1_Update(&sha, update_key, 8);          SHA1_Update(&sha, update_key, rc4_key_len);
225          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
226          SHA1_Update(&sha, key, 8);          SHA1_Update(&sha, key, rc4_key_len);
227          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
228    
229          MD5_Init(&md5);          MD5_Init(&md5);
230          MD5_Update(&md5, update_key, 8);          MD5_Update(&md5, update_key, rc4_key_len);
231          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
232          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
233          MD5_Final(key, &md5);          MD5_Final(key, &md5);
# Line 230  sec_update(uint8 *key, uint8 *update_key Line 241  sec_update(uint8 *key, uint8 *update_key
241    
242  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
243  static void  static void
244  sec_encrypt(uint8 *data, int length)  sec_encrypt(uint8 * data, int length)
245  {  {
246          static int use_count;          static int use_count;
247    
# Line 246  sec_encrypt(uint8 *data, int length) Line 257  sec_encrypt(uint8 *data, int length)
257  }  }
258    
259  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
260  static void  void
261  sec_decrypt(uint8 *data, int length)  sec_decrypt(uint8 * data, int length)
262  {  {
263          static int use_count;          static int use_count;
264    
# Line 262  sec_decrypt(uint8 *data, int length) Line 273  sec_decrypt(uint8 *data, int length)
273          use_count++;          use_count++;
274  }  }
275    
 /* Read in a NUMBER from a buffer */  
 static void  
 sec_read_number(NUMBER * num, uint8 *buffer, int len)  
 {  
         INT *data = num->n_part;  
         int i, j;  
   
         for (i = 0, j = 0; j < len; i++, j += 2)  
                 data[i] = buffer[j] | (buffer[j + 1] << 8);  
   
         num->n_len = i;  
 }  
   
 /* Write a NUMBER to a buffer */  
276  static void  static void
277  sec_write_number(NUMBER * num, uint8 *buffer, int len)  reverse(uint8 * p, int len)
278  {  {
         INT *data = num->n_part;  
279          int i, j;          int i, j;
280            uint8 temp;
281    
282          for (i = 0, j = 0; j < len; i++, j += 2)          for (i = 0, j = len - 1; i < j; i++, j--)
283          {          {
284                  buffer[j] = data[i] & 0xff;                  temp = p[i];
285                  buffer[j + 1] = data[i] >> 8;                  p[i] = p[j];
286                    p[j] = temp;
287          }          }
288  }  }
289    
290  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
291  static void  static void
292  sec_rsa_encrypt(uint8 *out, uint8 *in, int len,  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
                 uint8 *modulus, uint8 *exponent)  
293  {  {
294          NUMBER data, key;          BN_CTX *ctx;
295            BIGNUM mod, exp, x, y;
296          /* Set modulus for arithmetic */          uint8 inr[SEC_MODULUS_SIZE];
297          sec_read_number(&key, modulus, SEC_MODULUS_SIZE);          int outlen;
298          m_init(&key, NULL);  
299            reverse(modulus, SEC_MODULUS_SIZE);
300          /* Exponentiate */          reverse(exponent, SEC_EXPONENT_SIZE);
301          sec_read_number(&data, in, len);          memcpy(inr, in, len);
302          sec_read_number(&key, exponent, SEC_EXPONENT_SIZE);          reverse(inr, len);
303          m_exp(&data, &key, &data);  
304          sec_write_number(&data, out, SEC_MODULUS_SIZE);          ctx = BN_CTX_new();
305            BN_init(&mod);
306            BN_init(&exp);
307            BN_init(&x);
308            BN_init(&y);
309    
310            BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
311            BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
312            BN_bin2bn(inr, len, &x);
313            BN_mod_exp(&y, &x, &exp, &mod, ctx);
314            outlen = BN_bn2bin(&y, out);
315            reverse(out, outlen);
316            if (outlen < SEC_MODULUS_SIZE)
317                    memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
318    
319            BN_free(&y);
320            BN_clear_free(&x);
321            BN_free(&exp);
322            BN_free(&mod);
323            BN_CTX_free(ctx);
324  }  }
325    
326  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 339  sec_send(STREAM s, uint32 flags) Line 355  sec_send(STREAM s, uint32 flags)
355                  flags &= ~SEC_ENCRYPT;                  flags &= ~SEC_ENCRYPT;
356                  datalen = s->end - s->p - 8;                  datalen = s->end - s->p - 8;
357    
358  #if RDP_DEBUG  #if WITH_DEBUG
359                  DEBUG("Sending encrypted packet:\n");                  DEBUG(("Sending encrypted packet:\n"));
360                  hexdump(s->p + 8, datalen);                  hexdump(s->p + 8, datalen);
361  #endif  #endif
362    
363                  sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);                  sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
364                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
365          }          }
366    
# Line 353  sec_send(STREAM s, uint32 flags) Line 369  sec_send(STREAM s, uint32 flags)
369    
370  /* Transfer the client random to the server */  /* Transfer the client random to the server */
371  static void  static void
372  sec_establish_key()  sec_establish_key(void)
373  {  {
374          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
375          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
# Line 374  static void Line 390  static void
390  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
391  {  {
392          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(hostname);
393            int length = 158 + 76 + 12 + 4 + 20;
394    
395            if (hostlen > 30)
396                    hostlen = 30;
397    
398          out_uint16_be(s, 5);    /* unknown */          out_uint16_be(s, 5);    /* unknown */
399          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
400          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
401          out_uint16_be(s, 1);          out_uint16_be(s, 1);
402    
403          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
404    
405          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
406          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 389  sec_out_mcs_data(STREAM s) Line 409  sec_out_mcs_data(STREAM s)
409          out_uint8(s, 0);          out_uint8(s, 0);
410    
411          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */
412          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
413    
414          /* Client information */          /* Client information */
415          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
416          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
417          out_uint16_le(s, 1);          out_uint16_le(s, use_rdp5 ? 4 : 1);     /* RDP version. 1 == RDP4, 4 == RDP5. */
418          out_uint16_le(s, 8);          out_uint16_le(s, 8);
419          out_uint16_le(s, width);          out_uint16_le(s, width);
420          out_uint16_le(s, height);          out_uint16_le(s, height);
421          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
422          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
423          out_uint32_le(s, keylayout);          out_uint32_le(s, keylayout);
424          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
425    
426          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
427          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, hostname, hostlen);
# Line 412  sec_out_mcs_data(STREAM s) Line 432  sec_out_mcs_data(STREAM s)
432          out_uint32_le(s, 12);          out_uint32_le(s, 12);
433          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
434    
435          out_uint16(s, 0xca01);          switch (server_bpp)
436          out_uint16(s, 0);          {
437                    case 8:
438                            out_uint16_le(s, 0xca01);
439                            break;
440                    case 15:
441                            out_uint16_le(s, 0xca02);
442                            break;
443                    case 16:
444                            out_uint16_le(s, 0xca03);
445                            break;
446                    case 24:
447                            out_uint16_le(s, 0xca04);
448                            break;
449            }
450            out_uint16(s, 1);
451    
452            out_uint32(s, 0);
453            out_uint32_le(s, 0x070008);
454            out_uint32_le(s, 1);
455            out_uint8s(s, 64);      /* End of client info */
456    
457            out_uint16_le(s, SEC_TAG_CLI_4);
458            out_uint16_le(s, 12);
459            out_uint32_le(s, 9);
460            out_uint32_le(s, 0);
461    
462          /* Client encryption settings */          /* Client encryption settings */
463          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
464          out_uint16(s, 8);       /* length */          out_uint16_le(s, 12);   /* length */
465          out_uint32_le(s, use_encryption ? 1 : 0);       /* encryption enabled */          out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
466            out_uint32_le(s, 0);    /* Unknown */
467    
468            out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
469            out_uint16_le(s, 20);   /* length */
470            out_uint32_le(s, 1);    /* number of virtual channels */
471            out_uint8p(s, "cliprdr", 8);    /* name padded to 8(?) */
472            out_uint16(s, 0);
473            out_uint16_le(s, 0xc0a0);       /* Flags. Rumours tell this is documented in MSDN. */
474    
475          s_mark_end(s);          s_mark_end(s);
476  }  }
477    
478  /* Parse a public key structure */  /* Parse a public key structure */
479  static BOOL  static BOOL
480  sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
481  {  {
482          uint32 magic, modulus_len;          uint32 magic, modulus_len;
483    
484          in_uint32_le(s, magic);          in_uint32_le(s, magic);
485          if (magic != SEC_RSA_MAGIC)          if (magic != SEC_RSA_MAGIC)
486          {          {
487                  ERROR("RSA magic 0x%x\n", magic);                  error("RSA magic 0x%x\n", magic);
488                  return False;                  return False;
489          }          }
490    
491          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
492          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
493          {          {
494                  ERROR("modulus len 0x%x\n", modulus_len);                  error("modulus len 0x%x\n", modulus_len);
495                  return False;                  return False;
496          }          }
497    
# Line 450  sec_parse_public_key(STREAM s, uint8 **m Line 503  sec_parse_public_key(STREAM s, uint8 **m
503          return s_check(s);          return s_check(s);
504  }  }
505    
506    static BOOL
507    sec_parse_x509_key(X509 * cert)
508    {
509            EVP_PKEY *epk = NULL;
510            /* By some reason, Microsoft sets the OID of the Public RSA key to
511               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
512    
513               Kudos to Richard Levitte for the following (. intiutive .)
514               lines of code that resets the OID and let's us extract the key. */
515            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
516            {
517                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
518                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
519            }
520            epk = X509_get_pubkey(cert);
521            if (NULL == epk)
522            {
523                    error("Failed to extract public key from certificate\n");
524                    return False;
525            }
526    
527            server_public_key = (RSA *) epk->pkey.ptr;
528    
529            return True;
530    }
531    
532    
533  /* Parse a crypto information structure */  /* Parse a crypto information structure */
534  static BOOL  static BOOL
535  sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
536                       uint8 **server_random, uint8 **modulus, uint8 **exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
537  {  {
538          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
539            uint32 cacert_len, cert_len;
540            X509 *cacert, *server_cert;
541          uint16 tag, length;          uint16 tag, length;
542          uint8 *next_tag, *end;          uint8 *next_tag, *end;
543    
544          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 */
545          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
546            if (crypt_level == 0)   /* no encryption */
547                    return False;
548          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
549          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
550    
551          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
552          {          {
553                  ERROR("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
554                  return False;                  return False;
555          }          }
556    
# Line 477  sec_parse_crypt_info(STREAM s, uint32 *r Line 561  sec_parse_crypt_info(STREAM s, uint32 *r
561          if (end > s->end)          if (end > s->end)
562                  return False;                  return False;
563    
564          in_uint8s(s, 12);       /* unknown */          if (!use_rdp5 || 1 == server_rdp_version)
565            {
566                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
567                    in_uint8s(s, 12);       /* unknown */
568    
569          while (s->p < end)                  while (s->p < end)
570                    {
571                            in_uint16_le(s, tag);
572                            in_uint16_le(s, length);
573    
574                            next_tag = s->p + length;
575    
576                            switch (tag)
577                            {
578                                    case SEC_TAG_PUBKEY:
579                                            if (!sec_parse_public_key(s, modulus, exponent))
580                                                    return False;
581                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
582    
583                                            break;
584    
585                                    case SEC_TAG_KEYSIG:
586                                            /* Is this a Microsoft key that we just got? */
587                                            /* Care factor: zero! */
588                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
589                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
590                                            break;
591    
592                                    default:
593                                            unimpl("crypt tag 0x%x\n", tag);
594                            }
595    
596                            s->p = next_tag;
597                    }
598            }
599            else if (4 == server_rdp_version)
600          {          {
601                  in_uint16_le(s, tag);                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
602                  in_uint16_le(s, length);                  in_uint8s(s, 8);        /* Unknown */
603    
604                  next_tag = s->p + length;                  /* Do da funky X.509 stuffy
605    
606                  switch (tag)                     "How did I find out about this?  I looked up and saw a
607                       bright light and when I came to I had a scar on my forehead
608                       and knew about X.500"
609                       - Peter Gutman in a early version of
610                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
611                     */
612    
613                    in_uint32_le(s, cacert_len);
614                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
615                    /* Note: We don't need to move s->p here - d2i_X509 is
616                       "kind" enough to do it for us */
617                    if (NULL == cacert)
618                  {                  {
619                          case SEC_TAG_PUBKEY:                          error("Couldn't load CA Certificate from server\n");
620                                  if (!sec_parse_public_key                          return False;
621                                      (s, modulus, exponent))                  }
                                         return False;  
622    
623                                  break;                  /* Currently, we don't use the CA Certificate.
624                       FIXME:
625                       *) Verify the server certificate (server_cert) with the
626                       CA certificate.
627                       *) Store the CA Certificate with the hostname of the
628                       server we are connecting to as key, and compare it
629                       when we connect the next time, in order to prevent
630                       MITM-attacks.
631                     */
632    
633                    in_uint32_le(s, cert_len);
634                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
635                    if (NULL == server_cert)
636                    {
637                            error("Couldn't load Certificate from server\n");
638                            return False;
639                    }
640    
641                          case SEC_TAG_KEYSIG:                  in_uint8s(s, 16);       /* Padding */
                                 /* Is this a Microsoft key that we just got? */  
                                 /* Care factor: zero! */  
                                 break;  
642    
643                          default:                  /* Note: Verifying the server certificate must be done here,
644                                  NOTIMP("crypt tag 0x%x\n", tag);                     before sec_parse_public_key since we'll have to apply
645                  }                     serious violence to the key after this */
646    
647                  s->p = next_tag;                  if (!sec_parse_x509_key(server_cert))
648                    {
649                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
650                            return False;
651                    }
652                    return True;    /* There's some garbage here we don't care about */
653            }
654            else
655            {
656                    error("Unknown Server RDP version %d", server_rdp_version);
657                    return False;
658          }          }
   
659          return s_check_end(s);          return s_check_end(s);
660  }  }
661    
# Line 517  sec_process_crypt_info(STREAM s) Line 666  sec_process_crypt_info(STREAM s)
666          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
667          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
668          uint32 rc4_key_size;          uint32 rc4_key_size;
669            uint8 inr[SEC_MODULUS_SIZE];
670    
671          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
672                                    &modulus, &exponent))          {
673                    DEBUG(("Failed to parse crypt info\n"));
674                  return;                  return;
675            }
676    
677            DEBUG(("Generating client random\n"));
678          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
679            generate_random(inr);
680            // This is what the MS client do:
681            //      memset(inr, 0, SEC_RANDOM_SIZE);
682            // *ARIGL!*
683          generate_random(client_random);          generate_random(client_random);
684          sec_rsa_encrypt(sec_crypted_random, client_random,          if (NULL != server_public_key)
685                          SEC_RANDOM_SIZE, modulus, exponent);          {                       /* Which means we should use
686                                       RDP5-style encryption */
687    
688                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
689                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
690    
691                    RSA_public_encrypt(SEC_MODULUS_SIZE,
692                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
693    
694                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
695    
696            }
697            else
698            {                       /* RDP4-style encryption */
699                    sec_rsa_encrypt(sec_crypted_random,
700                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
701            }
702          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
703  }  }
704    
705  /* Process connect response data blob */  
706    /* Process SRV_INFO, find RDP version supported by server */
707  static void  static void
708    sec_process_srv_info(STREAM s)
709    {
710            in_uint16_le(s, server_rdp_version);
711            DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
712    }
713    
714    
715    /* Process connect response data blob */
716    void
717  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
718  {  {
719          uint16 tag, length;          uint16 tag, length;
720          uint8 *next_tag;          uint8 *next_tag;
721            uint8 len;
722    
723          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */
724            in_uint8(s, len);
725            if (len & 0x80)
726                    in_uint8(s, len);
727    
728          while (s->p < s->end)          while (s->p < s->end)
729          {          {
# Line 551  sec_process_mcs_data(STREAM s) Line 738  sec_process_mcs_data(STREAM s)
738                  switch (tag)                  switch (tag)
739                  {                  {
740                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
741                                    sec_process_srv_info(s);
742                                    break;
743    
744                          case SEC_TAG_SRV_3:                          case SEC_TAG_SRV_3:
745                                  break;                                  break;
746    
# Line 559  sec_process_mcs_data(STREAM s) Line 749  sec_process_mcs_data(STREAM s)
749                                  break;                                  break;
750    
751                          default:                          default:
752                                  NOTIMP("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
753                  }                  }
754    
755                  s->p = next_tag;                  s->p = next_tag;
# Line 568  sec_process_mcs_data(STREAM s) Line 758  sec_process_mcs_data(STREAM s)
758    
759  /* Receive secure transport packet */  /* Receive secure transport packet */
760  STREAM  STREAM
761  sec_recv()  sec_recv(void)
762  {  {
763          uint32 sec_flags;          uint32 sec_flags;
764            uint16 channel;
765          STREAM s;          STREAM s;
766    
767          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
768          {          {
769                  if (use_encryption || !licence_issued)                  if (encryption || !licence_issued)
770                  {                  {
771                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
772    
# Line 592  sec_recv() Line 783  sec_recv()
783                          }                          }
784                  }                  }
785    
786                  return s;                  if (MCS_GLOBAL_CHANNEL == channel)
787                    {
788                            return s;
789                    }
790                    else
791                            rdp5_process_channel(s, channel);
792    
793          }          }
794    
795          return NULL;          return NULL;
# Line 600  sec_recv() Line 797  sec_recv()
797    
798  /* Establish a secure connection */  /* Establish a secure connection */
799  BOOL  BOOL
800  sec_connect(char *server)  sec_connect(char *server, char *username)
801  {  {
802          struct stream mcs_data;          struct stream mcs_data;
803    
# Line 609  sec_connect(char *server) Line 806  sec_connect(char *server)
806          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);
807          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
808    
809          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
810                  return False;                  return False;
811    
812          sec_process_mcs_data(&mcs_data);          //      sec_process_mcs_data(&mcs_data);
813          if (use_encryption)          if (encryption)
814                  sec_establish_key();                  sec_establish_key();
815            xfree(mcs_data.data);
816          return True;          return True;
817  }  }
818    
819  /* Disconnect a connection */  /* Disconnect a connection */
820  void  void
821  sec_disconnect()  sec_disconnect(void)
822  {  {
823          mcs_disconnect();          mcs_disconnect();
824  }  }

Legend:
Removed from v.28  
changed lines
  Added in v.352

  ViewVC Help
Powered by ViewVC 1.1.26