~ubuntu-branches/ubuntu/dapper/rdesktop/dapper

« back to all changes in this revision

Viewing changes to secure.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

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