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

« back to all changes in this revision

Viewing changes to libfreerdp-core/credssp.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
/**
 
2
 * FreeRDP: A Remote Desktop Protocol Client
 
3
 * Credential Security Support Provider (CredSSP)
 
4
 *
 
5
 * Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
 
6
 *
 
7
 * Licensed under the Apache License, Version 2.0 (the "License");
 
8
 * you may not use this file except in compliance with the License.
 
9
 * You may obtain a copy of the License at
 
10
 *
 
11
 *               http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
13
 * Unless required by applicable law or agreed to in writing, software
 
14
 * distributed under the License is distributed on an "AS IS" BASIS,
 
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
16
 * See the License for the specific language governing permissions and
 
17
 * limitations under the License.
 
18
 */
 
19
 
 
20
#ifndef _WIN32
 
21
#include <unistd.h>
 
22
#endif
 
23
 
 
24
#include <time.h>
 
25
#include "ntlmssp.h"
 
26
 
 
27
#include "credssp.h"
 
28
/**
 
29
 * TSRequest ::= SEQUENCE {
 
30
 *      version    [0] INTEGER,
 
31
 *      negoTokens [1] NegoData OPTIONAL,
 
32
 *      authInfo   [2] OCTET STRING OPTIONAL,
 
33
 *      pubKeyAuth [3] OCTET STRING OPTIONAL
 
34
 * }
 
35
 *
 
36
 * NegoData ::= SEQUENCE OF NegoDataItem
 
37
 *
 
38
 * NegoDataItem ::= SEQUENCE {
 
39
 *      negoToken [0] OCTET STRING
 
40
 * }
 
41
 *
 
42
 * TSCredentials ::= SEQUENCE {
 
43
 *      credType    [0] INTEGER,
 
44
 *      credentials [1] OCTET STRING
 
45
 * }
 
46
 *
 
47
 * TSPasswordCreds ::= SEQUENCE {
 
48
 *      domainName  [0] OCTET STRING,
 
49
 *      userName    [1] OCTET STRING,
 
50
 *      password    [2] OCTET STRING
 
51
 * }
 
52
 *
 
53
 * TSSmartCardCreds ::= SEQUENCE {
 
54
 *      pin        [0] OCTET STRING,
 
55
 *      cspData    [1] TSCspDataDetail,
 
56
 *      userHint   [2] OCTET STRING OPTIONAL,
 
57
 *      domainHint [3] OCTET STRING OPTIONAL
 
58
 * }
 
59
 *
 
60
 * TSCspDataDetail ::= SEQUENCE {
 
61
 *      keySpec       [0] INTEGER,
 
62
 *      cardName      [1] OCTET STRING OPTIONAL,
 
63
 *      readerName    [2] OCTET STRING OPTIONAL,
 
64
 *      containerName [3] OCTET STRING OPTIONAL,
 
65
 *      cspName       [4] OCTET STRING OPTIONAL
 
66
 * }
 
67
 *
 
68
 */
 
69
 
 
70
/**
 
71
 * Initialize NTLMSSP authentication module.
 
72
 * @param credssp
 
73
 */
 
74
 
 
75
int credssp_ntlmssp_init(rdpCredssp* credssp)
 
