From 63a3fe70cbd3eda5cc24791d18d1e45a5509fd27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 1 Jul 2012 14:33:36 -0400 Subject: [PATCH] libwinpr-sspi: improve NTLM message debugging --- winpr/sspi/NTLM/ntlm.c | 1 + winpr/sspi/NTLM/ntlm.h | 34 +++++ winpr/sspi/NTLM/ntlm_av_pairs.c | 181 +++++++++++++++-------- winpr/sspi/NTLM/ntlm_av_pairs.h | 10 ++ winpr/sspi/NTLM/ntlm_compute.c | 44 ++++-- winpr/sspi/NTLM/ntlm_compute.h | 2 + winpr/sspi/NTLM/ntlm_message.c | 255 ++++++++++++-------------------- 7 files changed, 297 insertions(+), 230 deletions(-) diff --git a/winpr/sspi/NTLM/ntlm.c b/winpr/sspi/NTLM/ntlm.c index a0a545829..487e8c448 100644 --- a/winpr/sspi/NTLM/ntlm.c +++ b/winpr/sspi/NTLM/ntlm.c @@ -65,6 +65,7 @@ void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName) GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize); TargetName = malloc(nSize); GetComputerNameExA(ComputerNameDnsHostname, TargetName, &nSize); + CharUpperA(TargetName); } context->TargetName.cbBuffer = strlen(TargetName) * 2; diff --git a/winpr/sspi/NTLM/ntlm.h b/winpr/sspi/NTLM/ntlm.h index 3a6e06e04..097de9ae1 100644 --- a/winpr/sspi/NTLM/ntlm.h +++ b/winpr/sspi/NTLM/ntlm.h @@ -81,6 +81,13 @@ enum _NTLM_STATE }; typedef enum _NTLM_STATE NTLM_STATE; +struct _NTLM_AV_PAIR +{ + UINT16 AvId; + UINT16 AvLen; +}; +typedef struct _NTLM_AV_PAIR NTLM_AV_PAIR; + struct _AV_PAIR { UINT16 length; @@ -136,6 +143,32 @@ struct _NTLM_VERSION_INFO }; typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO; +struct _NTLM_RESPONSE +{ + BYTE Response[24]; +}; +typedef struct _NTLM_RESPONSE NTLM_RESPONSE; + +struct _NTLMv2_CLIENT_CHALLENGE +{ + UINT8 RespType; + UINT8 HiRespType; + UINT16 Reserved1; + UINT32 Reserved2; + BYTE Timestamp[8]; + BYTE ClientChallenge[8]; + UINT32 Reserved3; + NTLM_AV_PAIR* AvPairs; +}; +typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE; + +struct _NTLMv2_RESPONSE +{ + BYTE Response[16]; + NTLMv2_CLIENT_CHALLENGE Challenge; +}; +typedef struct _NTLMv2_RESPONSE NTLMv2_RESPONSE; + struct _NTLM_MESSAGE_FIELDS { UINT16 Len; @@ -169,6 +202,7 @@ struct _NTLM_CHALLENGE_MESSAGE UINT32 MessageType; UINT32 NegotiateFlags; BYTE ServerChallenge[8]; + BYTE Reserved[8]; NTLM_VERSION_INFO Version; NTLM_MESSAGE_FIELDS TargetName; NTLM_MESSAGE_FIELDS TargetInfo; diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/sspi/NTLM/ntlm_av_pairs.c index 29167fca6..e246d4653 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/sspi/NTLM/ntlm_av_pairs.c @@ -43,6 +43,78 @@ const char* const AV_PAIRS_STRINGS[] = "MsvChannelBindings" }; +void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList) +{ + NTLM_AV_PAIR* pAvPair = pAvPairList; + + pAvPair->AvId = MsvAvEOL; + pAvPair->AvLen = 0; +} + +ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength) +{ + /* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */ + return (AvPairsCount + 1) * sizeof(NTLM_AV_PAIR) + AvPairsValueLength; +} + +PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair) +{ + return &((PBYTE) pAvPair)[sizeof(NTLM_AV_PAIR)]; +} + +int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair) +{ + return pAvPair->AvLen + sizeof(NTLM_AV_PAIR); +} + +NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair) +{ + return (NTLM_AV_PAIR*) ((PBYTE) pAvPair + ntlm_av_pair_get_next_offset(pAvPair)); +} + +NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPairListSize) +{ + NTLM_AV_PAIR* pAvPair = pAvPairList; + + if (!pAvPair) + return NULL; + + while (1) + { + if (pAvPair->AvId == AvId) + return pAvPair; + + if (pAvPair->AvId == MsvAvEOL) + return NULL; + + AvPairListSize -= ntlm_av_pair_get_next_offset(pAvPair); + + if (AvPairListSize <= 0) + return NULL; + + pAvPair = ntlm_av_pair_get_next_pointer(pAvPair); + } + + return NULL; +} + +NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize) +{ + NTLM_AV_PAIR* pAvPair; + + pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL, AvPairListSize); + + if (!pAvPair) + return NULL; + + pAvPair->AvId = AvId; + pAvPair->AvLen = pValue->Length; + + CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), pValue->Buffer, pValue->Length); + + return pAvPair; +} + /** * Input array of AV_PAIRs.\n * AV_PAIR @msdn{cc236646} @@ -322,74 +394,65 @@ void ntlm_populate_av_pairs(NTLM_CONTEXT* context) ntlm_output_av_pairs(context, &context->TargetInfo); } -/** - * Populate array of AV_PAIRs (server).\n - * AV_PAIR @msdn{cc236646} - * @param NTLM context - */ +void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type) +{ + char* name; + DWORD nSize = 0; -void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context) + GetComputerNameExA(type, NULL, &nSize); + name = malloc(nSize); + GetComputerNameExA(type, name, &nSize); + + if (type == ComputerNameNetBIOS) + CharUpperA(name); + + pName->Length = strlen(name) * 2; + pName->Buffer = (PWSTR) malloc(pName->Length); + MultiByteToWideChar(CP_ACP, 0, name, strlen(name), + (LPWSTR) pName->Buffer, pName->Length / 2); + + pName->MaximumLength = pName->Length; + + free(name); +} + +void ntlm_construct_server_target_info(NTLM_CONTEXT* context) { int length; - DWORD nSize; - AV_PAIRS* av_pairs; - char* NbDomainName; - char* NbComputerName; - char* DnsDomainName; - char* DnsComputerName; + ULONG AvPairsCount; + ULONG AvPairsLength; + LONG AvPairListSize; + NTLM_AV_PAIR* pAvPairList; + UNICODE_STRING NbDomainName; + UNICODE_STRING NbComputerName; + UNICODE_STRING DnsDomainName; + UNICODE_STRING DnsComputerName; + UNICODE_STRING Timestamp; - av_pairs = context->av_pairs; + ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS); + ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS); + ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain); + ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname); - nSize = 0; - GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize); - NbDomainName = malloc(nSize); - GetComputerNameExA(ComputerNameNetBIOS, NbDomainName, &nSize); - CharUpperA(NbDomainName); + Timestamp.Buffer = (PWSTR) context->Timestamp; + Timestamp.Length = sizeof(context->Timestamp); - nSize = 0; - GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize); - NbComputerName = malloc(nSize); - GetComputerNameExA(ComputerNameNetBIOS, NbComputerName, &nSize); - CharUpperA(NbComputerName); + AvPairsCount = 5; + AvPairsLength = NbDomainName.Length + NbComputerName.Length + + DnsDomainName.Length + DnsComputerName.Length + 8; - nSize = 0; - GetComputerNameExA(ComputerNameDnsDomain, NULL, &nSize); - DnsDomainName = malloc(nSize); - GetComputerNameExA(ComputerNameDnsDomain, DnsDomainName, &nSize); - - nSize = 0; - GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize); - DnsComputerName = malloc(nSize); - GetComputerNameExA(ComputerNameDnsHostname, DnsComputerName, &nSize); - - av_pairs->NbDomainName.length = strlen(NbDomainName) * 2; - av_pairs->NbDomainName.value = (BYTE*) malloc(av_pairs->NbDomainName.length); - MultiByteToWideChar(CP_ACP, 0, NbDomainName, strlen(NbDomainName), - (LPWSTR) av_pairs->NbDomainName.value, av_pairs->NbDomainName.length / 2); - - av_pairs->NbComputerName.length = strlen(NbDomainName) * 2; - av_pairs->NbComputerName.value = (BYTE*) malloc(av_pairs->NbComputerName.length); - MultiByteToWideChar(CP_ACP, 0, NbComputerName, strlen(NbComputerName), - (LPWSTR) av_pairs->NbComputerName.value, av_pairs->NbComputerName.length / 2); - - av_pairs->DnsDomainName.length = strlen(DnsDomainName) * 2; - av_pairs->DnsDomainName.value = (BYTE*) malloc(av_pairs->DnsDomainName.length); - MultiByteToWideChar(CP_ACP, 0, DnsDomainName, strlen(DnsDomainName), - (LPWSTR) av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length / 2); - - av_pairs->DnsComputerName.length = strlen(DnsComputerName) * 2; - av_pairs->DnsComputerName.value = (BYTE*) malloc(av_pairs->DnsComputerName.length); - MultiByteToWideChar(CP_ACP, 0, DnsComputerName, strlen(DnsComputerName), - (LPWSTR) av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length / 2); - - length = ntlm_compute_av_pairs_length(context) + 4; + length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength); sspi_SecBufferAlloc(&context->TargetInfo, length); - ntlm_output_av_pairs(context, &context->TargetInfo); - free(NbDomainName); - free(NbComputerName); - free(DnsDomainName); - free(DnsComputerName); + pAvPairList = (NTLM_AV_PAIR*) context->TargetInfo.pvBuffer; + AvPairListSize = (ULONG) context->TargetInfo.cbBuffer; + + ntlm_av_pair_list_init(pAvPairList); + ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, &NbDomainName, AvPairListSize); + ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, &NbComputerName, AvPairListSize); + ntlm_av_pair_add(pAvPairList, MsvAvDnsDomainName, &DnsDomainName, AvPairListSize); + ntlm_av_pair_add(pAvPairList, MsvAvDnsComputerName, &DnsComputerName, AvPairListSize); + ntlm_av_pair_add(pAvPairList, MsvAvTimestamp, &Timestamp, AvPairListSize); } /** diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.h b/winpr/sspi/NTLM/ntlm_av_pairs.h index 1fac6bd04..d4ed2426e 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.h +++ b/winpr/sspi/NTLM/ntlm_av_pairs.h @@ -24,6 +24,16 @@ #include +void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList); +ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength); +PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair); +int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair); +NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair); +NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, LONG AvPairListSize); +NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize); + +void ntlm_construct_server_target_info(NTLM_CONTEXT* context); + void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s); void ntlm_output_av_pairs(NTLM_CONTEXT* context, PSecBuffer buffer); void ntlm_populate_av_pairs(NTLM_CONTEXT* context); diff --git a/winpr/sspi/NTLM/ntlm_compute.c b/winpr/sspi/NTLM/ntlm_compute.c index b91b479dd..e4f730363 100644 --- a/winpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/sspi/NTLM/ntlm_compute.c @@ -56,6 +56,21 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo) versionInfo->NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3; } +/** + * Read VERSION structure.\n + * VERSION @msdn{cc236654} + * @param s + */ + +void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo) +{ + StreamRead_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */ + StreamRead_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */ + StreamRead_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */ + StreamRead(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */ + StreamRead_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */ +} + /** * Write VERSION structure.\n * VERSION @msdn{cc236654} @@ -64,17 +79,28 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo) void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo) { - OSVERSIONINFOA osVersionInfo; + StreamWrite_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */ + StreamWrite_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */ + StreamWrite_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */ + StreamWrite(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */ + StreamWrite_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */ +} - osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); +/** + * Print VERSION structure.\n + * VERSION @msdn{cc236654} + * @param s + */ - GetVersionExA(&osVersionInfo); - - StreamWrite_UINT8(s, osVersionInfo.dwMajorVersion); /* ProductMajorVersion (1 byte) */ - StreamWrite_UINT8(s, osVersionInfo.dwMinorVersion); /* ProductMinorVersion (1 byte) */ - StreamWrite_UINT16(s, osVersionInfo.dwBuildNumber); /* ProductBuild (2 bytes) */ - StreamZero(s, 3); /* Reserved (3 bytes) */ - StreamWrite_UINT8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */ +void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo) +{ + printf("VERSION =\n{\n"); + printf("\tProductMajorVersion: %d\n", versionInfo->ProductMajorVersion); + printf("\tProductMinorVersion: %d\n", versionInfo->ProductMinorVersion); + printf("\tProductBuild: %d\n", versionInfo->ProductBuild); + printf("\tReserved: 0x%02X%02X%02X\n", versionInfo->Reserved[0], + versionInfo->Reserved[1], versionInfo->Reserved[2]); + printf("\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent); } /** diff --git a/winpr/sspi/NTLM/ntlm_compute.h b/winpr/sspi/NTLM/ntlm_compute.h index 3555f1aa9..7fa5b7094 100644 --- a/winpr/sspi/NTLM/ntlm_compute.h +++ b/winpr/sspi/NTLM/ntlm_compute.h @@ -25,7 +25,9 @@ #include "ntlm_av_pairs.h" void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo); +void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo); void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo); +void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo); void ntlm_output_restriction_encoding(NTLM_CONTEXT* context); void ntlm_output_target_name(NTLM_CONTEXT* context); diff --git a/winpr/sspi/NTLM/ntlm_message.c b/winpr/sspi/NTLM/ntlm_message.c index bae8d1774..3964b5d06 100644 --- a/winpr/sspi/NTLM/ntlm_message.c +++ b/winpr/sspi/NTLM/ntlm_message.c @@ -187,6 +187,15 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ + if (!((message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE))) + { + PStreamFreeDetach(s); + return SEC_E_INVALID_TOKEN; + } + context->NegotiateFlags = message.NegotiateFlags; /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ @@ -202,7 +211,7 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) { /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ - StreamSeek(s, 8); /* Version (8 bytes) */ + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ } length = StreamSize(s); @@ -322,7 +331,7 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { - BYTE* p; + PBYTE p; PStream s; int length; PBYTE StartOffset; @@ -334,6 +343,8 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); + StartOffset = StreamGetPointer(s); + ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) &message); if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE)) @@ -342,60 +353,38 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf return SEC_E_INVALID_TOKEN; } - StartOffset = StreamGetPointer(s) - 12; - /* TargetNameFields (8 bytes) */ ntlm_read_message_fields(s, &(message.TargetName)); StreamRead_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ -#ifdef WITH_DEBUG_NTLM - ntlm_print_negotiate_flags(context->NegotiateFlags); -#endif + StreamRead(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */ + CopyMemory(context->ServerChallenge, message.ServerChallenge, 8); - StreamRead(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */ - StreamSeek(s, 8); /* Reserved (8 bytes), should be ignored */ + StreamRead(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */ /* TargetInfoFields (8 bytes) */ ntlm_read_message_fields(s, &(message.TargetInfo)); - /* only present if NTLMSSP_NEGOTIATE_VERSION is set */ - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - StreamSeek(s, 8); /* Version (8 bytes), can be ignored */ - } + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ /* Payload (variable) */ PayloadOffset = StreamGetPointer(s); if (message.TargetName.Len > 0) - { - p = StartOffset + message.TargetName.BufferOffset; - sspi_SecBufferAlloc(&context->TargetName, message.TargetName.Len); - CopyMemory(context->TargetName.pvBuffer, p, message.TargetName.Len); - -#ifdef WITH_DEBUG_NTLM - printf("TargetName (length = %d, offset = %d)\n", message.TargetName.Len, message.TargetName.BufferOffset); - winpr_HexDump(context->TargetName.pvBuffer, context->TargetName.cbBuffer); - printf("\n"); -#endif - } + ntlm_read_message_fields_buffer(s, &(message.TargetName)); if (message.TargetInfo.Len > 0) { - p = StartOffset + message.TargetInfo.BufferOffset; - sspi_SecBufferAlloc(&context->TargetInfo, message.TargetInfo.Len); - CopyMemory(context->TargetInfo.pvBuffer, p, message.TargetInfo.Len); + ntlm_read_message_fields_buffer(s, &(message.TargetInfo)); -#ifdef WITH_DEBUG_NTLM - printf("TargetInfo (length = %d, offset = %d)\n", message.TargetInfo.Len, message.TargetInfo.BufferOffset); - winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); - printf("\n"); -#endif + context->TargetInfo.pvBuffer = message.TargetInfo.Buffer; + context->TargetInfo.cbBuffer = message.TargetInfo.Len; if (context->ntlm_v2) { + p = StartOffset + message.TargetInfo.BufferOffset; StreamSetPointer(s, p); ntlm_input_av_pairs(context, s); } @@ -410,6 +399,14 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf printf("CHALLENGE_MESSAGE (length = %d)\n", length); winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); printf("\n"); + + ntlm_print_negotiate_flags(context->NegotiateFlags); + + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.TargetName), "TargetName"); + ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo"); #endif /* AV_PAIRs */ @@ -508,6 +505,12 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu UINT32 PayloadOffset; NTLM_CHALLENGE_MESSAGE message; + ZeroMemory(&message, sizeof(message)); + s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); + + /* Version */ + ntlm_get_version_info(&(message.Version)); + /* Server Challenge */ ntlm_generate_server_challenge(context); @@ -515,10 +518,10 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu ntlm_generate_timestamp(context); /* TargetInfo */ - ntlm_populate_server_av_pairs(context); + ntlm_construct_server_target_info(context); - ZeroMemory(&message, sizeof(message)); - s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); + /* ServerChallenge */ + CopyMemory(message.ServerChallenge, context->ServerChallenge, 8); ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE); @@ -530,11 +533,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu message.TargetName.Len = (UINT16) context->TargetName.cbBuffer; message.TargetName.Buffer = context->TargetName.pvBuffer; } - else - { - message.TargetName.Len = 0; - message.TargetName.Buffer = NULL; - } context->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; @@ -543,11 +541,6 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu message.TargetInfo.Len = (UINT16) context->TargetInfo.cbBuffer; message.TargetInfo.Buffer = context->TargetInfo.pvBuffer; } - else - { - message.TargetInfo.Len = 0; - message.TargetInfo.Buffer = NULL; - } PayloadOffset = 48; @@ -562,41 +555,22 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu StreamWrite_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ - StreamWrite(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */ - StreamZero(s, 8); /* Reserved (8 bytes), should be ignored */ + StreamWrite(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */ + StreamWrite(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */ /* TargetInfoFields (8 bytes) */ ntlm_write_message_fields(s, &(message.TargetInfo)); - /* only present if NTLMSSP_NEGOTIATE_VERSION is set */ - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - ntlm_get_version_info(&(message.Version)); - ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes), can be ignored */ - } + ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes) */ /* Payload (variable) */ - if (message.TargetName.Len > 0) - { - StreamWrite(s, message.TargetName.Buffer, message.TargetName.Len); -#ifdef WITH_DEBUG_NTLM - printf("TargetName (length = %d, offset = %d)\n", message.TargetName.Len, message.TargetName.BufferOffset); - winpr_HexDump(message.TargetName.Buffer, message.TargetName.Len); - printf("\n"); -#endif - } + if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET) + ntlm_write_message_fields_buffer(s, &(message.TargetName)); - if (message.TargetInfo.Len > 0) - { - StreamWrite(s, message.TargetInfo.Buffer, message.TargetInfo.Len); -#ifdef WITH_DEBUG_NTLM - printf("TargetInfo (length = %d, offset = %d)\n", message.TargetInfo.Len, message.TargetInfo.BufferOffset); - winpr_HexDump(message.TargetInfo.Buffer, message.TargetInfo.Len); - printf("\n"); -#endif - } + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) + ntlm_write_message_fields_buffer(s, &(message.TargetInfo)); length = StreamSize(s); buffer->cbBuffer = length; @@ -608,6 +582,12 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu printf("CHALLENGE_MESSAGE (length = %d)\n", length); winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); printf("\n"); + + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.TargetName), "TargetName"); + ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo"); #endif context->state = NTLM_STATE_AUTHENTICATE; @@ -659,57 +639,25 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ - -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump(s->p, 8); - printf("\n"); -#endif - - StreamSeek(s, 8); /* Version (8 bytes) */ - } + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ length = StreamSize(s); sspi_SecBufferAlloc(&context->AuthenticateMessage, length); CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length); buffer->cbBuffer = length; -#ifdef WITH_DEBUG_NTLM - printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); - winpr_HexDump(s->data, length); - printf("\n"); -#endif - /* DomainName */ ntlm_read_message_fields_buffer(s, &(message.DomainName)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.DomainName), "DomainName"); -#endif - /* UserName */ ntlm_read_message_fields_buffer(s, &(message.UserName)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.UserName), "UserName"); -#endif - /* Workstation */ ntlm_read_message_fields_buffer(s, &(message.Workstation)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.Workstation), "Workstation"); -#endif - /* LmChallengeResponse */ ntlm_read_message_fields_buffer(s, &(message.LmChallengeResponse)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); -#endif - /* NtChallengeResponse */ ntlm_read_message_fields_buffer(s, &(message.NtChallengeResponse)); @@ -720,15 +668,23 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer CopyMemory(context->ClientChallenge, ClientChallengeBuffer, 8); } -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); -#endif - /* EncryptedRandomSessionKey */ ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16); #ifdef WITH_DEBUG_NTLM + printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); + winpr_HexDump(s->data, length); + printf("\n"); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.DomainName), "DomainName"); + ntlm_print_message_fields(&(message.UserName), "UserName"); + ntlm_print_message_fields(&(message.Workstation), "Workstation"); + ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); + ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey"); #endif @@ -941,21 +897,9 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ -#ifdef WITH_DEBUG_NTLM - ntlm_print_negotiate_flags(message.NegotiateFlags); -#endif - if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { ntlm_write_version_info(s, &(message.Version)); -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump((s->p - 8), 8); - printf("\n"); -#endif - } - if (context->ntlm_v2) { /* Message Integrity Check */ @@ -966,56 +910,21 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer /* DomainName */ ntlm_write_message_fields_buffer(s, &(message.DomainName)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.DomainName), "DomainName"); -#endif - /* UserName */ ntlm_write_message_fields_buffer(s, &(message.UserName)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.UserName), "UserName"); -#endif - /* Workstation */ ntlm_write_message_fields_buffer(s, &(message.Workstation)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.Workstation), "Workstation"); -#endif - /* LmChallengeResponse */ ntlm_write_message_fields_buffer(s, &(message.LmChallengeResponse)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); -#endif - /* NtChallengeResponse */ ntlm_write_message_fields_buffer(s, &(message.NtChallengeResponse)); -#ifdef WITH_DEBUG_NTLM - if (context->ntlm_v2) - { - ntlm_print_av_pairs(context); - - printf("targetInfo (length = %d)\n", (int) context->TargetInfo.cbBuffer); - winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); - printf("\n"); - } -#endif - -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); -#endif - /* EncryptedRandomSessionKey */ ntlm_write_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); -#ifdef WITH_DEBUG_NTLM - ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey"); -#endif - length = StreamSize(s); sspi_SecBufferAlloc(&context->AuthenticateMessage, length); CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length); @@ -1029,18 +938,40 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer s->p = MicOffset; StreamWrite(s, context->MessageIntegrityCheck, 16); s->p = s->data + length; - -#ifdef WITH_DEBUG_NTLM - printf("MessageIntegrityCheck (length = 16)\n"); - winpr_HexDump(MicOffset, 16); - printf("\n"); -#endif } #ifdef WITH_DEBUG_NTLM printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); winpr_HexDump(s->data, length); printf("\n"); + + ntlm_print_negotiate_flags(message.NegotiateFlags); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.DomainName), "DomainName"); + ntlm_print_message_fields(&(message.UserName), "UserName"); + ntlm_print_message_fields(&(message.Workstation), "Workstation"); + ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); + ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); + ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey"); + + if (context->ntlm_v2) + { + ntlm_print_av_pairs(context); + + printf("targetInfo (length = %d)\n", (int) context->TargetInfo.cbBuffer); + winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); + printf("\n"); + } + + if (context->ntlm_v2) + { + printf("MessageIntegrityCheck (length = 16)\n"); + winpr_HexDump(MicOffset, 16); + printf("\n"); + } #endif context->state = NTLM_STATE_FINAL;