]> git.sesse.net Git - rdpsrv/blob - secure.c
51e5f84c22062d965d3f6ea21a87ba34abd93049
[rdpsrv] / secure.c
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-2002
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
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "rdesktop.h"
22
23 #include <openssl/rc4.h>
24 #include <openssl/md5.h>
25 #include <openssl/sha.h>
26 #include <openssl/bn.h>
27 #include <openssl/x509v3.h>
28
29 extern char hostname[16];
30 extern int g_width;
31 extern int g_height;
32 extern int keylayout;
33 extern BOOL g_encryption;
34 extern BOOL g_licence_issued;
35 extern BOOL g_use_rdp5;
36 extern BOOL g_console_session;
37 extern int g_server_bpp;
38 extern uint16 mcs_userid;
39 extern VCHANNEL g_channels[];
40 extern unsigned int g_num_channels;
41
42 static int rc4_key_len;
43 static RC4_KEY rc4_decrypt_key;
44 static RC4_KEY rc4_encrypt_key;
45 static RSA *server_public_key;
46
47 static uint8 sec_sign_key[16];
48 static uint8 sec_decrypt_key[16];
49 static uint8 sec_encrypt_key[16];
50 static uint8 sec_decrypt_update_key[16];
51 static uint8 sec_encrypt_update_key[16];
52 static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
53
54 RSA *privkey;
55
56 uint16 g_server_rdp_version = 0;
57
58 /*
59  * General purpose 48-byte transformation, using two 32-byte salts (generally,
60  * a client and server salt) and a global salt value used for padding.
61  * Both SHA1 and MD5 algorithms are used.
62  */
63 void
64 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
65 {
66         uint8 shasig[20];
67         uint8 pad[4];
68         SHA_CTX sha;
69         MD5_CTX md5;
70         int i;
71
72         for (i = 0; i < 3; i++)
73         {
74                 memset(pad, salt + i, i + 1);
75
76                 SHA1_Init(&sha);
77                 SHA1_Update(&sha, pad, i + 1);
78                 SHA1_Update(&sha, in, 48);
79                 SHA1_Update(&sha, salt1, 32);
80                 SHA1_Update(&sha, salt2, 32);
81                 SHA1_Final(shasig, &sha);
82
83                 MD5_Init(&md5);
84                 MD5_Update(&md5, in, 48);
85                 MD5_Update(&md5, shasig, 20);
86                 MD5_Final(&out[i * 16], &md5);
87         }
88 }
89
90 /*
91  * Weaker 16-byte transformation, also using two 32-byte salts, but
92  * only using a single round of MD5.
93  */
94 void
95 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
96 {
97         MD5_CTX md5;
98
99         MD5_Init(&md5);
100         MD5_Update(&md5, in, 16);
101         MD5_Update(&md5, salt1, 32);
102         MD5_Update(&md5, salt2, 32);
103         MD5_Final(out, &md5);
104 }
105
106 /* Reduce key entropy from 64 to 40 bits */
107 static void
108 sec_make_40bit(uint8 * key)
109 {
110         key[0] = 0xd1;
111         key[1] = 0x26;
112         key[2] = 0x9e;
113 }
114
115 /* Generate a session key and RC4 keys, given client and server randoms */
116 static void
117 sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
118 {
119         uint8 session_key[48];
120         uint8 temp_hash[48];
121         uint8 input[48];
122
123         /* Construct input data to hash */
124         memcpy(input, client_key, 24);
125         memcpy(input + 24, server_key, 24);
126
127         /* Generate session key - two rounds of sec_hash_48 */
128         sec_hash_48(temp_hash, input, client_key, server_key, 65);
129         sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
130
131         /* Store first 16 bytes of session key, for generating signatures */
132         memcpy(sec_sign_key, session_key, 16);
133
134         /* Generate RC4 keys */
135         sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
136         sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
137
138         if (rc4_key_size == 1)
139         {
140                 DEBUG(("40-bit encryption enabled\n"));
141                 sec_make_40bit(sec_sign_key);
142                 sec_make_40bit(sec_decrypt_key);
143                 sec_make_40bit(sec_encrypt_key);
144                 rc4_key_len = 8;
145         }
146         else
147         {
148                 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
149                 rc4_key_len = 16;
150         }
151
152         /* Save initial RC4 keys as update keys */
153         memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
154         memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
155
156         /* Initialise RC4 state arrays */
157         RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
158         RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
159
160         {
161                 int i;
162                 printf("sec_decrypt_key: ");
163                 for (i = 0; i < 16; ++i)
164                         printf("0x%02x ", sec_decrypt_key[i]);
165                 printf("\n");
166                 
167                 printf("sec_encrypt_key: ");
168                 for (i = 0; i < 16; ++i)
169                         printf("0x%02x ", sec_encrypt_key[i]);
170                 printf("\n");
171         }
172 }
173
174 static uint8 pad_54[40] = {
175         54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
176         54, 54, 54,
177         54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
178         54, 54, 54
179 };
180
181 static uint8 pad_92[48] = {
182         92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
183         92, 92, 92, 92, 92, 92, 92,
184         92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
185         92, 92, 92, 92, 92, 92, 92
186 };
187
188 /* Output a uint32 into a buffer (little-endian) */
189 void
190 buf_out_uint32(uint8 * buffer, uint32 value)
191 {
192         buffer[0] = (value) & 0xff;
193         buffer[1] = (value >> 8) & 0xff;
194         buffer[2] = (value >> 16) & 0xff;
195         buffer[3] = (value >> 24) & 0xff;
196 }
197
198 /* Generate a signature hash, using a combination of SHA1 and MD5 */
199 void
200 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
201 {
202         uint8 shasig[20];
203         uint8 md5sig[16];
204         uint8 lenhdr[4];
205         SHA_CTX sha;
206         MD5_CTX md5;
207
208         buf_out_uint32(lenhdr, datalen);
209
210         SHA1_Init(&sha);
211         SHA1_Update(&sha, session_key, keylen);
212         SHA1_Update(&sha, pad_54, 40);
213         SHA1_Update(&sha, lenhdr, 4);
214         SHA1_Update(&sha, data, datalen);
215         SHA1_Final(shasig, &sha);
216
217         MD5_Init(&md5);
218         MD5_Update(&md5, session_key, keylen);
219         MD5_Update(&md5, pad_92, 48);
220         MD5_Update(&md5, shasig, 20);
221         MD5_Final(md5sig, &md5);
222
223         memcpy(signature, md5sig, siglen);
224 }
225
226 /* Update an encryption key - similar to the signing process */
227 static void
228 sec_update(uint8 * key, uint8 * update_key)
229 {
230         uint8 shasig[20];
231         SHA_CTX sha;
232         MD5_CTX md5;
233         RC4_KEY update;
234
235         SHA1_Init(&sha);
236         SHA1_Update(&sha, update_key, rc4_key_len);
237         SHA1_Update(&sha, pad_54, 40);
238         SHA1_Update(&sha, key, rc4_key_len);
239         SHA1_Final(shasig, &sha);
240
241         MD5_Init(&md5);
242         MD5_Update(&md5, update_key, rc4_key_len);
243         MD5_Update(&md5, pad_92, 48);
244         MD5_Update(&md5, shasig, 20);
245         MD5_Final(key, &md5);
246
247         RC4_set_key(&update, rc4_key_len, key);
248         RC4(&update, rc4_key_len, key, key);
249
250         if (rc4_key_len == 8)
251                 sec_make_40bit(key);
252 }
253
254 /* Encrypt data using RC4 */
255 static void
256 sec_encrypt(uint8 * data, int length)
257 {
258         static int use_count;
259
260         if (use_count == 4096)
261         {
262                 sec_update(sec_decrypt_key, sec_decrypt_update_key);
263                 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
264                 use_count = 0;
265         }
266
267         RC4(&rc4_decrypt_key, length, data, data);
268         use_count++;
269 }
270
271 /* Decrypt data using RC4 */
272 void
273 sec_decrypt(uint8 * data, int length)
274 {
275         static int use_count;
276
277         if (use_count == 4096)
278         {
279                 sec_update(sec_encrypt_key, sec_encrypt_update_key);
280                 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
281                 use_count = 0;
282         }
283
284         RC4(&rc4_encrypt_key, length, data, data);
285         use_count++;
286 }
287
288 static void
289 reverse(uint8 * p, int len)
290 {
291         int i, j;
292         uint8 temp;
293
294         for (i = 0, j = len - 1; i < j; i++, j--)
295         {
296                 temp = p[i];
297                 p[i] = p[j];
298                 p[j] = temp;
299         }
300 }
301
302 /* Perform an RSA public key encryption operation */
303 static void
304 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
305 {
306         BN_CTX *ctx;
307         BIGNUM mod, exp, x, y;
308         uint8 inr[SEC_MODULUS_SIZE];
309         int outlen;
310
311         reverse(modulus, SEC_MODULUS_SIZE);
312         reverse(exponent, SEC_EXPONENT_SIZE);
313         memcpy(inr, in, len);
314         reverse(inr, len);
315
316         ctx = BN_CTX_new();
317         BN_init(&mod);
318         BN_init(&exp);
319         BN_init(&x);
320         BN_init(&y);
321
322         BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
323         BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
324         BN_bin2bn(inr, len, &x);
325         BN_mod_exp(&y, &x, &exp, &mod, ctx);
326         outlen = BN_bn2bin(&y, out);
327         reverse(out, outlen);
328         if (outlen < SEC_MODULUS_SIZE)
329                 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
330
331         BN_free(&y);
332         BN_clear_free(&x);
333         BN_free(&exp);
334         BN_free(&mod);
335         BN_CTX_free(ctx);
336 }
337
338 /* Initialise secure transport packet */
339 STREAM
340 sec_init(uint32 flags, int maxlen)
341 {
342         int hdrlen;
343         STREAM s;
344
345         /*if (!g_licence_issued) */
346                 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
347 /*      else
348                 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0; */
349         s = mcs_init(maxlen + hdrlen);
350         s_push_layer(s, sec_hdr, hdrlen);
351
352         return s;
353 }
354
355 /* Transmit secure transport packet over specified channel */
356 void
357 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
358 {
359         int datalen;
360
361 //      DEBUG(("sending packet to channel %u\n", channel));
362         
363         s_pop_layer(s, sec_hdr);
364 //      if (!g_licence_issued || (flags & SEC_ENCRYPT))
365                 out_uint32_le(s, flags);
366
367         if (flags & SEC_ENCRYPT)
368         {
369                 flags &= ~SEC_ENCRYPT;
370                 datalen = s->end - s->p - 8;
371
372 #if WITH_DEBUG
373                 DEBUG(("Sending encrypted packet:\n"));
374                 hexdump(s->p + 8, datalen);
375 #endif
376
377                 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
378                 sec_encrypt(s->p + 8, datalen);
379         }
380
381         mcs_send_to_channel(s, channel);
382 }
383
384 /* Transmit secure transport packet */
385
386 void
387 sec_send(STREAM s, uint32 flags)
388 {
389         sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
390 }
391
392
393 /* Transfer the client random to the server */
394 static void
395 sec_establish_key(void)
396 {
397         uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
398         uint32 flags = SEC_CLIENT_RANDOM;
399         STREAM s;
400
401         s = sec_init(flags, 76);
402
403         out_uint32_le(s, length);
404         out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
405         out_uint8s(s, SEC_PADDING_SIZE);
406
407         s_mark_end(s);
408         sec_send(s, flags);
409 }
410
411 /* Parse a public key structure */
412 static BOOL
413 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
414 {
415         uint32 magic, modulus_len;
416
417         in_uint32_le(s, magic);
418         if (magic != SEC_RSA_MAGIC)
419         {
420                 error("RSA magic 0x%x\n", magic);
421                 return False;
422         }
423
424         in_uint32_le(s, modulus_len);
425         if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
426         {
427                 error("modulus len 0x%x\n", modulus_len);
428                 return False;
429         }
430
431         in_uint8s(s, 8);        /* modulus_bits, unknown */
432         in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
433         in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
434         in_uint8s(s, SEC_PADDING_SIZE);
435
436         return s_check(s);
437 }
438
439 static BOOL
440 sec_parse_x509_key(X509 * cert)
441 {
442         EVP_PKEY *epk = NULL;
443         /* By some reason, Microsoft sets the OID of the Public RSA key to
444            the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
445
446            Kudos to Richard Levitte for the following (. intiutive .) 
447            lines of code that resets the OID and let's us extract the key. */
448         if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
449         {
450                 DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
451                 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
452         }
453         epk = X509_get_pubkey(cert);
454         if (NULL == epk)
455         {
456                 error("Failed to extract public key from certificate\n");
457                 return False;
458         }
459
460         server_public_key = (RSA *) epk->pkey.ptr;
461
462         return True;
463 }
464
465
466 /* Parse a crypto information structure */
467 static BOOL
468 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
469                      uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
470 {
471         uint32 crypt_level, random_len, rsa_info_len;
472         uint32 cacert_len, cert_len, flags;
473         X509 *cacert, *server_cert;
474         uint16 tag, length;
475         uint8 *next_tag, *end;
476
477         in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
478         in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
479         if (crypt_level == 0)   /* no encryption */
480                 return False;
481         in_uint32_le(s, random_len);
482         in_uint32_le(s, rsa_info_len);
483
484         if (random_len != SEC_RANDOM_SIZE)
485         {
486                 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
487                 return False;
488         }
489
490         in_uint8p(s, *server_random, random_len);
491
492         /* RSA info */
493         end = s->p + rsa_info_len;
494         if (end > s->end)
495                 return False;
496
497         in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
498         if (flags & 1)
499         {
500                 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
501                 in_uint8s(s, 8);        /* unknown */
502
503                 while (s->p < end)
504                 {
505                         in_uint16_le(s, tag);
506                         in_uint16_le(s, length);
507
508                         next_tag = s->p + length;
509
510                         switch (tag)
511                         {
512                                 case SEC_TAG_PUBKEY:
513                                         if (!sec_parse_public_key(s, modulus, exponent))
514                                                 return False;
515                                         DEBUG_RDP5(("Got Public key, RDP4-style\n"));
516
517                                         break;
518
519                                 case SEC_TAG_KEYSIG:
520                                         /* Is this a Microsoft key that we just got? */
521                                         /* Care factor: zero! */
522                                         /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this 
523                                            key as a known key of the hostname. This would prevent some MITM-attacks. */
524                                         break;
525
526                                 default:
527                                         unimpl("crypt tag 0x%x\n", tag);
528                         }
529
530                         s->p = next_tag;
531                 }
532         }
533         else
534         {
535                 uint32 certcount;
536
537                 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
538                 in_uint32_le(s, certcount); /* Number of certificates */
539
540                 if(certcount < 2) 
541                 {
542                         error("Server didn't send enough X509 certificates\n");
543                         return False;
544                 }
545
546                 for(; certcount > 2; certcount--)
547                 { /* ignore all the certificates between the root and the signing CA */
548                         uint32 ignorelen;
549                         X509 *ignorecert;
550
551                         DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
552
553                         in_uint32_le(s, ignorelen);
554                         DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
555                         ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
556
557                         if(ignorecert == NULL)
558                         { /* XXX: error out? */
559                                 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
560                         }
561
562 #ifdef WITH_DEBUG_RDP5
563                         DEBUG_RDP5(("cert #%d (ignored):\n",certcount));
564                         X509_print_fp(stdout, ignorecert);
565 #endif
566                 }
567
568                 /* Do da funky X.509 stuffy 
569
570                    "How did I find out about this?  I looked up and saw a
571                    bright light and when I came to I had a scar on my forehead
572                    and knew about X.500"
573                    - Peter Gutman in a early version of 
574                    http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
575                  */
576
577                 in_uint32_le(s, cacert_len);
578                 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
579                 cacert = d2i_X509(NULL, &(s->p), cacert_len);
580                 /* Note: We don't need to move s->p here - d2i_X509 is
581                    "kind" enough to do it for us */
582                 if (NULL == cacert)
583                 {
584                         error("Couldn't load CA Certificate from server\n");
585                         return False;
586                 }
587
588                 /* Currently, we don't use the CA Certificate. 
589                    FIXME: 
590                    *) Verify the server certificate (server_cert) with the 
591                    CA certificate.
592                    *) Store the CA Certificate with the hostname of the 
593                    server we are connecting to as key, and compare it
594                    when we connect the next time, in order to prevent
595                    MITM-attacks.
596                  */
597
598                 in_uint32_le(s, cert_len);
599                 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
600                 server_cert = d2i_X509(NULL, &(s->p), cert_len);
601                 if (NULL == server_cert)
602                 {
603                         error("Couldn't load Certificate from server\n");
604                         return False;
605                 }
606
607                 in_uint8s(s, 16);       /* Padding */
608
609                 /* Note: Verifying the server certificate must be done here, 
610                    before sec_parse_public_key since we'll have to apply
611                    serious violence to the key after this */
612
613                 if (!sec_parse_x509_key(server_cert))
614                 {
615                         DEBUG_RDP5(("Didn't parse X509 correctly\n"));
616                         return False;
617                 }
618                 return True;    /* There's some garbage here we don't care about */
619         }
620         return s_check_end(s);
621 }
622
623 /* Process crypto information blob */
624 static void
625 sec_process_crypt_info(STREAM s)
626 {
627         uint8 *server_random, *modulus, *exponent;
628         uint8 client_random[SEC_RANDOM_SIZE];
629         uint32 rc4_key_size;
630         uint8 inr[SEC_MODULUS_SIZE];
631
632         if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
633         {
634                 DEBUG(("Failed to parse crypt info\n"));
635                 return;
636         }
637
638         DEBUG(("Generating client random\n"));
639         /* Generate a client random, and hence determine encryption keys */
640         /* This is what the MS client do: */
641         memset(inr, 0, SEC_RANDOM_SIZE);
642         /*  *ARIGL!* Plaintext attack, anyone?
643            I tried doing:
644            generate_random(inr);
645            ..but that generates connection errors now and then (yes, 
646            "now and then". Something like 0 to 3 attempts needed before a 
647            successful connection. Nice. Not! 
648          */
649
650         generate_random(client_random);
651         if (NULL != server_public_key)
652         {                       /* Which means we should use 
653                                    RDP5-style encryption */
654
655                 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
656                 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
657
658                 RSA_public_encrypt(SEC_MODULUS_SIZE,
659                                    inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
660
661                 reverse(sec_crypted_random, SEC_MODULUS_SIZE);
662
663         }
664         else
665         {                       /* RDP4-style encryption */
666                 sec_rsa_encrypt(sec_crypted_random,
667                                 client_random, SEC_RANDOM_SIZE, modulus, exponent);
668         }
669         sec_generate_keys(client_random, server_random, rc4_key_size);
670 }
671
672
673 /* Process SRV_INFO, find RDP version supported by server */
674 static void
675 sec_process_srv_info(STREAM s)
676 {
677         in_uint16_le(s, g_server_rdp_version);
678         DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
679 /*      if (1 == g_server_rdp_version)
680                 g_use_rdp5 = 0; */
681 }
682
683
684 /* Process connect response data blob */
685 void
686 sec_process_mcs_data(STREAM s)
687 {
688         uint16 tag, length;
689         uint8 *next_tag;
690         uint8 len;
691
692         in_uint8s(s, 21);       /* header (T.124 stuff, probably) */
693         in_uint8(s, len);
694         if (len & 0x80)
695                 in_uint8(s, len);
696
697         while (s->p < s->end)
698         {
699                 in_uint16_le(s, tag);
700                 in_uint16_le(s, length);
701
702                 if (length <= 4)
703                         return;
704
705                 next_tag = s->p + length - 4;
706
707                 switch (tag)
708                 {
709                         case SEC_TAG_SRV_INFO:
710                                 sec_process_srv_info(s);
711                                 break;
712
713                         case SEC_TAG_SRV_CRYPT:
714                                 sec_process_crypt_info(s);
715                                 break;
716
717                         case SEC_TAG_SRV_CHANNELS:
718                                 /* FIXME: We should parse this information and
719                                    use it to map RDP5 channels to MCS 
720                                    channels */
721                                 break;
722
723                         default:
724                                 unimpl("response tag 0x%x\n", tag);
725                 }
726
727                 s->p = next_tag;
728         }
729 }
730
731 extern unsigned char cacert[];
732
733 /* Receive secure transport packet */
734 STREAM
735 sec_recv(void)
736 {
737         uint32 sec_flags;
738         uint16 channel;
739         STREAM s;
740
741         while ((s = mcs_recv(&channel)) != NULL)
742         {
743                 if (/*g_encryption || !g_licence_issued*/ 1)
744                 {
745                         in_uint32_le(s, sec_flags);
746                         printf("sec_flags=%x\n", sec_flags);
747                         
748                         if (sec_flags & SEC_ENCRYPT)
749                         {
750                                 printf("encrypt\n");
751                                 in_uint8s(s, 8);        /* signature */
752                                 sec_decrypt(s->p, s->end - s->p);
753                         }
754
755                         if (sec_flags & SEC_LICENCE_NEG)
756                         {
757                                 printf("SEC_LICENSE_NEG unknown\n");
758                                 //licence_process(s);
759                                 continue;
760                         }
761
762                         if (sec_flags & SEC_LOGON_INFO) 
763                         {
764                                 printf("Received logon packet!\n");
765                                 rdp_get_logon_info(s);
766                         }
767
768                         if (sec_flags & SEC_CLIENT_RANDOM) {
769                                 uint32 length;
770                                 uint8 inr[SEC_MODULUS_SIZE];
771                                 int i;
772                                 
773                                 printf("Receiving the client random!\n");
774                                 in_uint32_le(s, length);
775                                 if (length != SEC_MODULUS_SIZE + SEC_PADDING_SIZE) {
776                                         error("Client random was wrong size, %u bytes\n", length);
777                                 }
778                                 in_uint8a(s, sec_crypted_random, SEC_MODULUS_SIZE);
779                                 in_uint8s(s, SEC_PADDING_SIZE);
780                                 if (!s_check_end(s)) {
781                                         error("Junk after client random\n");
782                                 }
783                                 
784                                 reverse(sec_crypted_random, SEC_MODULUS_SIZE);
785
786                                 RSA_private_decrypt(SEC_MODULUS_SIZE, sec_crypted_random, inr, privkey, RSA_NO_PADDING);
787                         
788                                 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
789                                 
790                                 printf("Unencrypted client random: ");
791                                 for (i = 0; i < SEC_RANDOM_SIZE; ++i) {
792                                         printf("0x%x ", inr[i + SEC_RANDOM_SIZE]);
793                                 }
794                                 printf("\n");
795
796                                 // now we can generate the keys
797                                 sec_generate_keys(inr + SEC_RANDOM_SIZE, cacert, 8);
798                                 continue;
799                         }
800                 }
801
802                 printf("Received MCS data on ch %u\n", channel);
803                 if (channel != MCS_GLOBAL_CHANNEL)
804                 {
805                         channel_process(s, channel);
806                         continue;
807                 }
808
809                 return s;
810         }
811
812         return NULL;
813 }
814
815 /* Disconnect a connection */
816 void
817 sec_disconnect(void)
818 {
819         mcs_disconnect();
820 }