76
{
 
77
        freerdp* instance;
 
78
        NTLMSSP* ntlmssp = credssp->ntlmssp;
 
79
        rdpSettings* settings = credssp->transport->settings;
 
80
        instance = (freerdp*) settings->instance;
 
81
 
 
82
        if ((settings->password == NULL) || (settings->username == NULL))
 
83
        {
 
84
                if(instance->Authenticate)
 
85
                {
 
86
                        boolean proceed = instance->Authenticate(instance,
 
87
                                        &settings->username, &settings->password, &settings->domain);
 
88
                        if (!proceed)
 
89
                                return 0;
 
90
                }
 
91
        }
 
92
 
 
93
        if (settings->ntlm_version == 2)
 
94
                ntlmssp->ntlm_v2 = 1;
 
95
 
 
96
        ntlmssp_set_password(ntlmssp, settings->password);
 
97
        ntlmssp_set_username(ntlmssp, settings->username);
 
98
 
 
99
        if (ntlmssp->ntlm_v2)
 
100
        {
 
101
                ntlmssp_set_workstation(ntlmssp, "WORKSTATION");
 
102
        }
 
103
 
 
104
        if (settings->domain != NULL)
 
105
        {
 
106
                if (strlen(settings->domain) > 0)
 
107
                        ntlmssp_set_domain(ntlmssp, settings->domain);
 
108
        }
 
109
        else
 
110
        {
 
111
                ntlmssp_set_domain(ntlmssp, NULL);
 
112
        }
 
113
 
 
114
        ntlmssp_generate_client_challenge(ntlmssp);
 
115
        ntlmssp_generate_random_session_key(ntlmssp);
 
116
        ntlmssp_generate_exported_session_key(ntlmssp);
 
117
 
 
118
        return 1;
 
119
}
 
120
 
 
121
/**
 
122
 * Get TLS public key.
 
123
 * @param credssp
 
124
 */
 
125
 
 
126
int credssp_get_public_key(rdpCredssp* credssp)
 
127
{
 
128
        int status;
 
129
        CryptoCert cert;
 
130
        
 
131
        cert = tls_get_certificate(credssp->transport->tls);
 
132
 
 
133
        if (cert == NULL)
 
134
        {
 
135
                printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
 
136
                return 0;
 
137
        }
 
138
 
 
139
        if(tls_verify_certificate(cert, credssp->transport->settings, credssp->transport->settings->hostname))
 
140
                tls_disconnect(credssp->transport->tls);
 
141
 
 
142
        status = crypto_cert_get_public_key(cert, &credssp->public_key);
 
143
        crypto_cert_free(cert);
 
144
 
 
145
        return status;
 
146
}
 
147
 
 
148
/**
 
149
 * Authenticate with server using CredSSP.
 
150
 * @param credssp
 
151
 * @return 1 if authentication is successful
 
152
 */
 
153
 
 
154
int credssp_authenticate(rdpCredssp* credssp)
 
155
{
 
156
        NTLMSSP* ntlmssp = credssp->ntlmssp;
 
157
        STREAM* s = stream_new(0);
 
158
        uint8* negoTokenBuffer = (uint8*) xmalloc(2048);
 
159
 
 
160
        if (credssp_ntlmssp_init(credssp) == 0)
 
161
                return 0;
 
162
 
 
163
        if (credssp_get_public_key(credssp) == 0)
 
164
                return 0;
 
165
 
 
166
        /* NTLMSSP NEGOTIATE MESSAGE */
 
167
        s->p = s->data = negoTokenBuffer;
 
168
        ntlmssp_send(ntlmssp, s);
 
169
        credssp->negoToken.data = s->data;
 
170
        credssp->negoToken.length = s->p - s->data;
 
171
        credssp_send(credssp, &credssp->negoToken, NULL, NULL);
 
172
 
 
173
        /* NTLMSSP CHALLENGE MESSAGE */
 
174
        if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0)
 
175
                return -1;
 
176
 
 
177
        s->p = s->data = credssp->negoToken.data;
 
178
        ntlmssp_recv(ntlmssp, s);
 
179
 
 
180
        freerdp_blob_free(&credssp->negoToken);
 
181
 
 
182
        /* NTLMSSP AUTHENTICATE MESSAGE */
 
183
        s->p = s->data = negoTokenBuffer;
 
184
        ntlmssp_send(ntlmssp, s);
 
185
 
 
186
        /* The last NTLMSSP message is sent with the encrypted public key */
 
187
        credssp->negoToken.data = s->data;
 
188
        credssp->negoToken.length = s->p - s->data;
 
189
        credssp_encrypt_public_key(credssp, &credssp->pubKeyAuth);
 
190
        credssp_send(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth);
 
