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

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

  ViewVC Help
Powered by ViewVC 1.1.26