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