libwinpr-sspi: get rid of old AV_PAIR code for NTLM

This commit is contained in:
Marc-André Moreau 2012-07-01 21:40:33 -04:00
parent 6d7f1e427c
commit 693b1787b7
6 changed files with 202 additions and 535 deletions

View File

@ -47,10 +47,10 @@ void ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
GetComputerNameExA(ComputerNameNetBIOS, Workstation, &nSize);
}
context->WorkstationLength = strlen(Workstation) * 2;
context->Workstation = (UINT16*) malloc(context->WorkstationLength);
context->Workstation.Length = strlen(Workstation) * 2;
context->Workstation.Buffer = (PWSTR) malloc(context->Workstation.Length);
MultiByteToWideChar(CP_ACP, 0, Workstation, strlen(Workstation),
(LPWSTR) context->Workstation, context->WorkstationLength / 2);
context->Workstation.Buffer, context->Workstation.Length / 2);
if (nSize > 0)
free(Workstation);
@ -86,14 +86,16 @@ NTLM_CONTEXT* ntlm_ContextNew()
if (context != NULL)
{
context->ntlm_v2 = FALSE;
context->NTLMv2 = TRUE;
context->UseMIC = FALSE;
context->NegotiateFlags = 0;
context->SendVersionInfo = TRUE;
context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL;
context->SuppressExtendedProtection = TRUE;
context->av_pairs = (AV_PAIRS*) malloc(sizeof(AV_PAIRS));
ZeroMemory(context->av_pairs, sizeof(AV_PAIRS));
if (context->NTLMv2)
context->UseMIC = TRUE;
}
return context;
@ -107,7 +109,7 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
sspi_SecBufferFree(&context->NegotiateMessage);
sspi_SecBufferFree(&context->ChallengeMessage);
sspi_SecBufferFree(&context->AuthenticateMessage);
sspi_SecBufferFree(&context->TargetInfo);
sspi_SecBufferFree(&context->ChallengeTargetInfo);
sspi_SecBufferFree(&context->TargetName);
sspi_SecBufferFree(&context->NtChallengeResponse);
sspi_SecBufferFree(&context->LmChallengeResponse);
@ -115,9 +117,7 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
free(context->identity.User);
free(context->identity.Password);
free(context->identity.Domain);
free(context->Workstation);
free(context->av_pairs->Timestamp.value);
free(context->av_pairs);
free(context->Workstation.Buffer);
free(context);
}

View File

