2
* FreeRDP: A Remote Desktop Protocol Client
3
* Credential Security Support Provider (CredSSP)
5
* Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11
* http://www.apache.org/licenses/LICENSE-2.0
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.
29
* TSRequest ::= SEQUENCE {
30
* version [0] INTEGER,
31
* negoTokens [1] NegoData OPTIONAL,
32
* authInfo [2] OCTET STRING OPTIONAL,
33
* pubKeyAuth [3] OCTET STRING OPTIONAL
36
* NegoData ::= SEQUENCE OF NegoDataItem
38
* NegoDataItem ::= SEQUENCE {
39
* negoToken [0] OCTET STRING
42
* TSCredentials ::= SEQUENCE {
43
* credType [0] INTEGER,
44
* credentials [1] OCTET STRING
47
* TSPasswordCreds ::= SEQUENCE {
48
* domainName [0] OCTET STRING,
49
* userName [1] OCTET STRING,
50
* password [2] OCTET STRING
53
* TSSmartCardCreds ::= SEQUENCE {
54
* pin [0] OCTET STRING,
55
* cspData [1] TSCspDataDetail,
56
* userHint [2] OCTET STRING OPTIONAL,
57
* domainHint [3] OCTET STRING OPTIONAL
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
71
* Initialize NTLMSSP authentication module.
75
int credssp_ntlmssp_init(rdpCredssp* credssp)
78
NTLMSSP* ntlmssp = credssp->ntlmssp;
79
rdpSettings* settings = credssp->transport->settings;
80
instance = (freerdp*) settings->instance;
82
if ((settings->password == NULL) || (settings->username == NULL))
84
if(instance->Authenticate)
86
boolean proceed = instance->Authenticate(instance,
87
&settings->username, &settings->password, &settings->domain);
93
if (settings->ntlm_version == 2)
96
ntlmssp_set_password(ntlmssp, settings->password);
97
ntlmssp_set_username(ntlmssp, settings->username);
101
ntlmssp_set_workstation(ntlmssp, "WORKSTATION");
104
if (settings->domain != NULL)
106
if (strlen(settings->domain) > 0)
107
ntlmssp_set_domain(ntlmssp, settings->domain);
111
ntlmssp_set_domain(ntlmssp, NULL);
114
ntlmssp_generate_client_challenge(ntlmssp);
115
ntlmssp_generate_random_session_key(ntlmssp);
116
ntlmssp_generate_exported_session_key(ntlmssp);
122
* Get TLS public key.
126
int credssp_get_public_key(rdpCredssp* credssp)
131
cert = tls_get_certificate(credssp->transport->tls);
135
printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
139
if(tls_verify_certificate(cert, credssp->transport->settings, credssp->transport->settings->hostname))
140
tls_disconnect(credssp->transport->tls);
142
status = crypto_cert_get_public_key(cert, &credssp->public_key);
143
crypto_cert_free(cert);
149
* Authenticate with server using CredSSP.
151
* @return 1 if authentication is successful
154
int credssp_authenticate(rdpCredssp* credssp)
156
NTLMSSP* ntlmssp = credssp->ntlmssp;
157
STREAM* s = stream_new(0);
158
uint8* negoTokenBuffer = (uint8*) xmalloc(2048);
160
if (credssp_ntlmssp_init(credssp) == 0)
163
if (credssp_get_public_key(credssp) == 0)
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);
173
/* NTLMSSP CHALLENGE MESSAGE */
174
if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0)
177
s->p = s->data = credssp->negoToken.data;
178
ntlmssp_recv(ntlmssp, s);
180
freerdp_blob_free(&credssp->negoToken);
182
/* NTLMSSP AUTHENTICATE MESSAGE */
183
s->p = s->data = negoTokenBuffer;
184
ntlmssp_send(ntlmssp, s);
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);
192
/* Encrypted Public Key +1 */
193
if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0)
196
if (credssp_verify_public_key(credssp, &credssp->pubKeyAuth) == 0)
198
/* Failed to verify server public key echo */
199
return 0; /* DO NOT SEND CREDENTIALS! */
202
freerdp_blob_free(&credssp->negoToken);
203
freerdp_blob_free(&credssp->pubKeyAuth);
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);
216
* Encrypt TLS public key using CredSSP.
221
void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d)
225
rdpBlob encrypted_public_key;
226
NTLMSSP *ntlmssp = credssp->ntlmssp;
228
freerdp_blob_alloc(d, credssp->public_key.length + 16);
229
ntlmssp_encrypt_message(ntlmssp, &credssp->public_key, &encrypted_public_key, signature);
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);
236
printf("Encrypted Public Key (length = %d)\n", encrypted_public_key.length);
237
freerdp_hexdump(encrypted_public_key.data, encrypted_public_key.length);
240
printf("Signature\n");
241
freerdp_hexdump(signature, 16);
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 */
249
freerdp_blob_free(&encrypted_public_key);
253
* Verify TLS public key using CredSSP.
256
* @return 1 if verification is successful, 0 otherwise
259
int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d)
264
rdpBlob encrypted_public_key;
267
encrypted_public_key.data = (void*) (signature + 16);
268
encrypted_public_key.length = d->length - 16;
270
ntlmssp_decrypt_message(credssp->ntlmssp, &encrypted_public_key, &public_key, signature);
272
p1 = (uint8*) credssp->public_key.data;
273
p2 = (uint8*) public_key.data;
277
if (memcmp(p1, p2, public_key.length) != 0)
279
printf("Could not verify server's public key echo\n");
284
freerdp_blob_free(&public_key);
289
* Encrypt and sign TSCredentials structure.
294
void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d)
298
rdpBlob encrypted_ts_credentials;
299
NTLMSSP* ntlmssp = credssp->ntlmssp;
301
freerdp_blob_alloc(d, credssp->ts_credentials.length + 16);
302
ntlmssp_encrypt_message(ntlmssp, &credssp->ts_credentials, &encrypted_ts_credentials, signature);
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);
309
printf("Encrypted TSCredentials (length = %d)\n", encrypted_ts_credentials.length);
310
freerdp_hexdump(encrypted_ts_credentials.data, encrypted_ts_credentials.length);
313
printf("Signature\n");
314
freerdp_hexdump(signature, 16);
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 */
322
freerdp_blob_free(&encrypted_ts_credentials);
325
int credssp_skip_ts_password_creds(rdpCredssp* credssp)
328
int ts_password_creds_length = 0;
330
length = ber_skip_octet_string(credssp->ntlmssp->domain.length);
331
length += ber_skip_contextual_tag(length);
332
ts_password_creds_length += length;
334
length = ber_skip_octet_string(credssp->ntlmssp->username.length);
335
length += ber_skip_contextual_tag(length);
336
ts_password_creds_length += length;
338
length = ber_skip_octet_string(credssp->ntlmssp->password.length);
339
length += ber_skip_contextual_tag(length);
340
ts_password_creds_length += length;
342
length = ber_skip_sequence(ts_password_creds_length);
347
void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
351
length = credssp_skip_ts_password_creds(credssp);
353
/* TSPasswordCreds (SEQUENCE) */
354
length = ber_get_content_length(length);
355
ber_write_sequence_tag(s, length);
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);
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);
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);
370
int credssp_skip_ts_credentials(rdpCredssp* credssp)
373
int ts_password_creds_length;
374
int ts_credentials_length = 0;
376
length = ber_skip_integer(0);
377
length += ber_skip_contextual_tag(length);
378
ts_credentials_length += length;
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;
385
length = ber_skip_sequence(ts_credentials_length);
390
void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s)
393
int ts_password_creds_length;
395
length = credssp_skip_ts_credentials(credssp);
396
ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
398
/* TSCredentials (SEQUENCE) */
399
length = ber_get_content_length(length);
400
length -= ber_write_sequence_tag(s, length);
402
/* [0] credType (INTEGER) */
403
length -= ber_write_contextual_tag(s, 0, 3, true);
404
length -= ber_write_integer(s, 1);
406
/* [1] credentials (OCTET STRING) */
408
length -= ber_write_contextual_tag(s, 1, length, true);
409
length -= ber_write_octet_string_tag(s, ts_password_creds_length);
411
credssp_write_ts_password_creds(credssp, s);
415
* Encode TSCredentials structure.
419
void credssp_encode_ts_credentials(rdpCredssp* credssp)
425
length = credssp_skip_ts_credentials(credssp);
426
freerdp_blob_alloc(&credssp->ts_credentials, length);
427
s->p = s->data = credssp->ts_credentials.data;
430
credssp_write_ts_credentials(credssp, s);
433
int credssp_skip_nego_token(int length)
435
length = ber_skip_octet_string(length);
436
length += ber_skip_contextual_tag(length);
440
int credssp_skip_nego_tokens(int length)
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);
449
int credssp_skip_pub_key_auth(int length)
451
length = ber_skip_octet_string(length);
452
length += ber_skip_contextual_tag(length);
456
int credssp_skip_auth_info(int length)
458
length = ber_skip_octet_string(length);
459
length += ber_skip_contextual_tag(length);
463
int credssp_skip_ts_request(int length)
465
length += ber_skip_integer(2);
466
length += ber_skip_contextual_tag(3);
467
length += ber_skip_sequence_tag(length);
472
* Send CredSSP message.
479
void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth)
483
int ts_request_length;
484
int nego_tokens_length;
485
int pub_key_auth_length;
486
int auth_info_length;
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;
492
length = nego_tokens_length + pub_key_auth_length + auth_info_length;
493
ts_request_length = credssp_skip_ts_request(length);
495
s = stream_new(ts_request_length);
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 */
503
/* [1] negoTokens (NegoData) */
504
if (nego_tokens_length > 0)
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 */
514
/* [2] authInfo (OCTET STRING) */
515
if (auth_info_length > 0)
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);
522
/* [3] pubKeyAuth (OCTET STRING) */
523
if (pub_key_auth_length > 0)
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);
530
transport_write(credssp->transport, s);
534
* Receive CredSSP message.
542
int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdpBlob* pubKeyAuth)
549
s = transport_recv_stream_init(credssp->transport, 2048);
550
status = transport_read(credssp->transport, s);
556
ber_read_sequence_tag(s, &length);
557
ber_read_contextual_tag(s, 0, &length, true);
558
ber_read_integer(s, &version);
560
/* [1] negoTokens (NegoData) */
561
if (ber_read_contextual_tag(s, 1, &length, true) != false)
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);
571
/* [2] authInfo (OCTET STRING) */
572
if (ber_read_contextual_tag(s, 2, &length, true) != false)
574
ber_read_octet_string(s, &length); /* OCTET STRING */
575
freerdp_blob_alloc(authInfo, length);
576
stream_read(s, authInfo->data, length);
579
/* [3] pubKeyAuth (OCTET STRING) */
580
if (ber_read_contextual_tag(s, 3, &length, true) != false)
582
ber_read_octet_string(s, &length); /* OCTET STRING */
583
freerdp_blob_alloc(pubKeyAuth, length);
584
stream_read(s, pubKeyAuth->data, length);
591
* Encrypt the given plain text using RC4 and the given key.
593
* @param length text length
594
* @param plaintext plain text
595
* @param ciphertext cipher text
598
void credssp_rc4k(uint8* key, int length, uint8* plaintext, uint8* ciphertext)
602
/* Initialize RC4 cipher with key */
603
rc4 = crypto_rc4_init((void*) key, 16);
605
/* Encrypt plaintext with key */
606
crypto_rc4(rc4, length, (void*) plaintext, (void*) ciphertext);
608
/* Free RC4 Cipher */
609
crypto_rc4_free(rc4);
613
* Get current time, in tenths of microseconds since midnight of January 1, 1601.
614
* @param[out] timestamp 64-bit little-endian timestamp
617
void credssp_current_time(uint8* timestamp)
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 */
625
memcpy(timestamp, &time64, 8); /* Copy into timestamp in little-endian */
629
* Create new CredSSP state machine.
631
* @return new CredSSP state machine.
634
rdpCredssp* credssp_new(rdpTransport* transport)
638
self = (rdpCredssp*) xzalloc(sizeof(rdpCredssp));
642
self->transport = transport;
643
self->send_seq_num = 0;
644
self->ntlmssp = ntlmssp_new();
645
self->settings = transport->settings;
652
* Free CredSSP state machine.
656
void credssp_free(rdpCredssp* credssp)
660
freerdp_blob_free(&credssp->public_key);
661
freerdp_blob_free(&credssp->ts_credentials);
663
ntlmssp_free(credssp->ntlmssp);