2 * WinPR: Windows Portable Runtime
3 * Network Level Authentication (NLA)
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>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
32 #include <freerdp/log.h>
33 #include <freerdp/crypto/tls.h>
35 #include <winpr/crt.h>
36 #include <winpr/sspi.h>
37 #include <winpr/print.h>
38 #include <winpr/tchar.h>
39 #include <winpr/dsparse.h>
40 #include <winpr/library.h>
41 #include <winpr/registry.h>
45 #define TAG FREERDP_TAG("core.nla")
48 * TSRequest ::= SEQUENCE {
49 * version [0] INTEGER,
50 * negoTokens [1] NegoData OPTIONAL,
51 * authInfo [2] OCTET STRING OPTIONAL,
52 * pubKeyAuth [3] OCTET STRING OPTIONAL
55 * NegoData ::= SEQUENCE OF NegoDataItem
57 * NegoDataItem ::= SEQUENCE {
58 * negoToken [0] OCTET STRING
61 * TSCredentials ::= SEQUENCE {
62 * credType [0] INTEGER,
63 * credentials [1] OCTET STRING
66 * TSPasswordCreds ::= SEQUENCE {
67 * domainName [0] OCTET STRING,
68 * userName [1] OCTET STRING,
69 * password [2] OCTET STRING
72 * TSSmartCardCreds ::= SEQUENCE {
73 * pin [0] OCTET STRING,
74 * cspData [1] TSCspDataDetail,
75 * userHint [2] OCTET STRING OPTIONAL,
76 * domainHint [3] OCTET STRING OPTIONAL
79 * TSCspDataDetail ::= SEQUENCE {
80 * keySpec [0] INTEGER,
81 * cardName [1] OCTET STRING OPTIONAL,
82 * readerName [2] OCTET STRING OPTIONAL,
83 * containerName [3] OCTET STRING OPTIONAL,
84 * cspName [4] OCTET STRING OPTIONAL
89 #define NLA_PKG_NAME NEGOSSP_NAME
91 #define TERMSRV_SPN_PREFIX "TERMSRV/"
93 static BOOL nla_send(rdpNla* nla);
94 static int nla_recv(rdpNla* nla);
95 static void nla_buffer_print(rdpNla* nla);
96 static void nla_buffer_free(rdpNla* nla);
97 static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
98 static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
99 static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
100 static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
101 static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
103 #define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
104 #define ber_write_sequence_octet_string(stream, context, value, length) ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE) + ber_write_octet_string(stream, value, length)
107 * Initialize NTLMSSP authentication module (client).
111 int nla_client_init(rdpNla* nla)
116 BOOL PromptPassword = FALSE;
117 freerdp* instance = nla->instance;
118 rdpSettings* settings = nla->settings;
120 nla->state = NLA_STATE_INITIAL;
122 if (settings->RestrictedAdminModeRequired)
123 settings->DisableCredentialsDelegation = TRUE;
125 if ((!settings->Password) || (!settings->Username)
126 || (!strlen(settings->Password)) || (!strlen(settings->Username)))
128 PromptPassword = TRUE;
134 if (settings->RestrictedAdminModeRequired)
136 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
137 PromptPassword = FALSE;
144 if (instance->Authenticate)
146 BOOL proceed = instance->Authenticate(instance,
147 &settings->Username, &settings->Password, &settings->Domain);
151 freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
157 if (!settings->Username)
159 free (nla->identity);
160 nla->identity = NULL;
163 sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
168 SEC_WINNT_AUTH_IDENTITY* identity = nla->identity;
170 if (settings->RestrictedAdminModeRequired)
172 if (settings->PasswordHash)
174 if (strlen(settings->PasswordHash) == 32)
176 free(identity->Password);
178 identity->PasswordLength = ConvertToUnicode(CP_UTF8, 0,
179 settings->PasswordHash, -1, &identity->Password, 0) - 1;
181 * Multiply password hash length by 64 to obtain a length exceeding
182 * the maximum (256) and use it this for hash identification in WinPR.
184 identity->PasswordLength = 32 * 64; /* 2048 */
191 tls = nla->transport->tls;
195 WLog_ERR(TAG, "Unknown NLA transport layer");
199 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
201 WLog_ERR(TAG, "Failed to allocate sspic secBuffer");
204 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
205 length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname);
207 spn = (SEC_CHAR*) malloc(length + 1);
212 sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname);
215 nla->ServicePrincipalName = NULL;
216 ConvertToUnicode(CP_UTF8, 0, spn, -1, &nla->ServicePrincipalName, 0);
219 nla->ServicePrincipalName = spn;
222 nla->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR);
223 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
225 if (nla->status != SEC_E_OK)
227 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
231 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
232 nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
233 SECPKG_CRED_OUTBOUND, NULL, nla->identity, NULL, NULL, &nla->credentials,
236 if (nla->status != SEC_E_OK)
238 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
242 nla->haveContext = FALSE;
243 nla->haveInputBuffer = FALSE;
244 nla->havePubKeyAuth = FALSE;
245 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
246 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
247 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
250 * from tspkg.dll: 0x00000132
251 * ISC_REQ_MUTUAL_AUTH
252 * ISC_REQ_CONFIDENTIALITY
253 * ISC_REQ_USE_SESSION_KEY
254 * ISC_REQ_ALLOCATE_MEMORY
256 nla->fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY;
261 int nla_client_begin(rdpNla* nla)
263 if (nla_client_init(nla) < 1)
266 if (nla->state != NLA_STATE_INITIAL)
269 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
270 nla->outputBufferDesc.cBuffers = 1;
271 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
272 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
273 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
274 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
276 if (!nla->outputBuffer.pvBuffer)
279 nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
280 NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
281 SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
282 &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
284 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
286 if (nla->table->CompleteAuthToken)
287 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
289 if (nla->status == SEC_I_COMPLETE_NEEDED)
290 nla->status = SEC_E_OK;
291 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
292 nla->status = SEC_I_CONTINUE_NEEDED;
295 if (nla->status != SEC_I_CONTINUE_NEEDED)
298 if (nla->outputBuffer.cbBuffer < 1)
301 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
302 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
304 WLog_DBG(TAG, "Sending Authentication Token");
305 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
309 nla_buffer_free(nla);
313 nla_buffer_free(nla);
315 nla->state = NLA_STATE_NEGO_TOKEN;
320 int nla_client_recv(rdpNla* nla)
324 if (nla->state == NLA_STATE_NEGO_TOKEN)
326 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
327 nla->inputBufferDesc.cBuffers = 1;
328 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
329 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
330 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
331 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
333 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
334 nla->outputBufferDesc.cBuffers = 1;
335 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
336 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
337 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
338 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
340 if (!nla->outputBuffer.pvBuffer)
343 nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
344 &nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
345 SECURITY_NATIVE_DREP, &nla->inputBufferDesc,
346 0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
348 free(nla->inputBuffer.pvBuffer);
349 nla->inputBuffer.pvBuffer = NULL;
351 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
353 if (nla->table->CompleteAuthToken)
354 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
356 if (nla->status == SEC_I_COMPLETE_NEEDED)
357 nla->status = SEC_E_OK;
358 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
359 nla->status = SEC_I_CONTINUE_NEEDED;
362 if (nla->status == SEC_E_OK)
364 nla->havePubKeyAuth = TRUE;
366 if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
368 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
372 nla_encrypt_public_key_echo(nla);
375 if (nla->outputBuffer.cbBuffer < 1)
378 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
379 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
381 WLog_DBG(TAG, "Sending Authentication Token");
382 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
386 nla_buffer_free(nla);
389 nla_buffer_free(nla);
391 nla->state = NLA_STATE_PUB_KEY_AUTH;
394 else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
396 /* Verify Server Public Key Echo */
397 nla->status = nla_decrypt_public_key_echo(nla);
398 nla_buffer_free(nla);
400 if (nla->status != SEC_E_OK)
402 WLog_ERR(TAG, "Could not verify public key echo!");
406 /* Send encrypted credentials */
407 nla->status = nla_encrypt_ts_credentials(nla);
409 if (nla->status != SEC_E_OK)
411 WLog_ERR(TAG, "nla_encrypt_ts_credentials status: 0x%08X", nla->status);
417 nla_buffer_free(nla);
420 nla_buffer_free(nla);
422 nla->table->FreeCredentialsHandle(&nla->credentials);
423 nla->table->FreeContextBuffer(nla->pPackageInfo);
425 nla->state = NLA_STATE_AUTH_INFO;
432 int nla_client_authenticate(rdpNla* nla)
437 s = Stream_New(NULL, 4096);
441 WLog_ERR(TAG, "Stream_New failed!");
445 if (nla_client_begin(nla) < 1)
448 while (nla->state < NLA_STATE_AUTH_INFO)
450 Stream_SetPosition(s, 0);
452 status = transport_read_pdu(nla->transport, s);
456 WLog_ERR(TAG, "nla_client_authenticate failure");
457 Stream_Free(s, TRUE);
461 status = nla_recv_pdu(nla, s);
467 Stream_Free(s, TRUE);
473 * Initialize NTLMSSP authentication module (server).
477 int nla_server_init(rdpNla* nla)
479 rdpTls* tls = nla->transport->tls;
481 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
483 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
486 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
491 INIT_SECURITY_INTERFACE pInitSecurityInterface;
493 hSSPI = LoadLibrary(nla->SspiModule);
497 WLog_ERR(TAG, "Failed to load SSPI module: %s", nla->SspiModule);
502 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
504 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
506 nla->table = pInitSecurityInterface();
510 nla->table = InitSecurityInterfaceEx(0);
513 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
515 if (nla->status != SEC_E_OK)
517 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
521 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
522 nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
523 SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &nla->credentials, &nla->expiration);
525 if (nla->status != SEC_E_OK)
527 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
531 nla->haveContext = FALSE;
532 nla->haveInputBuffer = FALSE;
533 nla->havePubKeyAuth = FALSE;
534 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
535 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
536 ZeroMemory(&nla->inputBufferDesc, sizeof(SecBufferDesc));
537 ZeroMemory(&nla->outputBufferDesc, sizeof(SecBufferDesc));
538 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
541 * from tspkg.dll: 0x00000112
542 * ASC_REQ_MUTUAL_AUTH
543 * ASC_REQ_CONFIDENTIALITY
544 * ASC_REQ_ALLOCATE_MEMORY
546 nla->fContextReq = 0;
547 nla->fContextReq |= ASC_REQ_MUTUAL_AUTH;
548 nla->fContextReq |= ASC_REQ_CONFIDENTIALITY;
549 nla->fContextReq |= ASC_REQ_CONNECTION;
550 nla->fContextReq |= ASC_REQ_USE_SESSION_KEY;
551 nla->fContextReq |= ASC_REQ_REPLAY_DETECT;
552 nla->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
553 nla->fContextReq |= ASC_REQ_EXTENDED_ERROR;
559 * Authenticate with client using CredSSP (server).
561 * @return 1 if authentication is successful
564 int nla_server_authenticate(rdpNla* nla)
566 if (nla_server_init(nla) < 1)
571 /* receive authentication token */
572 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
573 nla->inputBufferDesc.cBuffers = 1;
574 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
575 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
577 if (nla_recv(nla) < 0)
580 WLog_DBG(TAG, "Receiving Authentication Token");
581 nla_buffer_print(nla);
583 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
584 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
586 if (nla->negoToken.cbBuffer < 1)
588 WLog_ERR(TAG, "CredSSP: invalid negoToken!");
592 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
593 nla->outputBufferDesc.cBuffers = 1;
594 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
595 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
596 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
597 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
599 if (!nla->outputBuffer.pvBuffer)
602 nla->status = nla->table->AcceptSecurityContext(&nla->credentials,
603 nla-> haveContext? &nla->context: NULL,
604 &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
605 &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
607 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
608 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
610 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
612 if (nla->table->CompleteAuthToken)
613 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
615 if (nla->status == SEC_I_COMPLETE_NEEDED)
616 nla->status = SEC_E_OK;
617 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
618 nla->status = SEC_I_CONTINUE_NEEDED;
621 if (nla->status == SEC_E_OK)
623 nla->havePubKeyAuth = TRUE;
625 if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
627 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
631 if (nla_decrypt_public_key_echo(nla) != SEC_E_OK)
633 WLog_ERR(TAG, "Error: could not verify client's public key echo");
637 sspi_SecBufferFree(&nla->negoToken);
638 nla->negoToken.pvBuffer = NULL;
639 nla->negoToken.cbBuffer = 0;
640 nla_encrypt_public_key_echo(nla);
643 if ((nla->status != SEC_E_OK) && (nla->status != SEC_I_CONTINUE_NEEDED))
645 WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
646 return -1; /* Access Denied */
649 /* send authentication token */
651 WLog_DBG(TAG, "Sending Authentication Token");
652 nla_buffer_print(nla);
656 nla_buffer_free(nla);
659 nla_buffer_free(nla);
661 if (nla->status != SEC_I_CONTINUE_NEEDED)
664 nla->haveContext = TRUE;
667 /* Receive encrypted credentials */
669 if (nla_recv(nla) < 0)
672 if (nla_decrypt_ts_credentials(nla) != SEC_E_OK)
674 WLog_ERR(TAG, "Could not decrypt TSCredentials status: 0x%08X", nla->status);
678 if (nla->status != SEC_E_OK)
680 WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
684 nla->status = nla->table->ImpersonateSecurityContext(&nla->context);
686 if (nla->status != SEC_E_OK)
688 WLog_ERR(TAG, "ImpersonateSecurityContext status: 0x%08X", nla->status);
693 nla->status = nla->table->RevertSecurityContext(&nla->context);
695 if (nla->status != SEC_E_OK)
697 WLog_ERR(TAG, "RevertSecurityContext status: 0x%08X", nla->status);
702 nla->table->FreeContextBuffer(nla->pPackageInfo);
708 * Authenticate using CredSSP.
710 * @return 1 if authentication is successful
713 int nla_authenticate(rdpNla* nla)
716 return nla_server_authenticate(nla);
718 return nla_client_authenticate(nla);
721 void ap_integer_increment_le(BYTE* number, int size)
725 for (index = 0; index < size; index++)
727 if (number[index] < 0xFF)
740 void ap_integer_decrement_le(BYTE* number, int size)
744 for (index = 0; index < size; index++)
746 if (number[index] > 0)
753 number[index] = 0xFF;
759 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
761 SecBuffer Buffers[2];
762 SecBufferDesc Message;
763 SECURITY_STATUS status;
764 int public_key_length;
766 public_key_length = nla->PublicKey.cbBuffer;
767 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbMaxSignature + public_key_length))
768 return SEC_E_INSUFFICIENT_MEMORY;
769 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
770 Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
771 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
772 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
773 Buffers[1].cbBuffer = public_key_length;
774 Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbMaxSignature;
775 CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
779 /* server echos the public key +1 */
780 ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
783 Message.cBuffers = 2;
784 Message.ulVersion = SECBUFFER_VERSION;
785 Message.pBuffers = (PSecBuffer) &Buffers;
786 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
788 if (status != SEC_E_OK)
790 WLog_ERR(TAG, "EncryptMessage status: 0x%08X", status);
797 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
804 int public_key_length;
805 SecBuffer Buffers[2];
806 SecBufferDesc Message;
807 SECURITY_STATUS status;
809 if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbMaxSignature) != nla->pubKeyAuth.cbBuffer)
811 WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %d", (int) nla->pubKeyAuth.cbBuffer);
812 return SEC_E_INVALID_TOKEN;
815 length = nla->pubKeyAuth.cbBuffer;
816 buffer = (BYTE*) malloc(length);
819 return SEC_E_INSUFFICIENT_MEMORY;
821 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
822 public_key_length = nla->PublicKey.cbBuffer;
823 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
824 Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
825 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
826 Buffers[0].pvBuffer = buffer;
827 Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
828 Buffers[1].pvBuffer = buffer + nla->ContextSizes.cbMaxSignature;
829 Message.cBuffers = 2;
830 Message.ulVersion = SECBUFFER_VERSION;
831 Message.pBuffers = (PSecBuffer) &Buffers;
832 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
834 if (status != SEC_E_OK)
836 WLog_ERR(TAG, "DecryptMessage failure: 0x%08X", status);
840 public_key1 = (BYTE*) nla->PublicKey.pvBuffer;
841 public_key2 = (BYTE*) Buffers[1].pvBuffer;
845 /* server echos the public key +1 */
846 ap_integer_decrement_le(public_key2, public_key_length);
849 if (memcmp(public_key1, public_key2, public_key_length) != 0)
851 WLog_ERR(TAG, "Could not verify server's public key echo");
852 WLog_ERR(TAG, "Expected (length = %d):", public_key_length);
853 winpr_HexDump(TAG, WLOG_ERROR, public_key1, public_key_length);
854 WLog_ERR(TAG, "Actual (length = %d):", public_key_length);
855 winpr_HexDump(TAG, WLOG_ERROR, public_key2, public_key_length);
856 return SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
863 int nla_sizeof_ts_password_creds(rdpNla* nla)
868 length += ber_sizeof_sequence_octet_string(nla->identity->DomainLength * 2);
869 length += ber_sizeof_sequence_octet_string(nla->identity->UserLength * 2);
870 length += ber_sizeof_sequence_octet_string(nla->identity->PasswordLength * 2);
875 BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
881 WLog_ERR(TAG, "nla->identity is NULL!");
885 /* TSPasswordCreds (SEQUENCE) */
886 ber_read_sequence_tag(s, &length);
888 /* [0] domainName (OCTET STRING) */
889 ber_read_contextual_tag(s, 0, &length, TRUE);
890 ber_read_octet_string_tag(s, &length);
891 nla->identity->DomainLength = (UINT32) length;
892 nla->identity->Domain = (UINT16*) malloc(length);
893 CopyMemory(nla->identity->Domain, Stream_Pointer(s), nla->identity->DomainLength);
894 Stream_Seek(s, nla->identity->DomainLength);
895 nla->identity->DomainLength /= 2;
897 /* [1] userName (OCTET STRING) */
898 ber_read_contextual_tag(s, 1, &length, TRUE);
899 ber_read_octet_string_tag(s, &length);
900 nla->identity->UserLength = (UINT32) length;
901 nla->identity->User = (UINT16*) malloc(length);
902 CopyMemory(nla->identity->User, Stream_Pointer(s), nla->identity->UserLength);
903 Stream_Seek(s, nla->identity->UserLength);
904 nla->identity->UserLength /= 2;
906 /* [2] password (OCTET STRING) */
907 ber_read_contextual_tag(s, 2, &length, TRUE);
908 ber_read_octet_string_tag(s, &length);
909 nla->identity->PasswordLength = (UINT32) length;
910 nla->identity->Password = (UINT16*) malloc(length);
911 CopyMemory(nla->identity->Password, Stream_Pointer(s), nla->identity->PasswordLength);
912 Stream_Seek(s, nla->identity->PasswordLength);
913 nla->identity->PasswordLength /= 2;
914 nla->identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
919 int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
922 int innerSize = nla_sizeof_ts_password_creds(nla);
923 /* TSPasswordCreds (SEQUENCE) */
924 size += ber_write_sequence_tag(s, innerSize);
927 /* [0] domainName (OCTET STRING) */
928 size += ber_write_sequence_octet_string(
929 s, 0, (BYTE*) nla->identity->Domain,
930 nla->identity->DomainLength * 2);
931 /* [1] userName (OCTET STRING) */
932 size += ber_write_sequence_octet_string(
933 s, 1, (BYTE*) nla->identity->User,
934 nla->identity->UserLength * 2);
935 /* [2] password (OCTET STRING) */
936 size += ber_write_sequence_octet_string(
937 s, 2, (BYTE*) nla->identity->Password,
938 nla->identity->PasswordLength * 2);
943 int nla_sizeof_ts_credentials(rdpNla* nla)
946 size += ber_sizeof_integer(1);
947 size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
948 size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
952 static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
957 int ts_password_creds_length;
959 s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer);
963 WLog_ERR(TAG, "Stream_New failed!");
968 /* TSCredentials (SEQUENCE) */
969 ber_read_sequence_tag(s, &length);
971 /* [0] credType (INTEGER) */
972 ber_read_contextual_tag(s, 0, &length, TRUE);
973 ber_read_integer(s, NULL);
975 /* [1] credentials (OCTET STRING) */
976 ber_read_contextual_tag(s, 1, &length, TRUE);
977 ber_read_octet_string_tag(s, &ts_password_creds_length);
979 rc = nla_read_ts_password_creds(nla, s);
981 Stream_Free(s, FALSE);
985 int nla_write_ts_credentials(rdpNla* nla, wStream* s)
989 int innerSize = nla_sizeof_ts_credentials(nla);
991 /* TSCredentials (SEQUENCE) */
992 size += ber_write_sequence_tag(s, innerSize);
994 /* [0] credType (INTEGER) */
995 size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), TRUE);
996 size += ber_write_integer(s, 1);
998 /* [1] credentials (OCTET STRING) */
999 passwordSize = ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla));
1000 size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), TRUE);
1001 size += ber_write_octet_string_tag(s, passwordSize);
1002 size += nla_write_ts_password_creds(nla, s);
1008 * Encode TSCredentials structure.
1012 BOOL nla_encode_ts_credentials(rdpNla* nla)
1016 int DomainLength = 0;
1018 int PasswordLength = 0;
1022 DomainLength = nla->identity->DomainLength;
1023 UserLength = nla->identity->UserLength;
1024 PasswordLength = nla->identity->PasswordLength;
1027 if (nla->settings->DisableCredentialsDelegation && nla->identity)
1029 nla->identity->DomainLength = 0;
1030 nla->identity->UserLength = 0;
1031 nla->identity->PasswordLength = 0;
1034 length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
1035 if (!sspi_SecBufferAlloc(&nla->tsCredentials, length))
1037 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1040 s = Stream_New((BYTE*) nla->tsCredentials.pvBuffer, length);
1044 sspi_SecBufferFree(&nla->tsCredentials);
1045 WLog_ERR(TAG, "Stream_New failed!");
1049 nla_write_ts_credentials(nla, s);
1051 if (nla->settings->DisableCredentialsDelegation)
1053 nla->identity->DomainLength = DomainLength;
1054 nla->identity->UserLength = UserLength;
1055 nla->identity->PasswordLength = PasswordLength;
1058 Stream_Free(s, FALSE);
1062 SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
1064 SecBuffer Buffers[2];
1065 SecBufferDesc Message;
1066 SECURITY_STATUS status;
1068 if (!nla_encode_ts_credentials(nla))
1069 return SEC_E_INSUFFICIENT_MEMORY;
1071 if (!sspi_SecBufferAlloc(&nla->authInfo, nla->ContextSizes.cbMaxSignature + nla->tsCredentials.cbBuffer))
1072 return SEC_E_INSUFFICIENT_MEMORY;
1073 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1074 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1075 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1076 Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
1077 ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
1078 Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
1079 Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
1080 CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
1082 Message.cBuffers = 2;
1083 Message.ulVersion = SECBUFFER_VERSION;
1084 Message.pBuffers = (PSecBuffer) &Buffers;
1086 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1088 if (status != SEC_E_OK)
1094 SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
1099 SecBuffer Buffers[2];
1100 SecBufferDesc Message;
1101 SECURITY_STATUS status;
1102 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1103 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1105 if (nla->authInfo.cbBuffer < 1)
1107 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1108 return SEC_E_INVALID_TOKEN;
1111 length = nla->authInfo.cbBuffer;
1112 buffer = (BYTE*) malloc(length);
1115 return SEC_E_INSUFFICIENT_MEMORY;
1117 CopyMemory(buffer, nla->authInfo.pvBuffer, length);
1118 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1119 Buffers[0].pvBuffer = buffer;
1120 Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
1121 Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbMaxSignature];
1122 Message.cBuffers = 2;
1123 Message.ulVersion = SECBUFFER_VERSION;
1124 Message.pBuffers = (PSecBuffer) &Buffers;
1125 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1127 if (status != SEC_E_OK)
1130 if(!nla_read_ts_credentials(nla, &Buffers[1]))
1133 return SEC_E_INSUFFICIENT_MEMORY;
1140 int nla_sizeof_nego_token(int length)
1142 length = ber_sizeof_octet_string(length);
1143 length += ber_sizeof_contextual_tag(length);
1147 int nla_sizeof_nego_tokens(int length)
1149 length = nla_sizeof_nego_token(length);
1150 length += ber_sizeof_sequence_tag(length);
1151 length += ber_sizeof_sequence_tag(length);
1152 length += ber_sizeof_contextual_tag(length);
1156 int nla_sizeof_pub_key_auth(int length)
1158 length = ber_sizeof_octet_string(length);
1159 length += ber_sizeof_contextual_tag(length);
1163 int nla_sizeof_auth_info(int length)
1165 length = ber_sizeof_octet_string(length);
1166 length += ber_sizeof_contextual_tag(length);
1170 int nla_sizeof_ts_request(int length)
1172 length += ber_sizeof_integer(2);
1173 length += ber_sizeof_contextual_tag(3);
1178 * Send CredSSP message.
1182 BOOL nla_send(rdpNla* nla)
1186 int ts_request_length;
1187 int nego_tokens_length;
1188 int pub_key_auth_length;
1189 int auth_info_length;
1191 nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(nla->negoToken.cbBuffer) : 0;
1192 pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(nla->pubKeyAuth.cbBuffer) : 0;
1193 auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
1194 length = nego_tokens_length + pub_key_auth_length + auth_info_length;
1195 ts_request_length = nla_sizeof_ts_request(length);
1197 s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
1201 WLog_ERR(TAG, "Stream_New failed!");
1207 ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */
1209 ber_write_contextual_tag(s, 0, 3, TRUE);
1210 ber_write_integer(s, 2); /* INTEGER */
1212 /* [1] negoTokens (NegoData) */
1213 if (nego_tokens_length > 0)
1215 length = nego_tokens_length;
1216 length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))), TRUE); /* NegoData */
1217 length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */
1218 length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer)); /* NegoDataItem */
1219 length -= ber_write_sequence_octet_string(s, 0, (BYTE*) nla->negoToken.pvBuffer, nla->negoToken.cbBuffer); /* OCTET STRING */
1222 /* [2] authInfo (OCTET STRING) */
1223 if (auth_info_length > 0)
1225 length = auth_info_length;
1226 length -= ber_write_sequence_octet_string(s, 2, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1229 /* [3] pubKeyAuth (OCTET STRING) */
1230 if (pub_key_auth_length > 0)
1232 length = pub_key_auth_length;
1233 length -= ber_write_sequence_octet_string(s, 3, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1236 Stream_SealLength(s);
1237 transport_write(nla->transport, s);
1238 Stream_Free(s, TRUE);
1242 int nla_decode_ts_request(rdpNla* nla, wStream* s)
1248 if (!ber_read_sequence_tag(s, &length) ||
1249 !ber_read_contextual_tag(s, 0, &length, TRUE) ||
1250 !ber_read_integer(s, &version))
1252 Stream_Free(s, TRUE);
1256 /* [1] negoTokens (NegoData) */
1257 if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
1259 if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
1260 !ber_read_sequence_tag(s, &length) || /* NegoDataItem */
1261 !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
1262 !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1263 ((int) Stream_GetRemainingLength(s)) < length)
1265 Stream_Free(s, TRUE);
1269 if (!sspi_SecBufferAlloc(&nla->negoToken, length))
1271 Stream_Free(s, TRUE);
1274 Stream_Read(s, nla->negoToken.pvBuffer, length);
1275 nla->negoToken.cbBuffer = length;
1278 /* [2] authInfo (OCTET STRING) */
1279 if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
1281 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1282 ((int) Stream_GetRemainingLength(s)) < length)
1284 Stream_Free(s, TRUE);
1288 if (!sspi_SecBufferAlloc(&nla->authInfo, length))
1290 Stream_Free(s, TRUE);
1293 Stream_Read(s, nla->authInfo.pvBuffer, length);
1294 nla->authInfo.cbBuffer = length;
1297 /* [3] pubKeyAuth (OCTET STRING) */
1298 if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
1300 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1301 ((int) Stream_GetRemainingLength(s)) < length)
1303 Stream_Free(s, TRUE);
1307 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
1309 Stream_Free(s, TRUE);
1312 Stream_Read(s, nla->pubKeyAuth.pvBuffer, length);
1313 nla->pubKeyAuth.cbBuffer = length;
1319 int nla_recv_pdu(rdpNla* nla, wStream* s)
1321 if (nla_decode_ts_request(nla, s) < 1)
1324 if (nla_client_recv(nla) < 1)
1330 int nla_recv(rdpNla* nla)
1335 s = Stream_New(NULL, 4096);
1339 WLog_ERR(TAG, "Stream_New failed!");
1343 status = transport_read_pdu(nla->transport, s);
1347 WLog_ERR(TAG, "nla_recv() error: %d", status);
1348 Stream_Free(s, TRUE);
1352 if (nla_decode_ts_request(nla, s) < 1)
1355 Stream_Free(s, TRUE);
1359 void nla_buffer_print(rdpNla* nla)
1361 if (nla->negoToken.cbBuffer > 0)
1363 WLog_DBG(TAG, "NLA.negoToken (length = %d):", (int) nla->negoToken.cbBuffer);
1364 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
1367 if (nla->pubKeyAuth.cbBuffer > 0)
1369 WLog_DBG(TAG, "NLA.pubKeyAuth (length = %d):", (int) nla->pubKeyAuth.cbBuffer);
1370 winpr_HexDump(TAG, WLOG_DEBUG, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1373 if (nla->authInfo.cbBuffer > 0)
1375 WLog_DBG(TAG, "NLA.authInfo (length = %d):", (int) nla->authInfo.cbBuffer);
1376 winpr_HexDump(TAG, WLOG_DEBUG, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1380 void nla_buffer_free(rdpNla* nla)
1382 sspi_SecBufferFree(&nla->negoToken);
1383 sspi_SecBufferFree(&nla->pubKeyAuth);
1384 sspi_SecBufferFree(&nla->authInfo);
1387 LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname)
1391 LPTSTR hostnameX = NULL;
1392 LPTSTR ServiceClassX = NULL;
1393 LPTSTR ServicePrincipalName = NULL;
1395 ConvertToUnicode(CP_UTF8, 0, hostname, -1, &hostnameX, 0);
1396 ConvertToUnicode(CP_UTF8, 0, ServiceClass, -1, &ServiceClassX, 0);
1398 hostnameX = _strdup(hostname);
1399 ServiceClassX = _strdup(ServiceClass);
1404 ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX);
1405 free(ServiceClassX);
1407 return ServicePrincipalName;
1411 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
1413 if (status != ERROR_BUFFER_OVERFLOW)
1415 free(ServiceClassX);
1420 ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR));
1422 if (!ServicePrincipalName)
1425 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, ServicePrincipalName);
1427 if (status != ERROR_SUCCESS)
1429 free(ServicePrincipalName);
1430 free(ServiceClassX);
1435 free(ServiceClassX);
1437 return ServicePrincipalName;
1441 * Create new CredSSP state machine.
1443 * @return new CredSSP state machine.
1446 rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
1453 rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla));
1458 nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
1465 nla->instance = instance;
1466 nla->settings = settings;
1467 nla->server = settings->ServerMode;
1468 nla->transport = transport;
1469 nla->sendSeqNum = 0;
1470 nla->recvSeqNum = 0;
1471 ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
1472 ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
1473 ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
1474 SecInvalidateHandle(&nla->context);
1478 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
1479 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
1481 if (status == ERROR_SUCCESS)
1483 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
1485 if (status == ERROR_SUCCESS)
1487 nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR));
1488 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType,
1489 (BYTE*) nla->SspiModule, &dwSize);
1491 if (status == ERROR_SUCCESS)
1493 WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
1504 * Free CredSSP state machine.
1508 void nla_free(rdpNla* nla)
1514 nla->table->DeleteSecurityContext(&nla->context);
1516 sspi_SecBufferFree(&nla->PublicKey);
1517 sspi_SecBufferFree(&nla->tsCredentials);
1519 free(nla->ServicePrincipalName);
1522 free(nla->identity->User);
1523 free(nla->identity->Domain);
1524 free(nla->identity->Password);
1526 free(nla->identity);