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

Legend:
Removed from v.10  
changed lines
  Added in v.710

  ViewVC Help
Powered by ViewVC 1.1.26