~ubuntu-branches/ubuntu/wily/freerdp/wily-proposed

« back to all changes in this revision

Viewing changes to libfreerdp/secure.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- c-basic-offset: 8 -*-
2
 
   FreeRDP: A Remote Desktop Protocol client.
3
 
   Protocol services - RDP encryption and licensing
4
 
   Copyright (C) Matthew Chapman 1999-2008
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 "frdp.h"
22
 
#include "mcs.h"
23
 
#include "chan.h"
24
 
#include "secure.h"
25
 
#include "licence.h"
26
 
#include "rdp.h"
27
 
#include "rdpset.h"
28
 
#include "iso.h"
29
 
#include "mem.h"
30
 
#include "debug.h"
31
 
#include "tcp.h"
32
 
 
33
 
#ifndef DISABLE_TLS
34
 
#include "tls.h"
35
 
#include "credssp.h"
36
 
#endif
37
 
 
38
 
RD_BOOL
39
 
sec_global_init(void)
40
 
{
41
 
        return crypto_global_init();
42
 
}
43
 
 
44
 
void
45
 
sec_global_finish(void)
46
 
{
47
 
        crypto_global_finish();
48
 
}
49
 
 
50
 
/* these are read only */
51
 
static uint8 pad_54[40] = {
52
 
        54, 54, 54, 54, 54, 54, 54, 54,
53
 
        54, 54, 54, 54, 54, 54, 54, 54,
54
 
        54, 54, 54, 54, 54, 54, 54, 54,
55
 
        54, 54, 54, 54, 54, 54, 54, 54,
56
 
        54, 54, 54, 54, 54, 54, 54, 54
57
 
};
58
 
 
59
 
static uint8 pad_92[48] = {
60
 
        92, 92, 92, 92, 92, 92, 92, 92,
61
 
        92, 92, 92, 92, 92, 92, 92, 92,
62
 
        92, 92, 92, 92, 92, 92, 92, 92,
63
 
        92, 92, 92, 92, 92, 92, 92, 92,
64
 
        92, 92, 92, 92, 92, 92, 92, 92,
65
 
        92, 92, 92, 92, 92, 92, 92, 92
66
 
};
67
 
 
68
 
/*
69
 
 * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
70
 
 * Both SHA1 and MD5 algorithms are used.
71
 
 */
72
 
void
73
 
sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
74
 
{
75
 
        int i;
76
 
        uint8 pad[4];
77
 
        uint8 shasig[20];
78
 
        CryptoMd5 md5;
79
 
        CryptoSha1 sha1;
80
 
 
81
 
        for (i = 0; i < 3; i++)
82
 
        {
83
 
                memset(pad, salt + i, i + 1);
84
 
 
85
 
                sha1 = crypto_sha1_init();
86
 
                crypto_sha1_update(sha1, pad, i + 1);
87
 
                crypto_sha1_update(sha1, in, 48);
88
 
                crypto_sha1_update(sha1, salt1, 32);
89
 
                crypto_sha1_update(sha1, salt2, 32);
90
 
                crypto_sha1_final(sha1, shasig);
91
 
 
92
 
                md5 = crypto_md5_init();
93
 
                crypto_md5_update(md5, in, 48);
94
 
                crypto_md5_update(md5, shasig, 20);
95
 
                crypto_md5_final(md5, &out[i * 16]);
96
 
        }
97
 
}
98
 
 
99
 
/*
100
 
 * 16-byte transformation used to generate export keys (6.2.2).
101
 
 */
102
 
void
103
 
sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
104
 
{
105
 
        CryptoMd5 md5 = crypto_md5_init();
106
 
        crypto_md5_update(md5, in, 16);
107
 
        crypto_md5_update(md5, salt1, 32);
108
 
        crypto_md5_update(md5, salt2, 32);
109
 
        crypto_md5_final(md5, out);
110
 
}
111
 
 
112
 
/* Reduce key entropy from 64 to 40 bits */
113
 
static void
114
 
sec_make_40bit(uint8 * key)
115
 
{
116
 
        key[0] = 0xd1;
117
 
        key[1] = 0x26;
118
 
        key[2] = 0x9e;
119
 
}
120
 
 
121
 
/* Generate encryption keys given client and server randoms */
122
 
static void
123
 
sec_generate_keys(rdpSec * sec, uint8 * client_random, uint8 * server_random, int rc4_key_size)
124
 
