/[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 24 by matty, Sat Jan 6 03:12:10 2001 UTC revision 557 by stargo, Wed Dec 10 08:02:59 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 g_width;
38  extern int height;  extern int g_height;
39  extern int keylayout;  extern int keylayout;
40    extern BOOL g_encryption;
41    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,
65   * a client and server salt) and a global salt value used for padding.   * a client and server salt) and a global salt value used for padding.
66   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
67   */   */
68  void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2,  void
69                   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 76  void sec_hash_48(uint8 *out, uint8 *in, Line 96  void sec_hash_48(uint8 *out, uint8 *in,
96   * Weaker 16-byte transformation, also using two 32-byte salts, but   * Weaker 16-byte transformation, also using two 32-byte salts, but
97   * only using a single round of MD5.   * only using a single round of MD5.
98   */   */
99  void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  void
100    sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
101  {  {
102          MD5_CTX md5;          MD5_CTX md5;
103    
# Line 88  void sec_hash_16(uint8 *out, uint8 *in, Line 109  void sec_hash_16(uint8 *out, uint8 *in,
109  }  }
110    
111  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
112  static void sec_make_40bit(uint8 *key)  static void
113    sec_make_40bit(uint8 * key)
114  {  {
115          key[0] = 0xd1;          key[0] = 0xd1;
116          key[1] = 0x26;          key[1] = 0x26;
# Line 96  static void sec_make_40bit(uint8 *key) Line 118  static void sec_make_40bit(uint8 *key)
118  }  }
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 sec_generate_keys(uint8 *client_key, uint8 *server_key,  static void
122                                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 111  static void sec_generate_keys(uint8 *cli Line 133  static void sec_generate_keys(uint8 *cli
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 130  static void sec_generate_keys(uint8 *cli Line 150  static void sec_generate_keys(uint8 *cli
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 145  static void sec_generate_keys(uint8 *cli Line 165  static void sec_generate_keys(uint8 *cli
165    
166  static uint8 pad_54[40] = {  static uint8 pad_54[40] = {
167          54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,          54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
168                  54, 54, 54,          54, 54, 54,
169          54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,          54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
170                  54, 54, 54          54, 54, 54
171  };  };
172    
173  static uint8 pad_92[48] = {  static uint8 pad_92[48] = {
174          92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,          92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
175                  92, 92, 92, 92, 92, 92, 92,          92, 92, 92, 92, 92, 92, 92,
176          92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,          92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
177                  92, 92, 92, 92, 92, 92, 92          92, 92, 92, 92, 92, 92, 92
178  };  };
179    
180  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
181  void buf_out_uint32(uint8 *buffer, uint32 value)  void
182    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 167  void buf_out_uint32(uint8 *buffer, uint3 Line 188  void buf_out_uint32(uint8 *buffer, uint3
188  }  }
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 sec_sign(uint8 *signature, uint8 *session_key, int length,  void
192                uint8 *data, int datalen)  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
193  {  {
194          uint8 shasig[20];          uint8 shasig[20];
195          uint8 md5sig[16];          uint8 md5sig[16];
# Line 179  void sec_sign(uint8 *signature, uint8 *s Line 200  void sec_sign(uint8 *signature, uint8 *s
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 sec_update(uint8 *key, uint8 *update_key)  static void
220    sec_update(uint8 * key, uint8 * update_key)
221  {  {
222          uint8 shasig[20];          uint8 shasig[20];
223          SHA_CTX sha;          SHA_CTX sha;
# Line 203  static void sec_update(uint8 *key, uint8 Line 225  static void sec_update(uint8 *key, uint8
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 222  static void sec_update(uint8 *key, uint8 Line 244  static void sec_update(uint8 *key, uint8
244  }  }
245    
246  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
247  static void sec_encrypt(uint8 *data, int length)  static void
248    sec_encrypt(uint8 * data, int length)
249  {  {
250          static int use_count;          static int use_count;
251    
# Line 238  static void sec_encrypt(uint8 *data, int Line 261  static void sec_encrypt(uint8 *data, int
261  }  }
262    
263  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
264  static void sec_decrypt(uint8 *data, int length)  void
265    sec_decrypt(uint8 * data, int length)
266  {  {
267          static int use_count;          static int use_count;
268    
# Line 253  static void sec_decrypt(uint8 *data, int Line 277  static void sec_decrypt(uint8 *data, int
277          use_count++;          use_count++;
278  }  }
279    
280  /* Read in a NUMBER from a buffer */  static void
281  static void sec_read_number(NUMBER * num, uint8 *buffer, int len)  reverse(uint8 * p, 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 */  
 static void sec_write_number(NUMBER * num, uint8 *buffer, 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--)
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 sec_rsa_encrypt(uint8 *out, uint8 *in, int len,  static void
296                              uint8 *modulus, uint8 *exponent)  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, 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 */
331  STREAM sec_init(uint32 flags, int maxlen)  STREAM
332    sec_init(uint32 flags, int maxlen)
333  {  {
334          int hdrlen;          int hdrlen;
335          STREAM s;          STREAM s;
336    
337          hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;          if (!g_licence_issued)
338                    hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
339            else
340                    hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
341          s = mcs_init(maxlen + hdrlen);          s = mcs_init(maxlen + hdrlen);
342          s_push_layer(s, sec_hdr, hdrlen);          s_push_layer(s, sec_hdr, hdrlen);
343    
344          return s;          return s;
345  }  }
346    
347  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
348  void sec_send(STREAM s, uint32 flags)  void
349    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          out_uint32_le(s, flags);          if (!g_licence_issued || (flags & SEC_ENCRYPT))
355                    out_uint32_le(s, flags);
356    
357          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
358          {          {
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 sec_establish_key()  static void
385    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 351  static void sec_establish_key() Line 399  static void sec_establish_key()
399  }  }
400    
401  /* Output connect initial data blob */  /* Output connect initial data blob */
402  static void sec_out_mcs_data(STREAM s)  static void
403    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            if (hostlen > 30)
413                    hostlen = 30;
414    
415          out_uint16_be(s, 5);    /* unknown */          out_uint16_be(s, 5);    /* unknown */
416          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
417          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
418          out_uint16_be(s, 1);          out_uint16_be(s, 1);
419    
420          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
421    
422          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
423          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 369  static void sec_out_mcs_data(STREAM s) Line 426  static void sec_out_mcs_data(STREAM s)
426          out_uint8(s, 0);          out_uint8(s, 0);
427    
428          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */
429          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
430    
431          /* Client information */          /* Client information */
432          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
433          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
434          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
435          out_uint16_le(s, 8);          out_uint16_le(s, 8);
436          out_uint16_le(s, width);          out_uint16_le(s, g_width);
437          out_uint16_le(s, height);          out_uint16_le(s, g_height);
438          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
439          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
440          out_uint32_le(s, keylayout);          out_uint32_le(s, keylayout);
441          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
442    
443          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
444          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, hostname, hostlen);
# Line 392  static void sec_out_mcs_data(STREAM s) Line 449  static void sec_out_mcs_data(STREAM s)
449          out_uint32_le(s, 12);          out_uint32_le(s, 12);
450          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
451    
452          out_uint16(s, 0xca01);          switch (g_server_bpp)
453          out_uint16(s, 0);          {
454                    case 8:
455                            out_uint16_le(s, 0xca01);
456                            break;
457                    case 15:
458                            out_uint16_le(s, 0xca02);
459                            break;
460                    case 16:
461                            out_uint16_le(s, 0xca03);
462                            break;
463                    case 24:
464                            out_uint16_le(s, 0xca04);
465                            break;
466            }
467            out_uint16_le(s, 1);
468    
469            out_uint32(s, 0);
470            out_uint8(s, g_server_bpp);
471            out_uint16_le(s, 0x0700);
472            out_uint8(s, 0);
473            out_uint32_le(s, 1);
474            out_uint8s(s, 64);      /* End of client info */
475    
476            out_uint16_le(s, SEC_TAG_CLI_4);
477            out_uint16_le(s, 12);
478            out_uint32_le(s, g_console_session ? 0xb : 9);
479            out_uint32(s, 0);
480    
481          /* Client encryption settings */          /* Client encryption settings */
482          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
483          out_uint16(s, 8);       /* length */          out_uint16_le(s, 12);   /* length */
484          out_uint32_le(s, 1);    /* encryption enabled */          out_uint32_le(s, g_encryption ? 0x3 : 0);       /* encryption supported, 128-bit supported */
485            out_uint32(s, 0);       /* Unknown */
486    
487            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
488            if (g_num_channels > 0)
489            {
490                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
491                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
492                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
493                    for (i = 0; i < g_num_channels; i++)
494                    {
495                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
496                            out_uint8a(s, g_channels[i].name, 8);
497                            out_uint32_be(s, g_channels[i].flags);
498                    }
499            }
500    
501          s_mark_end(s);          s_mark_end(s);
502  }  }
503    
504  /* Parse a public key structure */  /* Parse a public key structure */
505  static BOOL sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  static BOOL
506    sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
507  {  {
508          uint32 magic, modulus_len;          uint32 magic, modulus_len;
509    
510          in_uint32_le(s, magic);          in_uint32_le(s, magic);
511          if (magic != SEC_RSA_MAGIC)          if (magic != SEC_RSA_MAGIC)
512          {          {
513                  ERROR("RSA magic 0x%x\n", magic);                  error("RSA magic 0x%x\n", magic);
514                  return False;                  return False;
515          }          }
516    
517          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
518          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
519          {          {
520                  ERROR("modulus len 0x%x\n", modulus_len);                  error("modulus len 0x%x\n", modulus_len);
521                  return False;                  return False;
522          }          }
523    
# Line 429  static BOOL sec_parse_public_key(STREAM Line 529  static BOOL sec_parse_public_key(STREAM
529          return s_check(s);          return s_check(s);
530  }  }
531    
532    static BOOL
533    sec_parse_x509_key(X509 * cert)
534    {
535            EVP_PKEY *epk = NULL;
536            /* By some reason, Microsoft sets the OID of the Public RSA key to
537               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
538    
539               Kudos to Richard Levitte for the following (. intiutive .)
540               lines of code that resets the OID and let's us extract the key. */
541            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
542            {
543                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
544                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
545            }
546            epk = X509_get_pubkey(cert);
547            if (NULL == epk)
548            {
549                    error("Failed to extract public key from certificate\n");
550                    return False;
551            }
552    
553            server_public_key = (RSA *) epk->pkey.ptr;
554    
555            return True;
556    }
557    
558    
559  /* Parse a crypto information structure */  /* Parse a crypto information structure */
560  static BOOL sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  static BOOL
561                                   uint8 **server_random, uint8 **modulus,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
562                                   uint8 **exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
563  {  {
564          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
565            uint32 cacert_len, cert_len, flags;
566            X509 *cacert, *server_cert;
567          uint16 tag, length;          uint16 tag, length;
568          uint8 *next_tag, *end;          uint8 *next_tag, *end;
569    
570          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 */
571          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
572            if (crypt_level == 0)   /* no encryption */
573                    return False;
574          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
575          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
576    
577          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
578          {          {
579                  ERROR("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
580                  return False;                  return False;
581          }          }
582    
# Line 456  static BOOL sec_parse_crypt_info(STREAM Line 587  static BOOL sec_parse_crypt_info(STREAM
587          if (end > s->end)          if (end > s->end)
588                  return False;                  return False;
589    
590          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
591            if (flags & 1)
592            {
593                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
594                    in_uint8s(s, 8);        /* unknown */
595    
596                    while (s->p < end)
597                    {
598                            in_uint16_le(s, tag);
599                            in_uint16_le(s, length);
600    
601          while (s->p < end)                          next_tag = s->p + length;
602    
603                            switch (tag)
604                            {
605                                    case SEC_TAG_PUBKEY:
606                                            if (!sec_parse_public_key(s, modulus, exponent))
607                                                    return False;
608                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
609    
610                                            break;
611    
612                                    case SEC_TAG_KEYSIG:
613                                            /* Is this a Microsoft key that we just got? */
614                                            /* Care factor: zero! */
615                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
616                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
617                                            break;
618    
619                                    default:
620                                            unimpl("crypt tag 0x%x\n", tag);
621                            }
622    
623                            s->p = next_tag;
624                    }
625            }
626            else
627          {          {
628                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
629    
630                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
631                    in_uint32_le(s, certcount); /* Number of certificates */
632    
633                  switch (tag)                  if(certcount < 2)
634                  {                  {
635                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
636                                  if (!sec_parse_public_key                          return False;
637                                      (s, modulus, exponent))                  }
                                         return False;  
638    
639                                  break;                  for(; certcount > 2; certcount--)
640                    { /* ignore all the certificates between the root and the signing CA */
641                            uint32 ignorelen;
642                            X509 *ignorecert;
643    
644                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
645    
646                            in_uint32_le(s, ignorelen);
647                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
648                            ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
649    
650                            if(ignorecert == NULL)
651                            { /* XXX: error out? */
652                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
653                            }
654    
655    #ifdef WITH_DEBUG_RDP5
656                            DEBUG_RDP5(("cert #%d (ignored):\n",certcount));
657                            X509_print_fp(stdout, ignorecert);
658    #endif
659                    }
660    
661                          case SEC_TAG_KEYSIG:                  /* Do da funky X.509 stuffy
                                 /* Is this a Microsoft key that we just got? */  
                                 /* Care factor: zero! */  
                                 break;  
662    
663                          default:                     "How did I find out about this?  I looked up and saw a
664                                  NOTIMP("crypt tag 0x%x\n", tag);                     bright light and when I came to I had a scar on my forehead
665                       and knew about X.500"
666                       - Peter Gutman in a early version of
667                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
668                     */
669    
670                    in_uint32_le(s, cacert_len);
671                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
672                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
673                    /* Note: We don't need to move s->p here - d2i_X509 is
674                       "kind" enough to do it for us */
675                    if (NULL == cacert)
676                    {
677                            error("Couldn't load CA Certificate from server\n");
678                            return False;
679                  }                  }
680    
681                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
682          }                     FIXME:
683                       *) Verify the server certificate (server_cert) with the
684                       CA certificate.
685                       *) Store the CA Certificate with the hostname of the
686                       server we are connecting to as key, and compare it
687                       when we connect the next time, in order to prevent
688                       MITM-attacks.
689                     */
690    
691                    in_uint32_le(s, cert_len);
692                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
693                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
694                    if (NULL == server_cert)
695                    {
696                            error("Couldn't load Certificate from server\n");
697                            return False;
698                    }
699    
700                    in_uint8s(s, 16);       /* Padding */
701    
702                    /* Note: Verifying the server certificate must be done here,
703                       before sec_parse_public_key since we'll have to apply
704                       serious violence to the key after this */
705    
706                    if (!sec_parse_x509_key(server_cert))
707                    {
708                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
709                            return False;
710                    }
711                    return True;    /* There's some garbage here we don't care about */
712            }
713          return s_check_end(s);          return s_check_end(s);
714  }  }
715    
716  /* Process crypto information blob */  /* Process crypto information blob */
717  static void sec_process_crypt_info(STREAM s)  static void
718    sec_process_crypt_info(STREAM s)
719  {  {
720          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
721          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
722          uint32 rc4_key_size;          uint32 rc4_key_size;
723            uint8 inr[SEC_MODULUS_SIZE];
724    
725          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
726                                    &modulus, &exponent))          {
727                    DEBUG(("Failed to parse crypt info\n"));
728                  return;                  return;
729            }
730    
731            DEBUG(("Generating client random\n"));
732          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
733            /* This is what the MS client do: */
734            memset(inr, 0, SEC_RANDOM_SIZE);
735            /*  *ARIGL!* Plaintext attack, anyone?
736               I tried doing:
737               generate_random(inr);
738               ..but that generates connection errors now and then (yes,
739               "now and then". Something like 0 to 3 attempts needed before a
740               successful connection. Nice. Not!
741             */
742    
743          generate_random(client_random);          generate_random(client_random);
744          sec_rsa_encrypt(sec_crypted_random, client_random,          if (NULL != server_public_key)
745                          SEC_RANDOM_SIZE, modulus, exponent);          {                       /* Which means we should use
746                                       RDP5-style encryption */
747    
748                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
749                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
750    
751                    RSA_public_encrypt(SEC_MODULUS_SIZE,
752                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
753    
754                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
755    
756            }
757            else
758            {                       /* RDP4-style encryption */
759                    sec_rsa_encrypt(sec_crypted_random,
760                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
761            }
762          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
763  }  }
764    
765    
766    /* Process SRV_INFO, find RDP version supported by server */
767    static void
768    sec_process_srv_info(STREAM s)
769    {
770            in_uint16_le(s, g_server_rdp_version);
771            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
772            if (1 == g_server_rdp_version)
773                    g_use_rdp5 = 0;
774    }
775    
776    
777  /* Process connect response data blob */  /* Process connect response data blob */
778  static void sec_process_mcs_data(STREAM s)  void
779    sec_process_mcs_data(STREAM s)
780  {  {
781          uint16 tag, length;          uint16 tag, length;
782          uint8 *next_tag;          uint8 *next_tag;
783            uint8 len;
784    
785          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */
786            in_uint8(s, len);
787            if (len & 0x80)
788                    in_uint8(s, len);
789    
790          while (s->p < s->end)          while (s->p < s->end)
791          {          {
# Line 528  static void sec_process_mcs_data(STREAM Line 800  static void sec_process_mcs_data(STREAM
800                  switch (tag)                  switch (tag)
801                  {                  {
802                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
803                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
804                                  break;                                  break;
805    
806                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
807                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
808                                  break;                                  break;
809    
810                            case SEC_TAG_SRV_CHANNELS:
811                                    /* FIXME: We should parse this information and
812                                       use it to map RDP5 channels to MCS
813                                       channels */
814                                    break;
815    
816                          default:                          default:
817                                  NOTIMP("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
818                  }                  }
819    
820                  s->p = next_tag;                  s->p = next_tag;
# Line 544  static void sec_process_mcs_data(STREAM Line 822  static void sec_process_mcs_data(STREAM
822  }  }
823    
824  /* Receive secure transport packet */  /* Receive secure transport packet */
825  STREAM sec_recv()  STREAM
826    sec_recv(void)
827  {  {
828          uint32 sec_flags;          uint32 sec_flags;
829            uint16 channel;
830          STREAM s;          STREAM s;
831    
832          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
833          {          {
834                  in_uint32_le(s, sec_flags);                  if (g_encryption || !g_licence_issued)
   
                 if (sec_flags & SEC_LICENCE_NEG)  
835                  {                  {
836                          licence_process(s);                          in_uint32_le(s, sec_flags);
837                          continue;  
838                            if (sec_flags & SEC_ENCRYPT)
839                            {
840                                    in_uint8s(s, 8);        /* signature */
841                                    sec_decrypt(s->p, s->end - s->p);
842                            }
843    
844                            if (sec_flags & SEC_LICENCE_NEG)
845                            {
846                                    licence_process(s);
847                                    continue;
848                            }
849                  }                  }
850    
851                  if (sec_flags & SEC_ENCRYPT)                  if (channel != MCS_GLOBAL_CHANNEL)
852                  {                  {
853                          in_uint8s(s, 8);        /* signature */                          channel_process(s, channel);
854                          sec_decrypt(s->p, s->end - s->p);                          continue;
855                  }                  }
856    
857                  return s;                  return s;
# Line 572  STREAM sec_recv() Line 861  STREAM sec_recv()
861  }  }
862    
863  /* Establish a secure connection */  /* Establish a secure connection */
864  BOOL sec_connect(char *server)  BOOL
865    sec_connect(char *server, char *username)
866  {  {
867          struct stream mcs_data;          struct stream mcs_data;
868    
869          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
870          mcs_data.size = 512;          mcs_data.size = 512;
871          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
872          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
873    
874          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
875                  return False;                  return False;
876    
877          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
878          sec_establish_key();          if (g_encryption)
879                    sec_establish_key();
880            xfree(mcs_data.data);
881          return True;          return True;
882  }  }
883    
884  /* Disconnect a connection */  /* Disconnect a connection */
885  void sec_disconnect()  void
886    sec_disconnect(void)
887  {  {
888          mcs_disconnect();          mcs_disconnect();
889  }  }

Legend:
Removed from v.24  
changed lines
  Added in v.557

  ViewVC Help
Powered by ViewVC 1.1.26