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

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

  ViewVC Help
Powered by ViewVC 1.1.26