{
125
 
        uint8 pre_master_secret[48];
126
 
        uint8 master_secret[48];
127
 
        uint8 key_block[48];
128
 
 
129
 
        /* Construct pre-master secret */
130
 
        memcpy(pre_master_secret, client_random, 24);
131
 
        memcpy(pre_master_secret + 24, server_random, 24);
132
 
 
133
 
        /* Generate master secret and then key material */
134
 
        sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
135
 
        sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
136
 
 
137
 
        /* First 16 bytes of key material is MAC secret */
138
 
        memcpy(sec->sec_sign_key, key_block, 16);
139
 
 
140
 
        /* Generate export keys from next two blocks of 16 bytes */
141
 
        sec_hash_16(sec->sec_decrypt_key, &key_block[16], client_random, server_random);
142
 
        sec_hash_16(sec->sec_encrypt_key, &key_block[32], client_random, server_random);
143
 
 
144
 
        if (rc4_key_size == 1)
145
 
        {
146
 
                DEBUG("40-bit encryption enabled\n");
147
 
                sec_make_40bit(sec->sec_sign_key);
148
 
                sec_make_40bit(sec->sec_decrypt_key);
149
 
                sec_make_40bit(sec->sec_encrypt_key);
150
 
                sec->rc4_key_len = 8;
151
 
        }
152
 
        else
153
 
        {
154
 
                DEBUG("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size);
155
 
                sec->rc4_key_len = 16;
156
 
        }
157
 
 
158
 
        /* Save initial RC4 keys as update keys */
159
 
        memcpy(sec->sec_decrypt_update_key, sec->sec_decrypt_key, 16);
160
 
        memcpy(sec->sec_encrypt_update_key, sec->sec_encrypt_key, 16);
161
 
 
162
 
        /* Initialise RC4 state arrays */
163
 
        sec->rc4_decrypt_key = crypto_rc4_init(sec->sec_decrypt_key, sec->rc4_key_len);
164
 
        sec->rc4_encrypt_key = crypto_rc4_init(sec->sec_encrypt_key, sec->rc4_key_len);
165
 
}
166
 
 
167
 
/* Output a uint32 into a buffer (little-endian) */
168
 
void
169
 
buf_out_uint32(uint8 * buffer, uint32 value)
170
 
{
171
 
        buffer[0] = (value) & 0xff;
172
 
        buffer[1] = (value >> 8) & 0xff;
173
 
        buffer[2] = (value >> 16) & 0xff;
174
 
        buffer[3] = (value >> 24) & 0xff;
175
 
}
176
 
 
177
 
/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
178
 
void
179
 
sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
180
 
{
181
 
        uint8 shasig[20];
182
 
        uint8 md5sig[16];
183
 
        uint8 lenhdr[4];
184
 
        CryptoSha1 sha1;
185
 
        CryptoMd5 md5;
186
 
 
187
 
        buf_out_uint32(lenhdr, datalen);
188
 
 
189
 
        sha1 = crypto_sha1_init();
190
 
        crypto_sha1_update(sha1, session_key, keylen);
191
 
        crypto_sha1_update(sha1, pad_54, 40);
192
 
        crypto_sha1_update(sha1, lenhdr, 4);
193
 
        crypto_sha1_update(sha1, data, datalen);
194
 
        crypto_sha1_final(sha1, shasig);
195
 
 
196
 
        md5 = crypto_md5_init();
197
 
        crypto_md5_update(md5, session_key, keylen);
198
 
        crypto_md5_update(md5, pad_92, 48);
199
 
        crypto_md5_update(md5, shasig, 20);
200
 
        crypto_md5_final(md5, md5sig);
201
 
 
202
 
        memcpy(signature, md5sig, siglen);
203
 
}
204
 
 
205
 
/* Update an encryption key */
206
 
static void
207
 
sec_update(rdpSec * sec, uint8 * key, uint8 * update_key)
208
 
{
209
 
        uint8 shasig[20];
210
 
        CryptoSha1 sha1;
211
 
        CryptoMd5 md5;
212
 
        CryptoRc4 update;
213
 
 
214
 
        sha1 = crypto_sha1_init();
215
 
        crypto_sha1_update(sha1, update_key, sec->rc4_key_len);
216
 
        crypto_sha1_update(sha1, pad_54, 40);
217
 
        crypto_sha1_update(sha1, key, sec->rc4_key_len);
218
 
        crypto_sha1_final(sha1, shasig);
219
 
 
220
 
        md5 = crypto_md5_init();
221
 
        crypto_md5_update(md5, update_key, sec->rc4_key_len);
222
 
        crypto_md5_update(md5, pad_92, 48);
223
 
        crypto_md5_update(md5, shasig, 20);
224
 
        crypto_md5_final(md5, key);
225
 
 
226
 
        update = crypto_rc4_init(key, sec->rc4_key_len);
227
 
        crypto_rc4(update, sec->rc4_key_len, key, key);
228
 
        crypto_rc4_free(update);
229
 
 
230
 
        if (sec->rc4_key_len == 8)
231
 
                sec_make_40bit(key);
232
 
}
233
 
 
234
 
/* Encrypt data using RC4 */
235
 
static void
236
 
sec_encrypt(rdpSec * sec, uint8 * data, int length)
237
 
{
238
 
        if (sec->sec_encrypt_use_count == 4096)
239
 
        {
240
 
                sec_update(sec, sec->sec_encrypt_key, sec->sec_encrypt_update_key);
241
 
                crypto_rc4_free(sec->rc4_encrypt_key);
242
 
                sec->rc4_encrypt_key = crypto_rc4_init(sec->sec_encrypt_key, sec->rc4_key_len);
243
 
                sec->sec_encrypt_use_count = 0;
244
 
        }
245
 
 
246
 
        crypto_rc4(sec->rc4_encrypt_key, length, data, data);
247
 
        sec->sec_encrypt_use_count++;
248
 
}
249
 
 
250
 
/* Decrypt data using RC4 */
251
 
static void
252
 
sec_decrypt(rdpSec * sec, uint8 * data, int length)
253
 
{
254
 
#ifndef DISABLE_TLS
255
 
        if (sec->tls_connected)
256
 
                return;
257
 
#endif
258
 
 
259
 
        if (sec->sec_decrypt_use_count == 4096)
260
 
        {
261
 
                sec_update(sec, sec->sec_decrypt_key, sec->sec_decrypt_update_key);
262
 
                crypto_rc4_free(sec->rc4_decrypt_key);
263
 
                sec->rc4_decrypt_key = crypto_rc4_init(sec->sec_decrypt_key, sec->rc4_key_len);
264
 
                sec->sec_decrypt_use_count = 0;
265
 
        }
266
 
 
267
 
        crypto_rc4(sec->rc4_decrypt_key, length, data, data);
268
 
        sec->sec_decrypt_use_count++;
269
 
}
270
 
 
271
 
/* Initialise secure transport packet */
272
 
STREAM
273
 
sec_init(rdpSec * sec, uint32 flags, int maxlen)
274
 
{
275
 
        STREAM s;
276
 
        int hdrlen;
277
 
 
278
 
        if (flags)
279
 
        {
280
 
                if (!(sec->licence->licence_issued))
281
 
                        hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
282
 
                else
283
 
                        hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
284
 
        }
285
 
        else
286
 
                hdrlen = 0;
287
 
 
288
 
        s = mcs_init(sec->mcs, maxlen + hdrlen);
289
 
        s_push_layer(s, sec_hdr, hdrlen);
290
 
 
291
 
        return s;
292
 
}
293
 
 
294
 
/* Initialise fast path secure transport packet */
295
 
STREAM
296
 
sec_fp_init(rdpSec * sec, uint32 flags, int maxlen)
297
 
{
298
 
        STREAM s;
299
 
        int hdrlen;
300
 
 
301
 
        hdrlen = (flags & SEC_ENCRYPT) ? 8 : 0;
302
 
        s = mcs_fp_init(sec->mcs, maxlen + hdrlen);
303
 
        s_push_layer(s, sec_hdr, hdrlen);
304
 
 
305
 
        return s;
306
 
}
307
 
 
308
 
/* Transmit secure transport packet over specified channel */
309
 
void
310
 
sec_send_to_channel(rdpSec * sec, STREAM s, uint32 flags, uint16 channel)
311
 
{
312
 
        int datalen;
313
 
        s_pop_layer(s, sec_hdr);
314
 
 
315
 
        if (flags)
316
 
        {
317
 
                /* Basic Security Header */
318
 
                if (!(sec->licence->licence_issued) || (flags & SEC_ENCRYPT))
319
 
                        out_uint32_le(s, flags); /* flags */
320
 
 
321
 
                if (flags & SEC_ENCRYPT)
322
 
                {
323
 
                        flags &= ~SEC_ENCRYPT;
324
 
                        datalen = s->end - s->p - 8;
325
 
 
326
 
#if WITH_DEBUG
327
 
                        DEBUG("Sending encrypted packet:\n");
328
 
                        hexdump(s->p + 8, datalen);
329
 
#endif
330
 
 
331
 
                        sec_sign(s->p, 8, sec->sec_sign_key, sec->rc4_key_len, s->p + 8, datalen);
332
 
                        sec_encrypt(sec, s->p + 8, datalen);
333
 
                }
334
 
        }
335
 
 
336
 
        mcs_send_to_channel(sec->mcs, s, channel);
337
 
}
338
 
 
339
 
/* Transmit secure transport packet */
340
 
 
341
 
void
342
 
sec_send(rdpSec * sec, STREAM s, uint32 flags)
343
 
{
344
 
        sec_send_to_channel(sec, s, flags, MCS_GLOBAL_CHANNEL);
345
 
}
346
 
 
347
 
/* Transmit secure fast path packet */
348
 
void
349
 
sec_fp_send(rdpSec * sec, STREAM s, uint32 flags)
350
 
{
351
 
        int datalen;
352
 
        s_pop_layer(s, sec_hdr);
353
 
        if (flags & SEC_ENCRYPT)
354
 
        {
355
 
                datalen = ((int) (s->end - s->p)) - 8;
356
 
                sec_sign(s->p, 8, sec->sec_sign_key, sec->rc4_key_len, s->p + 8, datalen);
357
 
                sec_encrypt(sec, s->p + 8, datalen);
358
 
        }
359
 
        mcs_fp_send(sec->mcs, s, flags);
360
 
}
361
 
 
362
 
/* Transfer the client random to the server */
363
 
static void
364
 
sec_establish_key(rdpSec * sec)
365
 
{
366
 
        uint32 length = sec->server_public_key_len + SEC_PADDING_SIZE;
367
 
        uint32 flags = SEC_EXCHANGE_PKT;
368
 
        STREAM s;
369
 
 
370
 
        s = sec_init(sec, flags, length + 4);
371
 
 
372
 
        out_uint32_le(s, length);
373
 
        out_uint8p(s, sec->sec_crypted_random, sec->server_public_key_len);
374
 
        out_uint8s(s, SEC_PADDING_SIZE);
375
 
 
376
 
        s_mark_end(s);
377
 
        sec_send(sec, s, flags);
378
 
}
379
 
 
380
 
static void
381
 
sec_out_client_core_data(rdpSec * sec, rdpSet * settings, STREAM s)
382
 
{
383
 
        char * p;
384
 
        size_t len;
385
 
        uint16 highColorDepth;
386
 
        uint16 supportedColorDepths;
387
 
        uint16 earlyCapabilityFlags;
388
 
 
389
 
        out_uint16_le(s, UDH_CS_CORE);  /* User Data Header type */
390
 
        out_uint16_le(s, 216);          /* total length */
391
 
 
392
 
        out_uint32_le(s, settings->rdp_version >= 5 ? 0x00080004 : 0x00080001); /* client version */
393
 
        out_uint16_le(s, settings->width);              /* desktopWidth */
394
 
        out_uint16_le(s, settings->height);             /* desktopHeight */
395
 
        out_uint16_le(s, RNS_UD_COLOR_8BPP);            /* colorDepth, ignored because of postBeta2ColorDepth */
396
 
        out_uint16_le(s, RNS_UD_SAS_DEL);               /* SASSequence (Secure Access Sequence) */
397
 
        out_uint32_le(s, settings->keyboard_layout);    /* keyboardLayout */
398
 
        out_uint32_le(s, 2600);                         /* clientBuild */
399
 
 
400
 
        /* Unicode name of client, truncated to 15 characters */
401
 
        p = xstrdup_out_unistr(sec->rdp, settings->hostname, &len);
402
 
        if (len > 30)
403
 
        {
404
 
                len = 30;
405
 
                p[len] = 0;
406
 
                p[len + 1] = 0;
407
 
        }
408
 
        out_uint8a(s, p, len + 2);
409
 
        out_uint8s(s, 32 - len - 2);
410
 
        xfree(p);
411
 
 
412
 
        out_uint32_le(s, settings->keyboard_type);              /* keyboardType */
413
 
        out_uint32_le(s, settings->keyboard_subtype);           /* keyboardSubType */
414
 
        out_uint32_le(s, settings->keyboard_functionkeys);      /* keyboardFunctionKey */
415
 
 
416
 
        /* Input Method Editor (IME) file name associated with the input locale.
417
 
           Up to 31 Unicode characters plus a NULL terminator */
418
 
        /* FIXME: populate this field with real data */
419
 
        out_uint8s(s, 64);      /* imeFileName */
420
 
 
421
 
        out_uint16_le(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
422
 
        out_uint16_le(s, 1); /* clientProductID */
423
 
        out_uint32_le(s, 0); /* serialNumber (should be initialized to 0) */
424
 
 
425
 
        highColorDepth = MIN(settings->server_depth, 24);       /* 32 must be reported as 24 and RNS_UD_CS_WANT_32BPP_SESSION */
426
 
        out_uint16_le(s, highColorDepth); /* (requested) highColorDepth */
427
 
 
428
 
        supportedColorDepths = RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT;
429
 
        out_uint16_le(s, supportedColorDepths); /* supportedColorDepths */
430
 
 
431
 
        earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
432
 
 
433
 
        if (settings->server_depth == 32)
434
 
                earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
435
 
 
436
 
        out_uint16_le(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
437
 
        out_uint8s(s, 64); /* clientDigProductId (64 bytes) */
438
 
        out_uint8(s, 0); /* connectionType, only valid when RNS_UD_CS_VALID_CONNECTION_TYPE is set in earlyCapabilityFlags */
439
 
        out_uint8(s, 0); /* pad1octet */
440
 
        out_uint32_le(s, sec->negotiated_protocol); /* serverSelectedProtocol */
441
 
}
442
 
 
443
 
static void
444
 
sec_out_client_security_data(rdpSec * sec, rdpSet * settings, STREAM s)
445
 
{
446
 
        uint16 encryptionMethods = 0;
447
 
 
448
 
        out_uint16_le(s, UDH_CS_SECURITY);      /* User Data Header type */
449
 
        out_uint16_le(s, 12);                   /* total length */
450
 
 
451
 
        if (settings->encryption || sec->tls_connected)
452
 
                encryptionMethods = ENCRYPTION_40BIT_FLAG | ENCRYPTION_128BIT_FLAG;
453
 
 
454
 
        out_uint32_le(s, encryptionMethods);    /* encryptionMethods */
455
 
        out_uint32_le(s, 0);                    /* extEncryptionMethods */
456
 
}
457
 
 
458
 
static void
459
 
sec_out_client_network_data(rdpSec * sec, rdpSet * settings, STREAM s)
460
 
{
461
 
        int i;
462
 
 
463
 
        DEBUG_RDP5("num_channels is %d\n", settings->num_channels);
464
 
        if (settings->num_channels > 0)
465
 
        {
466
 
                out_uint16_le(s, UDH_CS_NET);   /* User Data Header type */
467
 
                out_uint16_le(s, settings->num_channels * 12 + 8);      /* total length */
468
 
 
469
 
                out_uint32_le(s, settings->num_channels);       /* channelCount */
470
 
                for (i = 0; i < settings->num_channels; i++)
471
 
                {
472
 
                        DEBUG_RDP5("Requesting channel %s\n", settings->channels[i].name);
473
 
                        out_uint8a(s, settings->channels[i].name, 8); /* name (8 bytes) 7 characters with null terminator */
474
 
                        out_uint32_le(s, settings->channels[i].flags); /* options (4 bytes) */
475
 
                }
476
 
        }
477
 
}
478
 
 
479
 
static void
480
 
sec_out_client_cluster_data(rdpSec * sec, rdpSet * settings, STREAM s)
481
 
{
482
 
        out_uint16_le(s, UDH_CS_CLUSTER);       /* User Data Header type */
483
 
        out_uint16_le(s, 12);                   /* total length */
484
 
 
485
 
        out_uint32_le(s, (settings->console_session || sec->rdp->redirect_session_id) ?
486
 
                REDIRECTED_SESSIONID_FIELD_VALID | REDIRECTION_SUPPORTED | REDIRECTION_VERSION4 :
487
 
                REDIRECTION_SUPPORTED | REDIRECTION_VERSION4); /* flags */
488
 
 
489
 
        out_uint32_le(s, sec->rdp->redirect_session_id); /* RedirectedSessionID */
490
 
}
491
 
 
492
 
void
493
 
sec_out_gcc_conference_create_request(rdpSec * sec, STREAM s)
494
 
{
495
 
        int length;
496
 
        rdpSet * settings = sec->rdp->settings;
497
 
 
498
 
        /* See ITU-T Rec. T.124 (02/98) Generic Conference Control */
499
 
 
500
 
        /* the part before userData is of a fixed size, making things convenient */
501
 
        s->p = s->data + 23;
502
 
        sec_out_client_core_data(sec, settings, s);
503
 
        sec_out_client_cluster_data(sec, settings, s);
504
 
        sec_out_client_security_data(sec, settings, s);
505
 
        sec_out_client_network_data(sec, settings, s);
506
 
        length = (s->p - s->data) - 23;
507
 
        s->p = s->data;
508
 
 
509
 
        /* t124Identifier = 0.0.20.124.0.1 */
510
 
        out_uint16_be(s, 5);
511
 
        out_uint16_be(s, 0x14);
512
 
        out_uint8(s, 0x7c);
513
 
        out_uint16_be(s, 1);
514
 
 
515
 
        /* connectPDU octet string */
516
 
        out_uint16_be(s, ((length + 14) | 0x8000));             /* connectPDU length in two bytes*/
517
 
 
518
 
        /* connectPDU content is ConnectGCCPDU PER encoded: */
519
 
        out_uint16_be(s, 8);                            /* ConferenceCreateRequest ... */
520
 
        out_uint16_be(s, 16);
521
 
        out_uint8(s, 0);
522
 
        out_uint16_le(s, 0xC001);                       /* userData key is h221NonStandard */
523
 
        out_uint8(s, 0);                                /* 4 bytes: */
524
 
        out_uint32_le(s, 0x61637544);                   /* "Duca" */
525
 
        out_uint16_be(s, (length | 0x8000));            /* userData value length in two bytes */
526
 
        s->p = s->data + length + 23;                   /* userData (outputted earlier) */
527
 
 
528
 
        s_mark_end(s);
529
 
}
530
 
 
531
 
static void
532
 
revcpy(uint8 * out, uint8 * in, int len)
533
 
{
534
 
        int i;
535
 
        in += len;
536
 
        for (i = 0; i < len; i++)
537
 
        {
538
 
                *out++ = *--in;
539
 
        }
540
 
}
541
 
 
542
 
/* Parse a Server Proprietary Certificate RSA Public Key */
543
 
static RD_BOOL
544
 
sec_parse_public_key(rdpSec * sec, STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
545
 
{
546
 
        uint32 magic;
547
 
        uint32 modulus_len;
548
 
 
549
 
        in_uint32_le(s, magic);
550
 
        if (magic != SEC_RSA_MAGIC)
551
 
        {
552
 
                ui_error(sec->rdp->inst, "RSA magic 0x%x\n", magic);
553
 
                return False;
554
 
        }
555
 
 
556
 
        in_uint32_le(s, modulus_len);
557
 
        if (4 + 4 + 4 + 4 + SEC_EXPONENT_SIZE + modulus_len != len)
558
 
        {
559
 
                ui_error(sec->rdp->inst, "Inconsistent Server Proprietary Certificate public key size\n");
560
 
                return False;
561
 
        }
562
 
        modulus_len -= SEC_PADDING_SIZE;
563
 
        if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
564
 
        {
565
 
                ui_error(sec->rdp->inst, "Bad Server Proprietary Certificate public key size (%u bits)\n", modulus_len * 8);
566
 
                return False;
567
 
        }
568
 
 
569
 
        in_uint8s(s, 4);        /* modulus_bits - must match modulus_len */
570
 
        in_uint8s(s, 4);        /* datalen - how much data can be encoded */
571
 
        revcpy(exponent, s->p, SEC_EXPONENT_SIZE);
572
 
        in_uint8s(s, SEC_EXPONENT_SIZE);
573
 
        revcpy(modulus, s->p, modulus_len);
574
 
        in_uint8s(s, modulus_len);
575
 
        in_uint8s(s, SEC_PADDING_SIZE); /* zero padding - included in modulus_len but not in modulus_bits */
576
 
        sec->server_public_key_len = modulus_len;
577
 
 
578
 
        return s_check(s);
579
 
}
580
 
 
581
 
/* Parse a Proprietary Certificate signature */
582
 
static RD_BOOL
583
 
sec_parse_public_sig(STREAM s, uint32 len)
584
 
{
585
 
        /* The Proprietary Certificate signature uses a static published private key.
586
 
         * That is completely nonsense, so we won't bother checking it. */
587
 
 
588
 
        in_uint8s(s, len);
589
 
        return len == 72;
590
 
}
591
 
 
592
 
/* Parse Server Security Data */
593
 
static RD_BOOL
594
 
sec_parse_server_security_data(rdpSec * sec, STREAM s, uint32 * encryptionMethod, uint8 server_random[SEC_RANDOM_SIZE], uint8 * modulus, uint8 * exponent)
595
 
{
596
 
        uint32 encryptionLevel;
597
 
        uint32 serverRandomLen;
598
 
        uint32 serverCertLen;
599
 
        uint32 certChainVersion;
600
 
        uint32 dwVersion;
601
 
 
602
 
        in_uint32_le(s, *encryptionMethod);     /* 1 = 40-bit, 2 = 128-bit, 0 for TLS/CredSSP */
603
 
        in_uint32_le(s, encryptionLevel);       /* 1 = low, 2 = client compatible, 3 = high */
604
 
        if (encryptionLevel == 0)               /* no encryption */
605
 
                return False;
606
 
        in_uint32_le(s, serverRandomLen);
607
 
        in_uint32_le(s, serverCertLen);
608
 
 
609
 
        if (serverRandomLen != SEC_RANDOM_SIZE)
610
 
        {
611
 
                ui_error(sec->rdp->inst, "random len %d, expected %d\n", serverRandomLen, SEC_RANDOM_SIZE);
612
 
                return False;
613
 
        }
614
 
 
615
 
        in_uint8a(s, server_random, SEC_RANDOM_SIZE);
616
 
 
617
 
        /* Server Certificate: */
618
 
        in_uint32_le(s, dwVersion); /* bit 0x80000000 = temporary certificate */
619
 
        certChainVersion = dwVersion & 0x7FFFFFFF;
620
 
 
621
 
        if (certChainVersion == 1)       /* Server Proprietary Certificate */
622
 
        {
623
 
                uint16 wPublicKeyBlobType, wPublicKeyBlobLen;
624
 
                uint16 wSignatureBlobType, wSignatureBlobLen;
625
 
 
626
 
                DEBUG_RDP5("We're going for a Server Proprietary Certificate (no TS license)\n");
627
 
                in_uint8s(s, 4);        /* dwSigAlgId must be 1 (SIGNATURE_ALG_RSA) */
628
 
                in_uint8s(s, 4);        /* dwKeyAlgId must be 1 (KEY_EXCHANGE_ALG_RSA ) */
629
 
 
630
 
                in_uint16_le(s, wPublicKeyBlobType);
631
 
                if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
632
 
                        return False;
633
 
 
634
 
                in_uint16_le(s, wPublicKeyBlobLen);
635
 
 
636
 
                if (!sec_parse_public_key(sec, s, wPublicKeyBlobLen, modulus, exponent))
637
 
                        return False;
638
 
 
639
 
                in_uint16_le(s, wSignatureBlobType);
640
 
                if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
641
 
                        return False;
642
 
 
643
 
                in_uint16_le(s, wSignatureBlobLen);
644
 
                if (!sec_parse_public_sig(s, wSignatureBlobLen))
645
 
                        return False;
646
 
        }
647
 
        else if (certChainVersion == 2)  /* X.509 */
648
 
        {
649
 
                uint32 cert_total_count, cert_counter;
650
 
                uint32 license_cert_len, ts_cert_len;
651
 
                CryptoCert license_cert, ts_cert;
652
 
 
653
 
                DEBUG_RDP5("We're going for a X.509 Certificate (TS license)\n");
654
 
                in_uint32_le(s, cert_total_count);      /* Number of certificates */
655
 
                DEBUG_RDP5("Cert chain length: %d\n", cert_total_count);
656
 
                if (cert_total_count < 2)
657
 
                {
658
 
                        ui_error(sec->rdp->inst, "Server didn't send enough X509 certificates\n");
659
 
                        return False;
660
 
                }
661
 
                /* X.509 Certificate Chain: */
662
 
                /* Only the 2 last certificates in chain are _really_ interesting */
663
 
                for (cert_counter=0; cert_counter < cert_total_count - 2; cert_counter++)
664
 
                {
665
 
                        uint32 ignorelen;
666
 
                        CryptoCert ignorecert;
667
 
 
668
 
                        DEBUG_RDP5("Ignoring cert: %d\n", cert_counter);
669
 
                        in_uint32_le(s, ignorelen);
670
 
                        DEBUG_RDP5("Ignored Certificate length is %d\n", ignorelen);
671
 
                        ignorecert = crypto_cert_read(s->p, ignorelen);
672
 
                        in_uint8s(s, ignorelen);
673
 
                        if (ignorecert == NULL)
674
 
                        {
675
 
                                ui_error(sec->rdp->inst, "Couldn't read certificate %d from server certificate chain\n", cert_counter);
676
 
                                return False;
677
 
                        }
678
 
 
679
 
#ifdef WITH_DEBUG_RDP5
680
 
                        DEBUG_RDP5("cert #%d (ignored):\n", cert_counter);
681
 
                        crypto_cert_print_fp(stdout, ignorecert);
682
 
#endif
683
 
                        /* TODO: Verify the certificate chain all the way from CA root to prevent MITM attacks */
684
 
                        crypto_cert_free(ignorecert);
685
 
                }
686
 
                /* The second to last certificate is the license server */
687
 
                in_uint32_le(s, license_cert_len);
688
 
                DEBUG_RDP5("License Server Certificate length is %d\n", license_cert_len);
689
 
                license_cert = crypto_cert_read(s->p, license_cert_len);
690
 
                in_uint8s(s, license_cert_len);
691
 
                if (NULL == license_cert)
692
 
                {
693
 
                        ui_error(sec->rdp->inst, "Couldn't load License Server Certificate from server\n");
694
 
                        return False;
695
 
                }
696
 
#ifdef WITH_DEBUG_RDP5
697
 
                crypto_cert_print_fp(stdout, license_cert);
698
 
#endif
699
 
                /* The last certificate is the Terminal Server */
700
 
                in_uint32_le(s, ts_cert_len);
701
 
                DEBUG_RDP5("TS Certificate length is %d\n", ts_cert_len);
702
 
                ts_cert = crypto_cert_read(s->p, ts_cert_len);
703
 
                in_uint8s(s, ts_cert_len);
704
 
                if (NULL == ts_cert)
705
 
                {
706
 
                        crypto_cert_free(license_cert);
707
 
                        ui_error(sec->rdp->inst, "Couldn't load TS Certificate from server\n");
708
 
                        return False;
709
 
                }
710
 
#ifdef WITH_DEBUG_RDP5
711
 
                crypto_cert_print_fp(stdout, ts_cert);
712
 
#endif
713
 
                if (!crypto_cert_verify(ts_cert, license_cert))
714
 
                {
715
 
                        crypto_cert_free(ts_cert);
716
 
                        crypto_cert_free(license_cert);
717
 
                        ui_error(sec->rdp->inst, "TS Certificate not signed with License Certificate\n");
718
 
                        return False;
719
 
                }
720
 
                crypto_cert_free(license_cert);
721
 
 
722
 
                if (crypto_cert_get_pub_exp_mod(ts_cert, &(sec->server_public_key_len),
723
 
                                exponent, SEC_EXPONENT_SIZE, modulus, SEC_MAX_MODULUS_SIZE) != 0)
724
 
                {
725
 
                        ui_error(sec->rdp->inst, "Problem extracting RSA key from TS Certificate\n");
726
 
                        crypto_cert_free(ts_cert);
727
 
                        return False;
728
 
                }
729
 
                crypto_cert_free(ts_cert);
730
 
                if ((sec->server_public_key_len < SEC_MODULUS_SIZE) ||
731
 
                    (sec->server_public_key_len > SEC_MAX_MODULUS_SIZE))
732
 
                {
733
 
                        ui_error(sec->rdp->inst, "Bad TS Certificate public key size (%u bits)\n",
734
 
                                 sec->server_public_key_len * 8);
735
 
                        return False;
736
 
                }
737
 
                in_uint8s(s, 8 + 4 * cert_total_count); /* Padding */
738
 
        }
739
 
        else
740
 
        {
741
 
                ui_error(sec->rdp->inst, "Invalid cert chain version\n");
742
 
                return False;
743
 
        }
744
 
 
745
 
        return s_check_end(s);
746
 
}
747
 
 
748
 
/* Process Server Security Data */
749
 
static void
750
 
sec_process_server_security_data(rdpSec * sec, STREAM s)
751
 
{
752
 
        uint32 rc4_key_size;
753
 
        uint8 server_random[SEC_RANDOM_SIZE];
754
 
        uint8 client_random[SEC_RANDOM_SIZE];
755
 
        uint8 modulus[SEC_MAX_MODULUS_SIZE];
756
 
        uint8 exponent[SEC_EXPONENT_SIZE];
757
 
        uint8 client_random_rev[SEC_RANDOM_SIZE];
758
 
        uint8 crypted_random_rev[SEC_MAX_MODULUS_SIZE];
759
 
 
760
 
        memset(modulus, 0, sizeof(modulus));
761
 
        memset(exponent, 0, sizeof(exponent));
762
 
        if (!sec_parse_server_security_data(sec, s, &rc4_key_size, server_random, modulus, exponent))
763
 
        {
764
 
                /* encryptionMethod (rc4_key_size) = 0 means TLS */
765
 
                if (rc4_key_size > 0)
766
 
                {
767
 
                        DEBUG("Failed to parse crypt info\n");
768
 
                }
769
 
                return;
770
 
        }
771
 
 
772
 
        DEBUG("Generating client random\n");
773
 
        generate_random(client_random);
774
 
        revcpy(client_random_rev, client_random, SEC_RANDOM_SIZE);
775
 
        crypto_rsa_encrypt(SEC_RANDOM_SIZE, client_random_rev, crypted_random_rev,
776
 
                        sec->server_public_key_len, modulus, exponent);
777
 
        revcpy(sec->sec_crypted_random, crypted_random_rev, sec->server_public_key_len);
778
 
        sec_generate_keys(sec, client_random, server_random, rc4_key_size);
779
 
}
780
 
 
781
 
/* Process Server Core Data */
782
 
static void
783
 
sec_process_server_core_data(rdpSec * sec, STREAM s, uint16 length)
784
 
{
785
 
        uint32 server_rdp_version, clientRequestedProtocols;
786
 
        in_uint32_le(s, server_rdp_version);
787
 
 
788
 
        if(server_rdp_version == 0x00080001)
789
 
        {
790
 
                sec->rdp->settings->rdp_version = 4;
791
 
                sec->rdp->settings->server_depth = 8;
792
 
        }
793
 
        else if(server_rdp_version == 0x00080004)
794
 
        {
795
 
                sec->rdp->settings->rdp_version = 5;    /* FIXME: We can't just upgrade the RDP version! */
796
 
        }
797
 
        else
798
 
        {
799
 
                ui_error(sec->rdp->inst, "Invalid server rdp version %ul\n", server_rdp_version);
800
 
        }
801
 
 
802
 
        DEBUG_RDP5("Server RDP version is %d\n", sec->rdp->settings->rdp_version);
803
 
        if (length >= 12)
804
 
        {
805
 
                in_uint32_le(s, clientRequestedProtocols);
806
 
        }
807
 
}
808
 
 
809
 
/* Process Server Network Data */
810
 
static void
811
 
sec_process_server_network_data(rdpSec * sec, STREAM s)
812
 
{
813
 
        int i;
814
 
        uint16 MCSChannelId;
815
 
        uint16 channelCount;
816
 
 
817
 
        in_uint16_le(s, MCSChannelId); /* MCSChannelId */
818
 
        in_uint16_le(s, channelCount); /* channelCount */
819
 
 
820
 
        /* TODO: Check that it matches rdp->settings->num_channels */
821
 
        if (channelCount != sec->rdp->settings->num_channels)
822
 
        {
823
 
                ui_error(sec->rdp->inst, "client requested %d channels, server replied with %d channels",
824
 
                         sec->rdp->settings->num_channels, channelCount);
825
 
        }
826
 
 
827
 
        /* channelIdArray */
828
 
        for (i = 0; i < channelCount; i++)
829
 
        {
830
 
                uint16 channelId;
831
 
                in_uint16_le(s, channelId);     /* Channel ID allocated to requested channel number i */
832
 
 
833
 
                /* TODO: Assign channel ids here instead of in freerdp.c l_rdp_connect */
834
 
                if (channelId != sec->rdp->settings->channels[i].chan_id)
835
 
                {
836
 
                        ui_error(sec->rdp->inst, "channel %d is %d but should have been %d\n",
837
 
                                 i, channelId, sec->rdp->settings->channels[i].chan_id);
838
 
                }
839
 
        }
840
 
 
841
 
        if (channelCount % 2 == 1)
842
 
                in_uint8s(s, 2);        /* Padding */
843
 
}
844
 
 
845
 
/* Process connect response data blob */
846
 
void
847
 
sec_process_mcs_data(rdpSec * sec, STREAM s)
848
 
{
849
 
        uint8 byte;
850
 
        uint16 type;
851
 
        uint16 length;
852
 
        uint16 totalLength;
853
 
        uint8 *next_tag;
854
 
 
855
 
        in_uint8s(s, 21);       /* TODO: T.124 ConferenceCreateResponse userData with key h221NonStandard McDn */
856
 
 
857
 
        in_uint8(s, byte);
858
 
        totalLength = (uint16) byte;
859
 
 
860
 
        if (byte & 0x80)
861
 
        {
862
 
                totalLength &= ~0x80;
863
 
                totalLength <<= 8;
864
 
                in_uint8(s, byte);
865
 
                totalLength += (uint16) byte;
866
 
        }
867
 
 
868
 
        while (s->p < s->end)
869
 
        {
870
 
                in_uint16_le(s, type);
871
 
                in_uint16_le(s, length);
872
 
 
873
 
                if (length <= 4)
874
 
                        return;
875
 
 
876
 
                next_tag = s->p + length - 4;
877
 
 
878
 
                switch (type)
879
 
                {
880
 
                        case UDH_SC_CORE: /* Server Core Data */
881
 
                                sec_process_server_core_data(sec, s, length);
882
 
                                break;
883
 
 
884
 
                        case UDH_SC_NET: /* Server Network Data */
885
 
                                sec_process_server_network_data(sec, s);
886
 
                                break;
887
 
 
888
 
                        case UDH_SC_SECURITY: /* Server Security Data */
889
 
                                sec_process_server_security_data(sec, s);
890
 
                                break;
891
 
                }
892
 
 
893
 
                s->p = next_tag;
894
 
        }
895
 
}
896
 
 
897
 
/* Receive secure transport packet */
898
 
STREAM
899
 
sec_recv(rdpSec * sec, secRecvType * type)
900
 
{
901
 
        STREAM s;
902
 
        uint16 channel;
903
 
        uint32 sec_flags;
904
 
        isoRecvType iso_type;
905
 
 
906
 
        while ((s = mcs_recv(sec->mcs, &channel, &iso_type)) != NULL)
907
 
        {
908
 
                if ((iso_type == ISO_RECV_FAST_PATH) ||
909
 
                        (iso_type == ISO_RECV_FAST_PATH_ENCRYPTED))
910
 
                {
911
 
                        *type = SEC_RECV_FAST_PATH;
912
 
                        if (iso_type == ISO_RECV_FAST_PATH_ENCRYPTED)
913
 
                        {
914
 
                                in_uint8s(s, 8);        /* dataSignature */ /* TODO: Check signature! */
915
 
                                sec_decrypt(sec, s->p, s->end - s->p);
916
 
                        }
917
 
                        return s;
918
 
                }
919
 
                if (sec->rdp->settings->encryption || !sec->licence->licence_issued)
920
 
                {
921
 
                        /* basicSecurityHeader: */
922
 
                        in_uint32_le(s, sec_flags);
923
 
 
924
 
                        if ((sec_flags & SEC_ENCRYPT) || (sec_flags & SEC_REDIRECTION_PKT))
925
 
                        {
926
 
                                in_uint8s(s, 8);        /* dataSignature */ /* TODO: Check signature! */
927
 
                                sec_decrypt(sec, s->p, s->end - s->p);
928
 
                        }
929
 
 
930
 
                        if (sec_flags & SEC_LICENSE_PKT)
931
 
                        {
932
 
                                *type = SEC_RECV_LICENSE;
933
 
                                licence_process(sec->licence, s);
934
 
                                continue;
935
 
                        }
936
 
 
937
 
                        if (sec_flags & SEC_REDIRECTION_PKT)
938
 
                        {
939
 
                                *type = SEC_RECV_REDIRECT;
940
 
                                return s;
941
 
                        }
942
 
                }
943
 
 
944
 
                if (channel != MCS_GLOBAL_CHANNEL)
945
 
                {
946
 
                        vchan_process(sec->mcs->chan, s, channel);
947
 
                        *type = SEC_RECV_IOCHANNEL;
948
 
                        return s;
949
 
                }
950
 
                *type = SEC_RECV_SHARE_CONTROL;
951
 
                return s;
952
 
        }
953
 
 
954
 
        return NULL;
955
 
}
956
 
 
957
 
/* Establish a secure connection */
958
 
RD_BOOL
959
 
sec_connect(rdpSec * sec, char *server, char *username, int port)
960
 
{
961
 
        /* Don't forget to set this *before* iso_connect(), otherwise you'll bang your head on the wall */
962
 
 
963
 
        if (sec->rdp->settings->tls)
964
 
                sec->requested_protocol = PROTOCOL_TLS;
965
 
        else
966
 
                sec->requested_protocol = PROTOCOL_RDP;
967
 
 
968
 
        if (!iso_connect(sec->mcs->iso, server, username, port))
969
 
                return False;
970
 
 
971
 
#ifndef DISABLE_TLS
972
 
        if(sec->negotiated_protocol == PROTOCOL_NLA)
973
 
        {
974
 
                /* TLS with NLA was successfully negotiated */
975
 
                printf("TLS encryption with NLA negotiated\n");
976
 
                sec->ctx = tls_create_context();
977
 
                sec->ssl = tls_connect(sec->ctx, sec->mcs->iso->tcp->sock, server);
978
 
                sec->tls_connected = 1;
979
 
                ntlm_send_negotiate_message(sec);
980
 
                credssp_recv(sec);
981
 
                exit(0); /* not implemented from this point */
982
 
        }
983
 
        else if(sec->negotiated_protocol == PROTOCOL_TLS)
984
 
        {
985
 
                /* TLS without NLA was successfully negotiated */
986
 
                RD_BOOL success;
987
 
                printf("TLS Encryption negotiated\n");
988
 
                sec->ctx = tls_create_context();
989
 
                sec->ssl = tls_connect(sec->ctx, sec->mcs->iso->tcp->sock, server);
990
 
                sec->tls_connected = 1;
991
 
                sec->rdp->settings->encryption = 0;
992
 
                success = mcs_connect(sec->mcs);
993
 
                return success;
994
 
        }
995
 
        else
996
 
#endif
997
 
        {
998
 
                RD_BOOL success;
999
 
 
1000
 
                if (sec->requested_protocol > PROTOCOL_RDP)
1001
 
                {
1002
 
                        /* only tell about the legacy RDP negotiation success when it wasn't the requested encryption */
1003
 
                        printf("Legacy RDP encryption negotiated\n");
1004
 
                }
1005
 
 
1006
 
                success = mcs_connect(sec->mcs);
1007
 
 
1008
 
                if (success && sec->rdp->settings->encryption)
1009
 
                        sec_establish_key(sec);
1010
 
 
1011
 
                return success;
1012
 
        }
1013
 
 
1014
 
        return 0;
1015
 
}
1016
 
 
1017
 
/* Disconnect a connection */
1018
 
void
1019
 
sec_disconnect(rdpSec * sec)
1020
 
{
1021
 
        mcs_disconnect(sec->mcs);
1022
 
 
1023
 
#ifndef DISABLE_TLS
1024
 
        if (sec->ctx)
1025
 
                tls_destroy_context(sec->ctx);
1026
 
        sec->ctx = NULL;
1027
 
#endif
1028
 
 
1029
 
        if (sec->rc4_decrypt_key)
1030
 
                crypto_rc4_free(sec->rc4_decrypt_key);
1031
 
        sec->rc4_decrypt_key = NULL;
1032
 
        if (sec->rc4_encrypt_key)
1033
 
                crypto_rc4_free(sec->rc4_encrypt_key);
1034
 
        sec->rc4_encrypt_key = NULL;
1035
 
}
1036
 
 
1037
 
rdpSec *
1038
 
sec_new(struct rdp_rdp * rdp)
1039
 
{
1040
 
        rdpSec * self;
1041
 
 
1042
 
        self = (rdpSec *) xmalloc(sizeof(rdpSec));
1043
 
        if (self != NULL)
1044
 
        {
1045
 
                memset(self, 0, sizeof(rdpSec));
1046
 
                self->rdp = rdp;
1047
 
                self->mcs = mcs_new(self);
1048
 
                self->licence = licence_new(self);
1049
 
 
1050
 
#ifndef DISABLE_TLS
1051
 
                self->nla = nla_new(self);
1052
 
#endif
1053
 
 
1054
 
                self->rc4_decrypt_key = NULL;
1055
 
                self->rc4_encrypt_key = NULL;
1056
 
        }
1057
 
        return self;
1058
 
}
1059
 
 
1060
 
void
1061
 
sec_free(rdpSec * sec)
1062
 
{
1063
 
        if (sec != NULL)
1064
 
        {
1065
 
                licence_free(sec->licence);
1066
 
                mcs_free(sec->mcs);
1067
 
 
1068
 
#ifndef DISABLE_TLS
1069
 
                nla_free(sec->nla);
1070
 
#endif
1071
 
 
1072
 
                xfree(sec);
1073
 
        }
1074
 
}