Fixed /pth: Consistently treat the hash offset to password length.

This commit is contained in:
Armin Novak 2018-05-03 17:49:14 +02:00
parent 1a27f28ba9
commit 5b961e9c75
8 changed files with 37 additions and 29 deletions

View File

@ -225,6 +225,8 @@
#define LB_CLIENT_TSV_URL 0x00001000
#define LB_SERVER_TSV_CAPABLE 0x00002000
#define LB_PASSWORD_MAX_LENGTH 512
/* Keyboard Hook */
#define KEYBOARD_HOOK_LOCAL 0
#define KEYBOARD_HOOK_REMOTE 1

View File

@ -517,7 +517,7 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbPassword % 2) || cbPassword > 512)
if ((cbPassword % 2) || cbPassword > LB_PASSWORD_MAX_LENGTH)
{
WLog_ERR(TAG, "protocol error: invalid cbPassword value: %"PRIu16"", cbPassword);
return FALSE;
@ -639,11 +639,11 @@ static void rdp_write_info_packet(rdpRdp* rdp, wStream* s)
BOOL usedPasswordCookie = FALSE;
rdpSettings* settings = rdp->settings;
flags = INFO_MOUSE |
INFO_UNICODE |
INFO_LOGONERRORS |
INFO_MAXIMIZESHELL |
INFO_ENABLEWINDOWSKEY |
INFO_DISABLECTRLALTDEL;
INFO_UNICODE |
INFO_LOGONERRORS |
INFO_MAXIMIZESHELL |
INFO_ENABLEWINDOWSKEY |
INFO_DISABLECTRLALTDEL;
if (settings->AudioCapture)
flags |= INFO_AUDIOCAPTURE;

View File

@ -150,7 +150,12 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
if (identity->Password)
{
memset(identity->Password, 0, identity->PasswordLength * 2);
size_t len = identity->PasswordLength;
if (len > LB_PASSWORD_MAX_LENGTH) /* [pth] Password hash */
len -= LB_PASSWORD_MAX_LENGTH;
memset(identity->Password, 0, len * 2);
free(identity->Password);
}
@ -286,7 +291,7 @@ static int nla_client_init(rdpNla* nla)
* Multiply password hash length by 64 to obtain a length exceeding
* the maximum (256) and use it this for hash identification in WinPR.
*/
identity->PasswordLength = 32 * 64; /* 2048 */
identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
}
}
}
@ -1941,7 +1946,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
if (nla->peerVersion == 0)
{
WLog_DBG(TAG, "CredSSP protocol support %"PRIu32", peer supports %"PRIu32,
nla->version, version);
nla->version, version);
nla->peerVersion = version;
}
@ -1949,7 +1954,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
if (nla->peerVersion != version)
{
WLog_ERR(TAG, "CredSSP peer changed protocol version from %"PRIu32" to %"PRIu32,
nla->peerVersion, version);
nla->peerVersion, version);
return -1;
}
@ -2247,7 +2252,6 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
nla->sendSeqNum = 0;
nla->recvSeqNum = 0;
nla->version = 6;
ZeroMemory(&nla->ClientNonce, sizeof(SecBuffer));
ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
@ -2308,7 +2312,6 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
}
return nla;
cleanup:
nla_free(nla);
return NULL;

View File

@ -357,7 +357,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (Stream_GetRemainingLength(s) < redirection->PasswordLength)
return -1;
if (redirection->PasswordLength > 512)
if (redirection->PasswordLength > LB_PASSWORD_MAX_LENGTH)
return -1;
redirection->Password = (BYTE*) calloc(1, redirection->PasswordLength + sizeof(WCHAR));

View File

@ -259,8 +259,8 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
char* PasswordHash = NULL;
UINT32 PasswordHashLength = 0;
SSPI_CREDENTIALS* credentials = context->credentials;
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
PasswordHashLength = credentials->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
/* Password contains a password hash of length (PasswordLength - SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) */
PasswordHashLength = credentials->identity.PasswordLength - SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) credentials->identity.Password,
PasswordHashLength, &PasswordHash, 0, NULL, NULL);
@ -280,7 +280,7 @@ int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
return 1;
}
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
static int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
{
SSPI_CREDENTIALS* credentials = context->credentials;
#ifdef WITH_DEBUG_NTLM
@ -316,7 +316,7 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
(LPWSTR) credentials->identity.Domain, credentials->identity.DomainLength * 2,
(BYTE*) hash);
}
else if (credentials->identity.PasswordLength > 256)
else if (credentials->identity.PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
{
/* Special case for WinPR: password hash */
if (ntlm_convert_password_hash(context, context->NtlmHash) < 0)
@ -349,8 +349,8 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash)
ret = context->HashCallback(context->HashCallbackArg, &credentials->identity, &proofValue,
context->EncryptedRandomSessionKey,
(&context->AUTHENTICATE_MESSAGE)->MessageIntegrityCheck,
&micValue, hash);
(&context->AUTHENTICATE_MESSAGE)->MessageIntegrityCheck,
&micValue, hash);
sspi_SecBufferFree(&proofValue);
sspi_SecBufferFree(&micValue);
return ret ? 1 : -1;
@ -723,14 +723,13 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context)
}
}
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context, BYTE *mic, UINT32 size)
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context, BYTE* mic, UINT32 size)
{
/*
* Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE,
* CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey
*/
WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
assert(size >= WINPR_MD5_DIGEST_LENGTH);
if (!hmac)

View File

@ -38,7 +38,6 @@ void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
void ntlm_current_time(BYTE* timestamp);
void ntlm_generate_timestamp(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash);
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
@ -57,6 +56,6 @@ void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context);
void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context);
void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context);
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context, BYTE *mic, UINT32 size);
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context, BYTE* mic, UINT32 size);
#endif /* WINPR_AUTH_NTLM_COMPUTE_H */

View File

@ -26,7 +26,7 @@
#define SSPI_CREDENTIALS_PASSWORD_HASH 0x00000001
#define SSPI_CREDENTIALS_HASH_LENGTH_FACTOR 64
#define SSPI_CREDENTIALS_HASH_LENGTH_OFFSET 512
struct _SSPI_CREDENTIALS
{

View File

@ -242,6 +242,9 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
domainLength = credentials->identity.DomainLength;
passwordLength = credentials->identity.PasswordLength;
if (passwordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) /* [pth] */
passwordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
if (credentials->identity.Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
{
userLength *= 2;
@ -413,7 +416,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
{
int status;
if (srcIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
if (srcIdentity->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User,
(char*) srcIdentity->Domain, (char*) srcIdentity->Password);
@ -421,11 +424,12 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
if (status <= 0)
return -1;
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
return 1;
}
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
/* login/password authentication */
identity->User = identity->Domain = identity->Password = NULL;
identity->UserLength = srcIdentity->UserLength;
@ -456,8 +460,8 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
identity->PasswordLength = srcIdentity->PasswordLength;
if (identity->PasswordLength > 256)
identity->PasswordLength /= SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
if (srcIdentity->Password)
{
@ -470,6 +474,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
identity->Password[identity->PasswordLength] = 0;
}
identity->PasswordLength = srcIdentity->PasswordLength;
/* End of login/password authentication */
return 1;
}