191
 
 
192
        /* Encrypted Public Key +1 */
 
193
        if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0)
 
194
                return -1;
 
195
 
 
196
        if (credssp_verify_public_key(credssp, &credssp->pubKeyAuth) == 0)
 
197
        {
 
198
                /* Failed to verify server public key echo */
 
199
                return 0; /* DO NOT SEND CREDENTIALS! */
 
200
        }
 
201
 
 
202
        freerdp_blob_free(&credssp->negoToken);
 
203
        freerdp_blob_free(&credssp->pubKeyAuth);
 
204
 
 
205
        /* Send encrypted credentials */
 
206
        credssp_encode_ts_credentials(credssp);
 
207
        credssp_encrypt_ts_credentials(credssp, &credssp->authInfo);
 
208
        credssp_send(credssp, NULL, &credssp->authInfo, NULL);
 
209
 
 
210
        xfree(s);
 
211
 
 
212
        return 1;
 
213
}
 
214
 
 
215
/**
 
216
 * Encrypt TLS public key using CredSSP.
 
217
 * @param credssp
 
218
 * @param s
 
219
 */
 
220
 
 
221
void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d)
 
222
{
 
223
        uint8* p;
 
224
        uint8 signature[16];
 
225
        rdpBlob encrypted_public_key;
 
226
        NTLMSSP *ntlmssp = credssp->ntlmssp;
 
227
 
 
228
        freerdp_blob_alloc(d, credssp->public_key.length + 16);
 
229
        ntlmssp_encrypt_message(ntlmssp, &credssp->public_key, &encrypted_public_key, signature);
 
230
 
 
231
#ifdef WITH_DEBUG_NLA
 
232
        printf("Public Key (length = %d)\n", credssp->public_key.length);
 
233
        freerdp_hexdump(credssp->public_key.data, credssp->public_key.length);
 
234
        printf("\n");
 
235
 
 
236
        printf("Encrypted Public Key (length = %d)\n", encrypted_public_key.length);
 
237
        freerdp_hexdump(encrypted_public_key.data, encrypted_public_key.length);
 
238
        printf("\n");
 
239
 
 
240
        printf("Signature\n");
 
241
        freerdp_hexdump(signature, 16);
 
242
        printf("\n");
 
243
#endif
 
244
 
 
245
        p = (uint8*) d->data;
 
246
        memcpy(p, signature, 16); /* Message Signature */
 
247
        memcpy(&p[16], encrypted_public_key.data, encrypted_public_key.length); /* Encrypted Public Key */
 
248
 
 
249
        freerdp_blob_free(&encrypted_public_key);
 
250
}
 
251
 
 
252
/**
 
253
 * Verify TLS public key using CredSSP.
 
254
 * @param credssp
 
255
 * @param s
 
256
 * @return 1 if verification is successful, 0 otherwise
 
257
 */
 
258
 
 
259
int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d)
 
260
{
 
261
        uint8 *p1, *p2;
 
262
        uint8* signature;
 
263
        rdpBlob public_key;
 
264
        rdpBlob encrypted_public_key;
 
265
 
 
266
        signature = d->data;
 
267
        encrypted_public_key.data = (void*) (signature + 16);
 
268
        encrypted_public_key.length = d->length - 16;
 
269
 
 
270
        ntlmssp_decrypt_message(credssp->ntlmssp, &encrypted_public_key, &public_key, signature);
 
271
 
 
272
        p1 = (uint8*) credssp->public_key.data;
 
273
        p2 = (uint8*) public_key.data;
 
274
 
 
275
        p2[0]--;
 
276
 
 
277
        if (memcmp(p1, p2, public_key.length) != 0)
 
278
        {
 
279
                printf("Could not verify server's public key echo\n");
 
280
                return 0;
 
281
        }
 
282
 
 
283
        p2[0]++;
 
284
        freerdp_blob_free(&public_key);
 
285
        return 1;
 
286
}
 
