Fixed /pth: Consistently treat the hash offset to password length.
authorArmin Novak <armin.novak@thincast.com>
Thu, 3 May 2018 15:49:14 +0000 (17:49 +0200)
committerArmin Novak <armin.novak@thincast.com>
Thu, 3 May 2018 15:51:11 +0000 (17:51 +0200)
include/freerdp/settings.h
libfreerdp/core/info.c
libfreerdp/core/nla.c
libfreerdp/core/redirection.c
winpr/libwinpr/sspi/NTLM/ntlm_compute.c
winpr/libwinpr/sspi/NTLM/ntlm_compute.h
winpr/libwinpr/sspi/sspi.h
winpr/libwinpr/sspi/sspi_winpr.c

index 3f30bf5..29949d8 100644 (file)
 #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
index 66d32ed..006585b 100644 (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;
index 0f1eb1f..fb210e0 100644 (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;
index ab96647..c403adc 100644 (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));
index 018b0ad..b68bb41 100644 (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, BYTEmic, 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)
index df06e37..47f6c5d 100644 (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, BYTEmic, UINT32 size);
 
 #endif /* WINPR_AUTH_NTLM_COMPUTE_H */
index 0c89343..bf08cc6 100644 (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
 {
index bad9992..46936d5 100644 (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;
 }