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; }
BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) { BYTE ClientRandom[32]; BYTE AutoReconnectRandom[32]; ARC_SC_PRIVATE_PACKET* serverCookie; ARC_CS_PRIVATE_PACKET* clientCookie; rdpSettings* settings = rdp->settings; serverCookie = settings->ServerAutoReconnectCookie; clientCookie = settings->ClientAutoReconnectCookie; clientCookie->cbLen = 28; clientCookie->version = serverCookie->version; clientCookie->logonId = serverCookie->logonId; ZeroMemory(clientCookie->securityVerifier, 16); ZeroMemory(AutoReconnectRandom, sizeof(AutoReconnectRandom)); CopyMemory(AutoReconnectRandom, serverCookie->arcRandomBits, 16); ZeroMemory(ClientRandom, sizeof(ClientRandom)); if (settings->SelectedProtocol == PROTOCOL_RDP) CopyMemory(ClientRandom, settings->ClientRandom, settings->ClientRandomLength); /* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */ if (!winpr_HMAC(WINPR_MD_MD5, AutoReconnectRandom, 16, ClientRandom, 32, clientCookie->securityVerifier, 16)) return FALSE; return TRUE; }
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; }