int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { BYTE* response; BYTE value[WINPR_MD5_DIGEST_LENGTH]; if (context->LmCompatibilityLevel < 2) { if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24)) return -1; ZeroMemory(context->LmChallengeResponse.pvBuffer, 24); return 1; } /* Compute the NTLMv2 hash */ if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0) return -1; /* Concatenate the server and client challenges */ CopyMemory(value, context->ServerChallenge, 8); CopyMemory(&value[8], context->ClientChallenge, 8); if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24)) return -1; response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); return 1; }
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { char* response; char value[16]; char ntlm_v2_hash[16]; if (context->LmCompatibilityLevel < 2) { sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); ZeroMemory(context->LmChallengeResponse.pvBuffer, 24); return; } /* Compute the NTLMv2 hash */ ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash); /* Concatenate the server and client challenges */ CopyMemory(value, context->ServerChallenge, 8); CopyMemory(&value[8], context->ClientChallenge, 8); sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); response = (char*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); }
void test_ntlm_compute_ntlm_v2_hash(void) { int i; NTLM_CONTEXT* ntlm; int ntlm_v2_hash_good; char ntlm_v2_hash[16]; char username[] = "User"; char password[] = "Password"; char domain[] = "Domain"; char expected_ntlm_v2_hash[16] = "\x0c\x86\x8a\x40\x3b\xfd\x7a\x93\xa3\x00\x1e\xf2\x2e\xf0\x2e\x3f"; ntlm = ntlm_client_new(); ntlm_set_password(ntlm, password); ntlm_set_username(ntlm, username); ntlm_set_domain(ntlm, domain); ntlm_compute_ntlm_v2_hash(ntlm, ntlm_v2_hash); ntlm_v2_hash_good = 1; for (i = 0; i < 16; i++) { if (ntlm_v2_hash[i] != expected_ntlm_v2_hash[i]) ntlm_v2_hash_good = 0; } CU_ASSERT(ntlm_v2_hash_good == 1); }
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; BYTE nt_proof_str[WINPR_MD5_DIGEST_LENGTH]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; SSPI_CREDENTIALS* credentials; credentials = context->credentials; TargetInfo = &context->ChallengeTargetInfo; if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28)) return -1; ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); blob = (BYTE*) ntlm_v2_temp.pvBuffer; /* Compute the NTLMv2 hash */ if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0) return -1; #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Password (length = %d)", credentials->identity.PasswordLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Password, credentials->identity.PasswordLength * 2); WLog_DBG(TAG, "Username (length = %d)", credentials->identity.UserLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.User, credentials->identity.UserLength * 2); WLog_DBG(TAG, "Domain (length = %d)", credentials->identity.DomainLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Domain, credentials->identity.DomainLength * 2); WLog_DBG(TAG, "Workstation (length = %d)", context->Workstation.Length); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) context->Workstation.Buffer, context->Workstation.Length); WLog_DBG(TAG, "NTOWFv2, NTLMv2 Hash"); winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ /* Reserved1 (2 bytes) */ /* Reserved2 (4 bytes) */ CopyMemory(&blob[8], context->Timestamp, 8); /* Timestamp (8 bytes) */ CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */ /* Reserved3 (4 bytes) */ CopyMemory(&blob[28], TargetInfo->pvBuffer, TargetInfo->cbBuffer); #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "NTLMv2 Response Temp Blob"); winpr_HexDump(TAG, WLOG_DEBUG, ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); #endif /* Concatenate server challenge with temp */ if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8)) return -1; blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16)) return -1; blob = (BYTE*) context->NtChallengeResponse.pvBuffer; CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; }
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; BYTE ntlm_v2_hash[16]; BYTE nt_proof_str[16]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; sspi_SecBufferAlloc(&ntlm_v2_temp, context->ChallengeTargetInfo.cbBuffer + 28); ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); blob = (BYTE*) ntlm_v2_temp.pvBuffer; /* Compute the NTLMv2 hash */ ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash); #ifdef WITH_DEBUG_NTLM printf("Password (length = %d)\n", context->identity.PasswordLength * 2); winpr_HexDump((BYTE*) context->identity.Password, context->identity.PasswordLength * 2); printf("\n"); printf("Username (length = %d)\n", context->identity.UserLength * 2); winpr_HexDump((BYTE*) context->identity.User, context->identity.UserLength * 2); printf("\n"); printf("Domain (length = %d)\n", context->identity.DomainLength * 2); winpr_HexDump((BYTE*) context->identity.Domain, context->identity.DomainLength * 2); printf("\n"); printf("Workstation (length = %d)\n", context->Workstation.Length); winpr_HexDump((BYTE*) context->Workstation.Buffer, context->Workstation.Length); printf("\n"); printf("NTOWFv2, NTLMv2 Hash\n"); winpr_HexDump(ntlm_v2_hash, 16); printf("\n"); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ /* Reserved1 (2 bytes) */ /* Reserved2 (4 bytes) */ CopyMemory(&blob[8], context->Timestamp, 8); /* Timestamp (8 bytes) */ CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */ /* Reserved3 (4 bytes) */ CopyMemory(&blob[28], context->ChallengeTargetInfo.pvBuffer, context->ChallengeTargetInfo.cbBuffer); #ifdef WITH_DEBUG_NTLM printf("NTLMv2 Response Temp Blob\n"); winpr_HexDump(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); printf("\n"); #endif /* Concatenate server challenge with temp */ sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8); blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL); /* NtChallengeResponse, Concatenate NTProofStr with temp */ sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16); blob = (BYTE*) context->NtChallengeResponse.pvBuffer; CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) context->SessionBaseKey, NULL); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); }