@ -81,36 +81,7 @@ 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;
BYTE* value;
};
typedef struct _AV_PAIR AV_PAIR;
struct _AV_PAIRS
{
AV_PAIR NbComputerName;
AV_PAIR NbDomainName;
AV_PAIR DnsComputerName;
AV_PAIR DnsDomainName;
AV_PAIR DnsTreeName;
AV_PAIR Timestamp;
AV_PAIR Restrictions;
AV_PAIR TargetName;
AV_PAIR ChannelBindings;
UINT32 Flags;
};
typedef struct _AV_PAIRS AV_PAIRS;
enum _AV_ID
enum _NTLM_AV_ID
{
MsvAvEOL,
MsvAvNbComputerName,
@ -124,7 +95,14 @@ enum _AV_ID
MsvAvTargetName,
MsvChannelBindings
};
typedef enum _AV_ID AV_ID;
typedef enum _NTLM_AV_ID NTLM_AV_ID;
struct _NTLM_AV_PAIR
{
UINT16 AvId;
UINT16 AvLen;
};
typedef struct _NTLM_AV_PAIR NTLM_AV_PAIR;
#define MSV_AV_FLAGS_AUTHENTICATION_CONSTRAINED 0x00000001
#define MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK 0x00000002
@ -242,7 +220,8 @@ typedef struct _NTLM_AUTHENTICATE_MESSAGE NTLM_AUTHENTICATE_MESSAGE;
struct _NTLM_CONTEXT
{
BOOL server;
BOOL ntlm_v2;
BOOL NTLMv2;
BOOL UseMIC;
NTLM_STATE state;
int SendSeqNum;
int RecvSeqNum;
@ -254,21 +233,21 @@ struct _NTLM_CONTEXT
BYTE* RecvSigningKey;
BYTE* SendSealingKey;
BYTE* RecvSealingKey;
AV_PAIRS* av_pairs;
UINT32 NegotiateFlags;
UINT16* Workstation;
UINT32 WorkstationLength;
int LmCompatibilityLevel;
int SuppressExtendedProtection;
UNICODE_STRING Workstation;
SEC_WINNT_AUTH_IDENTITY identity;
SecBuffer NegotiateMessage;
SecBuffer ChallengeMessage;
SecBuffer AuthenticateMessage;
SecBuffer TargetInfo;
SecBuffer ChallengeTargetInfo;
SecBuffer AuthenticateTargetInfo;
SecBuffer TargetName;
SecBuffer NtChallengeResponse;
SecBuffer LmChallengeResponse;
BYTE Timestamp[8];
BYTE ChallengeTimestamp[8];
BYTE ServerChallenge[8];
BYTE ClientChallenge[8];
BYTE SessionBaseKey[16];

View File

@ -113,7 +113,7 @@ 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)
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
@ -134,7 +134,7 @@ NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, AV_ID AvId)
return NULL;
}
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize)
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen)
{
NTLM_AV_PAIR* pAvPair;
@ -144,290 +144,29 @@ NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_S
return NULL;
pAvPair->AvId = AvId;
pAvPair->AvLen = pValue->Length;
pAvPair->AvLen = AvLen;
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), pValue->Buffer, pValue->Length);
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), Value, AvLen);
return pAvPair;
}
/**
* Input array of AV_PAIRs.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
* @param s
*/
void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s)
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair)
{
AV_ID AvId;
UINT16 AvLen;
BYTE* value;
AV_PAIRS* av_pairs = context->av_pairs;
NTLM_AV_PAIR* pAvPairCopy;
#ifdef WITH_DEBUG_NTLM
printf("AV_PAIRS = {\n");
#endif
pAvPairCopy = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
do
{
value = NULL;
StreamRead_UINT16(s, AvId);
StreamRead_UINT16(s, AvLen);
if (!pAvPairCopy)
return NULL;
if (AvLen > 0)
{
if (AvId != MsvAvFlags)
{
value = malloc(AvLen);
StreamRead(s, value, AvLen);
}
else
{
StreamRead_UINT32(s, av_pairs->Flags);
}
}
pAvPairCopy->AvId = pAvPair->AvId;
pAvPairCopy->AvLen = pAvPair->AvLen;
switch (AvId)
{
case MsvAvNbComputerName:
av_pairs->NbComputerName.length = AvLen;
av_pairs->NbComputerName.value = value;
break;
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy),
ntlm_av_pair_get_value_pointer(pAvPair), pAvPair->AvLen);
case MsvAvNbDomainName:
av_pairs->NbDomainName.length = AvLen;
av_pairs->NbDomainName.value = value;
break;
case MsvAvDnsComputerName:
av_pairs->DnsComputerName.length = AvLen;
av_pairs->DnsComputerName.value = value;
break;
case MsvAvDnsDomainName:
av_pairs->DnsDomainName.length = AvLen;
av_pairs->DnsDomainName.value = value;
break;
case MsvAvDnsTreeName:
av_pairs->DnsTreeName.length = AvLen;
av_pairs->DnsTreeName.value = value;
break;
case MsvAvTimestamp:
av_pairs->Timestamp.length = AvLen;
av_pairs->Timestamp.value = value;
break;
case MsvAvRestrictions:
av_pairs->Restrictions.length = AvLen;
av_pairs->Restrictions.value = value;
break;
case MsvAvTargetName:
av_pairs->TargetName.length = AvLen;
av_pairs->TargetName.value = value;
break;
case MsvChannelBindings:
av_pairs->ChannelBindings.length = AvLen;
av_pairs->ChannelBindings.value = value;
break;
default:
if (value != NULL)
free(value);
break;
}
#ifdef WITH_DEBUG_NTLM
if (AvId < 10)
printf("\tAvId: %s, AvLen: %d\n", AV_PAIR_STRINGS[AvId], AvLen);
else
printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen);
winpr_HexDump(value, AvLen);
#endif
}
while (AvId != MsvAvEOL);
#ifdef WITH_DEBUG_NTLM
printf("}\n");
#endif
}
/**
* Output array of AV_PAIRs.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
* @param s
*/
void ntlm_output_av_pairs(NTLM_CONTEXT* context, PSecBuffer buffer)
{
PStream s;
AV_PAIRS* av_pairs = context->av_pairs;
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
if (av_pairs->NbDomainName.length > 0)
{
StreamWrite_UINT16(s, MsvAvNbDomainName); /* AvId */
StreamWrite_UINT16(s, av_pairs->NbDomainName.length); /* AvLen */
StreamWrite(s, av_pairs->NbDomainName.value, av_pairs->NbDomainName.length); /* Value */
}
if (av_pairs->NbComputerName.length > 0)
{
StreamWrite_UINT16(s, MsvAvNbComputerName); /* AvId */
StreamWrite_UINT16(s, av_pairs->NbComputerName.length); /* AvLen */
StreamWrite(s, av_pairs->NbComputerName.value, av_pairs->NbComputerName.length); /* Value */
}
if (av_pairs->DnsDomainName.length > 0)
{
StreamWrite_UINT16(s, MsvAvDnsDomainName); /* AvId */
StreamWrite_UINT16(s, av_pairs->DnsDomainName.length); /* AvLen */
StreamWrite(s, av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length); /* Value */
}
if (av_pairs->DnsComputerName.length > 0)
{
StreamWrite_UINT16(s, MsvAvDnsComputerName); /* AvId */
StreamWrite_UINT16(s, av_pairs->DnsComputerName.length); /* AvLen */
StreamWrite(s, av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length); /* Value */
}
if (av_pairs->DnsTreeName.length > 0)
{
StreamWrite_UINT16(s, MsvAvDnsTreeName); /* AvId */
StreamWrite_UINT16(s, av_pairs->DnsTreeName.length); /* AvLen */
StreamWrite(s, av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length); /* Value */
}
if (av_pairs->Timestamp.length > 0)
{
StreamWrite_UINT16(s, MsvAvTimestamp); /* AvId */
StreamWrite_UINT16(s, av_pairs->Timestamp.length); /* AvLen */
StreamWrite(s, av_pairs->Timestamp.value, av_pairs->Timestamp.length); /* Value */
}
if (av_pairs->Flags > 0)
{
StreamWrite_UINT16(s, MsvAvFlags); /* AvId */
StreamWrite_UINT16(s, 4); /* AvLen */
StreamWrite_UINT32(s, av_pairs->Flags); /* Value */
}
if (av_pairs->Restrictions.length > 0)
{
StreamWrite_UINT16(s, MsvAvRestrictions); /* AvId */
StreamWrite_UINT16(s, av_pairs->Restrictions.length); /* AvLen */
StreamWrite(s, av_pairs->Restrictions.value, av_pairs->Restrictions.length); /* Value */
}
if (av_pairs->ChannelBindings.length > 0)
{
StreamWrite_UINT16(s, MsvChannelBindings); /* AvId */
StreamWrite_UINT16(s, av_pairs->ChannelBindings.length); /* AvLen */
StreamWrite(s, av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length); /* Value */
}
if (av_pairs->TargetName.length > 0)
{
StreamWrite_UINT16(s, MsvAvTargetName); /* AvId */
StreamWrite_UINT16(s, av_pairs->TargetName.length); /* AvLen */
StreamWrite(s, av_pairs->TargetName.value, av_pairs->TargetName.length); /* Value */
}
/* This indicates the end of the AV_PAIR array */
StreamWrite_UINT16(s, MsvAvEOL); /* AvId */
StreamWrite_UINT16(s, 0); /* AvLen */
if (context->ntlm_v2)
{
StreamZero(s, 8);
}
free(s);
}
/**
* Compute AV_PAIRs length.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
*/
int ntlm_compute_av_pairs_length(NTLM_CONTEXT* context)
{
int length = 0;
AV_PAIRS* av_pairs = context->av_pairs;
if (av_pairs->NbDomainName.length > 0)
length += av_pairs->NbDomainName.length + 4;
if (av_pairs->NbComputerName.length > 0)
length += av_pairs->NbComputerName.length + 4;
if (av_pairs->DnsDomainName.length > 0)
length += av_pairs->DnsDomainName.length + 4;
if (av_pairs->DnsComputerName.length > 0)
length += av_pairs->DnsComputerName.length + 4;
if (av_pairs->DnsTreeName.length > 0)
length += av_pairs->DnsTreeName.length + 4;
if (av_pairs->Timestamp.length > 0)
length += av_pairs->Timestamp.length;
if (av_pairs->Flags > 0)
length += 4 + 4;
if (av_pairs->Restrictions.length > 0)
length += av_pairs->Restrictions.length + 4;
if (av_pairs->ChannelBindings.length > 0)
length += av_pairs->ChannelBindings.length + 4;
if (av_pairs->TargetName.length > 0)
length += av_pairs->TargetName.length + 4;
length += 4;
if (context->ntlm_v2)
length += 8;
return length;
}
/**
* Populate array of AV_PAIRs.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
*/
void ntlm_populate_av_pairs(NTLM_CONTEXT* context)
{
int length;
AV_PAIRS* av_pairs = context->av_pairs;
/* MsvAvFlags */
av_pairs->Flags = 0x00000002; /* Indicates the present of a Message Integrity Check (MIC) */
/* Restriction_Encoding */
ntlm_output_restriction_encoding(context);
/* TargetName */
ntlm_output_target_name(context);
/* ChannelBindings */
ntlm_output_channel_bindings(context);
length = ntlm_compute_av_pairs_length(context);
sspi_SecBufferAlloc(&context->TargetInfo, length);
ntlm_output_av_pairs(context, &context->TargetInfo);
return pAvPairCopy;
}
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
@ -452,7 +191,7 @@ void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT t
free(name);
}
void ntlm_construct_server_target_info(NTLM_CONTEXT* context)
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
{
int length;
ULONG AvPairsCount;
@ -463,142 +202,132 @@ void ntlm_construct_server_target_info(NTLM_CONTEXT* context)
UNICODE_STRING NbComputerName;
UNICODE_STRING DnsDomainName;
UNICODE_STRING DnsComputerName;
UNICODE_STRING Timestamp;
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);
Timestamp.Buffer = (PWSTR) context->Timestamp;
Timestamp.Length = sizeof(context->Timestamp);
AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
DnsDomainName.Length + DnsComputerName.Length + 8;
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
sspi_SecBufferAlloc(&context->TargetInfo, length);
sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length);
pAvPairList = (NTLM_AV_PAIR*) context->TargetInfo.pvBuffer;
AvPairListSize = (ULONG) context->TargetInfo.cbBuffer;
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
AvPairListSize = (ULONG) context->ChallengeTargetInfo.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);
ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer, NbDomainName.Length);
ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, (PBYTE) NbComputerName.Buffer, NbComputerName.Length);
ntlm_av_pair_add(pAvPairList, MsvAvDnsDomainName, (PBYTE) DnsDomainName.Buffer, DnsDomainName.Length);
ntlm_av_pair_add(pAvPairList, MsvAvDnsComputerName, (PBYTE) DnsComputerName.Buffer, DnsComputerName.Length);
ntlm_av_pair_add(pAvPairList, MsvAvTimestamp, context->Timestamp, sizeof(context->Timestamp));
}
/**
* Print array of AV_PAIRs.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
*/
void ntlm_print_av_pairs(NTLM_CONTEXT* context)
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
{
AV_PAIRS* av_pairs = context->av_pairs;
ULONG size;
ULONG AvPairsCount;
ULONG AvPairsValueLength;
NTLM_AV_PAIR* AvTimestamp;
NTLM_AV_PAIR* AvNbDomainName;
NTLM_AV_PAIR* AvNbComputerName;
NTLM_AV_PAIR* AvDnsDomainName;
NTLM_AV_PAIR* AvDnsComputerName;
NTLM_AV_PAIR* AvDnsTreeName;
NTLM_AV_PAIR* ChallengeTargetInfo;
NTLM_AV_PAIR* AuthenticateTargetInfo;
printf("AV_PAIRS = {\n");
AvPairsCount = AvPairsValueLength = 0;
ChallengeTargetInfo = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
if (av_pairs->NbDomainName.length > 0)
AvNbDomainName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvNbDomainName);
AvNbComputerName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvNbComputerName);
AvDnsDomainName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsDomainName);
AvDnsComputerName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsComputerName);
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
if (AvNbDomainName != NULL)
{
printf("\tAvId: MsvAvNbDomainName AvLen: %d\n", av_pairs->NbDomainName.length);
winpr_HexDump(av_pairs->NbDomainName.value, av_pairs->NbDomainName.length);
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += AvNbDomainName->AvLen;
}
if (av_pairs->NbComputerName.length > 0)
if (AvNbComputerName != NULL)
{
printf("\tAvId: MsvAvNbComputerName AvLen: %d\n", av_pairs->NbComputerName.length);
winpr_HexDump(av_pairs->NbComputerName.value, av_pairs->NbComputerName.length);
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += AvNbComputerName->AvLen;
}
if (av_pairs->DnsDomainName.length > 0)
if (AvDnsDomainName != NULL)
{
printf("\tAvId: MsvAvDnsDomainName AvLen: %d\n", av_pairs->DnsDomainName.length);
winpr_HexDump(av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length);
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += AvDnsDomainName->AvLen;
}
if (av_pairs->DnsComputerName.length > 0)
if (AvDnsComputerName != NULL)
{
printf("\tAvId: MsvAvDnsComputerName AvLen: %d\n", av_pairs->DnsComputerName.length);
winpr_HexDump(av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length);
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += AvDnsComputerName->AvLen;
}
if (av_pairs->DnsTreeName.length > 0)
if (AvDnsTreeName != NULL)
{
printf("\tAvId: MsvAvDnsTreeName AvLen: %d\n", av_pairs->DnsTreeName.length);
winpr_HexDump(av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length);
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += AvDnsTreeName->AvLen;
}
if (av_pairs->Timestamp.length > 0)
AvPairsCount++; /* MsvAvTimestamp */
AvPairsValueLength += 8;
if (context->UseMIC)
{
printf("\tAvId: MsvAvTimestamp AvLen: %d\n", av_pairs->Timestamp.length);
winpr_HexDump(av_pairs->Timestamp.value, av_pairs->Timestamp.length);
AvPairsCount++; /* MsvAvFlags */
AvPairsValueLength += 4;
}
if (av_pairs->Flags > 0)
size = ntlm_av_pair_list_size(AvPairsCount, AvPairsValueLength);
if (context->NTLMv2)
size += 8; /* unknown 8-byte padding */
sspi_SecBufferAlloc(&context->AuthenticateTargetInfo, size);
AuthenticateTargetInfo = (NTLM_AV_PAIR*) context->AuthenticateTargetInfo.pvBuffer;
ntlm_av_pair_list_init(AuthenticateTargetInfo);
if (AvNbDomainName != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
if (AvNbComputerName != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
if (AvDnsDomainName != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
if (AvDnsComputerName != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
if (AvDnsTreeName != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
if (AvTimestamp != NULL)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
if (context->UseMIC)
{
printf("\tAvId: MsvAvFlags AvLen: %d\n", 4);
printf("0x%08X\n", av_pairs->Flags);
UINT32 flags = MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK;
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvFlags, (PBYTE) &flags, 4);
}
if (av_pairs->Restrictions.length > 0)
if (context->NTLMv2)
{
printf("\tAvId: MsvAvRestrictions AvLen: %d\n", av_pairs->Restrictions.length);
winpr_HexDump(av_pairs->Restrictions.value, av_pairs->Restrictions.length);
}
NTLM_AV_PAIR* AvEOL;
if (av_pairs->ChannelBindings.length > 0)
{
printf("\tAvId: MsvChannelBindings AvLen: %d\n", av_pairs->ChannelBindings.length);
winpr_HexDump(av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length);
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 12);
}
if (av_pairs->TargetName.length > 0)
{
printf("\tAvId: MsvAvTargetName AvLen: %d\n", av_pairs->TargetName.length);
winpr_HexDump(av_pairs->TargetName.value, av_pairs->TargetName.length);
}
printf("}\n");
}
/**
* Free array of AV_PAIRs.\n
* AV_PAIR @msdn{cc236646}
* @param NTLM context
*/
void ntlm_free_av_pairs(NTLM_CONTEXT* context)
{
AV_PAIRS* av_pairs = context->av_pairs;
if (av_pairs != NULL)
{
if (av_pairs->NbComputerName.value != NULL)
free(av_pairs->NbComputerName.value);
if (av_pairs->NbDomainName.value != NULL)
free(av_pairs->NbDomainName.value);
if (av_pairs->DnsComputerName.value != NULL)
free(av_pairs->DnsComputerName.value);
if (av_pairs->DnsDomainName.value != NULL)
free(av_pairs->DnsDomainName.value);
if (av_pairs->DnsTreeName.value != NULL)
free(av_pairs->DnsTreeName.value);
if (av_pairs->Timestamp.value != NULL)
free(av_pairs->Timestamp.value);
if (av_pairs->Restrictions.value != NULL)
free(av_pairs->Restrictions.value);
if (av_pairs->TargetName.value != NULL)
free(av_pairs->TargetName.value);
if (av_pairs->ChannelBindings.value != NULL)
free(av_pairs->ChannelBindings.value);
free(av_pairs);
}
context->av_pairs = NULL;
}

View File

@ -31,16 +31,11 @@ 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);
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, AV_ID AvId, PUNICODE_STRING pValue, LONG AvPairListSize);
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId);
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen);
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair);
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);
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context);
void ntlm_print_av_pairs(NTLM_CONTEXT* context);
void ntlm_free_av_pairs(NTLM_CONTEXT* context);
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */

