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

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

  ViewVC Help
Powered by ViewVC 1.1.26