1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Network Level Authentication (NLA)
4 *
5 * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 * Copyright 2015 Thincast Technologies GmbH
7 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8 * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com>
9 * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <time.h>
29
30 #ifndef _WIN32
31 #include <unistd.h>
32 #endif
33
34 #include <freerdp/log.h>
35 #include <freerdp/crypto/tls.h>
36 #include <freerdp/build-config.h>
37 #include <freerdp/peer.h>
38
39 #include <winpr/crt.h>
40 #include <winpr/sam.h>
41 #include <winpr/sspi.h>
42 #include <winpr/print.h>
43 #include <winpr/tchar.h>
44 #include <winpr/dsparse.h>
45 #include <winpr/library.h>
46 #include <winpr/registry.h>
47
48 #include "nla.h"
49
50 #define TAG FREERDP_TAG("core.nla")
51
52 #define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
53
54 /**
55 * TSRequest ::= SEQUENCE {
56 * version [0] INTEGER,
57 * negoTokens [1] NegoData OPTIONAL,
58 * authInfo [2] OCTET STRING OPTIONAL,
59 * pubKeyAuth [3] OCTET STRING OPTIONAL,
60 * errorCode [4] INTEGER OPTIONAL
61 * }
62 *
63 * NegoData ::= SEQUENCE OF NegoDataItem
64 *
65 * NegoDataItem ::= SEQUENCE {
66 * negoToken [0] OCTET STRING
67 * }
68 *
69 * TSCredentials ::= SEQUENCE {
70 * credType [0] INTEGER,
71 * credentials [1] OCTET STRING
72 * }
73 *
74 * TSPasswordCreds ::= SEQUENCE {
75 * domainName [0] OCTET STRING,
76 * userName [1] OCTET STRING,
77 * password [2] OCTET STRING
78 * }
79 *
80 * TSSmartCardCreds ::= SEQUENCE {
81 * pin [0] OCTET STRING,
82 * cspData [1] TSCspDataDetail,
83 * userHint [2] OCTET STRING OPTIONAL,
84 * domainHint [3] OCTET STRING OPTIONAL
85 * }
86 *
87 * TSCspDataDetail ::= SEQUENCE {
88 * keySpec [0] INTEGER,
89 * cardName [1] OCTET STRING OPTIONAL,
90 * readerName [2] OCTET STRING OPTIONAL,
91 * containerName [3] OCTET STRING OPTIONAL,
92 * cspName [4] OCTET STRING OPTIONAL
93 * }
94 *
95 */
96
97 #define NLA_PKG_NAME NEGO_SSP_NAME
98
99 #define TERMSRV_SPN_PREFIX "TERMSRV/"
100
101 struct rdp_nla
102 {
103 BOOL server;
104 NLA_STATE state;
105 int sendSeqNum;
106 int recvSeqNum;
107 freerdp* instance;
108 CtxtHandle context;
109 LPTSTR SspiModule;
110 char* SamFile;
111 rdpSettings* settings;
112 rdpTransport* transport;
113 UINT32 cbMaxToken;
114 #if defined(UNICODE)
115 SEC_WCHAR* packageName;
116 #else
117 SEC_CHAR* packageName;
118 #endif
119 UINT32 version;
120 UINT32 peerVersion;
121 UINT32 errorCode;
122 ULONG fContextReq;
123 ULONG pfContextAttr;
124 BOOL haveContext;
125 BOOL haveInputBuffer;
126 BOOL havePubKeyAuth;
127 SECURITY_STATUS status;
128 CredHandle credentials;
129 TimeStamp expiration;
130 PSecPkgInfo pPackageInfo;
131 SecBuffer inputBuffer;
132 SecBuffer outputBuffer;
133 SecBufferDesc inputBufferDesc;
134 SecBufferDesc outputBufferDesc;
135 SecBuffer negoToken;
136 SecBuffer pubKeyAuth;
137 SecBuffer authInfo;
138 SecBuffer ClientNonce;
139 SecBuffer PublicKey;
140 SecBuffer tsCredentials;
141 LPTSTR ServicePrincipalName;
142 SEC_WINNT_AUTH_IDENTITY* identity;
143 PSecurityFunctionTable table;
144 SecPkgContext_Sizes ContextSizes;
145 };
146
147 static BOOL nla_send(rdpNla* nla, const char* msg);
148 static int nla_recv(rdpNla* nla, const char* msg);
149 static void nla_buffer_print(rdpNla* nla);
150 static void nla_buffer_free(rdpNla* nla);
151 static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
152 static SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla);
153 static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
154 static SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla);
155 static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
156 static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
157 static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
158 static void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity);
159
160 #define ber_sizeof_sequence_octet_string(length) \
161 ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
162 #define ber_write_sequence_octet_string(stream, context, value, length) \
163 ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE) + \
164 ber_write_octet_string(stream, value, length)
165
166 /* CredSSP Client-To-Server Binding Hash\0 */
167 static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
168 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
169 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
170 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
171 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
172
173 /* CredSSP Server-To-Client Binding Hash\0 */
174 static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
175 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
176 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
177 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
178 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
179
180 static const UINT32 NonceLength = 32;
181
nla_identity_free(SEC_WINNT_AUTH_IDENTITY * identity)182 void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
183 {
184 if (identity)
185 {
186 /* Password authentication */
187 if (identity->User)
188 {
189 memset(identity->User, 0, identity->UserLength * 2);
190 free(identity->User);
191 }
192
193 if (identity->Password)
194 {
195 size_t len = identity->PasswordLength;
196
197 if (len > LB_PASSWORD_MAX_LENGTH) /* [pth] Password hash */
198 len -= LB_PASSWORD_MAX_LENGTH;
199
200 memset(identity->Password, 0, len * 2);
201 free(identity->Password);
202 }
203
204 if (identity->Domain)
205 {
206 memset(identity->Domain, 0, identity->DomainLength * 2);
207 free(identity->Domain);
208 }
209 }
210
211 free(identity);
212 }
213
214 /**
215 * Initialize NTLM/Kerberos SSP authentication module (client).
216 * @param credssp
217 */
218
is_empty(const char * str)219 static BOOL is_empty(const char* str)
220 {
221 if (!str)
222 return TRUE;
223 if (strlen(str) == 0)
224 return TRUE;
225 return FALSE;
226 }
227
nla_client_init(rdpNla * nla)228 static int nla_client_init(rdpNla* nla)
229 {
230 char* spn;
231 size_t length;
232 rdpTls* tls = NULL;
233 BOOL PromptPassword = FALSE;
234 freerdp* instance = nla->instance;
235 rdpSettings* settings = nla->settings;
236 WINPR_SAM* sam;
237 WINPR_SAM_ENTRY* entry;
238 nla->state = NLA_STATE_INITIAL;
239
240 if (settings->RestrictedAdminModeRequired)
241 settings->DisableCredentialsDelegation = TRUE;
242
243 if (is_empty(settings->Username) ||
244 (is_empty(settings->Password) && is_empty((const char*)settings->RedirectionPassword)))
245 {
246 PromptPassword = TRUE;
247 }
248
249 if (PromptPassword && !is_empty(settings->Username))
250 {
251 sam = SamOpen(NULL, TRUE);
252
253 if (sam)
254 {
255 entry = SamLookupUserA(sam, settings->Username, strlen(settings->Username), NULL, 0);
256
257 if (entry)
258 {
259 /**
260 * The user could be found in SAM database.
261 * Use entry in SAM database later instead of prompt
262 */
263 PromptPassword = FALSE;
264 SamFreeEntry(sam, entry);
265 }
266
267 SamClose(sam);
268 }
269 }
270
271 #ifndef _WIN32
272
273 if (PromptPassword)
274 {
275 if (settings->RestrictedAdminModeRequired)
276 {
277 if (!is_empty(settings->PasswordHash))
278 PromptPassword = FALSE;
279 }
280 }
281
282 #endif
283
284 if (PromptPassword)
285 {
286 if (freerdp_shall_disconnect(instance))
287 return 0;
288
289 if (!instance->Authenticate)
290 {
291 freerdp_set_last_error_log(instance->context,
292 FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS);
293 return 0;
294 }
295 else
296 {
297 BOOL proceed = instance->Authenticate(instance, &settings->Username,
298 &settings->Password, &settings->Domain);
299
300 if (!proceed)
301 {
302 freerdp_set_last_error_log(instance->context,
303 FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS);
304 return 0;
305 }
306 }
307 }
308
309 if (!settings->Username)
310 {
311 nla_identity_free(nla->identity);
312 nla->identity = NULL;
313 }
314 else
315 {
316 if (settings->RedirectionPassword && settings->RedirectionPasswordLength > 0)
317 {
318 if (sspi_SetAuthIdentityWithUnicodePassword(
319 nla->identity, settings->Username, settings->Domain,
320 (UINT16*)settings->RedirectionPassword,
321 settings->RedirectionPasswordLength / sizeof(WCHAR) - 1) < 0)
322 return -1;
323 }
324 else
325 {
326 BOOL usePassword = TRUE;
327
328 if (settings->RestrictedAdminModeRequired)
329 {
330 if (settings->PasswordHash)
331 {
332 if (strlen(settings->PasswordHash) == 32)
333 {
334 if (sspi_SetAuthIdentity(nla->identity, settings->Username,
335 settings->Domain, settings->PasswordHash) < 0)
336 return -1;
337
338 /**
339 * Increase password hash length by LB_PASSWORD_MAX_LENGTH to obtain a
340 * length exceeding the maximum (LB_PASSWORD_MAX_LENGTH) and use it this for
341 * hash identification in WinPR.
342 */
343 nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
344 usePassword = FALSE;
345 }
346 }
347 }
348
349 if (usePassword)
350 {
351 if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
352 settings->Password) < 0)
353 return -1;
354 }
355 }
356 }
357
358 tls = nla->transport->tls;
359
360 if (!tls)
361 {
362 WLog_ERR(TAG, "Unknown NLA transport layer");
363 return -1;
364 }
365
366 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
367 {
368 WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
369 return -1;
370 }
371
372 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
373 length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname);
374 spn = (SEC_CHAR*)malloc(length + 1);
375
376 if (!spn)
377 return -1;
378
379 sprintf_s(spn, length + 1, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname);
380 #ifdef UNICODE
381 nla->ServicePrincipalName = NULL;
382 ConvertToUnicode(CP_UTF8, 0, spn, -1, &nla->ServicePrincipalName, 0);
383 free(spn);
384 #else
385 nla->ServicePrincipalName = spn;
386 #endif
387 nla->table = InitSecurityInterfaceEx(0);
388 #ifdef WITH_GSSAPI /* KERBEROS SSP */
389 nla->status = nla->table->QuerySecurityPackageInfo(KERBEROS_SSP_NAME, &nla->pPackageInfo);
390
391 if (nla->status != SEC_E_OK)
392 {
393 WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08" PRIX32 "]",
394 GetSecurityStatusString(nla->status), nla->status);
395 return -1;
396 }
397
398 #else /* NTLM SSP */
399 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
400
401 if (nla->status != SEC_E_OK)
402 {
403 WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08" PRIX32 "]",
404 GetSecurityStatusString(nla->status), nla->status);
405 return -1;
406 }
407
408 #endif
409 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
410 nla->packageName = nla->pPackageInfo->Name;
411 WLog_DBG(TAG, "%s %" PRIu32 " : packageName=%ls ; cbMaxToken=%d", __FUNCTION__, __LINE__,
412 nla->packageName, nla->cbMaxToken);
413 nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_OUTBOUND,
414 NULL, nla->identity, NULL, NULL,
415 &nla->credentials, &nla->expiration);
416
417 if (nla->status != SEC_E_OK)
418 {
419 WLog_ERR(TAG, "AcquireCredentialsHandle status %s [0x%08" PRIX32 "]",
420 GetSecurityStatusString(nla->status), nla->status);
421 return -1;
422 }
423
424 nla->haveContext = FALSE;
425 nla->haveInputBuffer = FALSE;
426 nla->havePubKeyAuth = FALSE;
427 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
428 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
429 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
430 /*
431 * from tspkg.dll: 0x00000132
432 * ISC_REQ_MUTUAL_AUTH
433 * ISC_REQ_CONFIDENTIALITY
434 * ISC_REQ_USE_SESSION_KEY
435 * ISC_REQ_ALLOCATE_MEMORY
436 */
437 nla->fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY;
438 return 1;
439 }
440
nla_client_begin(rdpNla * nla)441 int nla_client_begin(rdpNla* nla)
442 {
443 if (nla_client_init(nla) < 1)
444 return -1;
445
446 if (nla->state != NLA_STATE_INITIAL)
447 return -1;
448
449 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
450 nla->outputBufferDesc.cBuffers = 1;
451 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
452 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
453 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
454 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
455
456 if (!nla->outputBuffer.pvBuffer)
457 return -1;
458
459 nla->status = nla->table->InitializeSecurityContext(
460 &nla->credentials, NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
461 SECURITY_NATIVE_DREP, NULL, 0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr,
462 &nla->expiration);
463 WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08" PRIX32 "]",
464 GetSecurityStatusString(nla->status), nla->status);
465
466 /* Handle kerberos context initialization failure.
467 * After kerberos failed initialize NTLM context */
468 if (nla->status == SEC_E_NO_CREDENTIALS)
469 {
470 nla->status = nla->table->InitializeSecurityContext(
471 &nla->credentials, NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
472 SECURITY_NATIVE_DREP, NULL, 0, &nla->context, &nla->outputBufferDesc,
473 &nla->pfContextAttr, &nla->expiration);
474 WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08" PRIX32 "]",
475 GetSecurityStatusString(nla->status), nla->status);
476
477 if (nla->status)
478 {
479 SECURITY_STATUS status =
480 nla->table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &nla->pPackageInfo);
481
482 if (status != SEC_E_OK)
483 {
484 WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08" PRIX32 "]",
485 GetSecurityStatusString(nla->status), status);
486 return -1;
487 }
488
489 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
490 nla->packageName = nla->pPackageInfo->Name;
491 }
492 }
493
494 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
495 {
496 if (nla->table->CompleteAuthToken)
497 {
498 SECURITY_STATUS status;
499 status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
500
501 if (status != SEC_E_OK)
502 {
503 WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
504 GetSecurityStatusString(status), status);
505 return -1;
506 }
507 }
508
509 if (nla->status == SEC_I_COMPLETE_NEEDED)
510 nla->status = SEC_E_OK;
511 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
512 nla->status = SEC_I_CONTINUE_NEEDED;
513 }
514
515 if (nla->status != SEC_I_CONTINUE_NEEDED)
516 return -1;
517
518 if (nla->outputBuffer.cbBuffer < 1)
519 return -1;
520
521 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
522 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
523
524 if (!nla_send(nla, "Client: Sending Authentication Token"))
525 {
526 nla_buffer_free(nla);
527 return -1;
528 }
529
530 nla_buffer_free(nla);
531 nla->state = NLA_STATE_NEGO_TOKEN;
532 return 1;
533 }
534
nla_client_recv(rdpNla * nla)535 static int nla_client_recv(rdpNla* nla)
536 {
537 int status = -1;
538
539 if (nla->state == NLA_STATE_NEGO_TOKEN)
540 {
541 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
542 nla->inputBufferDesc.cBuffers = 1;
543 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
544 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
545 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
546 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
547 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
548 nla->outputBufferDesc.cBuffers = 1;
549 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
550 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
551 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
552 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
553
554 if (!nla->outputBuffer.pvBuffer)
555 return -1;
556
557 nla->status = nla->table->InitializeSecurityContext(
558 &nla->credentials, &nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
559 SECURITY_NATIVE_DREP, &nla->inputBufferDesc, 0, &nla->context, &nla->outputBufferDesc,
560 &nla->pfContextAttr, &nla->expiration);
561 WLog_VRB(TAG, "InitializeSecurityContext %s [0x%08" PRIX32 "]",
562 GetSecurityStatusString(nla->status), nla->status);
563 free(nla->inputBuffer.pvBuffer);
564 nla->inputBuffer.pvBuffer = NULL;
565
566 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
567 {
568 if (nla->table->CompleteAuthToken)
569 {
570 SECURITY_STATUS status;
571 status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
572
573 if (status != SEC_E_OK)
574 {
575 WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
576 GetSecurityStatusString(status), status);
577 return -1;
578 }
579 }
580
581 if (nla->status == SEC_I_COMPLETE_NEEDED)
582 nla->status = SEC_E_OK;
583 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
584 nla->status = SEC_I_CONTINUE_NEEDED;
585 }
586
587 if (nla->status == SEC_E_OK)
588 {
589 nla->havePubKeyAuth = TRUE;
590 nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES,
591 &nla->ContextSizes);
592
593 if (nla->status != SEC_E_OK)
594 {
595 WLog_ERR(TAG,
596 "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [0x%08" PRIX32 "]",
597 GetSecurityStatusString(nla->status), nla->status);
598 return -1;
599 }
600
601 if (nla->peerVersion < 5)
602 nla->status = nla_encrypt_public_key_echo(nla);
603 else
604 nla->status = nla_encrypt_public_key_hash(nla);
605
606 if (nla->status != SEC_E_OK)
607 return -1;
608 }
609
610 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
611 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
612
613 if (!nla_send(nla, "Client: Sending Authentication Token"))
614 {
615 nla_buffer_free(nla);
616 return -1;
617 }
618
619 nla_buffer_free(nla);
620
621 if (nla->status == SEC_E_OK)
622 nla->state = NLA_STATE_PUB_KEY_AUTH;
623
624 status = 1;
625 }
626 else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
627 {
628 /* Verify Server Public Key Echo */
629 if (nla->peerVersion < 5)
630 nla->status = nla_decrypt_public_key_echo(nla);
631 else
632 nla->status = nla_decrypt_public_key_hash(nla);
633
634 nla_buffer_free(nla);
635
636 if (nla->status != SEC_E_OK)
637 {
638 WLog_ERR(TAG, "Could not verify public key echo %s [0x%08" PRIX32 "]",
639 GetSecurityStatusString(nla->status), nla->status);
640 return -1;
641 }
642
643 /* Send encrypted credentials */
644 nla->status = nla_encrypt_ts_credentials(nla);
645
646 if (nla->status != SEC_E_OK)
647 {
648 WLog_ERR(TAG, "nla_encrypt_ts_credentials status %s [0x%08" PRIX32 "]",
649 GetSecurityStatusString(nla->status), nla->status);
650 return -1;
651 }
652
653 if (!nla_send(nla, "Client: Sending PubKeyAuth Token"))
654 {
655 nla_buffer_free(nla);
656 return -1;
657 }
658
659 nla_buffer_free(nla);
660
661 if (SecIsValidHandle(&nla->credentials))
662 {
663 nla->table->FreeCredentialsHandle(&nla->credentials);
664 SecInvalidateHandle(&nla->credentials);
665 }
666
667 if (nla->status != SEC_E_OK)
668 {
669 WLog_ERR(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
670 GetSecurityStatusString(nla->status), nla->status);
671 }
672
673 nla->status = nla->table->FreeContextBuffer(nla->pPackageInfo);
674
675 if (nla->status != SEC_E_OK)
676 {
677 WLog_ERR(TAG, "FreeContextBuffer status %s [0x%08" PRIX32 "]",
678 GetSecurityStatusString(nla->status), nla->status);
679 }
680
681 if (nla->status != SEC_E_OK)
682 return -1;
683
684 nla->state = NLA_STATE_AUTH_INFO;
685 status = 1;
686 }
687
688 return status;
689 }
690
nla_client_authenticate(rdpNla * nla)691 static int nla_client_authenticate(rdpNla* nla)
692 {
693 wStream* s;
694 int status;
695 s = Stream_New(NULL, 4096);
696
697 if (!s)
698 {
699 WLog_ERR(TAG, "Stream_New failed!");
700 return -1;
701 }
702
703 if (nla_client_begin(nla) < 1)
704 {
705 Stream_Free(s, TRUE);
706 return -1;
707 }
708
709 while (nla->state < NLA_STATE_AUTH_INFO)
710 {
711 Stream_SetPosition(s, 0);
712 status = transport_read_pdu(nla->transport, s);
713
714 if (status < 0)
715 {
716 WLog_ERR(TAG, "nla_client_authenticate failure");
717 Stream_Free(s, TRUE);
718 return -1;
719 }
720
721 status = nla_recv_pdu(nla, s);
722
723 if (status < 0)
724 {
725 Stream_Free(s, TRUE);
726 return -1;
727 }
728 }
729
730 Stream_Free(s, TRUE);
731 return 1;
732 }
733
734 /**
735 * Initialize NTLMSSP authentication module (server).
736 * @param credssp
737 */
738
nla_server_init(rdpNla * nla)739 static int nla_server_init(rdpNla* nla)
740 {
741 rdpTls* tls = nla->transport->tls;
742
743 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
744 {
745 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
746 return -1;
747 }
748
749 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
750
751 if (nla->SspiModule)
752 {
753 HMODULE hSSPI;
754 INIT_SECURITY_INTERFACE pInitSecurityInterface;
755 hSSPI = LoadLibrary(nla->SspiModule);
756
757 if (!hSSPI)
758 {
759 WLog_ERR(TAG, "Failed to load SSPI module: %s", nla->SspiModule);
760 return -1;
761 }
762
763 #ifdef UNICODE
764 pInitSecurityInterface =
765 (INIT_SECURITY_INTERFACE)GetProcAddress(hSSPI, "InitSecurityInterfaceW");
766 #else
767 pInitSecurityInterface =
768 (INIT_SECURITY_INTERFACE)GetProcAddress(hSSPI, "InitSecurityInterfaceA");
769 #endif
770 nla->table = pInitSecurityInterface();
771 }
772 else
773 {
774 nla->table = InitSecurityInterfaceEx(0);
775 }
776
777 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
778
779 if (nla->status != SEC_E_OK)
780 {
781 WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08" PRIX32 "]",
782 GetSecurityStatusString(nla->status), nla->status);
783 return -1;
784 }
785
786 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
787 nla->packageName = nla->pPackageInfo->Name;
788 nla->status =
789 nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_INBOUND, NULL, NULL,
790 NULL, NULL, &nla->credentials, &nla->expiration);
791
792 if (nla->status != SEC_E_OK)
793 {
794 WLog_ERR(TAG, "AcquireCredentialsHandle status %s [0x%08" PRIX32 "]",
795 GetSecurityStatusString(nla->status), nla->status);
796 return -1;
797 }
798
799 nla->haveContext = FALSE;
800 nla->haveInputBuffer = FALSE;
801 nla->havePubKeyAuth = FALSE;
802 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
803 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
804 ZeroMemory(&nla->inputBufferDesc, sizeof(SecBufferDesc));
805 ZeroMemory(&nla->outputBufferDesc, sizeof(SecBufferDesc));
806 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
807 /*
808 * from tspkg.dll: 0x00000112
809 * ASC_REQ_MUTUAL_AUTH
810 * ASC_REQ_CONFIDENTIALITY
811 * ASC_REQ_ALLOCATE_MEMORY
812 */
813 nla->fContextReq = 0;
814 nla->fContextReq |= ASC_REQ_MUTUAL_AUTH;
815 nla->fContextReq |= ASC_REQ_CONFIDENTIALITY;
816 nla->fContextReq |= ASC_REQ_CONNECTION;
817 nla->fContextReq |= ASC_REQ_USE_SESSION_KEY;
818 nla->fContextReq |= ASC_REQ_REPLAY_DETECT;
819 nla->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
820 nla->fContextReq |= ASC_REQ_EXTENDED_ERROR;
821 return 1;
822 }
823
824 /**
825 * Authenticate with client using CredSSP (server).
826 * @param credssp
827 * @return 1 if authentication is successful
828 */
829
nla_server_authenticate(rdpNla * nla)830 static int nla_server_authenticate(rdpNla* nla)
831 {
832 if (nla_server_init(nla) < 1)
833 return -1;
834
835 while (TRUE)
836 {
837 /* receive authentication token */
838 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
839 nla->inputBufferDesc.cBuffers = 1;
840 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
841 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
842
843 if (nla_recv(nla, "Receiving Authentication Token") < 0)
844 return -1;
845
846 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
847 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
848
849 if (nla->negoToken.cbBuffer < 1)
850 {
851 WLog_ERR(TAG, "CredSSP: invalid negoToken!");
852 return -1;
853 }
854
855 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
856 nla->outputBufferDesc.cBuffers = 1;
857 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
858 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
859 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
860 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
861
862 if (!nla->outputBuffer.pvBuffer)
863 return -1;
864
865 nla->status = nla->table->AcceptSecurityContext(
866 &nla->credentials, nla->haveContext ? &nla->context : NULL, &nla->inputBufferDesc,
867 nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context, &nla->outputBufferDesc,
868 &nla->pfContextAttr, &nla->expiration);
869 WLog_VRB(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
870 GetSecurityStatusString(nla->status), nla->status);
871 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
872 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
873
874 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
875 {
876 freerdp_peer* peer = nla->instance->context->peer;
877
878 if (peer->ComputeNtlmHash)
879 {
880 SECURITY_STATUS status;
881 status = nla->table->SetContextAttributes(
882 &nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB, peer->ComputeNtlmHash, 0);
883
884 if (status != SEC_E_OK)
885 {
886 WLog_ERR(TAG, "SetContextAttributesA(hash cb) status %s [0x%08" PRIX32 "]",
887 GetSecurityStatusString(status), status);
888 }
889
890 status = nla->table->SetContextAttributes(
891 &nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA, peer, 0);
892
893 if (status != SEC_E_OK)
894 {
895 WLog_ERR(TAG, "SetContextAttributesA(hash cb data) status %s [0x%08" PRIX32 "]",
896 GetSecurityStatusString(status), status);
897 }
898 }
899 else if (nla->SamFile)
900 {
901 nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_SAM_FILE,
902 nla->SamFile, strlen(nla->SamFile) + 1);
903 }
904
905 if (nla->table->CompleteAuthToken)
906 {
907 SECURITY_STATUS status;
908 status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
909
910 if (status != SEC_E_OK)
911 {
912 WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
913 GetSecurityStatusString(status), status);
914 return -1;
915 }
916 }
917
918 if (nla->status == SEC_I_COMPLETE_NEEDED)
919 nla->status = SEC_E_OK;
920 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
921 nla->status = SEC_I_CONTINUE_NEEDED;
922 }
923
924 if (nla->status == SEC_E_OK)
925 {
926 if (nla->outputBuffer.cbBuffer != 0)
927 {
928 if (!nla_send(nla, "Server: Sending response"))
929 {
930 nla_buffer_free(nla);
931 return -1;
932 }
933
934 if (nla_recv(nla, "Receiving pubkey Token") < 0)
935 return -1;
936 }
937
938 nla->havePubKeyAuth = TRUE;
939 nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES,
940 &nla->ContextSizes);
941
942 if (nla->status != SEC_E_OK)
943 {
944 WLog_ERR(TAG,
945 "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [0x%08" PRIX32 "]",
946 GetSecurityStatusString(nla->status), nla->status);
947 return -1;
948 }
949
950 if (nla->peerVersion < 5)
951 nla->status = nla_decrypt_public_key_echo(nla);
952 else
953 nla->status = nla_decrypt_public_key_hash(nla);
954
955 if (nla->status != SEC_E_OK)
956 {
957 WLog_ERR(TAG,
958 "Error: could not verify client's public key echo %s [0x%08" PRIX32 "]",
959 GetSecurityStatusString(nla->status), nla->status);
960 return -1;
961 }
962
963 sspi_SecBufferFree(&nla->negoToken);
964 nla->negoToken.pvBuffer = NULL;
965 nla->negoToken.cbBuffer = 0;
966
967 if (nla->peerVersion < 5)
968 nla->status = nla_encrypt_public_key_echo(nla);
969 else
970 nla->status = nla_encrypt_public_key_hash(nla);
971
972 if (nla->status != SEC_E_OK)
973 return -1;
974 }
975
976 if ((nla->status != SEC_E_OK) && (nla->status != SEC_I_CONTINUE_NEEDED))
977 {
978 /* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
979 unfortunately does not map directly to the corresponding NTSTATUS values
980 */
981 switch (GetLastError())
982 {
983 case ERROR_PASSWORD_MUST_CHANGE:
984 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
985 break;
986
987 case ERROR_PASSWORD_EXPIRED:
988 nla->errorCode = STATUS_PASSWORD_EXPIRED;
989 break;
990
991 case ERROR_ACCOUNT_DISABLED:
992 nla->errorCode = STATUS_ACCOUNT_DISABLED;
993 break;
994
995 default:
996 nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
997 break;
998 }
999
1000 WLog_ERR(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
1001 GetSecurityStatusString(nla->status), nla->status);
1002 nla_send(nla, "Server: Sending AcceptSecurityContext error status");
1003 return -1; /* Access Denied */
1004 }
1005
1006 /* send authentication token */
1007 if (!nla_send(nla, "Server: Sending Authentication Token"))
1008 {
1009 nla_buffer_free(nla);
1010 return -1;
1011 }
1012
1013 nla_buffer_free(nla);
1014
1015 if (nla->status != SEC_I_CONTINUE_NEEDED)
1016 break;
1017
1018 nla->haveContext = TRUE;
1019 }
1020
1021 /* Receive encrypted credentials */
1022
1023 if (nla_recv(nla, "Receive Encryption Credentials") < 0)
1024 return -1;
1025
1026 nla->status = nla_decrypt_ts_credentials(nla);
1027
1028 if (nla->status != SEC_E_OK)
1029 {
1030 WLog_ERR(TAG, "Could not decrypt TSCredentials status %s [0x%08" PRIX32 "]",
1031 GetSecurityStatusString(nla->status), nla->status);
1032 return -1;
1033 }
1034
1035 nla->status = nla->table->ImpersonateSecurityContext(&nla->context);
1036
1037 if (nla->status != SEC_E_OK)
1038 {
1039 WLog_ERR(TAG, "ImpersonateSecurityContext status %s [0x%08" PRIX32 "]",
1040 GetSecurityStatusString(nla->status), nla->status);
1041 return -1;
1042 }
1043 else
1044 {
1045 nla->status = nla->table->RevertSecurityContext(&nla->context);
1046
1047 if (nla->status != SEC_E_OK)
1048 {
1049 WLog_ERR(TAG, "RevertSecurityContext status %s [0x%08" PRIX32 "]",
1050 GetSecurityStatusString(nla->status), nla->status);
1051 return -1;
1052 }
1053 }
1054
1055 nla->status = nla->table->FreeContextBuffer(nla->pPackageInfo);
1056
1057 if (nla->status != SEC_E_OK)
1058 {
1059 WLog_ERR(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
1060 GetSecurityStatusString(nla->status), nla->status);
1061 return -1;
1062 }
1063
1064 return 1;
1065 }
1066
1067 /**
1068 * Authenticate using CredSSP.
1069 * @param credssp
1070 * @return 1 if authentication is successful
1071 */
1072
nla_authenticate(rdpNla * nla)1073 int nla_authenticate(rdpNla* nla)
1074 {
1075 if (nla->server)
1076 return nla_server_authenticate(nla);
1077 else
1078 return nla_client_authenticate(nla);
1079 }
1080
ap_integer_increment_le(BYTE * number,int size)1081 static void ap_integer_increment_le(BYTE* number, int size)
1082 {
1083 int index;
1084
1085 for (index = 0; index < size; index++)
1086 {
1087 if (number[index] < 0xFF)
1088 {
1089 number[index]++;
1090 break;
1091 }
1092 else
1093 {
1094 number[index] = 0;
1095 continue;
1096 }
1097 }
1098 }
1099
ap_integer_decrement_le(BYTE * number,int size)1100 static void ap_integer_decrement_le(BYTE* number, int size)
1101 {
1102 int index;
1103
1104 for (index = 0; index < size; index++)
1105 {
1106 if (number[index] > 0)
1107 {
1108 number[index]--;
1109 break;
1110 }
1111 else
1112 {
1113 number[index] = 0xFF;
1114 continue;
1115 }
1116 }
1117 }
1118
nla_encrypt_public_key_echo(rdpNla * nla)1119 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
1120 {
1121 SecBuffer Buffers[2] = { { 0 } };
1122 SecBufferDesc Message;
1123 SECURITY_STATUS status;
1124 ULONG public_key_length;
1125 const BOOL krb =
1126 (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1127 const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0);
1128 const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0);
1129 public_key_length = nla->PublicKey.cbBuffer;
1130
1131 sspi_SecBufferFree(&nla->pubKeyAuth);
1132 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth,
1133 public_key_length + nla->ContextSizes.cbSecurityTrailer))
1134 return SEC_E_INSUFFICIENT_MEMORY;
1135
1136 if (krb)
1137 {
1138 Message.cBuffers = 1;
1139 Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */
1140 Buffers[0].cbBuffer = public_key_length;
1141 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
1142 CopyMemory(Buffers[0].pvBuffer, nla->PublicKey.pvBuffer, Buffers[0].cbBuffer);
1143 }
1144 else if (ntlm || nego)
1145 {
1146 Message.cBuffers = 2;
1147 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1148 Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
1149 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
1150 Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
1151 Buffers[1].cbBuffer = public_key_length;
1152 Buffers[1].pvBuffer =
1153 ((BYTE*)nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer;
1154 CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
1155 }
1156
1157 if (!krb && nla->server)
1158 {
1159 /* server echos the public key +1 */
1160 ap_integer_increment_le((BYTE*)Buffers[1].pvBuffer, Buffers[1].cbBuffer);
1161 }
1162
1163 Message.ulVersion = SECBUFFER_VERSION;
1164 Message.pBuffers = (PSecBuffer)&Buffers;
1165 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1166
1167 if (status != SEC_E_OK)
1168 {
1169 WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
1170 status);
1171 return status;
1172 }
1173
1174 if (Message.cBuffers == 2 && Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer)
1175 {
1176 /* IMPORTANT: EncryptMessage may not use all the signature space, so we need to shrink the
1177 * excess between the buffers */
1178 MoveMemory(((BYTE*)Buffers[0].pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer,
1179 Buffers[1].cbBuffer);
1180 nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer;
1181 }
1182
1183 return status;
1184 }
1185
nla_encrypt_public_key_hash(rdpNla * nla)1186 SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla)
1187 {
1188 SecBuffer Buffers[2] = { { 0 } };
1189 SecBufferDesc Message;
1190 SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
1191 WINPR_DIGEST_CTX* sha256 = NULL;
1192 const BOOL krb =
1193 (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1194 const ULONG auth_data_length =
1195 (nla->ContextSizes.cbSecurityTrailer + WINPR_SHA256_DIGEST_LENGTH);
1196 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
1197 const size_t hashSize =
1198 nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
1199
1200 sspi_SecBufferFree(&nla->pubKeyAuth);
1201 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, auth_data_length))
1202 {
1203 status = SEC_E_INSUFFICIENT_MEMORY;
1204 goto out;
1205 }
1206
1207 /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
1208 if (!(sha256 = winpr_Digest_New()))
1209 goto out;
1210
1211 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1212 goto out;
1213
1214 /* include trailing \0 from hashMagic */
1215 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1216 goto out;
1217
1218 if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer))
1219 goto out;
1220
1221 /* SubjectPublicKey */
1222 if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer))
1223 goto out;
1224
1225 if (krb)
1226 {
1227 Message.cBuffers = 1;
1228 Buffers[0].BufferType = SECBUFFER_DATA; /* SHA256 hash */
1229 Buffers[0].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
1230 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
1231
1232 if (!winpr_Digest_Final(sha256, Buffers[0].pvBuffer, Buffers[0].cbBuffer))
1233 goto out;
1234 }
1235 else
1236 {
1237 Message.cBuffers = 2;
1238 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1239 Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
1240 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
1241 Buffers[1].BufferType = SECBUFFER_DATA; /* SHA256 hash */
1242 Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
1243 Buffers[1].pvBuffer =
1244 ((BYTE*)nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer;
1245
1246 if (!winpr_Digest_Final(sha256, Buffers[1].pvBuffer, Buffers[1].cbBuffer))
1247 goto out;
1248 }
1249
1250 Message.pBuffers = (PSecBuffer)&Buffers;
1251 Message.ulVersion = SECBUFFER_VERSION;
1252 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1253
1254 if (status != SEC_E_OK)
1255 {
1256 WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
1257 status);
1258 goto out;
1259 }
1260
1261 if (Message.cBuffers == 2 && Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer)
1262 {
1263 /* IMPORTANT: EncryptMessage may not use all the signature space, so we need to shrink the
1264 * excess between the buffers */
1265 MoveMemory(((BYTE*)Buffers[0].pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer,
1266 Buffers[1].cbBuffer);
1267 nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer;
1268 }
1269
1270 out:
1271 winpr_Digest_Free(sha256);
1272 return status;
1273 }
1274
nla_decrypt_public_key_echo(rdpNla * nla)1275 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
1276 {
1277 ULONG length;
1278 BYTE* buffer = NULL;
1279 ULONG pfQOP = 0;
1280 BYTE* public_key1 = NULL;
1281 BYTE* public_key2 = NULL;
1282 ULONG public_key_length = 0;
1283 int signature_length;
1284 SecBuffer Buffers[2] = { { 0 } };
1285 SecBufferDesc Message;
1286 BOOL krb, ntlm, nego;
1287 SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
1288
1289 if (!nla)
1290 goto fail;
1291
1292 krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1293 nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0);
1294 ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0);
1295 signature_length = nla->pubKeyAuth.cbBuffer - nla->PublicKey.cbBuffer;
1296
1297 if ((signature_length < 0) || ((UINT32)signature_length > nla->ContextSizes.cbSecurityTrailer))
1298 {
1299 WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %" PRIu32 "", nla->pubKeyAuth.cbBuffer);
1300 goto fail;
1301 }
1302
1303 length = nla->pubKeyAuth.cbBuffer;
1304 buffer = (BYTE*)malloc(length);
1305
1306 if (!buffer)
1307 {
1308 status = SEC_E_INSUFFICIENT_MEMORY;
1309 goto fail;
1310 }
1311
1312 if (krb)
1313 {
1314 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
1315 Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TLS Public Key */
1316 Buffers[0].cbBuffer = length;
1317 Buffers[0].pvBuffer = buffer;
1318 Message.cBuffers = 1;
1319 }
1320 else if (ntlm || nego)
1321 {
1322 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
1323 public_key_length = nla->PublicKey.cbBuffer;
1324 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1325 Buffers[0].cbBuffer = signature_length;
1326 Buffers[0].pvBuffer = buffer;
1327 Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
1328 Buffers[1].cbBuffer = length - signature_length;
1329 Buffers[1].pvBuffer = buffer + signature_length;
1330 Message.cBuffers = 2;
1331 }
1332
1333 Message.ulVersion = SECBUFFER_VERSION;
1334 Message.pBuffers = (PSecBuffer)&Buffers;
1335 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1336
1337 if (status != SEC_E_OK)
1338 {
1339 WLog_ERR(TAG, "DecryptMessage failure %s [%08" PRIX32 "]", GetSecurityStatusString(status),
1340 status);
1341 goto fail;
1342 }
1343
1344 if (krb)
1345 {
1346 public_key1 = public_key2 = (BYTE*)nla->pubKeyAuth.pvBuffer;
1347 public_key_length = length;
1348 }
1349 else if (ntlm || nego)
1350 {
1351 public_key1 = (BYTE*)nla->PublicKey.pvBuffer;
1352 public_key2 = (BYTE*)Buffers[1].pvBuffer;
1353 }
1354
1355 if (!nla->server)
1356 {
1357 /* server echos the public key +1 */
1358 ap_integer_decrement_le(public_key2, public_key_length);
1359 }
1360
1361 if (!public_key1 || !public_key2 || memcmp(public_key1, public_key2, public_key_length) != 0)
1362 {
1363 WLog_ERR(TAG, "Could not verify server's public key echo");
1364 #if defined(WITH_DEBUG_NLA)
1365 WLog_ERR(TAG, "Expected (length = %d):", public_key_length);
1366 winpr_HexDump(TAG, WLOG_ERROR, public_key1, public_key_length);
1367 WLog_ERR(TAG, "Actual (length = %d):", public_key_length);
1368 winpr_HexDump(TAG, WLOG_ERROR, public_key2, public_key_length);
1369 #endif
1370 status = SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
1371 goto fail;
1372 }
1373
1374 status = SEC_E_OK;
1375 fail:
1376 free(buffer);
1377 return status;
1378 }
1379
nla_decrypt_public_key_hash(rdpNla * nla)1380 SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla)
1381 {
1382 unsigned long length;
1383 BYTE* buffer = NULL;
1384 ULONG pfQOP = 0;
1385 int signature_length;
1386 SecBuffer Buffers[2] = { { 0 } };
1387 SecBufferDesc Message;
1388 WINPR_DIGEST_CTX* sha256 = NULL;
1389 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH];
1390 SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
1391 const BOOL krb =
1392 (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1393 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1394 const size_t hashSize =
1395 nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1396 signature_length = nla->pubKeyAuth.cbBuffer - WINPR_SHA256_DIGEST_LENGTH;
1397
1398 if ((signature_length < 0) || (signature_length > (int)nla->ContextSizes.cbSecurityTrailer))
1399 {
1400 WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %" PRIu32 "", nla->pubKeyAuth.cbBuffer);
1401 goto fail;
1402 }
1403
1404 length = nla->pubKeyAuth.cbBuffer;
1405 buffer = (BYTE*)malloc(length);
1406
1407 if (!buffer)
1408 {
1409 status = SEC_E_INSUFFICIENT_MEMORY;
1410 goto fail;
1411 }
1412
1413 if (krb)
1414 {
1415 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
1416 Buffers[0].BufferType = SECBUFFER_DATA; /* Encrypted Hash */
1417 Buffers[0].cbBuffer = length;
1418 Buffers[0].pvBuffer = buffer;
1419 Message.cBuffers = 1;
1420 }
1421 else
1422 {
1423 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
1424 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1425 Buffers[0].cbBuffer = signature_length;
1426 Buffers[0].pvBuffer = buffer;
1427 Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted Hash */
1428 Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
1429 Buffers[1].pvBuffer = buffer + signature_length;
1430 Message.cBuffers = 2;
1431 }
1432
1433 Message.ulVersion = SECBUFFER_VERSION;
1434 Message.pBuffers = (PSecBuffer)&Buffers;
1435 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1436
1437 if (status != SEC_E_OK)
1438 {
1439 WLog_ERR(TAG, "DecryptMessage failure %s [%08" PRIX32 "]", GetSecurityStatusString(status),
1440 status);
1441 goto fail;
1442 }
1443
1444 /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1445 if (!(sha256 = winpr_Digest_New()))
1446 goto fail;
1447
1448 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1449 goto fail;
1450
1451 /* include trailing \0 from hashMagic */
1452 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1453 goto fail;
1454
1455 if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer))
1456 goto fail;
1457
1458 /* SubjectPublicKey */
1459 if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer))
1460 goto fail;
1461
1462 if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1463 goto fail;
1464
1465 /* verify hash */
1466 if (memcmp(serverClientHash, Buffers[krb ? 0 : 1].pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1467 {
1468 WLog_ERR(TAG, "Could not verify server's hash");
1469 status = SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
1470 goto fail;
1471 }
1472
1473 status = SEC_E_OK;
1474 fail:
1475 free(buffer);
1476 winpr_Digest_Free(sha256);
1477 return status;
1478 }
1479
nla_sizeof_ts_password_creds(rdpNla * nla)1480 static size_t nla_sizeof_ts_password_creds(rdpNla* nla)
1481 {
1482 size_t length = 0;
1483
1484 if (nla->identity)
1485 {
1486 length += ber_sizeof_sequence_octet_string(nla->identity->DomainLength * 2);
1487 length += ber_sizeof_sequence_octet_string(nla->identity->UserLength * 2);
1488 length += ber_sizeof_sequence_octet_string(nla->identity->PasswordLength * 2);
1489 }
1490
1491 return length;
1492 }
1493
nla_sizeof_ts_credentials(rdpNla * nla)1494 static size_t nla_sizeof_ts_credentials(rdpNla* nla)
1495 {
1496 size_t size = 0;
1497 size += ber_sizeof_integer(1);
1498 size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
1499 size +=
1500 ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
1501 return size;
1502 }
1503
nla_read_ts_password_creds(rdpNla * nla,wStream * s)1504 BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
1505 {
1506 size_t length;
1507
1508 if (!nla->identity)
1509 {
1510 WLog_ERR(TAG, "nla->identity is NULL!");
1511 return FALSE;
1512 }
1513
1514 /* TSPasswordCreds (SEQUENCE)
1515 * Initialise to default values. */
1516 nla->identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1517 nla->identity->UserLength = (UINT32)0;
1518 nla->identity->User = NULL;
1519 nla->identity->DomainLength = (UINT32)0;
1520 nla->identity->Domain = NULL;
1521 nla->identity->Password = NULL;
1522 nla->identity->PasswordLength = (UINT32)0;
1523
1524 if (!ber_read_sequence_tag(s, &length))
1525 return FALSE;
1526
1527 /* The sequence is empty, return early,
1528 * TSPasswordCreds (SEQUENCE) is optional. */
1529 if (length == 0)
1530 return TRUE;
1531
1532 /* [0] domainName (OCTET STRING) */
1533 if (!ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
1534 {
1535 return FALSE;
1536 }
1537
1538 nla->identity->DomainLength = (UINT32)length;
1539
1540 if (nla->identity->DomainLength > 0)
1541 {
1542 nla->identity->Domain = (UINT16*)malloc(length);
1543
1544 if (!nla->identity->Domain)
1545 return FALSE;
1546
1547 CopyMemory(nla->identity->Domain, Stream_Pointer(s), nla->identity->DomainLength);
1548 Stream_Seek(s, nla->identity->DomainLength);
1549 nla->identity->DomainLength /= 2;
1550 }
1551
1552 /* [1] userName (OCTET STRING) */
1553 if (!ber_read_contextual_tag(s, 1, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
1554 {
1555 return FALSE;
1556 }
1557
1558 nla->identity->UserLength = (UINT32)length;
1559
1560 if (nla->identity->UserLength > 0)
1561 {
1562 nla->identity->User = (UINT16*)malloc(length);
1563
1564 if (!nla->identity->User)
1565 return FALSE;
1566
1567 CopyMemory(nla->identity->User, Stream_Pointer(s), nla->identity->UserLength);
1568 Stream_Seek(s, nla->identity->UserLength);
1569 nla->identity->UserLength /= 2;
1570 }
1571
1572 /* [2] password (OCTET STRING) */
1573 if (!ber_read_contextual_tag(s, 2, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
1574 {
1575 return FALSE;
1576 }
1577
1578 nla->identity->PasswordLength = (UINT32)length;
1579
1580 if (nla->identity->PasswordLength > 0)
1581 {
1582 nla->identity->Password = (UINT16*)malloc(length);
1583
1584 if (!nla->identity->Password)
1585 return FALSE;
1586
1587 CopyMemory(nla->identity->Password, Stream_Pointer(s), nla->identity->PasswordLength);
1588 Stream_Seek(s, nla->identity->PasswordLength);
1589 nla->identity->PasswordLength /= 2;
1590 }
1591
1592 return TRUE;
1593 }
1594
nla_write_ts_password_creds(rdpNla * nla,wStream * s)1595 static size_t nla_write_ts_password_creds(rdpNla* nla, wStream* s)
1596 {
1597 size_t size = 0;
1598 size_t innerSize = nla_sizeof_ts_password_creds(nla);
1599 /* TSPasswordCreds (SEQUENCE) */
1600 size += ber_write_sequence_tag(s, innerSize);
1601
1602 if (nla->identity)
1603 {
1604 /* [0] domainName (OCTET STRING) */
1605 size += ber_write_sequence_octet_string(s, 0, (BYTE*)nla->identity->Domain,
1606 nla->identity->DomainLength * 2);
1607 /* [1] userName (OCTET STRING) */
1608 size += ber_write_sequence_octet_string(s, 1, (BYTE*)nla->identity->User,
1609 nla->identity->UserLength * 2);
1610 /* [2] password (OCTET STRING) */
1611 size += ber_write_sequence_octet_string(s, 2, (BYTE*)nla->identity->Password,
1612 nla->identity->PasswordLength * 2);
1613 }
1614
1615 return size;
1616 }
1617
nla_read_ts_credentials(rdpNla * nla,PSecBuffer ts_credentials)1618 static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
1619 {
1620 wStream* s;
1621 size_t length;
1622 size_t ts_password_creds_length = 0;
1623 BOOL ret;
1624
1625 if (!ts_credentials || !ts_credentials->pvBuffer)
1626 return FALSE;
1627
1628 s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer);
1629
1630 if (!s)
1631 {
1632 WLog_ERR(TAG, "Stream_New failed!");
1633 return FALSE;
1634 }
1635
1636 /* TSCredentials (SEQUENCE) */
1637 ret = ber_read_sequence_tag(s, &length) &&
1638 /* [0] credType (INTEGER) */
1639 ber_read_contextual_tag(s, 0, &length, TRUE) && ber_read_integer(s, NULL) &&
1640 /* [1] credentials (OCTET STRING) */
1641 ber_read_contextual_tag(s, 1, &length, TRUE) &&
1642 ber_read_octet_string_tag(s, &ts_password_creds_length) &&
1643 nla_read_ts_password_creds(nla, s);
1644 Stream_Free(s, FALSE);
1645 return ret;
1646 }
1647
nla_write_ts_credentials(rdpNla * nla,wStream * s)1648 static size_t nla_write_ts_credentials(rdpNla* nla, wStream* s)
1649 {
1650 size_t size = 0;
1651 size_t passwordSize;
1652 size_t innerSize = nla_sizeof_ts_credentials(nla);
1653 /* TSCredentials (SEQUENCE) */
1654 size += ber_write_sequence_tag(s, innerSize);
1655 /* [0] credType (INTEGER) */
1656 size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), TRUE);
1657 size += ber_write_integer(s, 1);
1658 /* [1] credentials (OCTET STRING) */
1659 passwordSize = ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla));
1660 size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), TRUE);
1661 size += ber_write_octet_string_tag(s, passwordSize);
1662 size += nla_write_ts_password_creds(nla, s);
1663 return size;
1664 }
1665
1666 /**
1667 * Encode TSCredentials structure.
1668 * @param credssp
1669 */
1670
nla_encode_ts_credentials(rdpNla * nla)1671 static BOOL nla_encode_ts_credentials(rdpNla* nla)
1672 {
1673 wStream* s;
1674 size_t length;
1675 int DomainLength = 0;
1676 int UserLength = 0;
1677 int PasswordLength = 0;
1678
1679 if (nla->identity)
1680 {
1681 /* TSPasswordCreds */
1682 DomainLength = nla->identity->DomainLength;
1683 UserLength = nla->identity->UserLength;
1684 PasswordLength = nla->identity->PasswordLength;
1685 }
1686
1687 if (nla->settings->DisableCredentialsDelegation && nla->identity)
1688 {
1689 /* TSPasswordCreds */
1690 nla->identity->DomainLength = 0;
1691 nla->identity->UserLength = 0;
1692 nla->identity->PasswordLength = 0;
1693 }
1694
1695 length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
1696
1697 if (!sspi_SecBufferAlloc(&nla->tsCredentials, length))
1698 {
1699 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1700 return FALSE;
1701 }
1702
1703 s = Stream_New((BYTE*)nla->tsCredentials.pvBuffer, length);
1704
1705 if (!s)
1706 {
1707 sspi_SecBufferFree(&nla->tsCredentials);
1708 WLog_ERR(TAG, "Stream_New failed!");
1709 return FALSE;
1710 }
1711
1712 nla_write_ts_credentials(nla, s);
1713
1714 if (nla->settings->DisableCredentialsDelegation && nla->identity)
1715 {
1716 /* TSPasswordCreds */
1717 nla->identity->DomainLength = DomainLength;
1718 nla->identity->UserLength = UserLength;
1719 nla->identity->PasswordLength = PasswordLength;
1720 }
1721
1722 Stream_Free(s, FALSE);
1723 return TRUE;
1724 }
1725
nla_encrypt_ts_credentials(rdpNla * nla)1726 static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
1727 {
1728 SecBuffer Buffers[2] = { { 0 } };
1729 SecBufferDesc Message;
1730 SECURITY_STATUS status;
1731 const BOOL krb =
1732 (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1733 const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0);
1734 const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0);
1735
1736 if (!nla_encode_ts_credentials(nla))
1737 return SEC_E_INSUFFICIENT_MEMORY;
1738
1739 if (!sspi_SecBufferAlloc(&nla->authInfo,
1740 nla->tsCredentials.cbBuffer + nla->ContextSizes.cbSecurityTrailer))
1741 return SEC_E_INSUFFICIENT_MEMORY;
1742
1743 if (krb)
1744 {
1745 Buffers[0].BufferType = SECBUFFER_DATA; /* TSCredentials */
1746 Buffers[0].cbBuffer = nla->tsCredentials.cbBuffer;
1747 Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
1748 CopyMemory(Buffers[0].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[0].cbBuffer);
1749 Message.cBuffers = 1;
1750 }
1751 else if (ntlm || nego)
1752 {
1753 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1754 Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
1755 Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
1756 MoveMemory(Buffers[0].pvBuffer, nla->authInfo.pvBuffer, Buffers[0].cbBuffer);
1757 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1758 Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
1759 Buffers[1].pvBuffer = &((BYTE*)nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
1760 CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
1761 Message.cBuffers = 2;
1762 }
1763
1764 Message.ulVersion = SECBUFFER_VERSION;
1765 Message.pBuffers = (PSecBuffer)&Buffers;
1766 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1767
1768 if (status != SEC_E_OK)
1769 {
1770 WLog_ERR(TAG, "EncryptMessage failure %s [0x%08" PRIX32 "]",
1771 GetSecurityStatusString(status), status);
1772 return status;
1773 }
1774
1775 if (Message.cBuffers == 2 && Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer)
1776 {
1777 /* IMPORTANT: EncryptMessage may not use all the signature space, so we need to shrink the
1778 * excess between the buffers */
1779 MoveMemory(((BYTE*)Buffers[0].pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer,
1780 Buffers[1].cbBuffer);
1781 nla->authInfo.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer;
1782 }
1783
1784 return SEC_E_OK;
1785 }
1786
nla_decrypt_ts_credentials(rdpNla * nla)1787 static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
1788 {
1789 int length;
1790 BYTE* buffer;
1791 ULONG pfQOP;
1792 SecBuffer Buffers[2] = { { 0 } };
1793 SecBufferDesc Message;
1794 SECURITY_STATUS status;
1795 const BOOL krb =
1796 (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
1797 const BOOL nego = (_tcsncmp(nla->packageName, NEGO_SSP_NAME, ARRAYSIZE(NEGO_SSP_NAME)) == 0);
1798 const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0);
1799
1800 if (nla->authInfo.cbBuffer < 1)
1801 {
1802 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1803 return SEC_E_INVALID_TOKEN;
1804 }
1805
1806 length = nla->authInfo.cbBuffer;
1807 buffer = (BYTE*)malloc(length);
1808
1809 if (!buffer)
1810 return SEC_E_INSUFFICIENT_MEMORY;
1811
1812 if (krb)
1813 {
1814 CopyMemory(buffer, nla->authInfo.pvBuffer, length);
1815 Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TSCredentials */
1816 Buffers[0].cbBuffer = length;
1817 Buffers[0].pvBuffer = buffer;
1818 Message.cBuffers = 1;
1819 }
1820 else if (ntlm || nego)
1821 {
1822 CopyMemory(buffer, nla->authInfo.pvBuffer, length);
1823 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1824 Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
1825 Buffers[0].pvBuffer = buffer;
1826 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1827 Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer;
1828 Buffers[1].pvBuffer = &buffer[Buffers[0].cbBuffer];
1829 Message.cBuffers = 2;
1830 }
1831
1832 Message.ulVersion = SECBUFFER_VERSION;
1833 Message.pBuffers = (PSecBuffer)&Buffers;
1834 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1835
1836 if (status != SEC_E_OK)
1837 {
1838 WLog_ERR(TAG, "DecryptMessage failure %s [0x%08" PRIX32 "]",
1839 GetSecurityStatusString(status), status);
1840 free(buffer);
1841 return status;
1842 }
1843
1844 if (!nla_read_ts_credentials(nla, &Buffers[1]))
1845 {
1846 free(buffer);
1847 return SEC_E_INSUFFICIENT_MEMORY;
1848 }
1849
1850 free(buffer);
1851 return SEC_E_OK;
1852 }
1853
nla_sizeof_nego_token(size_t length)1854 static size_t nla_sizeof_nego_token(size_t length)
1855 {
1856 length = ber_sizeof_octet_string(length);
1857 length += ber_sizeof_contextual_tag(length);
1858 return length;
1859 }
1860
nla_sizeof_nego_tokens(size_t length)1861 static size_t nla_sizeof_nego_tokens(size_t length)
1862 {
1863 length = nla_sizeof_nego_token(length);
1864 length += ber_sizeof_sequence_tag(length);
1865 length += ber_sizeof_sequence_tag(length);
1866 length += ber_sizeof_contextual_tag(length);
1867 return length;
1868 }
1869
nla_sizeof_pub_key_auth(size_t length)1870 static size_t nla_sizeof_pub_key_auth(size_t length)
1871 {
1872 length = ber_sizeof_octet_string(length);
1873 length += ber_sizeof_contextual_tag(length);
1874 return length;
1875 }
1876
nla_sizeof_auth_info(size_t length)1877 static size_t nla_sizeof_auth_info(size_t length)
1878 {
1879 length = ber_sizeof_octet_string(length);
1880 length += ber_sizeof_contextual_tag(length);
1881 return length;
1882 }
1883
nla_sizeof_client_nonce(size_t length)1884 static size_t nla_sizeof_client_nonce(size_t length)
1885 {
1886 length = ber_sizeof_octet_string(length);
1887 length += ber_sizeof_contextual_tag(length);
1888 return length;
1889 }
1890
nla_sizeof_ts_request(size_t length)1891 static size_t nla_sizeof_ts_request(size_t length)
1892 {
1893 length += ber_sizeof_integer(2);
1894 length += ber_sizeof_contextual_tag(3);
1895 return length;
1896 }
1897
1898 /**
1899 * Send CredSSP message.
1900 * @param credssp
1901 */
1902
nla_send(rdpNla * nla,const char * msg)1903 BOOL nla_send(rdpNla* nla, const char* msg)
1904 {
1905 BOOL rc = TRUE;
1906 wStream* s;
1907 size_t length;
1908 size_t ts_request_length;
1909 size_t nego_tokens_length = 0;
1910 size_t pub_key_auth_length = 0;
1911 size_t auth_info_length = 0;
1912 size_t error_code_context_length = 0;
1913 size_t error_code_length = 0;
1914 size_t client_nonce_length = 0;
1915 WLog_DBG(TAG, "%s", msg);
1916 nla_buffer_print(nla);
1917
1918 nego_tokens_length =
1919 (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(nla->negoToken.cbBuffer) : 0;
1920 pub_key_auth_length =
1921 (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(nla->pubKeyAuth.cbBuffer) : 0;
1922 auth_info_length =
1923 (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
1924 client_nonce_length =
1925 (nla->ClientNonce.cbBuffer > 0) ? nla_sizeof_client_nonce(nla->ClientNonce.cbBuffer) : 0;
1926
1927 if (nla->peerVersion >= 3 && nla->peerVersion != 5 && nla->errorCode != 0)
1928 {
1929 error_code_length = ber_sizeof_integer(nla->errorCode);
1930 error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
1931 }
1932
1933 length = nego_tokens_length + pub_key_auth_length + auth_info_length +
1934 error_code_context_length + error_code_length + client_nonce_length;
1935 ts_request_length = nla_sizeof_ts_request(length);
1936 s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
1937
1938 if (!s)
1939 {
1940 WLog_ERR(TAG, "Stream_New failed!");
1941 return FALSE;
1942 }
1943
1944 /* TSRequest */
1945 ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */
1946 /* [0] version */
1947 ber_write_contextual_tag(s, 0, 3, TRUE);
1948 ber_write_integer(s, nla->version); /* INTEGER */
1949
1950 /* [1] negoTokens (NegoData) */
1951 if (nego_tokens_length > 0)
1952 {
1953 length = ber_write_contextual_tag(
1954 s, 1,
1955 ber_sizeof_sequence(
1956 ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))),
1957 TRUE); /* NegoData */
1958 length +=
1959 ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(
1960 nla->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */
1961 length += ber_write_sequence_tag(
1962 s, ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer)); /* NegoDataItem */
1963 length += ber_write_sequence_octet_string(s, 0, (BYTE*)nla->negoToken.pvBuffer,
1964 nla->negoToken.cbBuffer); /* OCTET STRING */
1965
1966 if (length != nego_tokens_length)
1967 {
1968 Stream_Free(s, TRUE);
1969 return FALSE;
1970 }
1971 }
1972
1973 /* [2] authInfo (OCTET STRING) */
1974 if (auth_info_length > 0)
1975 {
1976 if (ber_write_sequence_octet_string(s, 2, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer) !=
1977 auth_info_length)
1978 {
1979 Stream_Free(s, TRUE);
1980 return FALSE;
1981 }
1982 }
1983
1984 /* [3] pubKeyAuth (OCTET STRING) */
1985 if (pub_key_auth_length > 0)
1986 {
1987 if (ber_write_sequence_octet_string(s, 3, nla->pubKeyAuth.pvBuffer,
1988 nla->pubKeyAuth.cbBuffer) != pub_key_auth_length)
1989 {
1990 Stream_Free(s, TRUE);
1991 return FALSE;
1992 }
1993 }
1994
1995 /* [4] errorCode (INTEGER) */
1996 if (error_code_length > 0)
1997 {
1998 ber_write_contextual_tag(s, 4, error_code_length, TRUE);
1999 ber_write_integer(s, nla->errorCode);
2000 }
2001
2002 /* [5] clientNonce (OCTET STRING) */
2003 if (client_nonce_length > 0)
2004 {
2005 if (ber_write_sequence_octet_string(s, 5, nla->ClientNonce.pvBuffer,
2006 nla->ClientNonce.cbBuffer) != client_nonce_length)
2007 {
2008 Stream_Free(s, TRUE);
2009 return FALSE;
2010 }
2011 }
2012
2013 Stream_SealLength(s);
2014
2015 if (transport_write(nla->transport, s) < 0)
2016 rc = FALSE;
2017
2018 Stream_Free(s, TRUE);
2019 return rc;
2020 }
2021
nla_decode_ts_request(rdpNla * nla,wStream * s)2022 static int nla_decode_ts_request(rdpNla* nla, wStream* s)
2023 {
2024 size_t length;
2025 UINT32 version = 0;
2026
2027 /* TSRequest */
2028 if (!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) ||
2029 !ber_read_integer(s, &version))
2030 {
2031 return -1;
2032 }
2033
2034 if (nla->peerVersion == 0)
2035 {
2036 WLog_DBG(TAG, "CredSSP protocol support %" PRIu32 ", peer supports %" PRIu32, nla->version,
2037 version);
2038 nla->peerVersion = version;
2039 }
2040
2041 /* if the peer suddenly changed its version - kick it */
2042 if (nla->peerVersion != version)
2043 {
2044 WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
2045 nla->peerVersion, version);
2046 return -1;
2047 }
2048
2049 /* [1] negoTokens (NegoData) */
2050 if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
2051 {
2052 if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
2053 !ber_read_sequence_tag(s, &length) || /* NegoDataItem */
2054 !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
2055 !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
2056 Stream_GetRemainingLength(s) < length)
2057 {
2058 return -1;
2059 }
2060
2061 sspi_SecBufferFree(&nla->negoToken);
2062 if (!sspi_SecBufferAlloc(&nla->negoToken, length))
2063 return -1;
2064
2065 Stream_Read(s, nla->negoToken.pvBuffer, length);
2066 nla->negoToken.cbBuffer = length;
2067 }
2068
2069 /* [2] authInfo (OCTET STRING) */
2070 if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
2071 {
2072 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
2073 Stream_GetRemainingLength(s) < length)
2074 return -1;
2075
2076 if (!sspi_SecBufferAlloc(&nla->authInfo, length))
2077 return -1;
2078
2079 Stream_Read(s, nla->authInfo.pvBuffer, length);
2080 nla->authInfo.cbBuffer = length;
2081 }
2082
2083 /* [3] pubKeyAuth (OCTET STRING) */
2084 if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
2085 {
2086 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
2087 Stream_GetRemainingLength(s) < length)
2088 return -1;
2089
2090 sspi_SecBufferFree(&nla->pubKeyAuth);
2091 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
2092 return -1;
2093
2094 Stream_Read(s, nla->pubKeyAuth.pvBuffer, length);
2095 nla->pubKeyAuth.cbBuffer = length;
2096 }
2097
2098 /* [4] errorCode (INTEGER) */
2099 if (nla->peerVersion >= 3)
2100 {
2101 if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE)
2102 {
2103 if (!ber_read_integer(s, &nla->errorCode))
2104 return -1;
2105 WLog_WARN(TAG, "SPNEGO received NTSTATUS: %s [0x%08" PRIX32 "] from server",
2106 GetSecurityStatusString(nla->errorCode), nla->errorCode);
2107 }
2108
2109 if (nla->peerVersion >= 5)
2110 {
2111 if (ber_read_contextual_tag(s, 5, &length, TRUE) != FALSE)
2112 {
2113 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
2114 Stream_GetRemainingLength(s) < length)
2115 return -1;
2116
2117 sspi_SecBufferFree(&nla->ClientNonce);
2118 if (!sspi_SecBufferAlloc(&nla->ClientNonce, length))
2119 return -1;
2120
2121 Stream_Read(s, nla->ClientNonce.pvBuffer, length);
2122 nla->ClientNonce.cbBuffer = length;
2123 }
2124 }
2125 }
2126
2127 return 1;
2128 }
2129
nla_recv_pdu(rdpNla * nla,wStream * s)2130 int nla_recv_pdu(rdpNla* nla, wStream* s)
2131 {
2132 if (nla_decode_ts_request(nla, s) < 1)
2133 return -1;
2134
2135 if (nla->errorCode)
2136 {
2137 UINT32 code;
2138
2139 switch (nla->errorCode)
2140 {
2141 case STATUS_PASSWORD_MUST_CHANGE:
2142 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2143 break;
2144
2145 case STATUS_PASSWORD_EXPIRED:
2146 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2147 break;
2148
2149 case STATUS_ACCOUNT_DISABLED:
2150 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2151 break;
2152
2153 case STATUS_LOGON_FAILURE:
2154 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2155 break;
2156
2157 case STATUS_WRONG_PASSWORD:
2158 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2159 break;
2160
2161 case STATUS_ACCESS_DENIED:
2162 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2163 break;
2164
2165 case STATUS_ACCOUNT_RESTRICTION:
2166 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2167 break;
2168
2169 case STATUS_ACCOUNT_LOCKED_OUT:
2170 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2171 break;
2172
2173 case STATUS_ACCOUNT_EXPIRED:
2174 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2175 break;
2176
2177 case STATUS_LOGON_TYPE_NOT_GRANTED:
2178 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2179 break;
2180
2181 default:
2182 WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]",
2183 GetSecurityStatusString(nla->errorCode), nla->errorCode);
2184 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2185 break;
2186 }
2187
2188 freerdp_set_last_error_log(nla->instance->context, code);
2189 return -1;
2190 }
2191
2192 if (nla_client_recv(nla) < 1)
2193 return -1;
2194
2195 return 1;
2196 }
2197
nla_recv(rdpNla * nla,const char * msg)2198 int nla_recv(rdpNla* nla, const char* msg)
2199 {
2200 wStream* s;
2201 int status;
2202 s = Stream_New(NULL, 4096);
2203
2204 if (!s)
2205 {
2206 WLog_ERR(TAG, "[%s] Stream_New failed!", __FUNCTION__);
2207 return -1;
2208 }
2209
2210 status = transport_read_pdu(nla->transport, s);
2211
2212 if (status < 0)
2213 {
2214 WLog_ERR(TAG, "[%s] error: %d", __FUNCTION__, status);
2215 Stream_Free(s, TRUE);
2216 return -1;
2217 }
2218
2219 if (nla_decode_ts_request(nla, s) < 1)
2220 {
2221 WLog_ERR(TAG, "[%s] Invalid data received, aborting", __FUNCTION__);
2222 Stream_Free(s, TRUE);
2223 return -1;
2224 }
2225
2226 Stream_Free(s, TRUE);
2227 WLog_DBG(TAG, "[%s] %s", __FUNCTION__, msg);
2228 nla_buffer_print(nla);
2229 return 1;
2230 }
2231
nla_buffer_print(rdpNla * nla)2232 void nla_buffer_print(rdpNla* nla)
2233 {
2234 if (nla->negoToken.cbBuffer > 0)
2235 {
2236 WLog_DBG(TAG, "NLA.negoToken (length = %" PRIu32 "):", nla->negoToken.cbBuffer);
2237 #if defined(WITH_DEBUG_NLA)
2238 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
2239 #endif
2240 }
2241
2242 if (nla->pubKeyAuth.cbBuffer > 0)
2243 {
2244 WLog_DBG(TAG, "NLA.pubKeyAuth (length = %" PRIu32 "):", nla->pubKeyAuth.cbBuffer);
2245 #if defined(WITH_DEBUG_NLA)
2246 winpr_HexDump(TAG, WLOG_DEBUG, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
2247 #endif
2248 }
2249
2250 if (nla->authInfo.cbBuffer > 0)
2251 {
2252 WLog_DBG(TAG, "NLA.authInfo (length = %" PRIu32 "):", nla->authInfo.cbBuffer);
2253 #if defined(WITH_DEBUG_NLA)
2254 winpr_HexDump(TAG, WLOG_DEBUG, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
2255 #endif
2256 }
2257 }
2258
nla_buffer_free(rdpNla * nla)2259 void nla_buffer_free(rdpNla* nla)
2260 {
2261 sspi_SecBufferFree(&nla->negoToken);
2262 sspi_SecBufferFree(&nla->pubKeyAuth);
2263 sspi_SecBufferFree(&nla->authInfo);
2264 }
2265
nla_make_spn(const char * ServiceClass,const char * hostname)2266 LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname)
2267 {
2268 DWORD status;
2269 DWORD SpnLength;
2270 LPTSTR hostnameX = NULL;
2271 LPTSTR ServiceClassX = NULL;
2272 LPTSTR ServicePrincipalName = NULL;
2273 #ifdef UNICODE
2274 ConvertToUnicode(CP_UTF8, 0, hostname, -1, &hostnameX, 0);
2275 ConvertToUnicode(CP_UTF8, 0, ServiceClass, -1, &ServiceClassX, 0);
2276 #else
2277 hostnameX = _strdup(hostname);
2278 ServiceClassX = _strdup(ServiceClass);
2279 #endif
2280
2281 if (!hostnameX || !ServiceClassX)
2282 {
2283 free(hostnameX);
2284 free(ServiceClassX);
2285 return NULL;
2286 }
2287
2288 if (!ServiceClass)
2289 {
2290 ServicePrincipalName = (LPTSTR)_tcsdup(hostnameX);
2291 free(ServiceClassX);
2292 free(hostnameX);
2293 return ServicePrincipalName;
2294 }
2295
2296 SpnLength = 0;
2297 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
2298
2299 if (status != ERROR_BUFFER_OVERFLOW)
2300 {
2301 free(ServiceClassX);
2302 free(hostnameX);
2303 return NULL;
2304 }
2305
2306 ServicePrincipalName = (LPTSTR)calloc(SpnLength, sizeof(TCHAR));
2307
2308 if (!ServicePrincipalName)
2309 {
2310 free(ServiceClassX);
2311 free(hostnameX);
2312 return NULL;
2313 }
2314
2315 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, ServicePrincipalName);
2316
2317 if (status != ERROR_SUCCESS)
2318 {
2319 free(ServicePrincipalName);
2320 free(ServiceClassX);
2321 free(hostnameX);
2322 return NULL;
2323 }
2324
2325 free(ServiceClassX);
2326 free(hostnameX);
2327 return ServicePrincipalName;
2328 }
2329
2330 /**
2331 * Create new CredSSP state machine.
2332 * @param transport
2333 * @return new CredSSP state machine.
2334 */
2335
nla_new(freerdp * instance,rdpTransport * transport,rdpSettings * settings)2336 rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
2337 {
2338 rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2339
2340 if (!nla)
2341 return NULL;
2342
2343 nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2344
2345 if (!nla->identity)
2346 {
2347 free(nla);
2348 return NULL;
2349 }
2350
2351 nla->instance = instance;
2352 nla->settings = settings;
2353 nla->server = settings->ServerMode;
2354 nla->transport = transport;
2355 nla->sendSeqNum = 0;
2356 nla->recvSeqNum = 0;
2357 nla->version = 6;
2358 SecInvalidateHandle(&nla->context);
2359
2360 if (settings->NtlmSamFile)
2361 {
2362 nla->SamFile = _strdup(settings->NtlmSamFile);
2363
2364 if (!nla->SamFile)
2365 goto cleanup;
2366 }
2367
2368 /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2369 if (!sspi_SecBufferAlloc(&nla->ClientNonce, NonceLength))
2370 goto cleanup;
2371
2372 /* generate random 32-byte nonce */
2373 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2374 goto cleanup;
2375
2376 if (nla->server)
2377 {
2378 LONG status;
2379 HKEY hKey;
2380 DWORD dwType;
2381 DWORD dwSize;
2382 status =
2383 RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
2384
2385 if (status != ERROR_SUCCESS)
2386 return nla;
2387
2388 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
2389
2390 if (status != ERROR_SUCCESS)
2391 {
2392 RegCloseKey(hKey);
2393 return nla;
2394 }
2395
2396 nla->SspiModule = (LPTSTR)malloc(dwSize + sizeof(TCHAR));
2397
2398 if (!nla->SspiModule)
2399 {
2400 RegCloseKey(hKey);
2401 goto cleanup;
2402 }
2403
2404 status =
2405 RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, (BYTE*)nla->SspiModule, &dwSize);
2406
2407 if (status == ERROR_SUCCESS)
2408 WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
2409
2410 RegCloseKey(hKey);
2411 }
2412
2413 return nla;
2414 cleanup:
2415 nla_free(nla);
2416 return NULL;
2417 }
2418
2419 /**
2420 * Free CredSSP state machine.
2421 * @param credssp
2422 */
2423
nla_free(rdpNla * nla)2424 void nla_free(rdpNla* nla)
2425 {
2426 if (!nla)
2427 return;
2428
2429 if (nla->table)
2430 {
2431 SECURITY_STATUS status;
2432
2433 if (SecIsValidHandle(&nla->credentials))
2434 {
2435 status = nla->table->FreeCredentialsHandle(&nla->credentials);
2436
2437 if (status != SEC_E_OK)
2438 {
2439 WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
2440 GetSecurityStatusString(status), status);
2441 }
2442
2443 SecInvalidateHandle(&nla->credentials);
2444 }
2445
2446 status = nla->table->DeleteSecurityContext(&nla->context);
2447
2448 if (status != SEC_E_OK)
2449 {
2450 WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
2451 GetSecurityStatusString(status), status);
2452 }
2453 }
2454
2455 free(nla->SamFile);
2456 nla->SamFile = NULL;
2457 sspi_SecBufferFree(&nla->ClientNonce);
2458 sspi_SecBufferFree(&nla->PublicKey);
2459 sspi_SecBufferFree(&nla->tsCredentials);
2460 free(nla->ServicePrincipalName);
2461 nla_identity_free(nla->identity);
2462 nla_buffer_free(nla);
2463 free(nla);
2464 }
2465
nla_get_identity(rdpNla * nla)2466 SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2467 {
2468 if (!nla)
2469 return NULL;
2470
2471 return nla->identity;
2472 }
2473
nla_get_state(rdpNla * nla)2474 NLA_STATE nla_get_state(rdpNla* nla)
2475 {
2476 if (!nla)
2477 return NLA_STATE_FINAL;
2478
2479 return nla->state;
2480 }
2481
nla_set_state(rdpNla * nla,NLA_STATE state)2482 BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2483 {
2484 if (!nla)
2485 return FALSE;
2486
2487 nla->state = state;
2488 return TRUE;
2489 }
2490
nla_set_service_principal(rdpNla * nla,LPSTR principal)2491 BOOL nla_set_service_principal(rdpNla* nla, LPSTR principal)
2492 {
2493 if (!nla || !principal)
2494 return FALSE;
2495
2496 nla->ServicePrincipalName = principal;
2497 return TRUE;
2498 }
2499
nla_impersonate(rdpNla * nla)2500 BOOL nla_impersonate(rdpNla* nla)
2501 {
2502 if (!nla)
2503 return FALSE;
2504
2505 if (!nla->table || !nla->table->ImpersonateSecurityContext)
2506 return FALSE;
2507
2508 return (nla->table->ImpersonateSecurityContext(&nla->context) == SEC_E_OK);
2509 }
2510
nla_revert_to_self(rdpNla * nla)2511 BOOL nla_revert_to_self(rdpNla* nla)
2512 {
2513 if (!nla)
2514 return FALSE;
2515
2516 if (!nla->table || !nla->table->RevertSecurityContext)
2517 return FALSE;
2518
2519 return (nla->table->RevertSecurityContext(&nla->context) == SEC_E_OK);
2520 }
2521