287
 
 
288
/**
 
289
 * Encrypt and sign TSCredentials structure.
 
290
 * @param credssp
 
291
 * @param s
 
292
 */
 
293
 
 
294
void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d)
 
295
{
 
296
        uint8* p;
 
297
        uint8 signature[16];
 
298
        rdpBlob encrypted_ts_credentials;
 
299
        NTLMSSP* ntlmssp = credssp->ntlmssp;
 
300
 
 
301
        freerdp_blob_alloc(d, credssp->ts_credentials.length + 16);
 
302
        ntlmssp_encrypt_message(ntlmssp, &credssp->ts_credentials, &encrypted_ts_credentials, signature);
 
303
 
 
304
#ifdef WITH_DEBUG_NLA
 
305
        printf("TSCredentials (length = %d)\n", credssp->ts_credentials.length);
 
306
        freerdp_hexdump(credssp->ts_credentials.data, credssp->ts_credentials.length);
 
307
        printf("\n");
 
308
 
 
309
        printf("Encrypted TSCredentials (length = %d)\n", encrypted_ts_credentials.length);
 
310
        freerdp_hexdump(encrypted_ts_credentials.data, encrypted_ts_credentials.length);
 
311
        printf("\n");
 
312
 
 
313
        printf("Signature\n");
 
314
        freerdp_hexdump(signature, 16);
 
315
        printf("\n");
 
316
#endif
 
317
 
 
318
        p = (uint8*) d->data;
 
319
        memcpy(p, signature, 16); /* Message Signature */
 
320
        memcpy(&p[16], encrypted_ts_credentials.data, encrypted_ts_credentials.length); /* Encrypted TSCredentials */
 
321
 
 
322
        freerdp_blob_free(&encrypted_ts_credentials);
 
323
}
 
324
 
 
325
int credssp_skip_ts_password_creds(rdpCredssp* credssp)
 
326
{
 
327
        int length;
 
328
        int ts_password_creds_length = 0;
 
329
 
 
330
        length = ber_skip_octet_string(credssp->ntlmssp->domain.length);
 
331
        length += ber_skip_contextual_tag(length);
 
332
        ts_password_creds_length += length;
 
333
 
 
334
        length = ber_skip_octet_string(credssp->ntlmssp->username.length);
 
335
        length += ber_skip_contextual_tag(length);
 
336
        ts_password_creds_length += length;
 
337
 
 
338
        length = ber_skip_octet_string(credssp->ntlmssp->password.length);
 
339
        length += ber_skip_contextual_tag(length);
 
340
        ts_password_creds_length += length;
 
341
 
 
342
        length = ber_skip_sequence(ts_password_creds_length);
 
343
 
 
344
        return length;
 
345
}
 
346
 
 
347
void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
 
348
{
 
349
        int length;
 
350
 
 
351
        length = credssp_skip_ts_password_creds(credssp);
 
352
 
 
353
        /* TSPasswordCreds (SEQUENCE) */
 
354
        length = ber_get_content_length(length);
 
355
        ber_write_sequence_tag(s, length);
 
356
 
 
357
        /* [0] domainName (OCTET STRING) */
 
358
        ber_write_contextual_tag(s, 0, credssp->ntlmssp->domain.length + 2, true);
 
359
        ber_write_octet_string(s, credssp->ntlmssp->domain.data, credssp->ntlmssp->domain.length);
 
360
 
 
361
        /* [1] userName (OCTET STRING) */
 
362
        ber_write_contextual_tag(s, 1, credssp->ntlmssp->username.length + 2, true);
 
363
        ber_write_octet_string(s, credssp->ntlmssp->username.data, credssp->ntlmssp->username.length);
 
364
 
 
365
        /* [2] password (OCTET STRING) */
 
366
        ber_write_contextual_tag(s, 2, credssp->ntlmssp->password.length + 2, true);
 
367
        ber_write_octet_string(s, credssp->ntlmssp->password.data, credssp->ntlmssp->password.length);
 
368
}
 
