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 BOOL nla_send(rdpNla* nla);
94 int nla_recv(rdpNla* nla);
95 void nla_buffer_print(rdpNla* nla);
96 void nla_buffer_free(rdpNla* nla);
97 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
98 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
99 SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
100 SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
102 #define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
103 #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)
106 * Initialize NTLMSSP authentication module (client).
110 int nla_client_init(rdpNla* nla)
115 BOOL PromptPassword = FALSE;
116 freerdp* instance = nla->instance;
117 rdpSettings* settings = nla->settings;
119 nla->state = NLA_STATE_INITIAL;
121 if (settings->RestrictedAdminModeRequired)
122 settings->DisableCredentialsDelegation = TRUE;
124 if ((!settings->Password) || (!settings->Username)
125 || (!strlen(settings->Password)) || (!strlen(settings->Username)))
127 PromptPassword = TRUE;
133 if (settings->RestrictedAdminModeRequired)
135 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
136 PromptPassword = FALSE;
143 if (instance->Authenticate)
145 BOOL proceed = instance->Authenticate(instance,
146 &settings->Username, &settings->Password, &settings->Domain);
150 freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
156 sspi_SetAuthIdentity(&(nla->identity), settings->Username, settings->Domain, settings->Password);
160 SEC_WINNT_AUTH_IDENTITY* identity = &(nla->identity);
162 if (settings->RestrictedAdminModeRequired)
164 if (settings->PasswordHash)
166 if (strlen(settings->PasswordHash) == 32)
168 free(identity->Password);
170 identity->PasswordLength = ConvertToUnicode(CP_UTF8, 0,
171 settings->PasswordHash, -1, &identity->Password, 0) - 1;
173 * Multiply password hash length by 64 to obtain a length exceeding
174 * the maximum (256) and use it this for hash identification in WinPR.
176 identity->PasswordLength = 32 * 64; /* 2048 */
183 tls = nla->transport->tls;
187 WLog_ERR(TAG, "Unknown NLA transport layer");
191 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
193 WLog_ERR(TAG, "Failed to allocate sspic secBuffer");
196 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
197 length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname);
199 spn = (SEC_CHAR*) malloc(length + 1);
204 sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname);
207 nla->ServicePrincipalName = NULL;
208 ConvertToUnicode(CP_UTF8, 0, spn, -1, &nla->ServicePrincipalName, 0);
211 nla->ServicePrincipalName = spn;
214 nla->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR);
215 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
217 if (nla->status != SEC_E_OK)
219 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
223 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
224 nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
225 SECPKG_CRED_OUTBOUND, NULL, &nla->identity, NULL, NULL, &nla->credentials, &nla->expiration);
227 if (nla->status != SEC_E_OK)
229 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
233 nla->haveContext = FALSE;
234 nla->haveInputBuffer = FALSE;
235 nla->havePubKeyAuth = FALSE;
236 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
237 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
238 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
241 * from tspkg.dll: 0x00000132
242 * ISC_REQ_MUTUAL_AUTH
243 * ISC_REQ_CONFIDENTIALITY
244 * ISC_REQ_USE_SESSION_KEY
245 * ISC_REQ_ALLOCATE_MEMORY
247 nla->fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY;
252 int nla_client_begin(rdpNla* nla)
254 if (nla_client_init(nla) < 1)
257 if (nla->state != NLA_STATE_INITIAL)
260 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
261 nla->outputBufferDesc.cBuffers = 1;
262 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
263 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
264 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
265 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
267 if (!nla->outputBuffer.pvBuffer)
270 nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
271 NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
272 SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
273 &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
275 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
277 if (nla->table->CompleteAuthToken)
278 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
280 if (nla->status == SEC_I_COMPLETE_NEEDED)
281 nla->status = SEC_E_OK;
282 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
283 nla->status = SEC_I_CONTINUE_NEEDED;
286 if (nla->status != SEC_I_CONTINUE_NEEDED)
289 if (nla->outputBuffer.cbBuffer < 1)
292 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
293 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
295 WLog_DBG(TAG, "Sending Authentication Token");
296 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
300 nla_buffer_free(nla);
304 nla_buffer_free(nla);
306 nla->state = NLA_STATE_NEGO_TOKEN;
311 int nla_client_recv(rdpNla* nla)
315 if (nla->state == NLA_STATE_NEGO_TOKEN)
317 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
318 nla->inputBufferDesc.cBuffers = 1;
319 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
320 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
321 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
322 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
324 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
325 nla->outputBufferDesc.cBuffers = 1;
326 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
327 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
328 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
329 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
331 if (!nla->outputBuffer.pvBuffer)
334 nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
335 &nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
336 SECURITY_NATIVE_DREP, &nla->inputBufferDesc,
337 0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
339 free(nla->inputBuffer.pvBuffer);
340 nla->inputBuffer.pvBuffer = NULL;
342 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
344 if (nla->table->CompleteAuthToken)
345 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
347 if (nla->status == SEC_I_COMPLETE_NEEDED)
348 nla->status = SEC_E_OK;
349 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
350 nla->status = SEC_I_CONTINUE_NEEDED;
353 if (nla->status == SEC_E_OK)
355 nla->havePubKeyAuth = TRUE;
357 if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
359 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
363 nla_encrypt_public_key_echo(nla);
366 if (nla->outputBuffer.cbBuffer < 1)
369 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
370 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
372 WLog_DBG(TAG, "Sending Authentication Token");
373 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
377 nla_buffer_free(nla);
380 nla_buffer_free(nla);
382 nla->state = NLA_STATE_PUB_KEY_AUTH;
385 else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
387 /* Verify Server Public Key Echo */
388 nla->status = nla_decrypt_public_key_echo(nla);
389 nla_buffer_free(nla);
391 if (nla->status != SEC_E_OK)
393 WLog_ERR(TAG, "Could not verify public key echo!");
397 /* Send encrypted credentials */
398 nla->status = nla_encrypt_ts_credentials(nla);
400 if (nla->status != SEC_E_OK)
402 WLog_ERR(TAG, "nla_encrypt_ts_credentials status: 0x%08X", nla->status);
408 nla_buffer_free(nla);
411 nla_buffer_free(nla);
413 nla->table->FreeCredentialsHandle(&nla->credentials);
414 nla->table->FreeContextBuffer(nla->pPackageInfo);
416 nla->state = NLA_STATE_AUTH_INFO;
423 int nla_client_authenticate(rdpNla* nla)
428 s = Stream_New(NULL, 4096);
432 WLog_ERR(TAG, "Stream_New failed!");
436 if (nla_client_begin(nla) < 1)
439 while (nla->state < NLA_STATE_AUTH_INFO)
441 Stream_SetPosition(s, 0);
443 status = transport_read_pdu(nla->transport, s);
447 WLog_ERR(TAG, "nla_client_authenticate failure");
448 Stream_Free(s, TRUE);
452 status = nla_recv_pdu(nla, s);
458 Stream_Free(s, TRUE);
464 * Initialize NTLMSSP authentication module (server).
468 int nla_server_init(rdpNla* nla)
470 rdpTls* tls = nla->transport->tls;
472 if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
474 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
477 CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
482 INIT_SECURITY_INTERFACE pInitSecurityInterface;
484 hSSPI = LoadLibrary(nla->SspiModule);
488 WLog_ERR(TAG, "Failed to load SSPI module: %s", nla->SspiModule);
493 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
495 pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
497 nla->table = pInitSecurityInterface();
501 nla->table = InitSecurityInterfaceEx(0);
504 nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
506 if (nla->status != SEC_E_OK)
508 WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", nla->status);
512 nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
513 nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
514 SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &nla->credentials, &nla->expiration);
516 if (nla->status != SEC_E_OK)
518 WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", nla->status);
522 nla->haveContext = FALSE;
523 nla->haveInputBuffer = FALSE;
524 nla->havePubKeyAuth = FALSE;
525 ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer));
526 ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer));
527 ZeroMemory(&nla->inputBufferDesc, sizeof(SecBufferDesc));
528 ZeroMemory(&nla->outputBufferDesc, sizeof(SecBufferDesc));
529 ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes));
532 * from tspkg.dll: 0x00000112
533 * ASC_REQ_MUTUAL_AUTH
534 * ASC_REQ_CONFIDENTIALITY
535 * ASC_REQ_ALLOCATE_MEMORY
537 nla->fContextReq = 0;
538 nla->fContextReq |= ASC_REQ_MUTUAL_AUTH;
539 nla->fContextReq |= ASC_REQ_CONFIDENTIALITY;
540 nla->fContextReq |= ASC_REQ_CONNECTION;
541 nla->fContextReq |= ASC_REQ_USE_SESSION_KEY;
542 nla->fContextReq |= ASC_REQ_REPLAY_DETECT;
543 nla->fContextReq |= ASC_REQ_SEQUENCE_DETECT;
544 nla->fContextReq |= ASC_REQ_EXTENDED_ERROR;
550 * Authenticate with client using CredSSP (server).
552 * @return 1 if authentication is successful
555 int nla_server_authenticate(rdpNla* nla)
557 if (nla_server_init(nla) < 1)
562 /* receive authentication token */
563 nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
564 nla->inputBufferDesc.cBuffers = 1;
565 nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
566 nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
568 if (nla_recv(nla) < 0)
571 WLog_DBG(TAG, "Receiving Authentication Token");
572 nla_buffer_print(nla);
574 nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
575 nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;
577 if (nla->negoToken.cbBuffer < 1)
579 WLog_ERR(TAG, "CredSSP: invalid negoToken!");
583 nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
584 nla->outputBufferDesc.cBuffers = 1;
585 nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
586 nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
587 nla->outputBuffer.cbBuffer = nla->cbMaxToken;
588 nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);
590 if (!nla->outputBuffer.pvBuffer)
593 nla->status = nla->table->AcceptSecurityContext(&nla->credentials,
594 nla-> haveContext? &nla->context: NULL,
595 &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
596 &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
598 nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
599 nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;
601 if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
603 if (nla->table->CompleteAuthToken)
604 nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
606 if (nla->status == SEC_I_COMPLETE_NEEDED)
607 nla->status = SEC_E_OK;
608 else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
609 nla->status = SEC_I_CONTINUE_NEEDED;
612 if (nla->status == SEC_E_OK)
614 nla->havePubKeyAuth = TRUE;
616 if (nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes) != SEC_E_OK)
618 WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
622 if (nla_decrypt_public_key_echo(nla) != SEC_E_OK)
624 WLog_ERR(TAG, "Error: could not verify client's public key echo");
628 sspi_SecBufferFree(&nla->negoToken);
629 nla->negoToken.pvBuffer = NULL;
630 nla->negoToken.cbBuffer = 0;
631 nla_encrypt_public_key_echo(nla);
634 if ((nla->status != SEC_E_OK) && (nla->status != SEC_I_CONTINUE_NEEDED))
636 WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
637 return -1; /* Access Denied */
640 /* send authentication token */
642 WLog_DBG(TAG, "Sending Authentication Token");
643 nla_buffer_print(nla);
647 nla_buffer_free(nla);
650 nla_buffer_free(nla);
652 if (nla->status != SEC_I_CONTINUE_NEEDED)
655 nla->haveContext = TRUE;
658 /* Receive encrypted credentials */
660 if (nla_recv(nla) < 0)
663 if (nla_decrypt_ts_credentials(nla) != SEC_E_OK)
665 WLog_ERR(TAG, "Could not decrypt TSCredentials status: 0x%08X", nla->status);
669 if (nla->status != SEC_E_OK)
671 WLog_ERR(TAG, "AcceptSecurityContext status: 0x%08X", nla->status);
675 nla->status = nla->table->ImpersonateSecurityContext(&nla->context);
677 if (nla->status != SEC_E_OK)
679 WLog_ERR(TAG, "ImpersonateSecurityContext status: 0x%08X", nla->status);
684 nla->status = nla->table->RevertSecurityContext(&nla->context);
686 if (nla->status != SEC_E_OK)
688 WLog_ERR(TAG, "RevertSecurityContext status: 0x%08X", nla->status);
693 nla->table->FreeContextBuffer(nla->pPackageInfo);
699 * Authenticate using CredSSP.
701 * @return 1 if authentication is successful
704 int nla_authenticate(rdpNla* nla)
707 return nla_server_authenticate(nla);
709 return nla_client_authenticate(nla);
712 void ap_integer_increment_le(BYTE* number, int size)
716 for (index = 0; index < size; index++)
718 if (number[index] < 0xFF)
731 void ap_integer_decrement_le(BYTE* number, int size)
735 for (index = 0; index < size; index++)
737 if (number[index] > 0)
744 number[index] = 0xFF;
750 SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
752 SecBuffer Buffers[2];
753 SecBufferDesc Message;
754 SECURITY_STATUS status;
755 int public_key_length;
757 public_key_length = nla->PublicKey.cbBuffer;
758 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbMaxSignature + public_key_length))
759 return SEC_E_INSUFFICIENT_MEMORY;
760 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
761 Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
762 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
763 Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
764 Buffers[1].cbBuffer = public_key_length;
765 Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbMaxSignature;
766 CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
770 /* server echos the public key +1 */
771 ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
774 Message.cBuffers = 2;
775 Message.ulVersion = SECBUFFER_VERSION;
776 Message.pBuffers = (PSecBuffer) &Buffers;
777 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
779 if (status != SEC_E_OK)
781 WLog_ERR(TAG, "EncryptMessage status: 0x%08X", status);
788 SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
795 int public_key_length;
796 SecBuffer Buffers[2];
797 SecBufferDesc Message;
798 SECURITY_STATUS status;
800 if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbMaxSignature) != nla->pubKeyAuth.cbBuffer)
802 WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %d", (int) nla->pubKeyAuth.cbBuffer);
803 return SEC_E_INVALID_TOKEN;
806 length = nla->pubKeyAuth.cbBuffer;
807 buffer = (BYTE*) malloc(length);
810 return SEC_E_INSUFFICIENT_MEMORY;
812 CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
813 public_key_length = nla->PublicKey.cbBuffer;
814 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
815 Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
816 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
817 Buffers[0].pvBuffer = buffer;
818 Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
819 Buffers[1].pvBuffer = buffer + nla->ContextSizes.cbMaxSignature;
820 Message.cBuffers = 2;
821 Message.ulVersion = SECBUFFER_VERSION;
822 Message.pBuffers = (PSecBuffer) &Buffers;
823 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
825 if (status != SEC_E_OK)
827 WLog_ERR(TAG, "DecryptMessage failure: 0x%08X", status);
831 public_key1 = (BYTE*) nla->PublicKey.pvBuffer;
832 public_key2 = (BYTE*) Buffers[1].pvBuffer;
836 /* server echos the public key +1 */
837 ap_integer_decrement_le(public_key2, public_key_length);
840 if (memcmp(public_key1, public_key2, public_key_length) != 0)
842 WLog_ERR(TAG, "Could not verify server's public key echo");
843 WLog_ERR(TAG, "Expected (length = %d):", public_key_length);
844 winpr_HexDump(TAG, WLOG_ERROR, public_key1, public_key_length);
845 WLog_ERR(TAG, "Actual (length = %d):", public_key_length);
846 winpr_HexDump(TAG, WLOG_ERROR, public_key2, public_key_length);
847 return SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
854 int nla_sizeof_ts_password_creds(rdpNla* nla)
857 length += ber_sizeof_sequence_octet_string(nla->identity.DomainLength * 2);
858 length += ber_sizeof_sequence_octet_string(nla->identity.UserLength * 2);
859 length += ber_sizeof_sequence_octet_string(nla->identity.PasswordLength * 2);
863 void nla_read_ts_password_creds(rdpNla* nla, wStream* s)
867 /* TSPasswordCreds (SEQUENCE) */
868 ber_read_sequence_tag(s, &length);
870 /* [0] domainName (OCTET STRING) */
871 ber_read_contextual_tag(s, 0, &length, TRUE);
872 ber_read_octet_string_tag(s, &length);
873 nla->identity.DomainLength = (UINT32) length;
874 nla->identity.Domain = (UINT16*) malloc(length);
875 CopyMemory(nla->identity.Domain, Stream_Pointer(s), nla->identity.DomainLength);
876 Stream_Seek(s, nla->identity.DomainLength);
877 nla->identity.DomainLength /= 2;
879 /* [1] userName (OCTET STRING) */
880 ber_read_contextual_tag(s, 1, &length, TRUE);
881 ber_read_octet_string_tag(s, &length);
882 nla->identity.UserLength = (UINT32) length;
883 nla->identity.User = (UINT16*) malloc(length);
884 CopyMemory(nla->identity.User, Stream_Pointer(s), nla->identity.UserLength);
885 Stream_Seek(s, nla->identity.UserLength);
886 nla->identity.UserLength /= 2;
888 /* [2] password (OCTET STRING) */
889 ber_read_contextual_tag(s, 2, &length, TRUE);
890 ber_read_octet_string_tag(s, &length);
891 nla->identity.PasswordLength = (UINT32) length;
892 nla->identity.Password = (UINT16*) malloc(length);
893 CopyMemory(nla->identity.Password, Stream_Pointer(s), nla->identity.PasswordLength);
894 Stream_Seek(s, nla->identity.PasswordLength);
895 nla->identity.PasswordLength /= 2;
896 nla->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
899 int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
902 int innerSize = nla_sizeof_ts_password_creds(nla);
903 /* TSPasswordCreds (SEQUENCE) */
904 size += ber_write_sequence_tag(s, innerSize);
905 /* [0] domainName (OCTET STRING) */
906 size += ber_write_sequence_octet_string(s, 0, (BYTE*) nla->identity.Domain, nla->identity.DomainLength * 2);
907 /* [1] userName (OCTET STRING) */
908 size += ber_write_sequence_octet_string(s, 1, (BYTE*) nla->identity.User, nla->identity.UserLength * 2);
909 /* [2] password (OCTET STRING) */
910 size += ber_write_sequence_octet_string(s, 2, (BYTE*) nla->identity.Password, nla->identity.PasswordLength * 2);
914 int nla_sizeof_ts_credentials(rdpNla* nla)
917 size += ber_sizeof_integer(1);
918 size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
919 size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
923 BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
927 int ts_password_creds_length;
929 s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer);
933 WLog_ERR(TAG, "Stream_New failed!");
938 /* TSCredentials (SEQUENCE) */
939 ber_read_sequence_tag(s, &length);
941 /* [0] credType (INTEGER) */
942 ber_read_contextual_tag(s, 0, &length, TRUE);
943 ber_read_integer(s, NULL);
945 /* [1] credentials (OCTET STRING) */
946 ber_read_contextual_tag(s, 1, &length, TRUE);
947 ber_read_octet_string_tag(s, &ts_password_creds_length);
949 nla_read_ts_password_creds(nla, s);
951 Stream_Free(s, FALSE);
955 int nla_write_ts_credentials(rdpNla* nla, wStream* s)
959 int innerSize = nla_sizeof_ts_credentials(nla);
961 /* TSCredentials (SEQUENCE) */
962 size += ber_write_sequence_tag(s, innerSize);
964 /* [0] credType (INTEGER) */
965 size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), TRUE);
966 size += ber_write_integer(s, 1);
968 /* [1] credentials (OCTET STRING) */
969 passwordSize = ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla));
970 size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), TRUE);
971 size += ber_write_octet_string_tag(s, passwordSize);
972 size += nla_write_ts_password_creds(nla, s);
978 * Encode TSCredentials structure.
982 BOOL nla_encode_ts_credentials(rdpNla* nla)
990 DomainLength = nla->identity.DomainLength;
991 UserLength = nla->identity.UserLength;
992 PasswordLength = nla->identity.PasswordLength;
994 if (nla->settings->DisableCredentialsDelegation)
996 nla->identity.DomainLength = 0;
997 nla->identity.UserLength = 0;
998 nla->identity.PasswordLength = 0;
1001 length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
1002 if (!sspi_SecBufferAlloc(&nla->tsCredentials, length))
1004 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1007 s = Stream_New((BYTE*) nla->tsCredentials.pvBuffer, length);
1011 sspi_SecBufferFree(&nla->tsCredentials);
1012 WLog_ERR(TAG, "Stream_New failed!");
1016 nla_write_ts_credentials(nla, s);
1018 if (nla->settings->DisableCredentialsDelegation)
1020 nla->identity.DomainLength = DomainLength;
1021 nla->identity.UserLength = UserLength;
1022 nla->identity.PasswordLength = PasswordLength;
1025 Stream_Free(s, FALSE);
1029 SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
1031 SecBuffer Buffers[2];
1032 SecBufferDesc Message;
1033 SECURITY_STATUS status;
1035 if (!nla_encode_ts_credentials(nla))
1036 return SEC_E_INSUFFICIENT_MEMORY;
1038 if (!sspi_SecBufferAlloc(&nla->authInfo, nla->ContextSizes.cbMaxSignature + nla->tsCredentials.cbBuffer))
1039 return SEC_E_INSUFFICIENT_MEMORY;
1040 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1041 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1042 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1043 Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
1044 ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
1045 Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
1046 Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
1047 CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
1049 Message.cBuffers = 2;
1050 Message.ulVersion = SECBUFFER_VERSION;
1051 Message.pBuffers = (PSecBuffer) &Buffers;
1053 status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
1055 if (status != SEC_E_OK)
1061 SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
1066 SecBuffer Buffers[2];
1067 SecBufferDesc Message;
1068 SECURITY_STATUS status;
1069 Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
1070 Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
1072 if (nla->authInfo.cbBuffer < 1)
1074 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1075 return SEC_E_INVALID_TOKEN;
1078 length = nla->authInfo.cbBuffer;
1079 buffer = (BYTE*) malloc(length);
1082 return SEC_E_INSUFFICIENT_MEMORY;
1084 CopyMemory(buffer, nla->authInfo.pvBuffer, length);
1085 Buffers[0].cbBuffer = nla->ContextSizes.cbMaxSignature;
1086 Buffers[0].pvBuffer = buffer;
1087 Buffers[1].cbBuffer = length - nla->ContextSizes.cbMaxSignature;
1088 Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbMaxSignature];
1089 Message.cBuffers = 2;
1090 Message.ulVersion = SECBUFFER_VERSION;
1091 Message.pBuffers = (PSecBuffer) &Buffers;
1092 status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
1094 if (status != SEC_E_OK)
1097 if(!nla_read_ts_credentials(nla, &Buffers[1]))
1100 return SEC_E_INSUFFICIENT_MEMORY;
1107 int nla_sizeof_nego_token(int length)
1109 length = ber_sizeof_octet_string(length);
1110 length += ber_sizeof_contextual_tag(length);
1114 int nla_sizeof_nego_tokens(int length)
1116 length = nla_sizeof_nego_token(length);
1117 length += ber_sizeof_sequence_tag(length);
1118 length += ber_sizeof_sequence_tag(length);
1119 length += ber_sizeof_contextual_tag(length);
1123 int nla_sizeof_pub_key_auth(int length)
1125 length = ber_sizeof_octet_string(length);
1126 length += ber_sizeof_contextual_tag(length);
1130 int nla_sizeof_auth_info(int length)
1132 length = ber_sizeof_octet_string(length);
1133 length += ber_sizeof_contextual_tag(length);
1137 int nla_sizeof_ts_request(int length)
1139 length += ber_sizeof_integer(2);
1140 length += ber_sizeof_contextual_tag(3);
1145 * Send CredSSP message.
1149 BOOL nla_send(rdpNla* nla)
1153 int ts_request_length;
1154 int nego_tokens_length;
1155 int pub_key_auth_length;
1156 int auth_info_length;
1158 nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(nla->negoToken.cbBuffer) : 0;
1159 pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(nla->pubKeyAuth.cbBuffer) : 0;
1160 auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
1161 length = nego_tokens_length + pub_key_auth_length + auth_info_length;
1162 ts_request_length = nla_sizeof_ts_request(length);
1164 s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
1168 WLog_ERR(TAG, "Stream_New failed!");
1174 ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */
1176 ber_write_contextual_tag(s, 0, 3, TRUE);
1177 ber_write_integer(s, 2); /* INTEGER */
1179 /* [1] negoTokens (NegoData) */
1180 if (nego_tokens_length > 0)
1182 length = nego_tokens_length;
1183 length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))), TRUE); /* NegoData */
1184 length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */
1185 length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(nla->negoToken.cbBuffer)); /* NegoDataItem */
1186 length -= ber_write_sequence_octet_string(s, 0, (BYTE*) nla->negoToken.pvBuffer, nla->negoToken.cbBuffer); /* OCTET STRING */
1189 /* [2] authInfo (OCTET STRING) */
1190 if (auth_info_length > 0)
1192 length = auth_info_length;
1193 length -= ber_write_sequence_octet_string(s, 2, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1196 /* [3] pubKeyAuth (OCTET STRING) */
1197 if (pub_key_auth_length > 0)
1199 length = pub_key_auth_length;
1200 length -= ber_write_sequence_octet_string(s, 3, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1203 Stream_SealLength(s);
1204 transport_write(nla->transport, s);
1205 Stream_Free(s, TRUE);
1209 int nla_decode_ts_request(rdpNla* nla, wStream* s)
1215 if (!ber_read_sequence_tag(s, &length) ||
1216 !ber_read_contextual_tag(s, 0, &length, TRUE) ||
1217 !ber_read_integer(s, &version))
1219 Stream_Free(s, TRUE);
1223 /* [1] negoTokens (NegoData) */
1224 if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
1226 if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
1227 !ber_read_sequence_tag(s, &length) || /* NegoDataItem */
1228 !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
1229 !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1230 ((int) Stream_GetRemainingLength(s)) < length)
1232 Stream_Free(s, TRUE);
1236 if (!sspi_SecBufferAlloc(&nla->negoToken, length))
1238 Stream_Free(s, TRUE);
1241 Stream_Read(s, nla->negoToken.pvBuffer, length);
1242 nla->negoToken.cbBuffer = length;
1245 /* [2] authInfo (OCTET STRING) */
1246 if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
1248 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1249 ((int) Stream_GetRemainingLength(s)) < length)
1251 Stream_Free(s, TRUE);
1255 if (!sspi_SecBufferAlloc(&nla->authInfo, length))
1257 Stream_Free(s, TRUE);
1260 Stream_Read(s, nla->authInfo.pvBuffer, length);
1261 nla->authInfo.cbBuffer = length;
1264 /* [3] pubKeyAuth (OCTET STRING) */
1265 if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
1267 if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
1268 ((int) Stream_GetRemainingLength(s)) < length)
1270 Stream_Free(s, TRUE);
1274 if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
1276 Stream_Free(s, TRUE);
1279 Stream_Read(s, nla->pubKeyAuth.pvBuffer, length);
1280 nla->pubKeyAuth.cbBuffer = length;
1286 int nla_recv_pdu(rdpNla* nla, wStream* s)
1288 if (nla_decode_ts_request(nla, s) < 1)
1291 if (nla_client_recv(nla) < 1)
1297 int nla_recv(rdpNla* nla)
1302 s = Stream_New(NULL, 4096);
1306 WLog_ERR(TAG, "Stream_New failed!");
1310 status = transport_read_pdu(nla->transport, s);
1314 WLog_ERR(TAG, "nla_recv() error: %d", status);
1315 Stream_Free(s, TRUE);
1319 if (nla_decode_ts_request(nla, s) < 1)
1322 Stream_Free(s, TRUE);
1326 void nla_buffer_print(rdpNla* nla)
1328 if (nla->negoToken.cbBuffer > 0)
1330 WLog_DBG(TAG, "NLA.negoToken (length = %d):", (int) nla->negoToken.cbBuffer);
1331 winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);
1334 if (nla->pubKeyAuth.cbBuffer > 0)
1336 WLog_DBG(TAG, "NLA.pubKeyAuth (length = %d):", (int) nla->pubKeyAuth.cbBuffer);
1337 winpr_HexDump(TAG, WLOG_DEBUG, nla->pubKeyAuth.pvBuffer, nla->pubKeyAuth.cbBuffer);
1340 if (nla->authInfo.cbBuffer > 0)
1342 WLog_DBG(TAG, "NLA.authInfo (length = %d):", (int) nla->authInfo.cbBuffer);
1343 winpr_HexDump(TAG, WLOG_DEBUG, nla->authInfo.pvBuffer, nla->authInfo.cbBuffer);
1347 void nla_buffer_free(rdpNla* nla)
1349 sspi_SecBufferFree(&nla->negoToken);
1350 sspi_SecBufferFree(&nla->pubKeyAuth);
1351 sspi_SecBufferFree(&nla->authInfo);
1354 LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname)
1358 LPTSTR hostnameX = NULL;
1359 LPTSTR ServiceClassX = NULL;
1360 LPTSTR ServicePrincipalName = NULL;
1362 ConvertToUnicode(CP_UTF8, 0, hostname, -1, &hostnameX, 0);
1363 ConvertToUnicode(CP_UTF8, 0, ServiceClass, -1, &ServiceClassX, 0);
1365 hostnameX = _strdup(hostname);
1366 ServiceClassX = _strdup(ServiceClass);
1371 ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX);
1372 free(ServiceClassX);
1374 return ServicePrincipalName;
1378 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
1380 if (status != ERROR_BUFFER_OVERFLOW)
1382 free(ServiceClassX);
1387 ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR));
1389 if (!ServicePrincipalName)
1392 status = DsMakeSpn(ServiceClassX, hostnameX, NULL, 0, NULL, &SpnLength, ServicePrincipalName);
1394 if (status != ERROR_SUCCESS)
1396 free(ServicePrincipalName);
1397 free(ServiceClassX);
1402 free(ServiceClassX);
1404 return ServicePrincipalName;
1408 * Create new CredSSP state machine.
1410 * @return new CredSSP state machine.
1413 rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings)
1415 rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla));
1423 nla->instance = instance;
1424 nla->settings = settings;
1425 nla->server = settings->ServerMode;
1426 nla->transport = transport;
1427 nla->sendSeqNum = 0;
1428 nla->recvSeqNum = 0;
1429 ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
1430 ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
1431 ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
1432 SecInvalidateHandle(&nla->context);
1436 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
1437 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
1439 if (status == ERROR_SUCCESS)
1441 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize);
1443 if (status == ERROR_SUCCESS)
1445 nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR));
1446 status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType,
1447 (BYTE*) nla->SspiModule, &dwSize);
1449 if (status == ERROR_SUCCESS)
1451 WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule);
1463 * Free CredSSP state machine.
1467 void nla_free(rdpNla* nla)
1473 nla->table->DeleteSecurityContext(&nla->context);
1475 sspi_SecBufferFree(&nla->PublicKey);
1476 sspi_SecBufferFree(&nla->tsCredentials);
1478 free(nla->ServicePrincipalName);
1479 free(nla->identity.User);
1480 free(nla->identity.Domain);
1481 free(nla->identity.Password);