ReactOS  0.4.13-dev-464-g6b95727
secure.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 8 -*-
2  rdesktop: A Remote Desktop Protocol client.
3  Protocol services - RDP encryption and licensing
4  Copyright (C) Matthew Chapman 1999-2005
5 
6  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
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "rdesktop.h"
22 #include <string.h>
23 
24 // TODO: remove dependency on OpenSSL
25 #include <openssl/rc4.h>
26 #include <openssl/md5.h>
27 #include <openssl/sha.h>
28 #include <openssl/bn.h>
29 #include <openssl/x509v3.h>
30 
31 /*
32  * I believe this is based on SSLv3 with the following differences:
33  * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
34  * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
35  * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
36  * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
37  * encryption/decryption keys updated every 4096 packets
38  * See http://wp.netscape.com/eng/ssl3/draft302.txt
39  */
40 
41 /*
42  * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
43  * Both SHA1 and MD5 algorithms are used.
44  */
45 void
46 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
47 {
48  uint8 shasig[20];
49  uint8 pad[4];
50  SHA_CTX sha;
51  MD5_CTX md5;
52  int i;
53 
54  for (i = 0; i < 3; i++)
55  {
56  memset(pad, salt + i, i + 1);
57 
58  SHA1_Init(&sha);
59  SHA1_Update(&sha, pad, i + 1);
60  SHA1_Update(&sha, in, 48);
61  SHA1_Update(&sha, salt1, 32);
62  SHA1_Update(&sha, salt2, 32);
63  SHA1_Final(shasig, &sha);
64 
65  MD5_Init(&md5);
66  MD5_Update(&md5, in, 48);
67  MD5_Update(&md5, shasig, 20);
68  MD5_Final(&out[i * 16], &md5);
69  }
70 }
71 
72 /*
73  * 16-byte transformation used to generate export keys (6.2.2).
74  */
75 void
76 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
77 {
78  MD5_CTX md5;
79 
80  MD5_Init(&md5);
81  MD5_Update(&md5, in, 16);
82  MD5_Update(&md5, salt1, 32);
83  MD5_Update(&md5, salt2, 32);
84  MD5_Final(out, &md5);
85 }
86 
87 /* Reduce key entropy from 64 to 40 bits */
88 static void
90 {
91  key[0] = 0xd1;
92  key[1] = 0x26;
93  key[2] = 0x9e;
94 }
95 
96 /* Generate encryption keys given client and server randoms */
97 static void
98 sec_generate_keys(RDPCLIENT * This, uint8 * client_random, uint8 * server_random, int rc4_key_size)
99 {
100  uint8 pre_master_secret[48];
101  uint8 master_secret[48];
102  uint8 key_block[48];
103 
104  /* Construct pre-master secret */
105  memcpy(pre_master_secret, client_random, 24);
106  memcpy(pre_master_secret + 24, server_random, 24);
107 
108  /* Generate master secret and then key material */
109  sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
110  sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
111 
112  /* First 16 bytes of key material is MAC secret */
113  memcpy(This->secure.sign_key, key_block, 16);
114 
115  /* Generate export keys from next two blocks of 16 bytes */
116  sec_hash_16(This->secure.decrypt_key, &key_block[16], client_random, server_random);
117  sec_hash_16(This->secure.encrypt_key, &key_block[32], client_random, server_random);
118 
119  if (rc4_key_size == 1)
120  {
121  DEBUG(("40-bit encryption enabled\n"));
122  sec_make_40bit(This->secure.sign_key);
123  sec_make_40bit(This->secure.decrypt_key);
124  sec_make_40bit(This->secure.encrypt_key);
125  This->secure.rc4_key_len = 8;
126  }
127  else
128  {
129  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
130  This->secure.rc4_key_len = 16;
131  }
132 
133  /* Save initial RC4 keys as update keys */
134  memcpy(This->secure.decrypt_update_key, This->secure.decrypt_key, 16);
135  memcpy(This->secure.encrypt_update_key, This->secure.encrypt_key, 16);
136 
137  /* Initialise RC4 state arrays */
138  RC4_set_key(&This->secure.rc4_decrypt_key, This->secure.rc4_key_len, This->secure.decrypt_key);
139  RC4_set_key(&This->secure.rc4_encrypt_key, This->secure.rc4_key_len, This->secure.encrypt_key);
140 }
141 
142 static const uint8 pad_54[40] = {
143  54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
144  54, 54, 54,
145  54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
146  54, 54, 54
147 };
148 
149 static const uint8 pad_92[48] = {
150  92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
151  92, 92, 92, 92, 92, 92, 92,
152  92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
153  92, 92, 92, 92, 92, 92, 92
154 };
155 
156 /* Output a uint32 into a buffer (little-endian) */
157 void
159 {
160  buffer[0] = (value) & 0xff;
161  buffer[1] = (value >> 8) & 0xff;
162  buffer[2] = (value >> 16) & 0xff;
163  buffer[3] = (value >> 24) & 0xff;
164 }
165 
166 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
167 void
168 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
169 {
170  uint8 shasig[20];
171  uint8 md5sig[16];
172  uint8 lenhdr[4];
173  SHA_CTX sha;
174  MD5_CTX md5;
175 
176  buf_out_uint32(lenhdr, datalen);
177 
178  SHA1_Init(&sha);
179  SHA1_Update(&sha, session_key, keylen);
180  SHA1_Update(&sha, pad_54, 40);
181  SHA1_Update(&sha, lenhdr, 4);
182  SHA1_Update(&sha, data, datalen);
183  SHA1_Final(shasig, &sha);
184 
185  MD5_Init(&md5);
186  MD5_Update(&md5, session_key, keylen);
187  MD5_Update(&md5, pad_92, 48);
188  MD5_Update(&md5, shasig, 20);
189  MD5_Final(md5sig, &md5);
190 
191  memcpy(signature, md5sig, siglen);
192 }
193 
194 /* Update an encryption key */
195 static void
196 sec_update(RDPCLIENT * This, uint8 * key, uint8 * update_key)
197 {
198  uint8 shasig[20];
199  SHA_CTX sha;
200  MD5_CTX md5;
201  RC4_KEY update;
202 
203  SHA1_Init(&sha);
204  SHA1_Update(&sha, update_key, This->secure.rc4_key_len);
205  SHA1_Update(&sha, pad_54, 40);
206  SHA1_Update(&sha, key, This->secure.rc4_key_len);
207  SHA1_Final(shasig, &sha);
208 
209  MD5_Init(&md5);
210  MD5_Update(&md5, update_key, This->secure.rc4_key_len);
211  MD5_Update(&md5, pad_92, 48);
212  MD5_Update(&md5, shasig, 20);
213  MD5_Final(key, &md5);
214 
215  RC4_set_key(&update, This->secure.rc4_key_len, key);
216  RC4(&update, This->secure.rc4_key_len, key, key);
217 
218  if (This->secure.rc4_key_len == 8)
220 }
221 
222 /* Encrypt data using RC4 */
223 static void
225 {
226  if (This->secure.encrypt_use_count == 4096)
227  {
228  sec_update(This, This->secure.encrypt_key, This->secure.encrypt_update_key);
229  RC4_set_key(&This->secure.rc4_encrypt_key, This->secure.rc4_key_len, This->secure.encrypt_key);
230  This->secure.encrypt_use_count = 0;
231  }
232 
233  RC4(&This->secure.rc4_encrypt_key, length, data, data);
234  This->secure.encrypt_use_count++;
235 }
236 
237 /* Decrypt data using RC4 */
238 void
240 {
241  if (This->secure.decrypt_use_count == 4096)
242  {
243  sec_update(This, This->secure.decrypt_key, This->secure.decrypt_update_key);
244  RC4_set_key(&This->secure.rc4_decrypt_key, This->secure.rc4_key_len, This->secure.decrypt_key);
245  This->secure.decrypt_use_count = 0;
246  }
247 
248  RC4(&This->secure.rc4_decrypt_key, length, data, data);
249  This->secure.decrypt_use_count++;
250 }
251 
252 static void
254 {
255  int i, j;
256  uint8 temp;
257 
258  for (i = 0, j = len - 1; i < j; i++, j--)
259  {
260  temp = p[i];
261  p[i] = p[j];
262  p[j] = temp;
263  }
264 }
265 
266 /* Perform an RSA public key encryption operation */
267 static void
268 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
269  uint8 * exponent)
270 {
271  BN_CTX *ctx;
272  BIGNUM mod, exp, x, y;
274  int outlen;
275 
276  reverse(modulus, modulus_size);
277  reverse(exponent, SEC_EXPONENT_SIZE);
278  memcpy(inr, in, len);
279  reverse(inr, len);
280 
281  ctx = BN_CTX_new();
282  BN_init(&mod);
283  BN_init(&exp);
284  BN_init(&x);
285  BN_init(&y);
286 
287  BN_bin2bn(modulus, modulus_size, &mod);
288  BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
289  BN_bin2bn(inr, len, &x);
290  BN_mod_exp(&y, &x, &exp, &mod, ctx);
291  outlen = BN_bn2bin(&y, out);
292  reverse(out, outlen);
293  if ((uint32)outlen < modulus_size)
294  memset(out + outlen, 0, modulus_size - outlen);
295 
296  BN_free(&y);
297  BN_clear_free(&x);
298  BN_free(&exp);
299  BN_free(&mod);
300  BN_CTX_free(ctx);
301 }
302 
303 /* Initialise secure transport packet */
304 STREAM
306 {
307  int hdrlen;
308  STREAM s;
309 
310  if (!This->licence_issued)
311  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
312  else
313  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
314  s = mcs_init(This, maxlen + hdrlen);
315 
316  if(s == NULL)
317  return s;
318 
319  s_push_layer(s, sec_hdr, hdrlen);
320 
321  return s;
322 }
323 
324 /* Transmit secure transport packet over specified channel */
325 
326 // !!! we need a lock here !!!
327 BOOL
329 {
330  int datalen;
331 
333  if (!This->licence_issued || (flags & SEC_ENCRYPT))
335 
336  if (flags & SEC_ENCRYPT)
337  {
338  flags &= ~SEC_ENCRYPT;
339  datalen = (int)(s->end - s->p - 8);
340 
341 #if WITH_DEBUG
342  DEBUG(("Sending encrypted packet:\n"));
343  hexdump(s->p + 8, datalen);
344 #endif
345 
346  sec_sign(s->p, 8, This->secure.sign_key, This->secure.rc4_key_len, s->p + 8, datalen);
347  sec_encrypt(This, s->p + 8, datalen);
348  }
349 
350  return mcs_send_to_channel(This, s, channel);
351 }
352 
353 /* Transmit secure transport packet */
354 
355 BOOL
357 {
359 }
360 
361 
362 /* Transfer the client random to the server */
363 static void
365 {
366  uint32 length = This->secure.server_public_key_len + SEC_PADDING_SIZE;
368  STREAM s;
369 
370  s = sec_init(This, flags, length + 4);
371 
373  out_uint8p(s, This->secure.crypted_random, This->secure.server_public_key_len);
375 
376  s_mark_end(s);
377  sec_send(This, s, flags);
378 }
379 
380 /* Output connect initial data blob */
381 static void
383 {
384  int hostlen = 2 * (int)wcslen(hostname);
385  int length = 158 + 76 + 12 + 4;
386  unsigned int i;
387 
388  if (This->num_channels > 0)
389  length += This->num_channels * 12 + 8;
390 
391  if (hostlen > 30)
392  hostlen = 30;
393 
394  /* Generic Conference Control (T.124) ConferenceCreateRequest */
395  out_uint16_be(s, 5);
396  out_uint16_be(s, 0x14);
397  out_uint8(s, 0x7c);
398  out_uint16_be(s, 1);
399 
400  out_uint16_be(s, (length | 0x8000)); /* remaining length */
401 
402  out_uint16_be(s, 8); /* length? */
403  out_uint16_be(s, 16);
404  out_uint8(s, 0);
405  out_uint16_le(s, 0xc001);
406  out_uint8(s, 0);
407 
408  out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
409  out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
410 
411  /* Client information */
413  out_uint16_le(s, 212); /* length */
414  out_uint16_le(s, This->use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
415  out_uint16_le(s, 8);
416  out_uint16_le(s, This->width);
417  out_uint16_le(s, This->height);
418  out_uint16_le(s, 0xca01);
419  out_uint16_le(s, 0xaa03);
420  out_uint32_le(s, This->keylayout);
421  out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
422 
423  /* Unicode name of client, padded to 32 bytes */
424  rdp_out_unistr(This, s, hostname, hostlen);
425  out_uint8s(s, 30 - hostlen);
426 
427  /* See
428  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
429  out_uint32_le(s, This->keyboard_type);
430  out_uint32_le(s, This->keyboard_subtype);
431  out_uint32_le(s, This->keyboard_functionkeys);
432  out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
433  out_uint16_le(s, 0xca01); /* colour depth? */
434  out_uint16_le(s, 1);
435 
436  out_uint32(s, 0);
437  out_uint8(s, This->server_depth);
438  out_uint16_le(s, 0x0700);
439  out_uint8(s, 0);
440  out_uint32_le(s, 1);
441  out_uint8s(s, 64); /* End of client info */
442 
444  out_uint16_le(s, 12);
445  out_uint32_le(s, This->console_session ? 0xb : 9);
446  out_uint32(s, 0);
447 
448  /* Client encryption settings */
450  out_uint16_le(s, 12); /* length */
451  out_uint32_le(s, This->encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
452  out_uint32(s, 0); /* Unknown */
453 
454  DEBUG_RDP5(("This->num_channels is %d\n", This->num_channels));
455  if (This->num_channels > 0)
456  {
458  out_uint16_le(s, This->num_channels * 12 + 8); /* length */
459  out_uint32_le(s, This->num_channels); /* number of virtual channels */
460  for (i = 0; i < This->num_channels; i++)
461  {
462  DEBUG_RDP5(("Requesting channel %s\n", This->channels[i].name));
463  out_uint8a(s, This->channel_defs[i].name, 8);
464  out_uint32_be(s, This->channel_defs[i].options);
465  }
466  }
467 
468  s_mark_end(s);
469 }
470 
471 /* Parse a public key structure */
472 static BOOL
474 {
475  uint32 magic, modulus_len;
476 
477  in_uint32_le(s, magic);
478  if (magic != SEC_RSA_MAGIC)
479  {
480  error("RSA magic 0x%x\n", magic);
481  return False;
482  }
483 
484  in_uint32_le(s, modulus_len);
485  modulus_len -= SEC_PADDING_SIZE;
486  if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
487  {
488  error("Bad server public key size (%u bits)\n", modulus_len * 8);
489  return False;
490  }
491 
492  in_uint8s(s, 8); /* modulus_bits, unknown */
493  in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
494  in_uint8p(s, *modulus, modulus_len);
496  This->secure.server_public_key_len = modulus_len;
497 
498  return s_check(s);
499 }
500 
501 static BOOL
503 {
504  EVP_PKEY *epk = NULL;
505  /* By some reason, Microsoft sets the OID of the Public RSA key to
506  the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
507 
508  Kudos to Richard Levitte for the following (. intiutive .)
509  lines of code that resets the OID and let's us extract the key. */
510  if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
511  {
512  DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
513  ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
514  cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
515  }
516  epk = X509_get_pubkey(cert);
517  if (NULL == epk)
518  {
519  error("Failed to extract public key from certificate\n");
520  return False;
521  }
522 
523  This->secure.server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
524  EVP_PKEY_free(epk);
525 
526  This->secure.server_public_key_len = RSA_size(This->secure.server_public_key);
527  if ((This->secure.server_public_key_len < 64) || (This->secure.server_public_key_len > SEC_MAX_MODULUS_SIZE))
528  {
529  error("Bad server public key size (%u bits)\n", This->secure.server_public_key_len * 8);
530  return False;
531  }
532 
533  return True;
534 }
535 
536 
537 /* Parse a crypto information structure */
538 static BOOL
540  uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
541 {
542  uint32 crypt_level, random_len, rsa_info_len;
543  uint32 cacert_len, cert_len, flags;
544  X509 *cacert, *server_cert;
545  uint16 tag, length;
546  uint8 *next_tag, *end;
547 
548  in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
549  in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
550  if (crypt_level == 0) /* no encryption */
551  return False;
552  in_uint32_le(s, random_len);
553  in_uint32_le(s, rsa_info_len);
554 
555  if (random_len != SEC_RANDOM_SIZE)
556  {
557  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
558  return False;
559  }
560 
561  in_uint8p(s, *server_random, random_len);
562 
563  /* RSA info */
564  end = s->p + rsa_info_len;
565  if (end > s->end)
566  return False;
567 
568  in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
569  if (flags & 1)
570  {
571  DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
572  in_uint8s(s, 8); /* unknown */
573 
574  while (s->p < end)
575  {
576  in_uint16_le(s, tag);
578 
579  next_tag = s->p + length;
580 
581  switch (tag)
582  {
583  case SEC_TAG_PUBKEY:
584  if (!sec_parse_public_key(This, s, modulus, exponent))
585  return False;
586  DEBUG_RDP5(("Got Public key, RDP4-style\n"));
587 
588  break;
589 
590  case SEC_TAG_KEYSIG:
591  /* Is this a Microsoft key that we just got? */
592  /* Care factor: zero! */
593  /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
594  key as a known key of the hostname. This would prevent some MITM-attacks. */
595  break;
596 
597  default:
598  unimpl("crypt tag 0x%x\n", tag);
599  }
600 
601  s->p = next_tag;
602  }
603  }
604  else
605  {
606  uint32 certcount;
607 
608  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
609  in_uint32_le(s, certcount); /* Number of certificates */
610 
611  if (certcount < 2)
612  {
613  error("Server didn't send enough X509 certificates\n");
614  This->disconnect_reason = 1798;
615  return False;
616  }
617 
618  for (; certcount > 2; certcount--)
619  { /* ignore all the certificates between the root and the signing CA */
620  uint32 ignorelen;
621  X509 *ignorecert;
622 
623  DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
624 
625  in_uint32_le(s, ignorelen);
626  DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
627  ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
628 
629  if (ignorecert == NULL)
630  { /* XXX: error out? */
631  DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
632  }
633 
634 #ifdef WITH_DEBUG_RDP5
635  DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
636  X509_print_fp(stdout, ignorecert);
637 #endif
638  }
639 
640  /* Do da funky X.509 stuffy
641 
642  "How did I find out about this? I looked up and saw a
643  bright light and when I came to I had a scar on my forehead
644  and knew about X.500"
645  - Peter Gutman in a early version of
646  http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
647  */
648 
649  in_uint32_le(s, cacert_len);
650  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
651  cacert = d2i_X509(NULL, &(s->p), cacert_len);
652  /* Note: We don't need to move s->p here - d2i_X509 is
653  "kind" enough to do it for us */
654  if (NULL == cacert)
655  {
656  error("Couldn't load CA Certificate from server\n");
657  This->disconnect_reason = 1798;
658  return False;
659  }
660 
661  /* Currently, we don't use the CA Certificate.
662  FIXME:
663  *) Verify the server certificate (server_cert) with the
664  CA certificate.
665  *) Store the CA Certificate with the hostname of the
666  server we are connecting to as key, and compare it
667  when we connect the next time, in order to prevent
668  MITM-attacks.
669  */
670 
671  X509_free(cacert);
672 
673  in_uint32_le(s, cert_len);
674  DEBUG_RDP5(("Certificate length is %d\n", cert_len));
675  server_cert = d2i_X509(NULL, &(s->p), cert_len);
676  if (NULL == server_cert)
677  {
678  error("Couldn't load Certificate from server\n");
679  This->disconnect_reason = 1798;
680  return False;
681  }
682 
683  in_uint8s(s, 16); /* Padding */
684 
685  /* Note: Verifying the server certificate must be done here,
686  before sec_parse_public_key since we'll have to apply
687  serious violence to the key after this */
688 
689  if (!sec_parse_x509_key(This, server_cert))
690  {
691  DEBUG_RDP5(("Didn't parse X509 correctly\n"));
692  X509_free(server_cert);
693  This->disconnect_reason = 1798;
694  return False;
695  }
696  X509_free(server_cert);
697  return True; /* There's some garbage here we don't care about */
698  }
699  return s_check_end(s);
700 }
701 
702 /* Process crypto information blob */
703 static void
705 {
706  uint8 *server_random, *modulus, *exponent;
707  uint8 client_random[SEC_RANDOM_SIZE];
708  uint32 rc4_key_size;
709 
710  if (!sec_parse_crypt_info(This, s, &rc4_key_size, &server_random, &modulus, &exponent))
711  {
712  DEBUG(("Failed to parse crypt info\n"));
713  return;
714  }
715 
716  DEBUG(("Generating client random\n"));
717  generate_random(client_random);
718 
719  if (NULL != This->secure.server_public_key)
720  { /* Which means we should use
721  RDP5-style encryption */
723  uint32 padding_len = This->secure.server_public_key_len - SEC_RANDOM_SIZE;
724 
725  /* This is what the MS client do: */
726  memset(inr, 0, padding_len);
727  /* *ARIGL!* Plaintext attack, anyone?
728  I tried doing:
729  generate_random(inr);
730  ..but that generates connection errors now and then (yes,
731  "now and then". Something like 0 to 3 attempts needed before a
732  successful connection. Nice. Not!
733  */
734  memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
735  reverse(inr + padding_len, SEC_RANDOM_SIZE);
736 
737  RSA_public_encrypt(This->secure.server_public_key_len,
738  inr, This->secure.crypted_random, This->secure.server_public_key, RSA_NO_PADDING);
739 
740  reverse(This->secure.crypted_random, This->secure.server_public_key_len);
741 
742  RSA_free(This->secure.server_public_key);
743  This->secure.server_public_key = NULL;
744  }
745  else
746  { /* RDP4-style encryption */
747  sec_rsa_encrypt(This->secure.crypted_random,
748  client_random, SEC_RANDOM_SIZE, This->secure.server_public_key_len, modulus,
749  exponent);
750  }
751  sec_generate_keys(This, client_random, server_random, rc4_key_size);
752 }
753 
754 
755 /* Process SRV_INFO, find RDP version supported by server */
756 static void
758 {
759  in_uint16_le(s, This->server_rdp_version);
760  DEBUG_RDP5(("Server RDP version is %d\n", This->server_rdp_version));
761  if (1 == This->server_rdp_version)
762  {
763  This->use_rdp5 = 0;
764  This->server_depth = 8;
765  }
766 }
767 
768 
769 /* Process connect response data blob */
770 void
772 {
773  uint16 tag, length;
774  uint8 *next_tag;
775  uint8 len;
776 
777  in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
778  in_uint8(s, len);
779  if (len & 0x80)
780  in_uint8(s, len);
781 
782  while (s->p < s->end)
783  {
784  in_uint16_le(s, tag);
786 
787  if (length <= 4)
788  return;
789 
790  next_tag = s->p + length - 4;
791 
792  switch (tag)
793  {
794  case SEC_TAG_SRV_INFO:
796  break;
797 
798  case SEC_TAG_SRV_CRYPT:
800  break;
801 
803  /* FIXME: We should parse this information and
804  use it to map RDP5 channels to MCS
805  channels */
806  break;
807 
808  default:
809  unimpl("response tag 0x%x\n", tag);
810  }
811 
812  s->p = next_tag;
813  }
814 }
815 
816 /* Receive secure transport packet */
817 STREAM
819 {
820  uint32 sec_flags;
821  uint16 channel;
822  STREAM s;
823 
824  while ((s = mcs_recv(This, &channel, rdpver)) != NULL)
825  {
826  if (rdpver != NULL)
827  {
828  if (*rdpver != 3)
829  {
830  if (*rdpver & 0x80)
831  {
832  in_uint8s(s, 8); /* signature */
833  sec_decrypt(This, s->p, (int)(s->end - s->p));
834  }
835  return s;
836  }
837  }
838  if (This->encryption || !This->licence_issued)
839  {
840  in_uint32_le(s, sec_flags);
841 
842  if (sec_flags & SEC_ENCRYPT)
843  {
844  in_uint8s(s, 8); /* signature */
845  sec_decrypt(This, s->p, (int)(s->end - s->p));
846  }
847 
848  if (sec_flags & SEC_LICENCE_NEG)
849  {
851  continue;
852  }
853 
854  if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
855  {
856  uint8 swapbyte;
857 
858  in_uint8s(s, 8); /* signature */
859  sec_decrypt(This, s->p, (int)(s->end - s->p));
860 
861  /* Check for a redirect packet, starts with 00 04 */
862  if (s->p[0] == 0 && s->p[1] == 4)
863  {
864  /* for some reason the PDU and the length seem to be swapped.
865  This isn't good, but we're going to do a byte for byte
866  swap. So the first foure value appear as: 00 04 XX YY,
867  where XX YY is the little endian length. We're going to
868  use 04 00 as the PDU type, so after our swap this will look
869  like: XX YY 04 00 */
870  swapbyte = s->p[0];
871  s->p[0] = s->p[2];
872  s->p[2] = swapbyte;
873 
874  swapbyte = s->p[1];
875  s->p[1] = s->p[3];
876  s->p[3] = swapbyte;
877 
878  swapbyte = s->p[2];
879  s->p[2] = s->p[3];
880  s->p[3] = swapbyte;
881  }
882 #ifdef WITH_DEBUG
883  /* warning! this debug statement will show passwords in the clear! */
884  hexdump(s->p, s->end - s->p);
885 #endif
886  }
887 
888  }
889 
890  if (channel != MCS_GLOBAL_CHANNEL)
891  {
892  channel_process(This, s, channel);
893  *rdpver = 0xff;
894  return s;
895  }
896 
897  return s;
898  }
899 
900  return NULL;
901 }
902 
903 /* Establish a secure connection */
904 BOOL
905 sec_connect(RDPCLIENT * This, char *server, wchar_t *hostname, char *cookie)
906 {
907  struct stream mcs_data;
908  void * p = malloc(512);
909 
910  if(p == NULL)
911  {
912  This->disconnect_reason = 262;
913  return False;
914  }
915 
916  /* We exchange some RDP data during the MCS-Connect */
917  mcs_data.size = 512;
918  mcs_data.p = mcs_data.data = (uint8 *) p;
919  sec_out_mcs_data(This, &mcs_data, hostname);
920 
921  if (!mcs_connect(This, server, cookie, &mcs_data))
922  return False;
923 
924  /* sec_process_mcs_data(&mcs_data); */
925  if (This->encryption)
927  free(mcs_data.data);
928  return True;
929 }
930 
931 /* Establish a secure connection */
932 BOOL
933 sec_reconnect(RDPCLIENT * This, char *server, wchar_t *hostname, char *cookie)
934 {
935  struct stream mcs_data;
936  void * p = malloc(512);
937 
938  if(p == NULL)
939  {
940  This->disconnect_reason = 262;
941  return False;
942  }
943 
944  /* We exchange some RDP data during the MCS-Connect */
945  mcs_data.size = 512;
946  mcs_data.p = mcs_data.data = (uint8 *) p;
947  sec_out_mcs_data(This, &mcs_data, hostname);
948 
949  if (!mcs_reconnect(This, server, cookie, &mcs_data))
950  return False;
951 
952  /* sec_process_mcs_data(&mcs_data); */
953  if (This->encryption)
955  free(mcs_data.data);
956  return True;
957 }
958 
959 /* Disconnect a connection */
960 void
962 {
964 }
965 
966 /* reset the state of the sec layer */
967 void
969 {
970  This->server_rdp_version = 0;
971  This->secure.encrypt_use_count = 0;
972  This->secure.decrypt_use_count = 0;
974 }
static const WCHAR sha[]
Definition: oid.c:1218
#define out_uint16_le(s, v)
Definition: parse.h:58
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
#define out_uint8p(s, v, n)
Definition: parse.h:93
static void sec_update(RDPCLIENT *This, uint8 *key, uint8 *update_key)
Definition: secure.c:196
#define SEC_TAG_CLI_INFO
Definition: constants.h:119
#define SEC_TAG_CLI_CRYPT
Definition: constants.h:120
#define SEC_RSA_MAGIC
Definition: constants.h:127
static rfbScreenInfoPtr server
Definition: vnc.c:74
#define error(str)
Definition: mkdosfs.c:1605
#define out_uint8a(s, v, n)
Definition: parse.h:94
void mcs_send_to_channel(STREAM s, uint16 channel)
Definition: mcs.c:254
void sec_reset_state(void)
Definition: secure.c:1039
void sec_process_mcs_data(STREAM s)
Definition: secure.c:856
unsigned int uint32
Definition: types.h:32
#define free
Definition: debug_ros.c:5
#define SEC_TAG_PUBKEY
Definition: constants.h:124
static BOOL sec_parse_x509_key(RDPCLIENT *This, X509 *cert)
Definition: secure.c:502
#define out_uint32_le(s, v)
Definition: parse.h:59
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
Definition: md5.c:258
u32_t magic(void)
Definition: ecma_167.h:138
#define SEC_MAX_MODULUS_SIZE
Definition: constants.h:93
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
void channel_process(STREAM s, uint16 mcs_channel)
Definition: channels.c:138
GLuint GLuint end
Definition: gl.h:1545
BOOL sec_reconnect(RDPCLIENT *This, char *server, wchar_t *hostname, char *cookie)
Definition: secure.c:933
unsigned char * data
Definition: parse.h:26
static void sec_process_srv_info(RDPCLIENT *This, STREAM s)
Definition: secure.c:757
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
#define in_uint8p(s, v, n)
Definition: parse.h:89
void sec_decrypt(uint8 *data, int length)
Definition: secure.c:396
FILE * stdout
#define s_check(s)
Definition: parse.h:42
char * hostname
Definition: ftp.c:88
#define SEC_TAG_CLI_CHANNELS
Definition: constants.h:121
#define MCS_GLOBAL_CHANNEL
Definition: constants.h:87
static BOOL sec_parse_crypt_info(RDPCLIENT *This, STREAM s, uint32 *rc4_key_size, uint8 **server_random, uint8 **modulus, uint8 **exponent)
Definition: secure.c:539
#define out_uint8(s, v)
Definition: parse.h:92
static const uint8 pad_92[48]
Definition: secure.c:149
static void reverse(uint8 *p, int len)
Definition: secure.c:253
void mcs_reset_state(void)
Definition: mcs.c:363
static void sec_out_mcs_data(RDPCLIENT *This, STREAM s, wchar_t *hostname)
Definition: secure.c:382
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
Definition: secure.c:314
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
static void sec_encrypt(RDPCLIENT *This, uint8 *data, int length)
Definition: secure.c:224
Definition: addons.c:68
unsigned int BOOL
Definition: ntddk_ex.h:94
static const WCHAR RSA[]
Definition: oid.c:1223
#define s_pop_layer(s, h)
Definition: parse.h:40
smooth NULL
Definition: ftsmooth.c:416
#define SEC_TAG_CLI_4
Definition: constants.h:82
#define in_uint8s(s, n)
Definition: parse.h:91
static BYTE cert[]
Definition: msg.c:1437
#define SEC_ENCRYPT
Definition: constants.h:101
#define out_uint8s(s, n)
Definition: parse.h:95
static void sec_establish_key(RDPCLIENT *This)
Definition: secure.c:364
#define s_check_end(s)
Definition: parse.h:44
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static void sec_rsa_encrypt(uint8 *out, uint8 *in, int len, uint32 modulus_size, uint8 *modulus, uint8 *exponent)
Definition: secure.c:268
#define SEC_TAG_SRV_CHANNELS
Definition: constants.h:117
static void sec_process_crypt_info(RDPCLIENT *This, STREAM s)
Definition: secure.c:704
#define True
Definition: types.h:24
static void pad(Char *s)
Definition: bzip2.c:908
void MD5_Init(MD5_CTX *ctx)
Definition: md5.c:207
#define False
Definition: types.h:25
#define SEC_EXPONENT_SIZE
Definition: constants.h:95
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define SEC_RANDOM_SIZE
Definition: constants.h:91
static FILE * out
Definition: regtests2xml.c:44
STREAM sec_recv(uint8 *rdpver)
Definition: secure.c:903
unsigned char uint8
Definition: types.h:28
static const uint8 pad_54[40]
Definition: secure.c:142
static void sec_make_40bit(uint8 *key)
Definition: secure.c:89
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
RD_BOOL sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
Definition: secure.c:1005
STREAM mcs_init(int length)
Definition: mcs.c:242
unsigned int size
Definition: parse.h:27
Definition: parse.h:22
#define SEC_PADDING_SIZE
Definition: constants.h:94
STREAM mcs_recv(uint16 *channel, uint8 *rdpver)
Definition: mcs.c:280
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
GLsizei const GLfloat * value
Definition: glext.h:6069
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:218
#define SEC_TAG_KEYSIG
Definition: constants.h:125
#define out_uint32_be(s, v)
Definition: parse.h:78
static BOOL sec_parse_public_key(RDPCLIENT *This, STREAM s, uint8 **modulus, uint8 **exponent)
Definition: secure.c:473
#define s_push_layer(s, h, n)
Definition: parse.h:39
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
static void sec_generate_keys(RDPCLIENT *This, uint8 *client_random, uint8 *server_random, int rc4_key_size)
Definition: secure.c:98
#define SEC_TAG_SRV_CRYPT
Definition: constants.h:116
GLuint in
Definition: glext.h:9616
static calc_node_t temp
Definition: rpn_ieee.c:38
void sec_disconnect(void)
Definition: secure.c:1032
void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
unsigned short uint16
Definition: types.h:30
void rdp_out_unistr(STREAM s, char *string, int len)
Definition: rdp.c:188
#define in_uint8(s, v)
Definition: parse.h:88
DWORD exp
Definition: msg.c:15681
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
unsigned char * p
Definition: parse.h:24
#define out_uint16_be(s, v)
Definition: parse.h:77
void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
Definition: secure.c:436
unsigned char * sec_hdr
Definition: parse.h:32
void generate_random(uint8 *random)
Definition: uimain.c:709
#define out_uint32(s, v)
Definition: parse.h:85
#define md5
Definition: compat-1.3.h:2010
#define malloc
Definition: debug_ros.c:4
void unimpl(char *format,...)
Definition: uimain.c:801
#define DEBUG(args)
Definition: rdesktop.h:129
#define s_mark_end(s)
Definition: parse.h:41
Definition: msi.c:4078
BOOL mcs_reconnect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:424
GLfloat GLfloat p
Definition: glext.h:8902
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
#define in_uint32_le(s, v)
Definition: parse.h:56
void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
Definition: secure.c:155
#define SEC_TAG_SRV_INFO
Definition: constants.h:115
BOOL mcs_connect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:388
#define memset(x, y, z)
Definition: compat.h:39
void mcs_disconnect(void)
Definition: mcs.c:356
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define SEC_LICENCE_NEG
Definition: constants.h:72
#define SEC_CLIENT_RANDOM
Definition: constants.h:69
void licence_process(STREAM s)
Definition: licence.c:378
#define in_uint16_le(s, v)
Definition: parse.h:55
Definition: path.c:42
static int mod
Definition: i386-dis.c:1273
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
char * tag
Definition: main.c:59