369
 
 
370
int credssp_skip_ts_credentials(rdpCredssp* credssp)
 
371
{
 
372
        int length;
 
373
        int ts_password_creds_length;
 
374
        int ts_credentials_length = 0;
 
375
 
 
376
        length = ber_skip_integer(0);
 
377
        length += ber_skip_contextual_tag(length);
 
378
        ts_credentials_length += length;
 
379
 
 
380
        ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
 
381
        length = ber_skip_octet_string(ts_password_creds_length);
 
382
        length += ber_skip_contextual_tag(length);
 
383
        ts_credentials_length += length;
 
384
 
 
385
        length = ber_skip_sequence(ts_credentials_length);
 
386
 
 
387
        return length;
 
388
}
 
389
 
 
390
void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s)
 
391
{
 
392
        int length;
 
393
        int ts_password_creds_length;
 
394
 
 
395
        length = credssp_skip_ts_credentials(credssp);
 
396
        ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
 
397
 
 
398
        /* TSCredentials (SEQUENCE) */
 
399
        length = ber_get_content_length(length);
 
400
        length -= ber_write_sequence_tag(s, length);
 
401
 
 
402
        /* [0] credType (INTEGER) */
 
403
        length -= ber_write_contextual_tag(s, 0, 3, true);
 
404
        length -= ber_write_integer(s, 1);
 
405
 
 
406
        /* [1] credentials (OCTET STRING) */
 
407
        length -= 1;
 
408
        length -= ber_write_contextual_tag(s, 1, length, true);
 
409
        length -= ber_write_octet_string_tag(s, ts_password_creds_length);
 
410
 
 
411
        credssp_write_ts_password_creds(credssp, s);
 
412
}
 
413
 
 
414
/**
 
415
 * Encode TSCredentials structure.
 
416
 * @param credssp
 
417
 */
 
418
 
 
419
void credssp_encode_ts_credentials(rdpCredssp* credssp)
 
420
{
 
421
        STREAM* s;
 
422
        int length;
 
423
 
 
424
        s = stream_new(0);
 
425
        length = credssp_skip_ts_credentials(credssp);
 
426
        freerdp_blob_alloc(&credssp->ts_credentials, length);
 
427
        s->p = s->data = credssp->ts_credentials.data;
 
428
        s->size = length;
 
429
 
 
430
        credssp_write_ts_credentials(credssp, s);
 
431
}
 
432
 
 
433
int credssp_skip_nego_token(int length)
 
434
{
 
435
        length = ber_skip_octet_string(length);
 
436
        length += ber_skip_contextual_tag(length);
 
437
        return length;
 
438
}
 
439
 
 
440
int credssp_skip_nego_tokens(int length)
 
441
{
 
442
        length = credssp_skip_nego_token(length);
 
443
        length += ber_skip_sequence_tag(length);
 
444
        length += ber_skip_sequence_tag(length);
 
445
        length += ber_skip_contextual_tag(length);
 
446
        return length;
 
447
}
 
448
 
 
449
int credssp_skip_pub_key_auth(int length)
 
450
{
 
451
        length = ber_skip_octet_string(length);
 
452
        length += ber_skip_contextual_tag(length);
 
453
        return length;
 
454
}
 
455
 
 
456
int credssp_skip_auth_info(int length)
 
457
{
 
458
        length = ber_skip_octet_string(length);
 
459
        length += ber_skip_contextual_tag(length);
 
460
        return length;
 
461
}
 
462
 
 
463
int credssp_skip_ts_request(int length)
 
464
{
 
465
        length += ber_skip_integer(2);
 
466
        length += ber_skip_contextual_tag(3);
 
467
        length += ber_skip_sequence_tag(length);
 
468
        return length;
 
469
}
 
470
 
 
471
/**
 
472
 * Send CredSSP message.
 
473
 * @param credssp
 
474
 * @param negoToken
 
475
 * @param authInfo
 
476
 * @param pubKeyAuth
 
477
 */
 
