/[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 352 by forsberg, Thu Mar 27 13:29:36 2003 UTC revision 642 by matthewc, Thu Mar 18 02:32:00 2004 UTC
# Line 34  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 use_rdp5;  extern BOOL g_use_rdp5;
43  extern int server_bpp;  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;
# Line 54  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 server_rdp_version = 0;  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,
# Line 330  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 340  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 364  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 390  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 + 20;          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);
# Line 408  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, ((length - 14) | 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, 212);  /* length */          out_uint16_le(s, 212);  /* length */
435          out_uint16_le(s, use_rdp5 ? 4 : 1);     /* RDP version. 1 == RDP4, 4 == RDP5. */          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);
# Line 432  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          switch (server_bpp)          switch (g_server_bpp)
454          {          {
455                  case 8:                  case 8:
456                          out_uint16_le(s, 0xca01);                          out_uint16_le(s, 0xca01);
# Line 447  sec_out_mcs_data(STREAM s) Line 465  sec_out_mcs_data(STREAM s)
465                          out_uint16_le(s, 0xca04);                          out_uint16_le(s, 0xca04);
466                          break;                          break;
467          }          }
468          out_uint16(s, 1);          out_uint16_le(s, 1);
469    
470          out_uint32(s, 0);          out_uint32(s, 0);
471          out_uint32_le(s, 0x070008);          out_uint8(s, g_server_bpp);
472            out_uint16_le(s, 0x0700);
473            out_uint8(s, 0);
474          out_uint32_le(s, 1);          out_uint32_le(s, 1);
475          out_uint8s(s, 64);      /* End of client info */          out_uint8s(s, 64);      /* End of client info */
476    
477          out_uint16_le(s, SEC_TAG_CLI_4);          out_uint16_le(s, SEC_TAG_CLI_4);
478          out_uint16_le(s, 12);          out_uint16_le(s, 12);
479          out_uint32_le(s, 9);          out_uint32_le(s, g_console_session ? 0xb : 9);
480          out_uint32_le(s, 0);          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, 12);   /* 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_le(s, 0);    /* Unknown */          out_uint32(s, 0);       /* Unknown */
487    
488          out_uint16_le(s, SEC_TAG_CLI_CHANNELS);          DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
489          out_uint16_le(s, 20);   /* length */          if (g_num_channels > 0)
490          out_uint32_le(s, 1);    /* number of virtual channels */          {
491          out_uint8p(s, "cliprdr", 8);    /* name padded to 8(?) */                  out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
492          out_uint16(s, 0);                  out_uint16_le(s, g_num_channels * 12 + 8);      /* length */
493          out_uint16_le(s, 0xc0a0);       /* Flags. Rumours tell this is documented in MSDN. */                  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  }  }
# Line 536  sec_parse_crypt_info(STREAM s, uint32 * Line 563  sec_parse_crypt_info(STREAM s, uint32 *
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;          uint32 cacert_len, cert_len, flags;
567          X509 *cacert, *server_cert;          X509 *cacert, *server_cert;
568          uint16 tag, length;          uint16 tag, length;
569          uint8 *next_tag, *end;          uint8 *next_tag, *end;
# Line 561  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          if (!use_rdp5 || 1 == server_rdp_version)          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"));                  DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
595                  in_uint8s(s, 12);       /* unknown */                  in_uint8s(s, 8);        /* unknown */
596    
597                  while (s->p < end)                  while (s->p < end)
598                  {                  {
# Line 596  sec_parse_crypt_info(STREAM s, uint32 * Line 624  sec_parse_crypt_info(STREAM s, uint32 *
624                          s->p = next_tag;                          s->p = next_tag;
625                  }                  }
626          }          }
627          else if (4 == server_rdp_version)          else
628          {          {
629                    uint32 certcount;
630    
631                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
632                  in_uint8s(s, 8);        /* Unknown */                  in_uint32_le(s, certcount);     /* Number of certificates */
633    
634                    if (certcount < 2)
635                    {
636                            error("Server didn't send enough X509 certificates\n");
637                            return False;
638                    }
639    
640                    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    #ifdef WITH_DEBUG_RDP5
657                            DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
658                            X509_print_fp(stdout, ignorecert);
659    #endif
660                    }
661    
662                  /* Do da funky X.509 stuffy                  /* Do da funky X.509 stuffy
663    
# Line 611  sec_parse_crypt_info(STREAM s, uint32 * Line 669  sec_parse_crypt_info(STREAM s, uint32 *
669                   */                   */
670    
671                  in_uint32_le(s, cacert_len);                  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);                  cacert = d2i_X509(NULL, &(s->p), cacert_len);
674                  /* Note: We don't need to move s->p here - d2i_X509 is                  /* Note: We don't need to move s->p here - d2i_X509 is
675                     "kind" enough to do it for us */                     "kind" enough to do it for us */
# Line 631  sec_parse_crypt_info(STREAM s, uint32 * Line 690  sec_parse_crypt_info(STREAM s, uint32 *
690                   */                   */
691    
692                  in_uint32_le(s, cert_len);                  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);                  server_cert = d2i_X509(NULL, &(s->p), cert_len);
695                  if (NULL == server_cert)                  if (NULL == server_cert)
696                  {                  {
# Line 651  sec_parse_crypt_info(STREAM s, uint32 * Line 711  sec_parse_crypt_info(STREAM s, uint32 *
711                  }                  }
712                  return True;    /* There's some garbage here we don't care about */                  return True;    /* There's some garbage here we don't care about */
713          }          }
         else  
         {  
                 error("Unknown Server RDP version %d", server_rdp_version);  
                 return False;  
         }  