View File

@ -148,6 +148,8 @@ void ntlm_write_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response)
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
}
#if 0
/**
* Output Restriction_Encoding.\n
* Restriction_Encoding @msdn{cc236647}
@ -230,6 +232,8 @@ void ntlm_output_channel_bindings(NTLM_CONTEXT* context)
PStreamFreeDetach(s);
}
#endif
/**
* Get current time, in tenths of microseconds since midnight of January 1, 1601.
* @param[out] timestamp 64-bit little-endian timestamp
@ -255,33 +259,14 @@ void ntlm_current_time(BYTE* timestamp)
void ntlm_generate_timestamp(NTLM_CONTEXT* context)
{
ntlm_current_time(context->Timestamp);
BYTE ZeroTimestamp[8];
if (context->ntlm_v2)
{
if (context->av_pairs->Timestamp.length == 8)
{
CopyMemory(context->av_pairs->Timestamp.value, context->Timestamp, 8);
return;
}
else
{
context->ntlm_v2 = FALSE;
context->av_pairs->Timestamp.length = 8;
context->av_pairs->Timestamp.value = malloc(context->av_pairs->Timestamp.length);
CopyMemory(context->av_pairs->Timestamp.value, context->Timestamp, 8);
}
}
ZeroMemory(ZeroTimestamp, 8);
if (memcmp(ZeroTimestamp, context->ChallengeTimestamp, 8) != 0)
CopyMemory(context->Timestamp, context->ChallengeTimestamp, 8);
else
{
if (context->av_pairs->Timestamp.length != 8)
{
context->av_pairs->Timestamp.length = 8;
context->av_pairs->Timestamp.value = malloc(context->av_pairs->Timestamp.length);
}
CopyMemory(context->av_pairs->Timestamp.value, context->Timestamp, 8);
}
ntlm_current_time(context->Timestamp);
}
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
@ -368,7 +353,7 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
SecBuffer ntlm_v2_temp;
SecBuffer ntlm_v2_temp_chal;
sspi_SecBufferAlloc(&ntlm_v2_temp, context->TargetInfo.cbBuffer + 28);
sspi_SecBufferAlloc(&ntlm_v2_temp, context->ChallengeTargetInfo.cbBuffer + 28);
ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
blob = (BYTE*) ntlm_v2_temp.pvBuffer;
@ -389,8 +374,8 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
winpr_HexDump((BYTE*) context->identity.Domain, context->identity.DomainLength * 2);
printf("\n");
printf("Workstation (length = %d)\n", context->WorkstationLength);
winpr_HexDump((BYTE*) context->Workstation, context->WorkstationLength);
printf("Workstation (length = %d)\n", context->Workstation.Length);
winpr_HexDump((BYTE*) context->Workstation.Buffer, context->Workstation.Length);
printf("\n");
printf("NTOWFv2, NTLMv2 Hash\n");
@ -403,10 +388,10 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
blob[1] = 1; /* HighRespType (1 byte) */
/* Reserved1 (2 bytes) */
/* Reserved2 (4 bytes) */
CopyMemory(&blob[8], context->av_pairs->Timestamp.value, 8); /* Timestamp (8 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->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
CopyMemory(&blob[28], context->ChallengeTargetInfo.pvBuffer, context->ChallengeTargetInfo.cbBuffer);
#ifdef WITH_DEBUG_NTLM
printf("NTLMv2 Response Temp Blob\n");

View File

@ -247,33 +247,23 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_NEGOTIATE);
if (context->ntlm_v2)
if (context->NTLMv2)
{
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
}
else
{
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
}
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_get_version_info(&(message.Version));
@ -328,11 +318,11 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
{
PBYTE p;
PStream s;
int length;
PBYTE StartOffset;
PBYTE PayloadOffset;
NTLM_AV_PAIR* AvTimestamp;
NTLM_CHALLENGE_MESSAGE message;
ntlm_generate_client_challenge(context);
@ -377,14 +367,17 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
{
ntlm_read_message_fields_buffer(s, &(message.TargetInfo));
context->TargetInfo.pvBuffer = message.TargetInfo.Buffer;
context->TargetInfo.cbBuffer = message.TargetInfo.Len;
context->ChallengeTargetInfo.pvBuffer = message.TargetInfo.Buffer;
context->ChallengeTargetInfo.cbBuffer = message.TargetInfo.Len;
if (context->ntlm_v2)
AvTimestamp = ntlm_av_pair_get((NTLM_AV_PAIR*) message.TargetInfo.Buffer, MsvAvTimestamp);
if (AvTimestamp != NULL)
{
p = StartOffset + message.TargetInfo.BufferOffset;
StreamSetPointer(s, p);
ntlm_input_av_pairs(context, s);
if (context->NTLMv2)
context->UseMIC = TRUE;
CopyMemory(context->ChallengeTimestamp, ntlm_av_pair_get_value_pointer(AvTimestamp), 8);
}
}
@ -408,8 +401,12 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
#endif
/* AV_PAIRs */
if (context->ntlm_v2)
ntlm_populate_av_pairs(context);
if (context->NTLMv2)
{
ntlm_construct_authenticate_target_info(context);
context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer;
context->ChallengeTargetInfo.cbBuffer = context->AuthenticateTargetInfo.cbBuffer;
}
/* Timestamp */
ntlm_generate_timestamp(context);
@ -516,7 +513,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
ntlm_generate_timestamp(context);
/* TargetInfo */
ntlm_construct_server_target_info(context);
ntlm_construct_challenge_target_info(context);
/* ServerChallenge */
CopyMemory(message.ServerChallenge, context->ServerChallenge, 8);
@ -538,8 +535,8 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
{
message.TargetInfo.Len = (UINT16) context->TargetInfo.cbBuffer;
message.TargetInfo.Buffer = context->TargetInfo.pvBuffer;
message.TargetInfo.Len = (UINT16) context->ChallengeTargetInfo.cbBuffer;
message.TargetInfo.Buffer = context->ChallengeTargetInfo.pvBuffer;
}
PayloadOffset = 48;
@ -678,8 +675,8 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
context->NtChallengeResponse.pvBuffer = message.NtChallengeResponse.Buffer;
context->NtChallengeResponse.cbBuffer = message.NtChallengeResponse.Len;
context->TargetInfo.pvBuffer = (void*) response.Challenge.AvPairs;
context->TargetInfo.cbBuffer = message.NtChallengeResponse.Len - (28 + 16);
context->ChallengeTargetInfo.pvBuffer = (void*) response.Challenge.AvPairs;
context->ChallengeTargetInfo.cbBuffer = message.NtChallengeResponse.Len - (28 + 16);
CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8);
@ -775,7 +772,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
printf("Actual MIC:\n");
winpr_HexDump(message.MessageIntegrityCheck, 16);
//return SEC_E_MESSAGE_ALTERED;
return SEC_E_MESSAGE_ALTERED;
}
}
@ -854,47 +851,38 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
{
PStream s;
int length;
BYTE* MicOffset = NULL;
UINT32 MicOffset = 0;
UINT32 PayloadBufferOffset;
NTLM_AUTHENTICATE_MESSAGE message;
ZeroMemory(&message, sizeof(message));
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
if (context->ntlm_v2)
if (context->NTLMv2)
{
/* observed: 35 82 88 e2 (0xE2888235) */
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
}
if (context->UseMIC)
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
}
else
{
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
}
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_get_version_info(&(message.Version));
message.Workstation.Len = context->WorkstationLength;
message.Workstation.Buffer = (BYTE*) context->Workstation;
message.Workstation.Len = context->Workstation.Length;
message.Workstation.Buffer = (BYTE*) context->Workstation.Buffer;
if (context->ntlm_v2 < 1)
if (!context->NTLMv2)
message.Workstation.Len = 0;
if (message.Workstation.Len > 0)
@ -923,7 +911,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
PayloadBufferOffset = 64;
if (context->ntlm_v2)
if (context->UseMIC)
PayloadBufferOffset += 16; /* Message Integrity Check */
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
@ -968,10 +956,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_write_version_info(s, &(message.Version));
if (context->ntlm_v2)
if (context->UseMIC)
{
/* Message Integrity Check */
MicOffset = s->p;
MicOffset = StreamGetOffset(s);
StreamZero(s, 16);
}
@ -998,14 +986,14 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
buffer->cbBuffer = length;
if (context->ntlm_v2)
if (context->UseMIC)
{
/* Message Integrity Check */
ntlm_compute_message_integrity_check(context);
s->p = MicOffset;
StreamSetOffset(s, MicOffset);
StreamWrite(s, context->MessageIntegrityCheck, 16);
s->p = s->data + length;
StreamSetOffset(s, length);
}
#ifdef WITH_DEBUG_NTLM
@ -1025,19 +1013,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
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)
if (context->UseMIC)
{
printf("MessageIntegrityCheck (length = 16)\n");
winpr_HexDump(MicOffset, 16);
winpr_HexDump(context->MessageIntegrityCheck, 16);
printf("\n");
}
#endif