478
 
 
479
void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth)
 
480
{
 
481
        STREAM* s;
 
482
        int length;
 
483
        int ts_request_length;
 
484
        int nego_tokens_length;
 
485
        int pub_key_auth_length;
 
486
        int auth_info_length;
 
487
 
 
488
        nego_tokens_length = (negoToken != NULL) ? credssp_skip_nego_tokens(negoToken->length) : 0;
 
489
        pub_key_auth_length = (pubKeyAuth != NULL) ? credssp_skip_pub_key_auth(pubKeyAuth->length) : 0;
 
490
        auth_info_length = (authInfo != NULL) ? credssp_skip_auth_info(authInfo->length) : 0;
 
491
 
 
492
        length = nego_tokens_length + pub_key_auth_length + auth_info_length;
 
493
        ts_request_length = credssp_skip_ts_request(length);
 
494
 
 
495
        s = stream_new(ts_request_length);
 
496
 
 
497
        /* TSRequest */
 
498
        length = ber_get_content_length(ts_request_length);
 
499
        ber_write_sequence_tag(s, length); /* SEQUENCE */
 
500
        ber_write_contextual_tag(s, 0, 3, true); /* [0] version */
 
501
        ber_write_integer(s, 2); /* INTEGER */
 
502
 
 
503
        /* [1] negoTokens (NegoData) */
 
504
        if (nego_tokens_length > 0)
 
505
        {
 
506
                length = ber_get_content_length(nego_tokens_length);
 
507
                length -= ber_write_contextual_tag(s, 1, length, true); /* NegoData */
 
508
                length -= ber_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */
 
509
                length -= ber_write_sequence_tag(s, length); /* NegoDataItem */
 
510
                length -= ber_write_contextual_tag(s, 0, length, true); /* [0] negoToken */
 
511
                ber_write_octet_string(s, negoToken->data, length); /* OCTET STRING */
 
512
        }
 
513
 
 
514
        /* [2] authInfo (OCTET STRING) */
 
515
        if (auth_info_length > 0)
 
516
        {
 
517
                length = ber_get_content_length(auth_info_length);
 
518
                length -= ber_write_contextual_tag(s, 2, length, true);
 
519
                ber_write_octet_string(s, authInfo->data, authInfo->length);
 
520
        }
 
521
 
 
522
        /* [3] pubKeyAuth (OCTET STRING) */
 
523
        if (pub_key_auth_length > 0)
 
524
        {
 
525
                length = ber_get_content_length(pub_key_auth_length);
 
526
                length -= ber_write_contextual_tag(s, 3, length, true);
 
527
                ber_write_octet_string(s, pubKeyAuth->data, length);
 
528
        }
 
529
 
 
530
        transport_write(credssp->transport, s);
 
531
}
 
532
 
 
533
/**
 
534
 * Receive CredSSP message.
 
535
 * @param credssp
 
536
 * @param negoToken
 
537
 * @param authInfo
 
538
 * @param pubKeyAuth
 
539
 * @return
 
540
 */
 
541
 
 
542
int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth)
 
