mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 20:04:11 +08:00
Merge pull request #4499 from mfleisz/cssp_v6
cssp: Add support for protocol version 6
This commit is contained in:
commit
de83f4df21
@ -104,7 +104,9 @@ static int nla_recv(rdpNla* nla);
|
|||||||
static void nla_buffer_print(rdpNla* nla);
|
static void nla_buffer_print(rdpNla* nla);
|
||||||
static void nla_buffer_free(rdpNla* nla);
|
static void nla_buffer_free(rdpNla* nla);
|
||||||
static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
|
static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla);
|
||||||
|
static SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla);
|
||||||
static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
|
static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
|
||||||
|
static SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla);
|
||||||
static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
|
static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
|
||||||
static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
|
static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
|
||||||
static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
|
static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
|
||||||
@ -113,6 +115,10 @@ static void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity);
|
|||||||
#define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
|
#define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length)
|
||||||
#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)
|
#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)
|
||||||
|
|
||||||
|
static const CHAR ClientServerHashMagic[] = "CredSSP Client-To-Server Binding Hash\0";
|
||||||
|
static const CHAR ServerClientHashMagic[] = "CredSSP Server-To-Client Binding Hash\0";
|
||||||
|
static const UINT32 NonceLength = 32;
|
||||||
|
|
||||||
void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
|
void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
|
||||||
{
|
{
|
||||||
if (identity)
|
if (identity)
|
||||||
@ -511,7 +517,10 @@ static int nla_client_recv(rdpNla* nla)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nla->version < 5)
|
||||||
nla->status = nla_encrypt_public_key_echo(nla);
|
nla->status = nla_encrypt_public_key_echo(nla);
|
||||||
|
else
|
||||||
|
nla->status = nla_encrypt_public_key_hash(nla);
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
if (nla->status != SEC_E_OK)
|
||||||
return -1;
|
return -1;
|
||||||
@ -538,7 +547,11 @@ static int nla_client_recv(rdpNla* nla)
|
|||||||
else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
|
else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
|
||||||
{
|
{
|
||||||
/* Verify Server Public Key Echo */
|
/* Verify Server Public Key Echo */
|
||||||
|
if (nla->version < 5)
|
||||||
nla->status = nla_decrypt_public_key_echo(nla);
|
nla->status = nla_decrypt_public_key_echo(nla);
|
||||||
|
else
|
||||||
|
nla->status = nla_decrypt_public_key_hash(nla);
|
||||||
|
|
||||||
nla_buffer_free(nla);
|
nla_buffer_free(nla);
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
if (nla->status != SEC_E_OK)
|
||||||
@ -856,7 +869,10 @@ static int nla_server_authenticate(rdpNla* nla)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nla->version < 5)
|
||||||
nla->status = nla_decrypt_public_key_echo(nla);
|
nla->status = nla_decrypt_public_key_echo(nla);
|
||||||
|
else
|
||||||
|
nla->status = nla_decrypt_public_key_hash(nla);
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
if (nla->status != SEC_E_OK)
|
||||||
{
|
{
|
||||||
@ -868,7 +884,11 @@ static int nla_server_authenticate(rdpNla* nla)
|
|||||||
sspi_SecBufferFree(&nla->negoToken);
|
sspi_SecBufferFree(&nla->negoToken);
|
||||||
nla->negoToken.pvBuffer = NULL;
|
nla->negoToken.pvBuffer = NULL;
|
||||||
nla->negoToken.cbBuffer = 0;
|
nla->negoToken.cbBuffer = 0;
|
||||||
|
|
||||||
|
if (nla->version < 5)
|
||||||
nla->status = nla_encrypt_public_key_echo(nla);
|
nla->status = nla_encrypt_public_key_echo(nla);
|
||||||
|
else
|
||||||
|
nla->status = nla_encrypt_public_key_hash(nla);
|
||||||
|
|
||||||
if (nla->status != SEC_E_OK)
|
if (nla->status != SEC_E_OK)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1073,6 +1093,93 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla)
|
||||||
|
{
|
||||||
|
SecBuffer Buffers[2] = { { 0 } };
|
||||||
|
SecBufferDesc Message;
|
||||||
|
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
|
||||||
|
WINPR_DIGEST_CTX* sha256 = NULL;
|
||||||
|
const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
|
||||||
|
const ULONG auth_data_length = krb ? WINPR_SHA256_DIGEST_LENGTH :
|
||||||
|
(nla->ContextSizes.cbSecurityTrailer
|
||||||
|
+ WINPR_SHA256_DIGEST_LENGTH);
|
||||||
|
const CHAR* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
|
||||||
|
|
||||||
|
if (!sspi_SecBufferAlloc(&nla->ClientNonce, NonceLength))
|
||||||
|
{
|
||||||
|
status = SEC_E_INSUFFICIENT_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, auth_data_length))
|
||||||
|
{
|
||||||
|
status = SEC_E_INSUFFICIENT_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate random 32-byte nonce */
|
||||||
|
if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
|
||||||
|
if (!(sha256 = winpr_Digest_New()))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* include trailing \0 from hashMagic */
|
||||||
|
if (!winpr_Digest_Update(sha256, hashMagic, strlen(hashMagic) + 1))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* SubjectPublicKey */
|
||||||
|
if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
Message.pBuffers = (PSecBuffer)&Buffers;
|
||||||
|
Message.ulVersion = SECBUFFER_VERSION;
|
||||||
|
|
||||||
|
if (krb)
|
||||||
|
{
|
||||||
|
Message.cBuffers = 1;
|
||||||
|
Buffers[0].BufferType = SECBUFFER_DATA; /* SHA256 hash */
|
||||||
|
Buffers[0].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
|
||||||
|
Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Final(sha256, Buffers[0].pvBuffer, Buffers[0].cbBuffer))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Message.cBuffers = 2;
|
||||||
|
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
|
||||||
|
Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
|
||||||
|
Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
|
||||||
|
Buffers[1].BufferType = SECBUFFER_DATA; /* SHA256 hash */
|
||||||
|
Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
|
||||||
|
Buffers[1].pvBuffer = ((BYTE*)nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Final(sha256, Buffers[1].pvBuffer, Buffers[1].cbBuffer))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encrypt message */
|
||||||
|
status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
|
||||||
|
|
||||||
|
if (status != SEC_E_OK)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]",
|
||||||
|
GetSecurityStatusString(status), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
winpr_Digest_Free(sha256);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
|
SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
|
||||||
{
|
{
|
||||||
size_t length;
|
size_t length;
|
||||||
@ -1184,6 +1291,111 @@ fail:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla)
|
||||||
|
{
|
||||||
|
unsigned long length;
|
||||||
|
BYTE* buffer = NULL;
|
||||||
|
ULONG pfQOP = 0;
|
||||||
|
int signature_length;
|
||||||
|
SecBuffer Buffers[2] = { { 0 } };
|
||||||
|
SecBufferDesc Message;
|
||||||
|
WINPR_DIGEST_CTX* sha256 = NULL;
|
||||||
|
BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH];
|
||||||
|
SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
|
||||||
|
const BOOL krb = (_tcsncmp(nla->packageName, KERBEROS_SSP_NAME, ARRAYSIZE(KERBEROS_SSP_NAME)) == 0);
|
||||||
|
const CHAR* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
|
||||||
|
signature_length = nla->pubKeyAuth.cbBuffer - WINPR_SHA256_DIGEST_LENGTH;
|
||||||
|
|
||||||
|
if ((signature_length < 0) || (signature_length > (int)nla->ContextSizes.cbSecurityTrailer))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", nla->pubKeyAuth.cbBuffer);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nla->ContextSizes.cbSecurityTrailer + WINPR_SHA256_DIGEST_LENGTH) != nla->pubKeyAuth.cbBuffer)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", (int)nla->pubKeyAuth.cbBuffer);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = nla->pubKeyAuth.cbBuffer;
|
||||||
|
buffer = (BYTE*)malloc(length);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
status = SEC_E_INSUFFICIENT_MEMORY;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (krb)
|
||||||
|
{
|
||||||
|
CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
|
||||||
|
Buffers[0].BufferType = SECBUFFER_DATA; /* Encrypted Hash */
|
||||||
|
Buffers[0].cbBuffer = length;
|
||||||
|
Buffers[0].pvBuffer = buffer;
|
||||||
|
Message.cBuffers = 1;
|
||||||
|
Message.ulVersion = SECBUFFER_VERSION;
|
||||||
|
Message.pBuffers = (PSecBuffer)&Buffers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
|
||||||
|
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
|
||||||
|
Buffers[0].cbBuffer = signature_length;
|
||||||
|
Buffers[0].pvBuffer = buffer;
|
||||||
|
Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted Hash */
|
||||||
|
Buffers[1].cbBuffer = WINPR_SHA256_DIGEST_LENGTH;
|
||||||
|
Buffers[1].pvBuffer = buffer + signature_length;
|
||||||
|
Message.cBuffers = 2;
|
||||||
|
Message.ulVersion = SECBUFFER_VERSION;
|
||||||
|
Message.pBuffers = (PSecBuffer)&Buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
|
||||||
|
|
||||||
|
if (status != SEC_E_OK)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "DecryptMessage failure %s [%08"PRIX32"]",
|
||||||
|
GetSecurityStatusString(status), status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
|
||||||
|
if (!(sha256 = winpr_Digest_New()))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* include trailing \0 from hashMagic */
|
||||||
|
if (!winpr_Digest_Update(sha256, hashMagic, strlen(hashMagic) + 1))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Update(sha256, nla->ClientNonce.pvBuffer, nla->ClientNonce.cbBuffer))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* SubjectPublicKey */
|
||||||
|
if (!winpr_Digest_Update(sha256, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* verify hash */
|
||||||
|
if (memcmp(serverClientHash, Buffers[krb ? 0 : 1].pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Could not verify server's hash");
|
||||||
|
status = SEC_E_MESSAGE_ALTERED; /* DO NOT SEND CREDENTIALS! */
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = SEC_E_OK;
|
||||||
|
fail:
|
||||||
|
free(buffer);
|
||||||
|
winpr_Digest_Free(sha256);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t nla_sizeof_ts_password_creds(rdpNla* nla)
|
static size_t nla_sizeof_ts_password_creds(rdpNla* nla)
|
||||||
{
|
{
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
@ -1587,6 +1799,13 @@ static size_t nla_sizeof_auth_info(size_t length)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t nla_sizeof_client_nonce(size_t length)
|
||||||
|
{
|
||||||
|
length = ber_sizeof_octet_string(length);
|
||||||
|
length += ber_sizeof_contextual_tag(length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t nla_sizeof_ts_request(size_t length)
|
static size_t nla_sizeof_ts_request(size_t length)
|
||||||
{
|
{
|
||||||
length += ber_sizeof_integer(2);
|
length += ber_sizeof_integer(2);
|
||||||
@ -1609,23 +1828,23 @@ BOOL nla_send(rdpNla* nla)
|
|||||||
size_t auth_info_length = 0;
|
size_t auth_info_length = 0;
|
||||||
size_t error_code_context_length = 0;
|
size_t error_code_context_length = 0;
|
||||||
size_t error_code_length = 0;
|
size_t error_code_length = 0;
|
||||||
|
size_t client_nonce_length = 0;
|
||||||
if (nla->version < 3 || nla->errorCode == 0)
|
|
||||||
{
|
|
||||||
nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(
|
nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(
|
||||||
nla->negoToken.cbBuffer) : 0;
|
nla->negoToken.cbBuffer) : 0;
|
||||||
pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(
|
pub_key_auth_length = (nla->pubKeyAuth.cbBuffer > 0) ? nla_sizeof_pub_key_auth(
|
||||||
nla->pubKeyAuth.cbBuffer) : 0;
|
nla->pubKeyAuth.cbBuffer) : 0;
|
||||||
auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
|
auth_info_length = (nla->authInfo.cbBuffer > 0) ? nla_sizeof_auth_info(nla->authInfo.cbBuffer) : 0;
|
||||||
}
|
client_nonce_length = (nla->ClientNonce.cbBuffer > 0) ? nla_sizeof_client_nonce(
|
||||||
else
|
nla->ClientNonce.cbBuffer) : 0;
|
||||||
|
|
||||||
|
if (nla->version >= 3 && nla->version != 5 && nla->errorCode != 0)
|
||||||
{
|
{
|
||||||
error_code_length = ber_sizeof_integer(nla->errorCode);
|
error_code_length = ber_sizeof_integer(nla->errorCode);
|
||||||
error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
|
error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
length = nego_tokens_length + pub_key_auth_length + auth_info_length + error_code_context_length +
|
length = nego_tokens_length + pub_key_auth_length + auth_info_length + error_code_context_length +
|
||||||
error_code_length;
|
error_code_length + client_nonce_length;
|
||||||
ts_request_length = nla_sizeof_ts_request(length);
|
ts_request_length = nla_sizeof_ts_request(length);
|
||||||
s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
|
s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
|
||||||
|
|
||||||
@ -1682,6 +1901,14 @@ BOOL nla_send(rdpNla* nla)
|
|||||||
ber_write_integer(s, nla->errorCode);
|
ber_write_integer(s, nla->errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [5] clientNonce (OCTET STRING) */
|
||||||
|
if (client_nonce_length > 0)
|
||||||
|
{
|
||||||
|
if (ber_write_sequence_octet_string(s, 5, nla->ClientNonce.pvBuffer,
|
||||||
|
nla->ClientNonce.cbBuffer) != client_nonce_length)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_SealLength(s);
|
Stream_SealLength(s);
|
||||||
transport_write(nla->transport, s);
|
transport_write(nla->transport, s);
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
@ -1711,7 +1938,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
|
|||||||
!ber_read_sequence_tag(s, &length) || /* NegoDataItem */
|
!ber_read_sequence_tag(s, &length) || /* NegoDataItem */
|
||||||
!ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
|
!ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
|
||||||
!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
||||||
((int) Stream_GetRemainingLength(s)) < length)
|
Stream_GetRemainingLength(s) < length)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1727,7 +1954,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
|
|||||||
if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
|
if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
|
||||||
{
|
{
|
||||||
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
||||||
((int) Stream_GetRemainingLength(s)) < length)
|
Stream_GetRemainingLength(s) < length)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!sspi_SecBufferAlloc(&nla->authInfo, length))
|
if (!sspi_SecBufferAlloc(&nla->authInfo, length))
|
||||||
@ -1741,7 +1968,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
|
|||||||
if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
|
if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
|
||||||
{
|
{
|
||||||
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
||||||
((int) Stream_GetRemainingLength(s)) < length)
|
Stream_GetRemainingLength(s) < length)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
|
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
|
||||||
@ -1759,6 +1986,22 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
|
|||||||
if (!ber_read_integer(s, &nla->errorCode))
|
if (!ber_read_integer(s, &nla->errorCode))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nla->version >= 5)
|
||||||
|
{
|
||||||
|
if (ber_read_contextual_tag(s, 5, &length, TRUE) != FALSE)
|
||||||
|
{
|
||||||
|
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
|
||||||
|
Stream_GetRemainingLength(s) < length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!sspi_SecBufferAlloc(&nla->ClientNonce, length))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Stream_Read(s, nla->ClientNonce.pvBuffer, length);
|
||||||
|
nla->ClientNonce.cbBuffer = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -1981,7 +2224,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
|
|||||||
nla->transport = transport;
|
nla->transport = transport;
|
||||||
nla->sendSeqNum = 0;
|
nla->sendSeqNum = 0;
|
||||||
nla->recvSeqNum = 0;
|
nla->recvSeqNum = 0;
|
||||||
nla->version = 3;
|
nla->version = 6;
|
||||||
|
|
||||||
if (settings->NtlmSamFile)
|
if (settings->NtlmSamFile)
|
||||||
{
|
{
|
||||||
@ -1998,6 +2241,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
|
|||||||
ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
|
ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
|
||||||
ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
|
ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
|
||||||
ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
|
ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
|
||||||
|
ZeroMemory(&nla->ClientNonce, sizeof(SecBuffer));
|
||||||
SecInvalidateHandle(&nla->context);
|
SecInvalidateHandle(&nla->context);
|
||||||
|
|
||||||
if (nla->server)
|
if (nla->server)
|
||||||
@ -2079,6 +2323,7 @@ void nla_free(rdpNla* nla)
|
|||||||
|
|
||||||
free(nla->SamFile);
|
free(nla->SamFile);
|
||||||
nla->SamFile = NULL;
|
nla->SamFile = NULL;
|
||||||
|
sspi_SecBufferFree(&nla->ClientNonce);
|
||||||
sspi_SecBufferFree(&nla->PublicKey);
|
sspi_SecBufferFree(&nla->PublicKey);
|
||||||
sspi_SecBufferFree(&nla->tsCredentials);
|
sspi_SecBufferFree(&nla->tsCredentials);
|
||||||
free(nla->ServicePrincipalName);
|
free(nla->ServicePrincipalName);
|
||||||
|
@ -83,6 +83,7 @@ struct rdp_nla
|
|||||||
SecBuffer negoToken;
|
SecBuffer negoToken;
|
||||||
SecBuffer pubKeyAuth;
|
SecBuffer pubKeyAuth;
|
||||||
SecBuffer authInfo;
|
SecBuffer authInfo;
|
||||||
|
SecBuffer ClientNonce;
|
||||||
SecBuffer PublicKey;
|
SecBuffer PublicKey;
|
||||||
SecBuffer tsCredentials;
|
SecBuffer tsCredentials;
|
||||||
LPTSTR ServicePrincipalName;
|
LPTSTR ServicePrincipalName;
|
||||||
|
@ -617,6 +617,7 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L
|
|||||||
#define WINPR_MD4_DIGEST_LENGTH 16
|
#define WINPR_MD4_DIGEST_LENGTH 16
|
||||||
#define WINPR_MD5_DIGEST_LENGTH 16
|
#define WINPR_MD5_DIGEST_LENGTH 16
|
||||||
#define WINPR_SHA1_DIGEST_LENGTH 20
|
#define WINPR_SHA1_DIGEST_LENGTH 20
|
||||||
|
#define WINPR_SHA256_DIGEST_LENGTH 32
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user