/[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 61 by matthewc, Sun Jul 14 12:06:03 2002 UTC revision 377 by forsberg, Thu May 22 08:37:57 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-2001     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 25  Line 25 
25  #include <openssl/md5.h>  #include <openssl/md5.h>
26  #include <openssl/sha.h>  #include <openssl/sha.h>
27  #include <openssl/bn.h>  #include <openssl/bn.h>
28    #include <openssl/x509v3.h>
29  #else  #else
30  #include "crypto/rc4.h"  #include "crypto/rc4.h"
31  #include "crypto/md5.h"  #include "crypto/md5.h"
# Line 38  extern int height; Line 39  extern int height;
39  extern int keylayout;  extern int keylayout;
40  extern BOOL encryption;  extern BOOL encryption;
41  extern BOOL licence_issued;  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[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 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  void
65  sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, 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 87  sec_hash_48(uint8 *out, uint8 *in, uint8 Line 93  sec_hash_48(uint8 *out, uint8 *in, uint8
93   * only using a single round of MD5.   * only using a single round of MD5.
94   */   */
95  void  void
96  sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
97  {  {
98          MD5_CTX md5;          MD5_CTX md5;
99    
# Line 100  sec_hash_16(uint8 *out, uint8 *in, uint8 Line 106  sec_hash_16(uint8 *out, uint8 *in, uint8
106    
107  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
108  static void  static void
109  sec_make_40bit(uint8 *key)  sec_make_40bit(uint8 * key)
110  {  {
111          key[0] = 0xd1;          key[0] = 0xd1;
112          key[1] = 0x26;          key[1] = 0x26;
# Line 109  sec_make_40bit(uint8 *key) Line 115  sec_make_40bit(uint8 *key)
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  static void
118  sec_generate_keys(uint8 *client_key, uint8 *server_key, 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 127  sec_generate_keys(uint8 *client_key, uin Line 133  sec_generate_keys(uint8 *client_key, uin
133          memcpy(sec_sign_key, session_key, 16);          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          {          {
# Line 142  sec_generate_keys(uint8 *client_key, uin Line 146  sec_generate_keys(uint8 *client_key, uin
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    
# Line 171  static uint8 pad_92[48] = { Line 175  static uint8 pad_92[48] = {
175    
176  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
177  void  void
178  buf_out_uint32(uint8 *buffer, uint32 value)  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 181  buf_out_uint32(uint8 *buffer, uint32 val Line 185  buf_out_uint32(uint8 *buffer, uint32 val
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  void
188  sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen,  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
          uint8 *data, int datalen)  
189  {  {
190          uint8 shasig[20];          uint8 shasig[20];
191          uint8 md5sig[16];          uint8 md5sig[16];
# Line 210  sec_sign(uint8 *signature, int siglen, u Line 213  sec_sign(uint8 *signature, int siglen, u
213    
214  /* Update an encryption key - similar to the signing process */  /* Update an encryption key - similar to the signing process */
215  static void  static void
216  sec_update(uint8 *key, uint8 *update_key)  sec_update(uint8 * key, uint8 * update_key)
217  {  {
218          uint8 shasig[20];          uint8 shasig[20];
219          SHA_CTX sha;          SHA_CTX sha;
# Line 238  sec_update(uint8 *key, uint8 *update_key Line 241  sec_update(uint8 *key, uint8 *update_key
241    
242  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
243  static void  static void
244  sec_encrypt(uint8 *data, int length)  sec_encrypt(uint8 * data, int length)
245  {  {
246          static int use_count;          static int use_count;
247    
# Line 254  sec_encrypt(uint8 *data, int length) Line 257  sec_encrypt(uint8 *data, int length)
257  }  }
258    
259  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
260  static void  void
261  sec_decrypt(uint8 *data, int length)  sec_decrypt(uint8 * data, int length)
262  {  {
263          static int use_count;          static int use_count;
264    
# Line 271  sec_decrypt(uint8 *data, int length) Line 274  sec_decrypt(uint8 *data, int length)
274  }  }
275    
276  static void  static void
277  reverse(uint8 *p, int len)  reverse(uint8 * p, int len)
278  {  {
279          int i, j;          int i, j;
280          uint8 temp;          uint8 temp;
281    
282          for (i = 0, j = len-1; i < j; i++, j--)          for (i = 0, j = len - 1; i < j; i++, j--)
283          {          {
284                  temp = p[i];                  temp = p[i];
285                  p[i] = p[j];                  p[i] = p[j];
# Line 286  reverse(uint8 *p, int len) Line 289  reverse(uint8 *p, int len)
289    
290  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
291  static void  static void
292  sec_rsa_encrypt(uint8 *out, uint8 *in, int len,  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
                 uint8 *modulus, uint8 *exponent)  
293  {  {
294          BN_CTX ctx;          BN_CTX *ctx;
295          BIGNUM mod, exp, x, y;          BIGNUM mod, exp, x, y;
296          uint8 inr[SEC_MODULUS_SIZE];          uint8 inr[SEC_MODULUS_SIZE];
297          int outlen;          int outlen;
# Line 299  sec_rsa_encrypt(uint8 *out, uint8 *in, i Line 301  sec_rsa_encrypt(uint8 *out, uint8 *in, i
301          memcpy(inr, in, len);          memcpy(inr, in, len);
302          reverse(inr, len);          reverse(inr, len);
303    
304          BN_CTX_init(&ctx);          ctx = BN_CTX_new();
305          BN_init(&mod);          BN_init(&mod);
306          BN_init(&exp);          BN_init(&exp);
307          BN_init(&x);          BN_init(&x);
# Line 308  sec_rsa_encrypt(uint8 *out, uint8 *in, i Line 310  sec_rsa_encrypt(uint8 *out, uint8 *in, i
310          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
311          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
312          BN_bin2bn(inr, len, &x);          BN_bin2bn(inr, len, &x);
313          BN_mod_exp(&y, &x, &exp, &mod, &ctx);          BN_mod_exp(&y, &x, &exp, &mod, ctx);
314          outlen = BN_bn2bin(&y, out);          outlen = BN_bn2bin(&y, out);
315          reverse(out, outlen);          reverse(out, outlen);
316          if (outlen < SEC_MODULUS_SIZE)          if (outlen < SEC_MODULUS_SIZE)
317                  memset(out+outlen, 0, SEC_MODULUS_SIZE-outlen);                  memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
318    
319          BN_free(&y);          BN_free(&y);
320          BN_clear_free(&x);          BN_clear_free(&x);
321          BN_free(&exp);          BN_free(&exp);
322          BN_free(&mod);          BN_free(&mod);
323          BN_CTX_free(&ctx);          BN_CTX_free(ctx);
324  }  }
325    
326  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 367  sec_send(STREAM s, uint32 flags) Line 369  sec_send(STREAM s, uint32 flags)
369    
370  /* Transfer the client random to the server */  /* Transfer the client random to the server */
371  static void  static void
372  sec_establish_key()  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 388  static void Line 390  static void
390  sec_out_mcs_data(STREAM s)  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 403  sec_out_mcs_data(STREAM s) Line 409  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 426  sec_out_mcs_data(STREAM s) Line 432  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_le(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(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, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */          out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
468            out_uint32(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  static BOOL
482  sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
483  {  {
484          uint32 magic, modulus_len;          uint32 magic, modulus_len;
485    
# Line 464  sec_parse_public_key(STREAM s, uint8 **m Line 505  sec_parse_public_key(STREAM s, uint8 **m
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  static BOOL
537  sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
538                       uint8 **server_random, uint8 **modulus, 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, flags;
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 491  sec_parse_crypt_info(STREAM s, uint32 *r Line 563  sec_parse_crypt_info(STREAM s, uint32 *r
563          if (end > s->end)          if (end > s->end)
564                  return False;                  return False;
565    
566          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
567            if (flags & 1)
568            {
569                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
570                    in_uint8s(s, 8);        /* unknown */
571    
572                    while (s->p < end)
573                    {
574                            in_uint16_le(s, tag);
575                            in_uint16_le(s, length);
576    
577                            next_tag = s->p + length;
578    
579                            switch (tag)
580                            {
581                                    case SEC_TAG_PUBKEY:
582                                            if (!sec_parse_public_key(s, modulus, exponent))
583                                                    return False;
584                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
585    
586                                            break;
587    
588                                    case SEC_TAG_KEYSIG:
589                                            /* Is this a Microsoft key that we just got? */
590                                            /* Care factor: zero! */
591                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
592                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
593                                            break;
594    
595                                    default:
596                                            unimpl("crypt tag 0x%x\n", tag);
597                            }
598    
599          while (s->p < end)                          s->p = next_tag;
600                    }
601            }
602            else
603          {          {
604                  in_uint16_le(s, tag);                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
605                  in_uint16_le(s, length);                  in_uint8s(s, 4);        /* Number of certificates */
606    
607                  next_tag = s->p + length;                  /* Do da funky X.509 stuffy
608    
609                  switch (tag)                     "How did I find out about this?  I looked up and saw a
610                       bright light and when I came to I had a scar on my forehead
611                       and knew about X.500"
612                       - Peter Gutman in a early version of
613                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
614                     */
615    
616                    in_uint32_le(s, cacert_len);
617                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
618                    /* Note: We don't need to move s->p here - d2i_X509 is
619                       "kind" enough to do it for us */
620                    if (NULL == cacert)
621                  {                  {
622                          case SEC_TAG_PUBKEY:                          error("Couldn't load CA Certificate from server\n");
623                                  if (!sec_parse_public_key                          return False;
624                                      (s, modulus, exponent))                  }
                                         return False;  
625    
626                                  break;                  /* Currently, we don't use the CA Certificate.
627                       FIXME:
628                       *) Verify the server certificate (server_cert) with the
629                       CA certificate.
630                       *) Store the CA Certificate with the hostname of the
631                       server we are connecting to as key, and compare it
632                       when we connect the next time, in order to prevent
633                       MITM-attacks.
634                     */
635    
636                    in_uint32_le(s, cert_len);
637                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
638                    if (NULL == server_cert)
639                    {
640                            error("Couldn't load Certificate from server\n");
641                            return False;
642                    }
643    
644                          case SEC_TAG_KEYSIG:                  in_uint8s(s, 16);       /* Padding */
                                 /* Is this a Microsoft key that we just got? */  
                                 /* Care factor: zero! */  
                                 break;  
645    
646                          default:                  /* Note: Verifying the server certificate must be done here,
647                                  unimpl("crypt tag 0x%x\n", tag);                     before sec_parse_public_key since we'll have to apply
648                  }                     serious violence to the key after this */
649    
650                  s->p = next_tag;                  if (!sec_parse_x509_key(server_cert))
651                    {
652                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
653                            return False;
654                    }
655                    return True;    /* There's some garbage here we don't care about */
656          }          }
   
657          return s_check_end(s);          return s_check_end(s);
658  }  }
659    
# Line 531  sec_process_crypt_info(STREAM s) Line 664  sec_process_crypt_info(STREAM s)
664          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
665          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
666          uint32 rc4_key_size;          uint32 rc4_key_size;
667            uint8 inr[SEC_MODULUS_SIZE];
668    
669          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
670                                    &modulus, &exponent))          {
671                    DEBUG(("Failed to parse crypt info\n"));
672                  return;                  return;
673            }
674    
675            DEBUG(("Generating client random\n"));
676            // This is what the MS client do:
677            memset(inr, 0, SEC_RANDOM_SIZE);
678            /*  *ARIGL!* Plaintext attack, anyone?
679                I tried doing:
680                generate_random(inr);
681                ..but that generates connection errors now and then (yes,
682                "now and then". Something like 0 to 3 attempts needed before a
683                successful connection. Nice. Not!
684            */
685    
         /* Generate a client random, and hence determine encryption keys */  
686          generate_random(client_random);          generate_random(client_random);
687          sec_rsa_encrypt(sec_crypted_random, client_random,          if (NULL != server_public_key)
688                          SEC_RANDOM_SIZE, modulus, exponent);          {                       /* Which means we should use
689                                       RDP5-style encryption */
690    
691                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
692                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
693    
694                    RSA_public_encrypt(SEC_MODULUS_SIZE,
695                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
696    
697                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
698    
699            }
700            else
701            {                       /* RDP4-style encryption */
702                    sec_rsa_encrypt(sec_crypted_random,
703                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
704            }
705          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
706  }  }
707    
708  /* Process connect response data blob */  
709    /* Process SRV_INFO, find RDP version supported by server */
710  static void  static void
711    sec_process_srv_info(STREAM s)
712    {
713            in_uint16_le(s, server_rdp_version);
714            DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
715    }
716    
717    
718    /* Process connect response data blob */
719    void
720  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
721  {  {
722          uint16 tag, length;          uint16 tag, length;
723          uint8 *next_tag;          uint8 *next_tag;
724            uint8 len;
725    
726          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */
727            in_uint8(s, len);
728            if (len & 0x80)
729                    in_uint8(s, len);
730    
731          while (s->p < s->end)          while (s->p < s->end)
732          {          {
# Line 565  sec_process_mcs_data(STREAM s) Line 741  sec_process_mcs_data(STREAM s)
741                  switch (tag)                  switch (tag)
742                  {                  {
743                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
744                                    sec_process_srv_info(s);
745                                    break;
746    
747                          case SEC_TAG_SRV_3:                          case SEC_TAG_SRV_3:
748                                  break;                                  break;
749    
# Line 582  sec_process_mcs_data(STREAM s) Line 761  sec_process_mcs_data(STREAM s)
761    
762  /* Receive secure transport packet */  /* Receive secure transport packet */
763  STREAM  STREAM
764  sec_recv()  sec_recv(void)
765  {  {
766          uint32 sec_flags;          uint32 sec_flags;
767            uint16 channel;
768          STREAM s;          STREAM s;
769    
770          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
771          {          {
772                  if (encryption || !licence_issued)                  if (encryption || !licence_issued)
773                  {                  {
# Line 595  sec_recv() Line 775  sec_recv()
775    
776                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
777                          {                          {
778                                    if (sec_flags & SEC_ENCRYPT) {
779                                            DEBUG_RDP5(("Encrypted license detected\n"));
780                                    }
781                                  licence_process(s);                                  licence_process(s);
782                                  continue;                                  continue;
783                          }                          }
# Line 606  sec_recv() Line 789  sec_recv()
789                          }                          }
790                  }                  }
791    
792                  return s;                  if (MCS_GLOBAL_CHANNEL == channel)
793                    {
794                            return s;
795                    }
796                    else
797                            rdp5_process_channel(s, channel);
798    
799          }          }
800    
801          return NULL;          return NULL;
# Line 614  sec_recv() Line 803  sec_recv()
803    
804  /* Establish a secure connection */  /* Establish a secure connection */
805  BOOL  BOOL
806  sec_connect(char *server)  sec_connect(char *server, char *username)
807  {  {
808          struct stream mcs_data;          struct stream mcs_data;
809    
810          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
811          mcs_data.size = 512;          mcs_data.size = 512;
812          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8*)xmalloc(mcs_data.size);
813          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
814    
815          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
816                  return False;                  return False;
817    
818          sec_process_mcs_data(&mcs_data);          //      sec_process_mcs_data(&mcs_data);
819          if (encryption)          if (encryption)
820                  sec_establish_key();                  sec_establish_key();
821            xfree(mcs_data.data);
822          return True;          return True;
823  }  }
824    
825  /* Disconnect a connection */  /* Disconnect a connection */
826  void  void
827  sec_disconnect()  sec_disconnect(void)
828  {  {
829          mcs_disconnect();          mcs_disconnect();
830  }  }

Legend:
Removed from v.61  
changed lines
  Added in v.377

  ViewVC Help
Powered by ViewVC 1.1.26