/[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 677 by n-ki, Mon Apr 26 13:48:39 2004 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 g_width;
38  extern int height;  extern int g_height;
39  extern int keylayout;  extern int keylayout;
40  extern BOOL use_encryption;  extern BOOL g_encryption;
41  extern BOOL licence_issued;  extern BOOL g_licence_issued;
42    extern BOOL g_use_rdp5;
43    extern BOOL g_console_session;
44    extern int g_server_bpp;
45    extern uint16 mcs_userid;
46    extern VCHANNEL g_channels[];
47    extern unsigned int g_num_channels;
48    
49  static int rc4_key_len;  static int rc4_key_len;
50  static RC4_KEY rc4_decrypt_key;  static RC4_KEY rc4_decrypt_key;
51  static RC4_KEY rc4_encrypt_key;  static RC4_KEY rc4_encrypt_key;
52    static RSA *server_public_key;
53    
54  static uint8 sec_sign_key[8];  static uint8 sec_sign_key[16];
55  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
56  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
57  static uint8 sec_decrypt_update_key[8];  static uint8 sec_decrypt_update_key[16];
58  static uint8 sec_encrypt_update_key[8];  static uint8 sec_encrypt_update_key[16];
59  static uint8 sec_crypted_random[64];  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
60    
61    uint16 g_server_rdp_version = 0;
62    
63  /*  /*
64   * 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 66  static uint8 sec_crypted_random[64];
66   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
67   */   */
68  void  void
69  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)
70  {  {
71          uint8 shasig[20];          uint8 shasig[20];
72          uint8 pad[4];          uint8 pad[4];
# Line 79  sec_hash_48(uint8 *out, uint8 *in, uint8 Line 97  sec_hash_48(uint8 *out, uint8 *in, uint8
97   * only using a single round of MD5.   * only using a single round of MD5.
98   */   */
99  void  void
100  sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
101  {  {
102          MD5_CTX md5;          MD5_CTX md5;
103    
# Line 92  sec_hash_16(uint8 *out, uint8 *in, uint8 Line 110  sec_hash_16(uint8 *out, uint8 *in, uint8
110    
111  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
112  static void  static void
113  sec_make_40bit(uint8 *key)  sec_make_40bit(uint8 * key)
114  {  {
115          key[0] = 0xd1;          key[0] = 0xd1;
116          key[1] = 0x26;          key[1] = 0x26;
# Line 101  sec_make_40bit(uint8 *key) Line 119  sec_make_40bit(uint8 *key)
119    
120  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate a session key and RC4 keys, given client and server randoms */
121  static void  static void
122  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)
123  {  {
124          uint8 session_key[48];          uint8 session_key[48];
125          uint8 temp_hash[48];          uint8 temp_hash[48];
# Line 115  sec_generate_keys(uint8 *client_key, uin Line 133  sec_generate_keys(uint8 *client_key, uin
133          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(temp_hash, input, client_key, server_key, 65);
134          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
135    
136          /* Store first 8 bytes of session key, for generating signatures */          /* Store first 16 bytes of session key, for generating signatures */
137          memcpy(sec_sign_key, session_key, 8);          memcpy(sec_sign_key, session_key, 16);
138    
139          /* Generate RC4 keys */          /* Generate RC4 keys */
140          sec_hash_16(sec_decrypt_key, &session_key[16], client_key,          sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
141                      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);  
142    
143          if (rc4_key_size == 1)          if (rc4_key_size == 1)
144          {          {
145                  DEBUG("40-bit encryption enabled\n");                  DEBUG(("40-bit encryption enabled\n"));
146                  sec_make_40bit(sec_sign_key);                  sec_make_40bit(sec_sign_key);
147                  sec_make_40bit(sec_decrypt_key);                  sec_make_40bit(sec_decrypt_key);
148                  sec_make_40bit(sec_encrypt_key);                  sec_make_40bit(sec_encrypt_key);
# Line 134  sec_generate_keys(uint8 *client_key, uin Line 150  sec_generate_keys(uint8 *client_key, uin
150          }          }
151          else          else
152          {          {
153                  DEBUG("128-bit encryption enabled\n");                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
154                  rc4_key_len = 16;                  rc4_key_len = 16;
155          }          }
156    
157          /* Store first 8 bytes of RC4 keys as update keys */          /* Save initial RC4 keys as update keys */
158          memcpy(sec_decrypt_update_key, sec_decrypt_key, 8);          memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
159          memcpy(sec_encrypt_update_key, sec_encrypt_key, 8);          memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
160    
161          /* Initialise RC4 state arrays */          /* Initialise RC4 state arrays */
162          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 179  static uint8 pad_92[48] = {
179    
180  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
181  void  void
182  buf_out_uint32(uint8 *buffer, uint32 value)  buf_out_uint32(uint8 * buffer, uint32 value)
183  {  {
184          buffer[0] = (value) & 0xff;          buffer[0] = (value) & 0xff;
185          buffer[1] = (value >> 8) & 0xff;          buffer[1] = (value >> 8) & 0xff;
# Line 173  buf_out_uint32(uint8 *buffer, uint32 val Line 189  buf_out_uint32(uint8 *buffer, uint32 val
189    
190  /* Generate a signature hash, using a combination of SHA1 and MD5 */  /* Generate a signature hash, using a combination of SHA1 and MD5 */
191  void  void
192  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)  
193  {  {
194          uint8 shasig[20];          uint8 shasig[20];
195          uint8 md5sig[16];          uint8 md5sig[16];
# Line 185  sec_sign(uint8 *signature, uint8 *sessio Line 200  sec_sign(uint8 *signature, uint8 *sessio
200          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
201    
202          SHA1_Init(&sha);          SHA1_Init(&sha);
203          SHA1_Update(&sha, session_key, length);          SHA1_Update(&sha, session_key, keylen);
204          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
205          SHA1_Update(&sha, lenhdr, 4);          SHA1_Update(&sha, lenhdr, 4);
206          SHA1_Update(&sha, data, datalen);          SHA1_Update(&sha, data, datalen);
207          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
208    
209          MD5_Init(&md5);          MD5_Init(&md5);
210          MD5_Update(&md5, session_key, length);          MD5_Update(&md5, session_key, keylen);
211          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
212          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
213          MD5_Final(md5sig, &md5);          MD5_Final(md5sig, &md5);
214    
215          memcpy(signature, md5sig, length);          memcpy(signature, md5sig, siglen);
216  }  }
217    
218  /* Update an encryption key - similar to the signing process */  /* Update an encryption key - similar to the signing process */
219  static void  static void
220  sec_update(uint8 *key, uint8 *update_key)  sec_update(uint8 * key, uint8 * update_key)
221  {  {
222          uint8 shasig[20];          uint8 shasig[20];
223          SHA_CTX sha;          SHA_CTX sha;
# Line 210  sec_update(uint8 *key, uint8 *update_key Line 225  sec_update(uint8 *key, uint8 *update_key
225          RC4_KEY update;          RC4_KEY update;
226    
227          SHA1_Init(&sha);          SHA1_Init(&sha);
228          SHA1_Update(&sha, update_key, 8);          SHA1_Update(&sha, update_key, rc4_key_len);
229          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
230          SHA1_Update(&sha, key, 8);          SHA1_Update(&sha, key, rc4_key_len);
231          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
232    
233          MD5_Init(&md5);          MD5_Init(&md5);
234          MD5_Update(&md5, update_key, 8);          MD5_Update(&md5, update_key, rc4_key_len);
235          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
236          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
237          MD5_Final(key, &md5);          MD5_Final(key, &md5);
# Line 230  sec_update(uint8 *key, uint8 *update_key Line 245  sec_update(uint8 *key, uint8 *update_key
245    
246  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
247  static void  static void
248  sec_encrypt(uint8 *data, int length)  sec_encrypt(uint8 * data, int length)
249  {  {
250          static int use_count;          static int use_count;
251    
# Line 246  sec_encrypt(uint8 *data, int length) Line 261  sec_encrypt(uint8 *data, int length)
261  }  }
262    
263  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
264  static void  void
265  sec_decrypt(uint8 *data, int length)  sec_decrypt(uint8 * data, int length)
266  {  {
267          static int use_count;          static int use_count;
268    
# Line 262  sec_decrypt(uint8 *data, int length) Line 277  sec_decrypt(uint8 *data, int length)
277          use_count++;          use_count++;
278  }  }
279    
 /* Read in a NUMBER from a buffer */  
280  static void  static void
281  sec_read_number(NUMBER * num, uint8 *buffer, int len)  reverse(uint8 * p, int len)
282  {  {
         INT *data = num->n_part;  
283          int i, j;          int i, j;
284            uint8 temp;
285    
286          for (i = 0, j = 0; j < len; i++, j += 2)          for (i = 0, j = len - 1; i < j; i++, j--)
                 data[i] = buffer[j] | (buffer[j + 1] << 8);  
   
         num->n_len = i;  
 }  
   
 /* Write a NUMBER to a buffer */  
 static void  
 sec_write_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)  
287          {          {
288                  buffer[j] = data[i] & 0xff;                  temp = p[i];
289                  buffer[j + 1] = data[i] >> 8;                  p[i] = p[j];
290                    p[j] = temp;
291          }          }
292  }  }
293    
294  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
295  static void  static void
296  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)  
297  {  {
298          NUMBER data, key;          BN_CTX *ctx;
299            BIGNUM mod, exp, x, y;
300          /* Set modulus for arithmetic */          uint8 inr[SEC_MODULUS_SIZE];
301          sec_read_number(&key, modulus, SEC_MODULUS_SIZE);          int outlen;
302          m_init(&key, NULL);  
303            reverse(modulus, SEC_MODULUS_SIZE);
304          /* Exponentiate */          reverse(exponent, SEC_EXPONENT_SIZE);
305          sec_read_number(&data, in, len);          memcpy(inr, in, len);
306          sec_read_number(&key, exponent, SEC_EXPONENT_SIZE);          reverse(inr, len);
307          m_exp(&data, &key, &data);  
308          sec_write_number(&data, out, SEC_MODULUS_SIZE);          ctx = BN_CTX_new();
309            BN_init(&mod);
310            BN_init(&exp);
311            BN_init(&x);
312            BN_init(&y);
313    
314            BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
315            BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
316            BN_bin2bn(inr, len, &x);
317            BN_mod_exp(&y, &x, &exp, &mod, ctx);
318            outlen = BN_bn2bin(&y, out);
319            reverse(out, outlen);
320            if (outlen < SEC_MODULUS_SIZE)
321                    memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
322    
323            BN_free(&y);
324            BN_clear_free(&x);
325            BN_free(&exp);
326            BN_free(&mod);
327            BN_CTX_free(ctx);
328  }  }
329    
330  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 314  sec_init(uint32 flags, int maxlen) Line 334  sec_init(uint32 flags, int maxlen)
334          int hdrlen;          int hdrlen;
335          STREAM s;          STREAM s;
336    
337          if (!licence_issued)          if (!g_licence_issued)
338                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
339          else          else
340                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
# Line 324  sec_init(uint32 flags, int maxlen) Line 344  sec_init(uint32 flags, int maxlen)
344          return s;          return s;
345  }  }
346    
347  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
348  void  void
349  sec_send(STREAM s, uint32 flags)  sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
350  {  {
351          int datalen;          int datalen;
352    
353          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
354          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
355                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
356    
357          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
# Line 339  sec_send(STREAM s, uint32 flags) Line 359  sec_send(STREAM s, uint32 flags)
359                  flags &= ~SEC_ENCRYPT;                  flags &= ~SEC_ENCRYPT;
360                  datalen = s->end - s->p - 8;                  datalen = s->end - s->p - 8;
361    
362  #if RDP_DEBUG  #if WITH_DEBUG
363                  DEBUG("Sending encrypted packet:\n");                  DEBUG(("Sending encrypted packet:\n"));
364                  hexdump(s->p + 8, datalen);                  hexdump(s->p + 8, datalen);
365  #endif  #endif
366    
367                  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);
368                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
369          }          }
370    
371          mcs_send(s);          mcs_send_to_channel(s, channel);
372    }
373    
374    /* Transmit secure transport packet */
375    
376    void
377    sec_send(STREAM s, uint32 flags)
378    {
379            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
380  }  }
381    
382    
383  /* Transfer the client random to the server */  /* Transfer the client random to the server */
384  static void  static void
385  sec_establish_key()  sec_establish_key(void)
386  {  {
387          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
388          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
# Line 374  static void Line 403  static void
403  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
404  {  {
405          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(hostname);
406            int length = 158 + 76 + 12 + 4;
407            unsigned int i;
408    
409            if (g_num_channels > 0)
410                    length += g_num_channels * 12 + 8;
411    
412          out_uint16_be(s, 5);    /* unknown */          if (hostlen > 30)
413                    hostlen = 30;
414    
415            /* Generic Conference Control (T.124) ConferenceCreateRequest */
416            out_uint16_be(s, 5);
417          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
418          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
419          out_uint16_be(s, 1);          out_uint16_be(s, 1);
420    
421          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
422    
423          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
424          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 388  sec_out_mcs_data(STREAM s) Line 426  sec_out_mcs_data(STREAM s)
426          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
427          out_uint8(s, 0);          out_uint8(s, 0);
428    
429          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
430          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
431    
432          /* Client information */          /* Client information */
433          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
434          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
435          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
436          out_uint16_le(s, 8);          out_uint16_le(s, 8);
437          out_uint16_le(s, width);          out_uint16_le(s, g_width);
438          out_uint16_le(s, height);          out_uint16_le(s, g_height);
439          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
440          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
441          out_uint32_le(s, keylayout);          out_uint32_le(s, keylayout);
442          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
443    
444          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
445          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, hostname, hostlen);
# Line 411  sec_out_mcs_data(STREAM s) Line 449  sec_out_mcs_data(STREAM s)
449          out_uint32(s, 0);          out_uint32(s, 0);
450          out_uint32_le(s, 12);          out_uint32_le(s, 12);
451          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
452            out_uint16_le(s, 0xca01);       /* colour depth? */
453            out_uint16_le(s, 1);
454    
455          out_uint16(s, 0xca01);          out_uint32(s, 0);
456          out_uint16(s, 0);          out_uint8(s, g_server_bpp);
457            out_uint16_le(s, 0x0700);
458            out_uint8(s, 0);
459            out_uint32_le(s, 1);
460            out_uint8s(s, 64);      /* End of client info */
461    
462            out_uint16_le(s, SEC_TAG_CLI_4);
463            out_uint16_le(s, 12);
464            out_uint32_le(s, g_console_session ? 0xb : 9);
465            out_uint32(s, 0);
466    
467          /* Client encryption settings */          /* Client encryption settings */
468          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
469          out_uint16(s, 8);       /* length */          out_uint16_le(s, 12);   /* length */
470          out_uint32_le(s, use_encryption ? 1 : 0);       /* encryption enabled */          out_uint32_le(s, g_encryption ? 0x3 : 0);       /* encryption supported, 128-bit supported */
471            out_uint32(s, 0);       /* Unknown */
472    
473            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
474            if (g_num_channels > 0)
475            {
476                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
477                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
478                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
479                    for (i = 0; i < g_num_channels; i++)
480                    {
481                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
482                            out_uint8a(s, g_channels[i].name, 8);
483                            out_uint32_be(s, g_channels[i].flags);
484                    }
485            }
486    
487          s_mark_end(s);          s_mark_end(s);
488  }  }
489    
490  /* Parse a public key structure */  /* Parse a public key structure */
491  static BOOL  static BOOL
492  sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
493  {  {
494          uint32 magic, modulus_len;          uint32 magic, modulus_len;
495    
496          in_uint32_le(s, magic);          in_uint32_le(s, magic);
497          if (magic != SEC_RSA_MAGIC)          if (magic != SEC_RSA_MAGIC)
498          {          {
499                  ERROR("RSA magic 0x%x\n", magic);                  error("RSA magic 0x%x\n", magic);
500                  return False;                  return False;
501          }          }
502    
503          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
504          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
505          {          {
506                  ERROR("modulus len 0x%x\n", modulus_len);                  error("modulus len 0x%x\n", modulus_len);
507                  return False;                  return False;
508          }          }
509    
# Line 450  sec_parse_public_key(STREAM s, uint8 **m Line 515  sec_parse_public_key(STREAM s, uint8 **m
515          return s_check(s);          return s_check(s);
516  }  }
517    
518    static BOOL
519    sec_parse_x509_key(X509 * cert)
520    {
521            EVP_PKEY *epk = NULL;
522            /* By some reason, Microsoft sets the OID of the Public RSA key to
523               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
524    
525               Kudos to Richard Levitte for the following (. intiutive .)
526               lines of code that resets the OID and let's us extract the key. */
527            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
528            {
529                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
530                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
531            }
532            epk = X509_get_pubkey(cert);
533            if (NULL == epk)
534            {
535                    error("Failed to extract public key from certificate\n");
536                    return False;
537            }
538    
539            server_public_key = (RSA *) epk->pkey.ptr;
540    
541            return True;
542    }
543    
544    
545  /* Parse a crypto information structure */  /* Parse a crypto information structure */
546  static BOOL  static BOOL
547  sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
548                       uint8 **server_random, uint8 **modulus, uint8 **exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
549  {  {
550          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
551            uint32 cacert_len, cert_len, flags;
552            X509 *cacert, *server_cert;
553          uint16 tag, length;          uint16 tag, length;
554          uint8 *next_tag, *end;          uint8 *next_tag, *end;
555    
556          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 */
557          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
558            if (crypt_level == 0)   /* no encryption */
559                    return False;
560          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
561          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
562    
563          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
564          {          {
565                  ERROR("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
566                  return False;                  return False;
567          }          }
568    
# Line 477  sec_parse_crypt_info(STREAM s, uint32 *r Line 573  sec_parse_crypt_info(STREAM s, uint32 *r
573          if (end > s->end)          if (end > s->end)
574                  return False;                  return False;
575    
576          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
577            if (flags & 1)
578            {
579                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
580                    in_uint8s(s, 8);        /* unknown */
581    
582                    while (s->p < end)
583                    {
584                            in_uint16_le(s, tag);
585                            in_uint16_le(s, length);
586    
587                            next_tag = s->p + length;
588    
589                            switch (tag)
590                            {
591                                    case SEC_TAG_PUBKEY:
592                                            if (!sec_parse_public_key(s, modulus, exponent))
593                                                    return False;
594                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
595    
596                                            break;
597    
598                                    case SEC_TAG_KEYSIG:
599                                            /* Is this a Microsoft key that we just got? */
600                                            /* Care factor: zero! */
601                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
602                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
603                                            break;
604    
605                                    default:
606                                            unimpl("crypt tag 0x%x\n", tag);
607                            }
608    
609          while (s->p < end)                          s->p = next_tag;
610                    }
611            }
612            else
613          {          {
614                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
615    
616                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
617                    in_uint32_le(s, certcount);     /* Number of certificates */
618    
619                  switch (tag)                  if (certcount < 2)
620                  {                  {
621                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
622                                  if (!sec_parse_public_key                          return False;
623                                      (s, modulus, exponent))                  }
                                         return False;  
624    
625                                  break;                  for (; certcount > 2; certcount--)
626                    {               /* ignore all the certificates between the root and the signing CA */
627                            uint32 ignorelen;
628                            X509 *ignorecert;
629    
630                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
631    
632                            in_uint32_le(s, ignorelen);
633                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
634                            ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
635    
636                            if (ignorecert == NULL)
637                            {       /* XXX: error out? */
638                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
639                            }
640    
641                          case SEC_TAG_KEYSIG:  #ifdef WITH_DEBUG_RDP5
642                                  /* Is this a Microsoft key that we just got? */                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
643                                  /* Care factor: zero! */                          X509_print_fp(stdout, ignorecert);
644                                  break;  #endif
645                    }
646    
647                          default:                  /* Do da funky X.509 stuffy
648                                  NOTIMP("crypt tag 0x%x\n", tag);  
649                       "How did I find out about this?  I looked up and saw a
650                       bright light and when I came to I had a scar on my forehead
651                       and knew about X.500"
652                       - Peter Gutman in a early version of
653                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
654                     */
655    
656                    in_uint32_le(s, cacert_len);
657                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
658                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
659                    /* Note: We don't need to move s->p here - d2i_X509 is
660                       "kind" enough to do it for us */
661                    if (NULL == cacert)
662                    {
663                            error("Couldn't load CA Certificate from server\n");
664                            return False;
665                  }                  }
666    
667                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
668          }                     FIXME:
669                       *) Verify the server certificate (server_cert) with the
670                       CA certificate.
671                       *) Store the CA Certificate with the hostname of the
672                       server we are connecting to as key, and compare it
673                       when we connect the next time, in order to prevent
674                       MITM-attacks.
675                     */
676    
677                    in_uint32_le(s, cert_len);
678                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
679                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
680                    if (NULL == server_cert)
681                    {
682                            error("Couldn't load Certificate from server\n");
683                            return False;
684                    }
685    
686                    in_uint8s(s, 16);       /* Padding */
687    
688                    /* Note: Verifying the server certificate must be done here,
689                       before sec_parse_public_key since we'll have to apply
690                       serious violence to the key after this */
691    
692                    if (!sec_parse_x509_key(server_cert))
693                    {
694                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
695                            return False;
696                    }
697                    return True;    /* There's some garbage here we don't care about */
698            }
699          return s_check_end(s);          return s_check_end(s);
700  }  }
701    
# Line 517  sec_process_crypt_info(STREAM s) Line 706  sec_process_crypt_info(STREAM s)
706          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
707          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
708          uint32 rc4_key_size;          uint32 rc4_key_size;
709            uint8 inr[SEC_MODULUS_SIZE];
710    
711          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
712                                    &modulus, &exponent))          {
713                    DEBUG(("Failed to parse crypt info\n"));
714                  return;                  return;
715            }
716    
717            DEBUG(("Generating client random\n"));
718          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
719            /* This is what the MS client do: */
720            memset(inr, 0, SEC_RANDOM_SIZE);
721            /*  *ARIGL!* Plaintext attack, anyone?
722               I tried doing:
723               generate_random(inr);
724               ..but that generates connection errors now and then (yes,
725               "now and then". Something like 0 to 3 attempts needed before a
726               successful connection. Nice. Not!
727             */
728    
729          generate_random(client_random);          generate_random(client_random);
730          sec_rsa_encrypt(sec_crypted_random, client_random,          if (NULL != server_public_key)
731                          SEC_RANDOM_SIZE, modulus, exponent);          {                       /* Which means we should use
732                                       RDP5-style encryption */
733    
734                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
735                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
736    
737                    RSA_public_encrypt(SEC_MODULUS_SIZE,
738                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
739    
740                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
741    
742            }
743            else
744            {                       /* RDP4-style encryption */
745                    sec_rsa_encrypt(sec_crypted_random,
746                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
747            }
748          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
749  }  }
750    
751  /* Process connect response data blob */  
752    /* Process SRV_INFO, find RDP version supported by server */
753  static void  static void
754    sec_process_srv_info(STREAM s)
755    {
756            in_uint16_le(s, g_server_rdp_version);
757            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
758            if (1 == g_server_rdp_version)
759            {
760                    g_use_rdp5 = 0;
761                    g_server_bpp = 8;
762            }
763    }
764    
765    
766    /* Process connect response data blob */
767    void
768  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
769  {  {
770          uint16 tag, length;          uint16 tag, length;
771          uint8 *next_tag;          uint8 *next_tag;
772            uint8 len;
773    
774          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
775            in_uint8(s, len);
776            if (len & 0x80)
777                    in_uint8(s, len);
778    
779          while (s->p < s->end)          while (s->p < s->end)
780          {          {
# Line 551  sec_process_mcs_data(STREAM s) Line 789  sec_process_mcs_data(STREAM s)
789                  switch (tag)                  switch (tag)
790                  {                  {
791                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
792                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
793                                  break;                                  break;
794    
795                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
796                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
797                                  break;                                  break;
798    
799                            case SEC_TAG_SRV_CHANNELS:
800                                    /* FIXME: We should parse this information and
801                                       use it to map RDP5 channels to MCS
802                                       channels */
803                                    break;
804    
805                          default:                          default:
806                                  NOTIMP("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
807                  }                  }
808    
809                  s->p = next_tag;                  s->p = next_tag;
# Line 568  sec_process_mcs_data(STREAM s) Line 812  sec_process_mcs_data(STREAM s)
812    
813  /* Receive secure transport packet */  /* Receive secure transport packet */
814  STREAM  STREAM
815  sec_recv()  sec_recv(void)
816  {  {
817          uint32 sec_flags;          uint32 sec_flags;
818            uint16 channel;
819          STREAM s;          STREAM s;
820    
821          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
822          {          {
823                  if (use_encryption || !licence_issued)                  if (g_encryption || !g_licence_issued)
824                  {                  {
825                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
826    
827                            if (sec_flags & SEC_ENCRYPT)
828                            {
829                                    in_uint8s(s, 8);        /* signature */
830                                    sec_decrypt(s->p, s->end - s->p);
831                            }
832    
833                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
834                          {                          {
835                                  licence_process(s);                                  licence_process(s);
836                                  continue;                                  continue;
837                          }                          }
838                    }
839    
840                          if (sec_flags & SEC_ENCRYPT)                  if (channel != MCS_GLOBAL_CHANNEL)
841                          {                  {
842                                  in_uint8s(s, 8);        /* signature */                          channel_process(s, channel);
843                                  sec_decrypt(s->p, s->end - s->p);                          continue;
                         }  
844                  }                  }
845    
846                  return s;                  return s;
# Line 600  sec_recv() Line 851  sec_recv()
851    
852  /* Establish a secure connection */  /* Establish a secure connection */
853  BOOL  BOOL
854  sec_connect(char *server)  sec_connect(char *server, char *username)
855  {  {
856          struct stream mcs_data;          struct stream mcs_data;
857    
858          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
859          mcs_data.size = 512;          mcs_data.size = 512;
860          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
861          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
862    
863          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
864                  return False;                  return False;
865    
866          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
867          if (use_encryption)          if (g_encryption)
868                  sec_establish_key();                  sec_establish_key();
869            xfree(mcs_data.data);
870          return True;          return True;
871  }  }
872    
873  /* Disconnect a connection */  /* Disconnect a connection */
874  void  void
875  sec_disconnect()  sec_disconnect(void)
876  {  {
877          mcs_disconnect();          mcs_disconnect();
878  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26