/[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 192 by matthewc, Tue Sep 24 07:59:14 2002 UTC revision 964 by astrand, Wed Aug 3 11:30:53 2005 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing     Protocol services - RDP encryption and licensing
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20    
21  #include "rdesktop.h"  #include "rdesktop.h"
22    
 #ifdef WITH_OPENSSL  
23  #include <openssl/rc4.h>  #include <openssl/rc4.h>
24  #include <openssl/md5.h>  #include <openssl/md5.h>
25  #include <openssl/sha.h>  #include <openssl/sha.h>
26  #include <openssl/bn.h>  #include <openssl/bn.h>
27  #else  #include <openssl/x509v3.h>
 #include "crypto/rc4.h"  
 #include "crypto/md5.h"  
 #include "crypto/sha.h"  
 #include "crypto/bn.h"  
 #endif  
28    
29  extern char hostname[16];  extern char g_hostname[16];
30  extern int width;  extern int g_width;
31  extern int height;  extern int g_height;
32  extern int keylayout;  extern int g_keylayout;
33  extern BOOL encryption;  extern int g_keyboard_type;
34  extern BOOL licence_issued;  extern int g_keyboard_subtype;
35    extern int g_keyboard_functionkeys;
36    extern BOOL g_encryption;
37    extern BOOL g_licence_issued;
38    extern BOOL g_use_rdp5;
39    extern BOOL g_console_session;
40    extern int g_server_bpp;
41    extern uint16 mcs_userid;
42    extern VCHANNEL g_channels[];
43    extern unsigned int g_num_channels;
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[16];  static uint8 sec_sign_key[16];
51  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
# Line 50  static uint8 sec_decrypt_update_key[16]; Line 54  static uint8 sec_decrypt_update_key[16];
54  static uint8 sec_encrypt_update_key[16];  static uint8 sec_encrypt_update_key[16];
55  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
56    
57    uint16 g_server_rdp_version = 0;
58    
59    /*
60     * I believe this is based on SSLv3 with the following differences:
61     *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
62     *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
63     *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
64     *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
65     *  encryption/decryption keys updated every 4096 packets
66     * See http://wp.netscape.com/eng/ssl3/draft302.txt
67     */
68    
69  /*  /*
70   * 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.  
71   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
72   */   */
73  void  void
# Line 83  sec_hash_48(uint8 * out, uint8 * in, uin Line 98  sec_hash_48(uint8 * out, uint8 * in, uin
98  }  }
99    
100  /*  /*
101   * 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.  
102   */   */
103  void  void
104  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
# Line 107  sec_make_40bit(uint8 * key) Line 121  sec_make_40bit(uint8 * key)
121          key[2] = 0x9e;          key[2] = 0x9e;
122  }  }
123    
124  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate encryption keys given client and server randoms */
125  static void  static void
126  sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)  sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
127  {  {
128          uint8 session_key[48];          uint8 pre_master_secret[48];
129          uint8 temp_hash[48];          uint8 master_secret[48];
130          uint8 input[48];          uint8 key_block[48];
131    
132          /* Construct input data to hash */          /* Construct pre-master secret */
133          memcpy(input, client_key, 24);          memcpy(pre_master_secret, client_random, 24);
134          memcpy(input + 24, server_key, 24);          memcpy(pre_master_secret + 24, server_random, 24);
135    
136          /* Generate session key - two rounds of sec_hash_48 */          /* Generate master secret and then key material */
137          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
138          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
139    
140          /* Store first 16 bytes of session key, for generating signatures */          /* First 16 bytes of key material is MAC secret */
141          memcpy(sec_sign_key, session_key, 16);          memcpy(sec_sign_key, key_block, 16);
142    
143          /* Generate RC4 keys */          /* Generate export keys from next two blocks of 16 bytes */
144          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);
145          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);
146    
147          if (rc4_key_size == 1)          if (rc4_key_size == 1)
148          {          {
# Line 140  sec_generate_keys(uint8 * client_key, ui Line 154  sec_generate_keys(uint8 * client_key, ui
154          }          }
155          else          else
156          {          {
157                  DEBUG(("128-bit encryption enabled\n"));                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
158                  rc4_key_len = 16;                  rc4_key_len = 16;
159          }          }
160    
# Line 177  buf_out_uint32(uint8 * buffer, uint32 va Line 191  buf_out_uint32(uint8 * buffer, uint32 va
191          buffer[3] = (value >> 24) & 0xff;          buffer[3] = (value >> 24) & 0xff;
192  }  }
193    
194  /* 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 */
195  void  void
196  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
197  {  {
# Line 205  sec_sign(uint8 * signature, int siglen, Line 219  sec_sign(uint8 * signature, int siglen,
219          memcpy(signature, md5sig, siglen);          memcpy(signature, md5sig, siglen);
220  }  }
221    
222  /* Update an encryption key - similar to the signing process */  /* Update an encryption key */
223  static void  static void
224  sec_update(uint8 * key, uint8 * update_key)  sec_update(uint8 * key, uint8 * update_key)
225  {  {
# Line 251  sec_encrypt(uint8 * data, int length) Line 265  sec_encrypt(uint8 * data, int length)
265  }  }
266    
267  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
268  static void  void
269  sec_decrypt(uint8 * data, int length)  sec_decrypt(uint8 * data, int length)
270  {  {
271          static int use_count;          static int use_count;
# Line 285  reverse(uint8 * p, int len) Line 299  reverse(uint8 * p, int len)
299  static void  static void
300  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
301  {  {
302          BN_CTX ctx;          BN_CTX *ctx;
303          BIGNUM mod, exp, x, y;          BIGNUM mod, exp, x, y;
304          uint8 inr[SEC_MODULUS_SIZE];          uint8 inr[SEC_MODULUS_SIZE];
305          int outlen;          int outlen;
# Line 295  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 309  sec_rsa_encrypt(uint8 * out, uint8 * in,
309          memcpy(inr, in, len);          memcpy(inr, in, len);
310          reverse(inr, len);          reverse(inr, len);
311    
312          BN_CTX_init(&ctx);          ctx = BN_CTX_new();
313          BN_init(&mod);          BN_init(&mod);
314          BN_init(&exp);          BN_init(&exp);
315          BN_init(&x);          BN_init(&x);
# Line 304  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 318  sec_rsa_encrypt(uint8 * out, uint8 * in,
318          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
319          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
320          BN_bin2bn(inr, len, &x);          BN_bin2bn(inr, len, &x);
321          BN_mod_exp(&y, &x, &exp, &mod, &ctx);          BN_mod_exp(&y, &x, &exp, &mod, ctx);
322          outlen = BN_bn2bin(&y, out);          outlen = BN_bn2bin(&y, out);
323          reverse(out, outlen);          reverse(out, outlen);
324          if (outlen < SEC_MODULUS_SIZE)          if (outlen < SEC_MODULUS_SIZE)
# Line 314  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 328  sec_rsa_encrypt(uint8 * out, uint8 * in,
328          BN_clear_free(&x);          BN_clear_free(&x);
329          BN_free(&exp);          BN_free(&exp);
330          BN_free(&mod);          BN_free(&mod);
331          BN_CTX_free(&ctx);          BN_CTX_free(ctx);
332  }  }
333    
334  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 324  sec_init(uint32 flags, int maxlen) Line 338  sec_init(uint32 flags, int maxlen)
338          int hdrlen;          int hdrlen;
339          STREAM s;          STREAM s;
340    
341          if (!licence_issued)          if (!g_licence_issued)
342                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
343          else          else
344                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
# Line 334  sec_init(uint32 flags, int maxlen) Line 348  sec_init(uint32 flags, int maxlen)
348          return s;          return s;
349  }  }
350    
351  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
352  void  void
353  sec_send(STREAM s, uint32 flags)  sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
354  {  {
355          int datalen;          int datalen;
356    
357          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
358          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
359                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
360    
361          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
# Line 358  sec_send(STREAM s, uint32 flags) Line 372  sec_send(STREAM s, uint32 flags)
372                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
373          }          }
374    
375          mcs_send(s);          mcs_send_to_channel(s, channel);
376  }  }
377    
378    /* Transmit secure transport packet */
379    
380    void
381    sec_send(STREAM s, uint32 flags)
382    {
383            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
384    }
385    
386    
387  /* Transfer the client random to the server */  /* Transfer the client random to the server */
388  static void  static void
389  sec_establish_key(void)  sec_establish_key(void)
# Line 383  sec_establish_key(void) Line 406  sec_establish_key(void)
406  static void  static void
407  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
408  {  {
409          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(g_hostname);
410            int length = 158 + 76 + 12 + 4;
411            unsigned int i;
412    
413            if (g_num_channels > 0)
414                    length += g_num_channels * 12 + 8;
415    
416          if (hostlen > 30)          if (hostlen > 30)
417                  hostlen = 30;                  hostlen = 30;
418    
419          out_uint16_be(s, 5);    /* unknown */          /* Generic Conference Control (T.124) ConferenceCreateRequest */
420            out_uint16_be(s, 5);
421          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
422          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
423          out_uint16_be(s, 1);          out_uint16_be(s, 1);
424    
425          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
426    
427          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
428          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 401  sec_out_mcs_data(STREAM s) Line 430  sec_out_mcs_data(STREAM s)
430          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
431          out_uint8(s, 0);          out_uint8(s, 0);
432    
433          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
434          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
435    
436          /* Client information */          /* Client information */
437          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
438          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
439          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
440          out_uint16_le(s, 8);          out_uint16_le(s, 8);
441          out_uint16_le(s, width);          out_uint16_le(s, g_width);
442          out_uint16_le(s, height);          out_uint16_le(s, g_height);
443          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
444          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
445          out_uint32_le(s, keylayout);          out_uint32_le(s, g_keylayout);
446          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
447    
448          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
449          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, g_hostname, hostlen);
450          out_uint8s(s, 30 - hostlen);          out_uint8s(s, 30 - hostlen);
451    
452          out_uint32_le(s, 4);          out_uint32_le(s, g_keyboard_type);
453          out_uint32(s, 0);          out_uint32_le(s, g_keyboard_subtype);
454          out_uint32_le(s, 12);          out_uint32_le(s, g_keyboard_functionkeys);
455          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
456            out_uint16_le(s, 0xca01);       /* colour depth? */
457            out_uint16_le(s, 1);
458    
459          out_uint16_le(s, 0xca01);          out_uint32(s, 0);
460          out_uint16(s, 0);          out_uint8(s, g_server_bpp);
461            out_uint16_le(s, 0x0700);
462            out_uint8(s, 0);
463            out_uint32_le(s, 1);
464            out_uint8s(s, 64);      /* End of client info */
465    
466            out_uint16_le(s, SEC_TAG_CLI_4);
467            out_uint16_le(s, 12);
468            out_uint32_le(s, g_console_session ? 0xb : 9);
469            out_uint32(s, 0);
470    
471          /* Client encryption settings */          /* Client encryption settings */
472          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
473          out_uint16_le(s, 8);    /* length */          out_uint16_le(s, 12);   /* length */
474          out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */          out_uint32_le(s, g_encryption ? 0x3 : 0);       /* encryption supported, 128-bit supported */
475            out_uint32(s, 0);       /* Unknown */
476    
477            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
478            if (g_num_channels > 0)
479            {
480                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
481                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
482                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
483                    for (i = 0; i < g_num_channels; i++)
484                    {
485                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
486                            out_uint8a(s, g_channels[i].name, 8);
487                            out_uint32_be(s, g_channels[i].flags);
488                    }
489            }
490    
491          s_mark_end(s);          s_mark_end(s);
492  }  }
493    
# Line 463  sec_parse_public_key(STREAM s, uint8 ** Line 519  sec_parse_public_key(STREAM s, uint8 **
519          return s_check(s);          return s_check(s);
520  }  }
521    
522    static BOOL
523    sec_parse_x509_key(X509 * cert)
524    {
525            EVP_PKEY *epk = NULL;
526            /* By some reason, Microsoft sets the OID of the Public RSA key to
527               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
528    
529               Kudos to Richard Levitte for the following (. intiutive .)
530               lines of code that resets the OID and let's us extract the key. */
531            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
532            {
533                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
534                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
535            }
536            epk = X509_get_pubkey(cert);
537            if (NULL == epk)
538            {
539                    error("Failed to extract public key from certificate\n");
540                    return False;
541            }
542    
543            server_public_key = (RSA *) epk->pkey.ptr;
544    
545            return True;
546    }
547    
548    
549  /* Parse a crypto information structure */  /* Parse a crypto information structure */
550  static BOOL  static BOOL
551  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
552                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
553  {  {
554          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
555            uint32 cacert_len, cert_len, flags;
556            X509 *cacert, *server_cert;
557          uint16 tag, length;          uint16 tag, length;
558          uint8 *next_tag, *end;          uint8 *next_tag, *end;
559    
560          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 */
561          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
562          if (crypt_level == 0)   /* no encryptation */          if (crypt_level == 0)   /* no encryption */
563                  return False;                  return False;
564          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
565          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
566    
567          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
568          {          {
569                  error("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
570                  return False;                  return False;
571          }          }
572    
# Line 492  sec_parse_crypt_info(STREAM s, uint32 * Line 577  sec_parse_crypt_info(STREAM s, uint32 *
577          if (end > s->end)          if (end > s->end)
578                  return False;                  return False;
579    
580          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
581            if (flags & 1)
582            {
583                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
584                    in_uint8s(s, 8);        /* unknown */
585    
586                    while (s->p < end)
587                    {
588                            in_uint16_le(s, tag);
589                            in_uint16_le(s, length);
590    
591                            next_tag = s->p + length;
592    
593          while (s->p < end)                          switch (tag)
594                            {
595                                    case SEC_TAG_PUBKEY:
596                                            if (!sec_parse_public_key(s, modulus, exponent))
597                                                    return False;
598                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
599    
600                                            break;
601    
602                                    case SEC_TAG_KEYSIG:
603                                            /* Is this a Microsoft key that we just got? */
604                                            /* Care factor: zero! */
605                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
606                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
607                                            break;
608    
609                                    default:
610                                            unimpl("crypt tag 0x%x\n", tag);
611                            }
612    
613                            s->p = next_tag;
614                    }
615            }
616            else
617          {          {
618                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
619    
620                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
621                    in_uint32_le(s, certcount);     /* Number of certificates */
622    
623                  switch (tag)                  if (certcount < 2)
624                  {                  {
625                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
626                                  if (!sec_parse_public_key(s, modulus, exponent))                          return False;
627                                          return False;                  }
628    
629                                  break;                  for (; certcount > 2; certcount--)
630                    {               /* ignore all the certificates between the root and the signing CA */
631                            uint32 ignorelen;
632                            X509 *ignorecert;
633    
634                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
635    
636                            in_uint32_le(s, ignorelen);
637                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
638                            ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
639    
640                            if (ignorecert == NULL)
641                            {       /* XXX: error out? */
642                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
643                            }
644    
645                          case SEC_TAG_KEYSIG:  #ifdef WITH_DEBUG_RDP5
646                                  /* Is this a Microsoft key that we just got? */                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
647                                  /* Care factor: zero! */                          X509_print_fp(stdout, ignorecert);
648                                  break;  #endif
649                    }
650    
651                          default:                  /* Do da funky X.509 stuffy
652                                  unimpl("crypt tag 0x%x\n", tag);  
653                       "How did I find out about this?  I looked up and saw a
654                       bright light and when I came to I had a scar on my forehead
655                       and knew about X.500"
656                       - Peter Gutman in a early version of
657                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
658                     */
659    
660                    in_uint32_le(s, cacert_len);
661                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
662                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
663                    /* Note: We don't need to move s->p here - d2i_X509 is
664                       "kind" enough to do it for us */
665                    if (NULL == cacert)
666                    {
667                            error("Couldn't load CA Certificate from server\n");
668                            return False;
669                  }                  }
670    
671                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
672          }                     FIXME:
673                       *) Verify the server certificate (server_cert) with the
674                       CA certificate.
675                       *) Store the CA Certificate with the hostname of the
676                       server we are connecting to as key, and compare it
677                       when we connect the next time, in order to prevent
678                       MITM-attacks.
679                     */
680    
681                    in_uint32_le(s, cert_len);
682                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
683                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
684                    if (NULL == server_cert)
685                    {
686                            error("Couldn't load Certificate from server\n");
687                            return False;
688                    }
689    
690                    in_uint8s(s, 16);       /* Padding */
691    
692                    /* Note: Verifying the server certificate must be done here,
693                       before sec_parse_public_key since we'll have to apply
694                       serious violence to the key after this */
695    
696                    if (!sec_parse_x509_key(server_cert))
697                    {
698                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
699                            return False;
700                    }
701                    return True;    /* There's some garbage here we don't care about */
702            }
703          return s_check_end(s);          return s_check_end(s);
704  }  }
705    
# Line 531  sec_process_crypt_info(STREAM s) Line 710  sec_process_crypt_info(STREAM s)
710          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
711          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
712          uint32 rc4_key_size;          uint32 rc4_key_size;
713            uint8 inr[SEC_MODULUS_SIZE];
714    
715          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
716            {
717                    DEBUG(("Failed to parse crypt info\n"));
718                  return;                  return;
719            }
720    
721            DEBUG(("Generating client random\n"));
722          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
723            /* This is what the MS client do: */
724            memset(inr, 0, SEC_RANDOM_SIZE);
725            /*  *ARIGL!* Plaintext attack, anyone?
726               I tried doing:
727               generate_random(inr);
728               ..but that generates connection errors now and then (yes,
729               "now and then". Something like 0 to 3 attempts needed before a
730               successful connection. Nice. Not!
731             */
732    
733          generate_random(client_random);          generate_random(client_random);
734          sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);          if (NULL != server_public_key)
735            {                       /* Which means we should use
736                                       RDP5-style encryption */
737    
738                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
739                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
740    
741                    RSA_public_encrypt(SEC_MODULUS_SIZE,
742                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
743    
744                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
745    
746            }
747            else
748            {                       /* RDP4-style encryption */
749                    sec_rsa_encrypt(sec_crypted_random,
750                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
751            }
752          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
753  }  }
754    
755  /* Process connect response data blob */  
756    /* Process SRV_INFO, find RDP version supported by server */
757  static void  static void
758    sec_process_srv_info(STREAM s)
759    {
760            in_uint16_le(s, g_server_rdp_version);
761            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
762            if (1 == g_server_rdp_version)
763            {
764                    g_use_rdp5 = 0;
765                    g_server_bpp = 8;
766            }
767    }
768    
769    
770    /* Process connect response data blob */
771    void
772  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
773  {  {
774          uint16 tag, length;          uint16 tag, length;
775          uint8 *next_tag;          uint8 *next_tag;
776          uint8 len;          uint8 len;
777    
778          in_uint8s(s, 21);       /* header */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
779          in_uint8(s, len);          in_uint8(s, len);
780          if (len & 0x80)          if (len & 0x80)
781                  in_uint8(s, len);                  in_uint8(s, len);
# Line 567  sec_process_mcs_data(STREAM s) Line 793  sec_process_mcs_data(STREAM s)
793                  switch (tag)                  switch (tag)
794                  {                  {
795                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
796                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
797                                  break;                                  break;
798    
799                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
800                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
801                                  break;                                  break;
802    
803                            case SEC_TAG_SRV_CHANNELS:
804                                    /* FIXME: We should parse this information and
805                                       use it to map RDP5 channels to MCS
806                                       channels */
807                                    break;
808    
809                          default:                          default:
810                                  unimpl("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
811                  }                  }
# Line 584  sec_process_mcs_data(STREAM s) Line 816  sec_process_mcs_data(STREAM s)
816    
817  /* Receive secure transport packet */  /* Receive secure transport packet */
818  STREAM  STREAM
819  sec_recv(void)  sec_recv(uint8 * rdpver)
820  {  {
821          uint32 sec_flags;          uint32 sec_flags;
822            uint16 channel;
823          STREAM s;          STREAM s;
824    
825          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel, rdpver)) != NULL)
826          {          {
827                  if (encryption || !licence_issued)                  if (rdpver != NULL)
828                  {                  {
829                          in_uint32_le(s, sec_flags);                          if (*rdpver != 3)
   
                         if (sec_flags & SEC_LICENCE_NEG)  
830                          {                          {
831                                  licence_process(s);                                  if (*rdpver & 0x80)
832                                  continue;                                  {
833                                            in_uint8s(s, 8);        /* signature */
834                                            sec_decrypt(s->p, s->end - s->p);
835                                    }
836                                    return s;
837                          }                          }
838                    }
839                    if (g_encryption || !g_licence_issued)
840                    {
841                            in_uint32_le(s, sec_flags);
842    
843                          if (sec_flags & SEC_ENCRYPT)                          if (sec_flags & SEC_ENCRYPT)
844                          {                          {
845                                  in_uint8s(s, 8);        /* signature */                                  in_uint8s(s, 8);        /* signature */
846                                  sec_decrypt(s->p, s->end - s->p);                                  sec_decrypt(s->p, s->end - s->p);
847                          }                          }
848    
849                            if (sec_flags & SEC_LICENCE_NEG)
850                            {
851                                    licence_process(s);
852                                    continue;
853                            }
854                    }
855    
856                    if (channel != MCS_GLOBAL_CHANNEL)
857                    {
858                            channel_process(s, channel);
859                            *rdpver = 0xff;
860                            return s;
861                  }                  }
862    
863                  return s;                  return s;
# Line 616  sec_recv(void) Line 868  sec_recv(void)
868    
869  /* Establish a secure connection */  /* Establish a secure connection */
870  BOOL  BOOL
871  sec_connect(char *server)  sec_connect(char *server, char *username)
872  {  {
873          struct stream mcs_data;          struct stream mcs_data;
874    
875          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
876          mcs_data.size = 512;          mcs_data.size = 512;
877          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
878          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
879    
880          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
881                  return False;                  return False;
882    
883          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
884          if (encryption)          if (g_encryption)
885                  sec_establish_key();                  sec_establish_key();
886            xfree(mcs_data.data);
887          return True;          return True;
888  }  }
889    

Legend:
Removed from v.192  
changed lines
  Added in v.964

  ViewVC Help
Powered by ViewVC 1.1.26