libwinpr-sspi: get partial server-side NLA functionality with mstsc.exe as a client

This commit is contained in:
Marc-André Moreau 2012-07-01 19:43:13 -04:00
parent bf559e37eb
commit 6d7f1e427c
4 changed files with 66 additions and 22 deletions

View File

@ -537,6 +537,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
status = SEC_I_CONTINUE_NEEDED; status = SEC_I_CONTINUE_NEEDED;
} }
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
printf("AcceptSecurityContext status: 0x%08X\n", status);
return -1;
}
/* send authentication token */ /* send authentication token */
#ifdef WITH_DEBUG_CREDSSP #ifdef WITH_DEBUG_CREDSSP

View File

@ -86,12 +86,12 @@ NTLM_CONTEXT* ntlm_ContextNew()
if (context != NULL) if (context != NULL)
{ {
context->ntlm_v2 = TRUE; context->ntlm_v2 = FALSE;
context->NegotiateFlags = 0; context->NegotiateFlags = 0;
context->SendVersionInfo = TRUE; context->SendVersionInfo = TRUE;
context->LmCompatibilityLevel = 3; context->LmCompatibilityLevel = 3;
context->state = NTLM_STATE_INITIAL; context->state = NTLM_STATE_INITIAL;
context->SuppressExtendedProtection = 1; context->SuppressExtendedProtection = TRUE;
context->av_pairs = (AV_PAIRS*) malloc(sizeof(AV_PAIRS)); context->av_pairs = (AV_PAIRS*) malloc(sizeof(AV_PAIRS));
ZeroMemory(context->av_pairs, sizeof(AV_PAIRS)); ZeroMemory(context->av_pairs, sizeof(AV_PAIRS));
} }

View File

@ -147,6 +147,16 @@ struct _NTLM_VERSION_INFO
}; };
typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO; typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO;
struct _NTLM_RESTRICTION_ENCODING
{
UINT32 Size;
UINT32 Z4;
UINT32 IntegrityLevel;
UINT32 SubjectIntegrityLevel;
BYTE MachineId[32];
};
typedef struct _NTLM_RESTRICTION_ENCODING NTLM_RESTRICTION_ENCODING;
struct _NTLM_RESPONSE struct _NTLM_RESPONSE
{ {
BYTE Response[24]; BYTE Response[24];
@ -236,7 +246,7 @@ struct _NTLM_CONTEXT
NTLM_STATE state; NTLM_STATE state;
int SendSeqNum; int SendSeqNum;
int RecvSeqNum; int RecvSeqNum;
int SendVersionInfo; BOOL SendVersionInfo;
BOOL confidentiality; BOOL confidentiality;
RC4_KEY SendRc4Seal; RC4_KEY SendRc4Seal;
RC4_KEY RecvRc4Seal; RC4_KEY RecvRc4Seal;

View File

@ -219,8 +219,8 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
context->NegotiateMessage.BufferType = buffer->BufferType; context->NegotiateMessage.BufferType = buffer->BufferType;
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("NEGOTIATE_MESSAGE (length = %d)\n", length); printf("NEGOTIATE_MESSAGE (length = %d)\n", (int) context->NegotiateMessage.cbBuffer);
winpr_HexDump(s->data, length); winpr_HexDump(context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
printf("\n"); printf("\n");
ntlm_print_negotiate_flags(message.NegotiateFlags); ntlm_print_negotiate_flags(message.NegotiateFlags);
@ -353,7 +353,8 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
/* TargetNameFields (8 bytes) */ /* TargetNameFields (8 bytes) */
ntlm_read_message_fields(s, &(message.TargetName)); ntlm_read_message_fields(s, &(message.TargetName));
StreamRead_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */
context->NegotiateFlags = message.NegotiateFlags;
StreamRead(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */ StreamRead(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */
CopyMemory(context->ServerChallenge, message.ServerChallenge, 8); CopyMemory(context->ServerChallenge, message.ServerChallenge, 8);
@ -602,11 +603,17 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
{ {
PStream s; PStream s;
int length; int length;
UINT32 flags = 0; UINT32 flags;
UINT32 MicOffset;
NTLM_AV_PAIR* AvFlags;
NTLMv2_RESPONSE response; NTLMv2_RESPONSE response;
UINT32 PayloadBufferOffset; UINT32 PayloadBufferOffset;
NTLM_AUTHENTICATE_MESSAGE message; NTLM_AUTHENTICATE_MESSAGE message;
flags = 0;
MicOffset = 0;
AvFlags = NULL;
ZeroMemory(&message, sizeof(message)); ZeroMemory(&message, sizeof(message));
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
@ -664,12 +671,16 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (message.NtChallengeResponse.Len > 0) if (message.NtChallengeResponse.Len > 0)
{ {
NTLM_AV_PAIR* AvFlags;
PStream s = PStreamAllocAttach(message.NtChallengeResponse.Buffer, message.NtChallengeResponse.Len); PStream s = PStreamAllocAttach(message.NtChallengeResponse.Buffer, message.NtChallengeResponse.Len);
ntlm_read_ntlm_v2_response(s, &response); ntlm_read_ntlm_v2_response(s, &response);
PStreamFreeDetach(s); PStreamFreeDetach(s);
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);
CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8); CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8);
AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags); AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags);
@ -682,25 +693,23 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey));
CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16); CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16);
StreamSetOffset(s, PayloadBufferOffset);
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
StreamRead(s, message.MessageIntegrityCheck, 16);
PayloadBufferOffset += 16;
}
/* move to end of stream, incorrectly assumes the EncryptedRandomSessionKey buffer is last */
StreamSetOffset(s, message.EncryptedRandomSessionKey.BufferOffset + message.EncryptedRandomSessionKey.Len);
length = StreamSize(s); length = StreamSize(s);
sspi_SecBufferAlloc(&context->AuthenticateMessage, length); sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length); CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length);
buffer->cbBuffer = length; buffer->cbBuffer = length;
StreamSetOffset(s, PayloadBufferOffset);
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
MicOffset = StreamGetOffset(s);
StreamRead(s, message.MessageIntegrityCheck, 16);
PayloadBufferOffset += 16;
}
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); printf("AUTHENTICATE_MESSAGE (length = %d)\n", (int) context->AuthenticateMessage.cbBuffer);
winpr_HexDump(s->data, length); winpr_HexDump(context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
printf("\n"); printf("\n");
if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
@ -751,6 +760,25 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
/* ExportedSessionKey */ /* ExportedSessionKey */
ntlm_generate_exported_session_key(context); ntlm_generate_exported_session_key(context);
if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK)
{
ZeroMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], 16);
ntlm_compute_message_integrity_check(context);
CopyMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], message.MessageIntegrityCheck, 16);
if (memcmp(context->MessageIntegrityCheck, message.MessageIntegrityCheck, 16) != 0)
{
printf("Message Integrity Check (MIC) verification failed!\n");
printf("Expected MIC:\n");
winpr_HexDump(context->MessageIntegrityCheck, 16);
printf("Actual MIC:\n");
winpr_HexDump(message.MessageIntegrityCheck, 16);
//return SEC_E_MESSAGE_ALTERED;
}
}
/* Generate signing keys */ /* Generate signing keys */
ntlm_generate_client_signing_key(context); ntlm_generate_client_signing_key(context);
ntlm_generate_server_signing_key(context); ntlm_generate_server_signing_key(context);