714          return s_check_end(s);          return s_check_end(s);
715  }  }
716    
# Line 676  sec_process_crypt_info(STREAM s) Line 731  sec_process_crypt_info(STREAM s)
731    
732          DEBUG(("Generating client random\n"));          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          generate_random(inr);          /* This is what the MS client do: */
735          // This is what the MS client do:          memset(inr, 0, SEC_RANDOM_SIZE);
736          //      memset(inr, 0, SEC_RANDOM_SIZE);          /*  *ARIGL!* Plaintext attack, anyone?
737          // *ARIGL!*             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          if (NULL != server_public_key)          if (NULL != server_public_key)
746          {                       /* Which means we should use          {                       /* Which means we should use
# Line 707  sec_process_crypt_info(STREAM s) Line 768  sec_process_crypt_info(STREAM s)
768  static void  static void
769  sec_process_srv_info(STREAM s)  sec_process_srv_info(STREAM s)
770  {  {
771          in_uint16_le(s, server_rdp_version);          in_uint16_le(s, g_server_rdp_version);
772          DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));          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    
# Line 720  sec_process_mcs_data(STREAM s) Line 783  sec_process_mcs_data(STREAM s)
783          uint8 *next_tag;          uint8 *next_tag;
784          uint8 len;          uint8 len;
785    
786          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */          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 741  sec_process_mcs_data(STREAM s) Line 804  sec_process_mcs_data(STREAM s)
804                                  sec_process_srv_info(s);                                  sec_process_srv_info(s);
805                                  break;                                  break;
806    
                         case SEC_TAG_SRV_3:  
                                 break;  
   
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 766  sec_recv(void) Line 832  sec_recv(void)
832    
833          while ((s = mcs_recv(&channel)) != 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    
                         if (sec_flags & SEC_LICENCE_NEG)  
                         {  
                                 licence_process(s);  
                                 continue;  
                         }  
   
839                          if (sec_flags & SEC_ENCRYPT)                          if (sec_flags & SEC_ENCRYPT)
840                          {                          {
841                                  in_uint8s(s, 8);        /* signature */                                  in_uint8s(s, 8);        /* signature */
842                                  sec_decrypt(s->p, s->end - s->p);                                  sec_decrypt(s->p, s->end - s->p);
843                          }                          }
844    
845                            if (sec_flags & SEC_LICENCE_NEG)
846                            {
847                                    licence_process(s);
848                                    continue;
849                            }
850                  }                  }
851    
852                  if (MCS_GLOBAL_CHANNEL == channel)                  if (channel != MCS_GLOBAL_CHANNEL)
853                  {                  {
854                          return s;                          channel_process(s, channel);
855                            continue;
856                  }                  }
                 else  
                         rdp5_process_channel(s, channel);  
857    
858                    return s;
859          }          }
860    
861          return NULL;          return NULL;
# Line 803  sec_connect(char *server, char *username Line 869  sec_connect(char *server, char *username
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, username))          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);          xfree(mcs_data.data);
882          return True;          return True;

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

  ViewVC Help
Powered by ViewVC 1.1.26