/[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 207 by matthewc, Thu Sep 26 14:26:46 2002 UTC revision 642 by matthewc, Thu Mar 18 02:32:00 2004 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing     Protocol services - RDP encryption and licensing
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2002
# 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 33  Line 34 
34  #endif  #endif
35    
36  extern char hostname[16];  extern char hostname[16];
37  extern int width;  extern int g_width;
38  extern int height;  extern int g_height;
39  extern int keylayout;  extern int keylayout;
40  extern BOOL encryption;  extern BOOL g_encryption;
41  extern BOOL licence_issued;  extern BOOL g_licence_issued;
42    extern BOOL g_use_rdp5;
43    extern BOOL g_console_session;
44    extern int g_server_bpp;
45    extern uint16 mcs_userid;
46    extern VCHANNEL g_channels[];
47    extern unsigned int g_num_channels;
48    
49  static int rc4_key_len;  static int rc4_key_len;
50  static RC4_KEY rc4_decrypt_key;  static RC4_KEY rc4_decrypt_key;
51  static RC4_KEY rc4_encrypt_key;  static RC4_KEY rc4_encrypt_key;
52    static RSA *server_public_key;
53    
54  static uint8 sec_sign_key[16];  static uint8 sec_sign_key[16];
55  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
# Line 50  static uint8 sec_decrypt_update_key[16]; Line 58  static uint8 sec_decrypt_update_key[16];
58  static uint8 sec_encrypt_update_key[16];  static uint8 sec_encrypt_update_key[16];
59  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
60    
61    uint16 g_server_rdp_version = 0;
62    
63  /*  /*
64   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * General purpose 48-byte transformation, using two 32-byte salts (generally,
65   * 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.
# Line 140  sec_generate_keys(uint8 * client_key, ui Line 150  sec_generate_keys(uint8 * client_key, ui
150          }          }
151          else          else
152          {          {
153                  DEBUG(("128-bit encryption enabled\n"));                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
154                  rc4_key_len = 16;                  rc4_key_len = 16;
155          }          }
156    
# Line 251  sec_encrypt(uint8 * data, int length) Line 261  sec_encrypt(uint8 * data, int length)
261  }  }
262    
263  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
264  static void  void
265  sec_decrypt(uint8 * data, int length)  sec_decrypt(uint8 * data, int length)
266  {  {
267          static int use_count;          static int use_count;
# Line 285  reverse(uint8 * p, int len) Line 295  reverse(uint8 * p, int len)
295  static void  static void
296  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)
297  {  {
298          BN_CTX ctx;          BN_CTX *ctx;
299          BIGNUM mod, exp, x, y;          BIGNUM mod, exp, x, y;
300          uint8 inr[SEC_MODULUS_SIZE];          uint8 inr[SEC_MODULUS_SIZE];
301          int outlen;          int outlen;
# Line 295  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 305  sec_rsa_encrypt(uint8 * out, uint8 * in,
305          memcpy(inr, in, len);          memcpy(inr, in, len);
306          reverse(inr, len);          reverse(inr, len);
307    
308          BN_CTX_init(&ctx);          ctx = BN_CTX_new();
309          BN_init(&mod);          BN_init(&mod);
310          BN_init(&exp);          BN_init(&exp);
311          BN_init(&x);          BN_init(&x);
# Line 304  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 314  sec_rsa_encrypt(uint8 * out, uint8 * in,
314          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);          BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
315          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);          BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
316          BN_bin2bn(inr, len, &x);          BN_bin2bn(inr, len, &x);
317          BN_mod_exp(&y, &x, &exp, &mod, &ctx);          BN_mod_exp(&y, &x, &exp, &mod, ctx);
318          outlen = BN_bn2bin(&y, out);          outlen = BN_bn2bin(&y, out);
319          reverse(out, outlen);          reverse(out, outlen);
320          if (outlen < SEC_MODULUS_SIZE)          if (outlen < SEC_MODULUS_SIZE)
# Line 314  sec_rsa_encrypt(uint8 * out, uint8 * in, Line 324  sec_rsa_encrypt(uint8 * out, uint8 * in,
324          BN_clear_free(&x);          BN_clear_free(&x);
325          BN_free(&exp);          BN_free(&exp);
326          BN_free(&mod);          BN_free(&mod);
327          BN_CTX_free(&ctx);          BN_CTX_free(ctx);
328  }  }
329    
330  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 324  sec_init(uint32 flags, int maxlen) Line 334  sec_init(uint32 flags, int maxlen)
334          int hdrlen;          int hdrlen;
335          STREAM s;          STREAM s;
336    
337          if (!licence_issued)          if (!g_licence_issued)
338                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
339          else          else
340                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
# Line 334  sec_init(uint32 flags, int maxlen) Line 344  sec_init(uint32 flags, int maxlen)
344          return s;          return s;
345  }  }
346    
347  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
348  void  void
349  sec_send(STREAM s, uint32 flags)  sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
350  {  {
351          int datalen;          int datalen;
352    
353          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
354          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
355                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
356    
357          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
# Line 358  sec_send(STREAM s, uint32 flags) Line 368  sec_send(STREAM s, uint32 flags)
368                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
369          }          }
370    
371          mcs_send(s);          mcs_send_to_channel(s, channel);
372    }
373    
374    /* Transmit secure transport packet */
375    
376    void
377    sec_send(STREAM s, uint32 flags)
378    {
379            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
380  }  }
381    
382    
383  /* Transfer the client random to the server */  /* Transfer the client random to the server */
384  static void  static void
385  sec_establish_key(void)  sec_establish_key(void)
# Line 384  static void Line 403  static void
403  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
404  {  {
405          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(hostname);
406            int length = 158 + 76 + 12 + 4;
407            unsigned int i;
408    
409            if (g_num_channels > 0)
410                    length += g_num_channels * 12 + 8;
411    
412          if (hostlen > 30)          if (hostlen > 30)
413                  hostlen = 30;                  hostlen = 30;
414    
415          out_uint16_be(s, 5);    /* unknown */          /* Generic Conference Control (T.124) ConferenceCreateRequest */
416            out_uint16_be(s, 5);
417          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
418          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
419          out_uint16_be(s, 1);          out_uint16_be(s, 1);
420    
421          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
422    
423          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
424          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 401  sec_out_mcs_data(STREAM s) Line 426  sec_out_mcs_data(STREAM s)
426          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
427          out_uint8(s, 0);          out_uint8(s, 0);
428    
429          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
430          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
431    
432          /* Client information */          /* Client information */
433          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
434          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
435          out_uint16_le(s, 1);          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
436          out_uint16_le(s, 8);          out_uint16_le(s, 8);
437          out_uint16_le(s, width);          out_uint16_le(s, g_width);
438          out_uint16_le(s, height);          out_uint16_le(s, g_height);
439          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
440          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
441          out_uint32_le(s, keylayout);          out_uint32_le(s, keylayout);
442          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
443    
444          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
445          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, hostname, hostlen);
# Line 425  sec_out_mcs_data(STREAM s) Line 450  sec_out_mcs_data(STREAM s)
450          out_uint32_le(s, 12);          out_uint32_le(s, 12);
451          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
452    
453          out_uint16_le(s, 0xca01);          switch (g_server_bpp)
454          out_uint16(s, 0);          {
455                    case 8:
456                            out_uint16_le(s, 0xca01);
457                            break;
458                    case 15:
459                            out_uint16_le(s, 0xca02);
460                            break;
461                    case 16:
462                            out_uint16_le(s, 0xca03);
463                            break;
464                    case 24:
465                            out_uint16_le(s, 0xca04);
466                            break;
467            }
468            out_uint16_le(s, 1);
469    
470            out_uint32(s, 0);
471            out_uint8(s, g_server_bpp);
472            out_uint16_le(s, 0x0700);
473            out_uint8(s, 0);
474            out_uint32_le(s, 1);
475            out_uint8s(s, 64);      /* End of client info */
476    
477            out_uint16_le(s, SEC_TAG_CLI_4);
478            out_uint16_le(s, 12);
479            out_uint32_le(s, g_console_session ? 0xb : 9);
480            out_uint32(s, 0);
481    
482          /* Client encryption settings */          /* Client encryption settings */
483          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
484          out_uint16_le(s, 8);    /* length */          out_uint16_le(s, 12);   /* length */
485          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 */
486            out_uint32(s, 0);       /* Unknown */
487    
488            DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
489            if (g_num_channels > 0)
490            {
491                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
492                    out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
493                    out_uint32_le(s, g_num_channels);       /* number of virtual channels */
494                    for (i = 0; i < g_num_channels; i++)
495                    {
496                            DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
497                            out_uint8a(s, g_channels[i].name, 8);
498                            out_uint32_be(s, g_channels[i].flags);
499                    }
500            }
501    
502          s_mark_end(s);          s_mark_end(s);
503  }  }
504    
# Line 463  sec_parse_public_key(STREAM s, uint8 ** Line 530  sec_parse_public_key(STREAM s, uint8 **
530          return s_check(s);          return s_check(s);
531  }  }
532    
533    static BOOL
534    sec_parse_x509_key(X509 * cert)
535    {
536            EVP_PKEY *epk = NULL;
537            /* By some reason, Microsoft sets the OID of the Public RSA key to
538               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
539    
540               Kudos to Richard Levitte for the following (. intiutive .)
541               lines of code that resets the OID and let's us extract the key. */
542            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
543            {
544                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
545                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
546            }
547            epk = X509_get_pubkey(cert);
548            if (NULL == epk)
549            {
550                    error("Failed to extract public key from certificate\n");
551                    return False;
552            }
553    
554            server_public_key = (RSA *) epk->pkey.ptr;
555    
556            return True;
557    }
558    
559    
560  /* Parse a crypto information structure */  /* Parse a crypto information structure */
561  static BOOL  static BOOL
562  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
563                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
564  {  {
565          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
566            uint32 cacert_len, cert_len, flags;
567            X509 *cacert, *server_cert;
568          uint16 tag, length;          uint16 tag, length;
569          uint8 *next_tag, *end;          uint8 *next_tag, *end;
570    
571          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 */
572          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
573          if (crypt_level == 0)   /* no encryptation */          if (crypt_level == 0)   /* no encryption */
574                  return False;                  return False;
575          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
576          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
577    
578          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
579          {          {
580                  error("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
581                  return False;                  return False;
582          }          }
583    
# Line 492  sec_parse_crypt_info(STREAM s, uint32 * Line 588  sec_parse_crypt_info(STREAM s, uint32 *
588          if (end > s->end)          if (end > s->end)
589                  return False;                  return False;
590    
591          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
592            if (flags & 1)
593            {
594                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
595                    in_uint8s(s, 8);        /* unknown */
596    
597                    while (s->p < end)
598                    {
599                            in_uint16_le(s, tag);
600                            in_uint16_le(s, length);
601    
602                            next_tag = s->p + length;
603    
604                            switch (tag)
605                            {
606                                    case SEC_TAG_PUBKEY:
607                                            if (!sec_parse_public_key(s, modulus, exponent))
608                                                    return False;
609                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
610    
611                                            break;
612    
613                                    case SEC_TAG_KEYSIG:
614                                            /* Is this a Microsoft key that we just got? */
615                                            /* Care factor: zero! */
616                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
617                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
618                                            break;
619    
620          while (s->p < end)                                  default:
621                                            unimpl("crypt tag 0x%x\n", tag);
622                            }
623    
624                            s->p = next_tag;
625                    }
626            }
627            else
628          {          {
629                  in_uint16_le(s, tag);                  uint32 certcount;
                 in_uint16_le(s, length);  
630    
631                  next_tag = s->p + length;                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
632                    in_uint32_le(s, certcount);     /* Number of certificates */
633    
634                  switch (tag)                  if (certcount < 2)
635                  {                  {
636                          case SEC_TAG_PUBKEY:                          error("Server didn't send enough X509 certificates\n");
637                                  if (!sec_parse_public_key(s, modulus, exponent))                          return False;
638                                          return False;                  }
639    
640                                  break;                  for (; certcount > 2; certcount--)
641                    {               /* ignore all the certificates between the root and the signing CA */
642                            uint32 ignorelen;
643                            X509 *ignorecert;
644    
645                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
646    
647                            in_uint32_le(s, ignorelen);
648                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
649                            ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
650    
651                            if (ignorecert == NULL)
652                            {       /* XXX: error out? */
653                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
654                            }
655    
656                          case SEC_TAG_KEYSIG:  #ifdef WITH_DEBUG_RDP5
657                                  /* Is this a Microsoft key that we just got? */                          DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
658                                  /* Care factor: zero! */                          X509_print_fp(stdout, ignorecert);
659                                  break;  #endif
660                    }
661    
662                          default:                  /* Do da funky X.509 stuffy
663                                  unimpl("crypt tag 0x%x\n", tag);  
664                       "How did I find out about this?  I looked up and saw a
665                       bright light and when I came to I had a scar on my forehead
666                       and knew about X.500"
667                       - Peter Gutman in a early version of
668                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
669                     */
670    
671                    in_uint32_le(s, cacert_len);
672                    DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
673                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
674                    /* Note: We don't need to move s->p here - d2i_X509 is
675                       "kind" enough to do it for us */
676                    if (NULL == cacert)
677                    {
678                            error("Couldn't load CA Certificate from server\n");
679                            return False;
680                  }                  }
681    
682                  s->p = next_tag;                  /* Currently, we don't use the CA Certificate.
683          }                     FIXME:
684                       *) Verify the server certificate (server_cert) with the
685                       CA certificate.
686                       *) Store the CA Certificate with the hostname of the
687                       server we are connecting to as key, and compare it
688                       when we connect the next time, in order to prevent
689                       MITM-attacks.
690                     */
691    
692                    in_uint32_le(s, cert_len);
693                    DEBUG_RDP5(("Certificate length is %d\n", cert_len));
694                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
695                    if (NULL == server_cert)
696                    {
697                            error("Couldn't load Certificate from server\n");
698                            return False;
699                    }
700    
701                    in_uint8s(s, 16);       /* Padding */
702    
703                    /* Note: Verifying the server certificate must be done here,
704                       before sec_parse_public_key since we'll have to apply
705                       serious violence to the key after this */
706    
707                    if (!sec_parse_x509_key(server_cert))
708                    {
709                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
710                            return False;
711                    }
712                    return True;    /* There's some garbage here we don't care about */
713            }
714          return s_check_end(s);          return s_check_end(s);
715  }  }
716    
# Line 531  sec_process_crypt_info(STREAM s) Line 721  sec_process_crypt_info(STREAM s)
721          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
722          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
723          uint32 rc4_key_size;          uint32 rc4_key_size;
724            uint8 inr[SEC_MODULUS_SIZE];
725    
726          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))
727            {
728                    DEBUG(("Failed to parse crypt info\n"));
729                  return;                  return;
730            }
731    
732            DEBUG(("Generating client random\n"));
733          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
734            /* This is what the MS client do: */
735            memset(inr, 0, SEC_RANDOM_SIZE);
736            /*  *ARIGL!* Plaintext attack, anyone?
737               I tried doing:
738               generate_random(inr);
739               ..but that generates connection errors now and then (yes,
740               "now and then". Something like 0 to 3 attempts needed before a
741               successful connection. Nice. Not!
742             */
743    
744          generate_random(client_random);          generate_random(client_random);
745          sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);          if (NULL != server_public_key)
746            {                       /* Which means we should use
747                                       RDP5-style encryption */
748    
749                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
750                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
751    
752                    RSA_public_encrypt(SEC_MODULUS_SIZE,
753                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
754    
755                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
756    
757            }
758            else
759            {                       /* RDP4-style encryption */
760                    sec_rsa_encrypt(sec_crypted_random,
761                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
762            }
763          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
764  }  }
765    
766  /* Process connect response data blob */  
767    /* Process SRV_INFO, find RDP version supported by server */
768  static void  static void
769    sec_process_srv_info(STREAM s)
770    {
771            in_uint16_le(s, g_server_rdp_version);
772            DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
773            if (1 == g_server_rdp_version)
774                    g_use_rdp5 = 0;
775    }
776    
777    
778    /* Process connect response data blob */
779    void
780  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
781  {  {
782          uint16 tag, length;          uint16 tag, length;
783          uint8 *next_tag;          uint8 *next_tag;
784          uint8 len;          uint8 len;
785    
786          in_uint8s(s, 21);       /* header */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
787          in_uint8(s, len);          in_uint8(s, len);
788          if (len & 0x80)          if (len & 0x80)
789                  in_uint8(s, len);                  in_uint8(s, len);
# Line 567  sec_process_mcs_data(STREAM s) Line 801  sec_process_mcs_data(STREAM s)
801                  switch (tag)                  switch (tag)
802                  {                  {
803                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
804                          case SEC_TAG_SRV_3:                                  sec_process_srv_info(s);
805                                  break;                                  break;
806    
807                          case SEC_TAG_SRV_CRYPT:                          case SEC_TAG_SRV_CRYPT:
808                                  sec_process_crypt_info(s);                                  sec_process_crypt_info(s);
809                                  break;                                  break;
810    
811                            case SEC_TAG_SRV_CHANNELS:
812                                    /* FIXME: We should parse this information and
813                                       use it to map RDP5 channels to MCS
814                                       channels */
815                                    break;
816    
817                          default:                          default:
818                                  unimpl("response tag 0x%x\n", tag);                                  unimpl("response tag 0x%x\n", tag);
819                  }                  }
# Line 587  STREAM Line 827  STREAM
827  sec_recv(void)  sec_recv(void)
828  {  {
829          uint32 sec_flags;          uint32 sec_flags;
830            uint16 channel;
831          STREAM s;          STREAM s;
832    
833          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
834          {          {
835                  if (encryption || !licence_issued)                  if (g_encryption || !g_licence_issued)
836                  {                  {
837                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
838    
839                            if (sec_flags & SEC_ENCRYPT)
840                            {
841                                    in_uint8s(s, 8);        /* signature */
842                                    sec_decrypt(s->p, s->end - s->p);
843                            }
844    
845                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
846                          {                          {
847                                  licence_process(s);                                  licence_process(s);
848                                  continue;                                  continue;
849                          }                          }
850                    }
851    
852                          if (sec_flags & SEC_ENCRYPT)                  if (channel != MCS_GLOBAL_CHANNEL)
853                          {                  {
854                                  in_uint8s(s, 8);        /* signature */                          channel_process(s, channel);
855                                  sec_decrypt(s->p, s->end - s->p);                          continue;
                         }  
856                  }                  }
857    
858                  return s;                  return s;
# Line 616  sec_recv(void) Line 863  sec_recv(void)
863    
864  /* Establish a secure connection */  /* Establish a secure connection */
865  BOOL  BOOL
866  sec_connect(char *server)  sec_connect(char *server, char *username)
867  {  {
868          struct stream mcs_data;          struct stream mcs_data;
869    
870          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
871          mcs_data.size = 512;          mcs_data.size = 512;
872          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
873          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
874    
875          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
876                  return False;                  return False;
877    
878          sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
879          if (encryption)          if (g_encryption)
880                  sec_establish_key();                  sec_establish_key();
881            xfree(mcs_data.data);
882          return True;          return True;
883  }  }
884    

Legend:
Removed from v.207  
changed lines
  Added in v.642

  ViewVC Help
Powered by ViewVC 1.1.26