543
{
 
544
        STREAM* s;
 
545
        int length;
 
546
        int status;
 
547
        uint32 version;
 
548
 
 
549
        s = transport_recv_stream_init(credssp->transport, 2048);
 
550
        status = transport_read(credssp->transport, s);
 
551
 
 
552
        if (status < 0)
 
553
                return -1;
 
554
 
 
555
        /* TSRequest */
 
556
        ber_read_sequence_tag(s, &length);
 
557
        ber_read_contextual_tag(s, 0, &length, true);
 
558
        ber_read_integer(s, &version);
 
559
 
 
560
        /* [1] negoTokens (NegoData) */
 
561
        if (ber_read_contextual_tag(s, 1, &length, true) != false)
 
562
        {
 
563
                ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */
 
564
                ber_read_sequence_tag(s, &length); /* NegoDataItem */
 
565
                ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */
 
566
                ber_read_octet_string(s, &length); /* OCTET STRING */
 
567
                freerdp_blob_alloc(negoToken, length);
 
568
                stream_read(s, negoToken->data, length);
 
569
        }
 
570
 
 
571
        /* [2] authInfo (OCTET STRING) */
 
572
        if (ber_read_contextual_tag(s, 2, &length, true) != false)
 
573
        {
 
574
                ber_read_octet_string(s, &length); /* OCTET STRING */
 
575
                freerdp_blob_alloc(authInfo, length);
 
576
                stream_read(s, authInfo->data, length);
 
577
        }
 
578
 
 
579
        /* [3] pubKeyAuth (OCTET STRING) */
 
580
        if (ber_read_contextual_tag(s, 3, &length, true) != false)
 
581
        {
 
582
                ber_read_octet_string(s, &length); /* OCTET STRING */
 
583
                freerdp_blob_alloc(pubKeyAuth, length);
 
584
                stream_read(s, pubKeyAuth->data, length);
 
585
        }
 
586
 
 
587
        return 0;
 
588
}
 
589
 
 
590
/**
 
591
 * Encrypt the given plain text using RC4 and the given key.
 
592
 * @param key RC4 key
 
593
 * @param length text length
 
594
 * @param plaintext plain text
 
595
 * @param ciphertext cipher text
 
596
 */
 
597
 
 
598
void credssp_rc4k(uint8* key, int length, uint8* plaintext, uint8* ciphertext)
 
599
{
 
600
        CryptoRc4 rc4;
 
601
 
 
602
        /* Initialize RC4 cipher with key */
 
603
        rc4 = crypto_rc4_init((void*) key, 16);
 
604
 
 
605
        /* Encrypt plaintext with key */
 
606
        crypto_rc4(rc4, length, (void*) plaintext, (void*) ciphertext);
 
607
 
 
608
        /* Free RC4 Cipher */
 
609
        crypto_rc4_free(rc4);
 
610
}
 
611
 
 
612
/**
 
613
 * Get current time, in tenths of microseconds since midnight of January 1, 1601.
 
614
 * @param[out] timestamp 64-bit little-endian timestamp
 
615
 */
 
616
 
 
617
void credssp_current_time(uint8* timestamp)
 
618
{
 
619
        uint64 time64;
 
620
 
 
621
        /* Timestamp (8 bytes), represented as the number of tenths of microseconds since midnight of January 1, 1601 */
 
622
        time64 = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */
 
623
        time64 *= 10000000; /* Convert timestamp to tenths of a microsecond */
 
624
 
 
625
        memcpy(timestamp, &time64, 8); /* Copy into timestamp in little-endian */
 
626
}
 
627
 
 
628
/**
 
629
 * Create new CredSSP state machine.
 
630
 * @param transport
 
631
 * @return new CredSSP state machine.
 
632
 */
 
633
 
 
634
rdpCredssp* credssp_new(rdpTransport* transport)
 
635
{
 
636
        rdpCredssp* self;
 
637
 
 
638
        self = (rdpCredssp*) xzalloc(sizeof(rdpCredssp));
 
639
 
 
640
        if (self != NULL)
 
641
        {
 
642
                self->transport = transport;
 
643
                self->send_seq_num = 0;
 
644
                self->ntlmssp = ntlmssp_new();
 
645
                self->settings = transport->settings;
 
646
        }
 
647
 
 
648
        return self;
 
649
}
 
650
 
 
651
/**
 
652
 * Free CredSSP state machine.
 
653
 * @param credssp
 
654
 */
 
655
 
 
656
void credssp_free(rdpCredssp* credssp)
 
657
{
 
658
        if (credssp != NULL)
 
659
        {
 
660
                freerdp_blob_free(&credssp->public_key);
 
661
                freerdp_blob_free(&credssp->ts_credentials);
 
662
 
 
663
                ntlmssp_free(credssp->ntlmssp);
 
664
                xfree(credssp);
 
665
        }
 
666
}