libfreerdp-auth: add server side messages

This commit is contained in:
Marc-André Moreau 2012-03-01 09:13:51 -05:00
parent 847fe0cb8c
commit 1b087615e7
2 changed files with 346 additions and 90 deletions

View File

@ -145,11 +145,85 @@ void ntlm_print_negotiate_flags(uint32 flags)
printf("}\n"); printf("}\n");
} }
SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer)
{
STREAM* s;
int length;
uint8 Signature[8];
uint32 MessageType;
uint32 NegotiateFlags;
uint16 DomainNameLen;
uint16 DomainNameMaxLen;
uint32 DomainNameBufferOffset;
uint16 WorkstationLen;
uint16 WorkstationMaxLen;
uint32 WorkstationBufferOffset;
s = stream_new(0);
stream_attach(s, buffer->pvBuffer, buffer->cbBuffer);
stream_read(s, Signature, 8);
stream_read_uint32(s, MessageType);
if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0)
{
printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE);
return SEC_E_INVALID_TOKEN;
}
if (MessageType != MESSAGE_TYPE_NEGOTIATE)
return SEC_E_INVALID_TOKEN;
stream_read_uint32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */
context->NegotiateFlags = NegotiateFlags;
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
/* DomainNameFields (8 bytes) */
stream_read_uint16(s, DomainNameLen); /* DomainNameLen */
stream_read_uint16(s, DomainNameMaxLen); /* DomainNameMaxLen */
stream_read_uint32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */
/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
/* WorkstationFields (8 bytes) */
stream_read_uint16(s, WorkstationLen); /* WorkstationLen */
stream_read_uint16(s, WorkstationMaxLen); /* WorkstationMaxLen */
stream_read_uint32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */
if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
stream_seek(s, 8); /* Version (8 bytes) */
}
length = s->p - s->data;
buffer->cbBuffer = length;
sspi_SecBufferAlloc(&context->NegotiateMessage, length);
memcpy(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
context->NegotiateMessage.BufferType = buffer->BufferType;
#ifdef WITH_DEBUG_NTLM
printf("NEGOTIATE_MESSAGE (length = %d)\n", length);
freerdp_hexdump(s->data, length);
printf("\n");
#endif
context->state = NTLM_STATE_CHALLENGE;
stream_detach(s);
stream_free(s);
return SEC_I_CONTINUE_NEEDED;
}
SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer) SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer)
{ {
STREAM* s; STREAM* s;
int length; int length;
uint32 negotiateFlags = 0; uint32 NegotiateFlags = 0;
s = stream_new(0); s = stream_new(0);
stream_attach(s, buffer->pvBuffer, buffer->cbBuffer); stream_attach(s, buffer->pvBuffer, buffer->cbBuffer);
@ -159,36 +233,36 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* b
if (context->ntlm_v2) if (context->ntlm_v2)
{ {
negotiateFlags |= NTLMSSP_NEGOTIATE_56; NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
negotiateFlags |= NTLMSSP_NEGOTIATE_128; NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
negotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
negotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
negotiateFlags |= NTLMSSP_NEGOTIATE_OEM; NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
} }
else else
{ {
negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
negotiateFlags |= NTLMSSP_NEGOTIATE_128; NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
negotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
} }
context->NegotiateFlags = negotiateFlags; context->NegotiateFlags = NegotiateFlags;
stream_write_uint32(s, negotiateFlags); /* NegotiateFlags (4 bytes) */ stream_write_uint32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
@ -204,7 +278,7 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* b
stream_write_uint16(s, 0); /* WorkstationMaxLen */ stream_write_uint16(s, 0); /* WorkstationMaxLen */
stream_write_uint32(s, 0); /* WorkstationBufferOffset */ stream_write_uint32(s, 0); /* WorkstationBufferOffset */
if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{ {
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
ntlm_output_version(s); ntlm_output_version(s);
@ -231,6 +305,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* b
context->state = NTLM_STATE_CHALLENGE; context->state = NTLM_STATE_CHALLENGE;
stream_detach(s);
stream_free(s);
return SEC_I_CONTINUE_NEEDED; return SEC_I_CONTINUE_NEEDED;
} }
@ -239,35 +316,38 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* bu
uint8* p; uint8* p;
STREAM* s; STREAM* s;
int length; int length;
char signature[8]; char Signature[8];
uint32 messageType; uint32 MessageType;
uint8* start_offset; uint8* StartOffset;
uint8* payload_offset; uint8* PayloadOffset;
uint16 targetNameLen; uint16 TargetNameLen;
uint16 targetNameMaxLen; uint16 TargetNameMaxLen;
uint32 targetNameBufferOffset; uint32 TargetNameBufferOffset;
uint16 targetInfoLen; uint16 TargetInfoLen;
uint16 targetInfoMaxLen; uint16 TargetInfoMaxLen;
uint32 targetInfoBufferOffset; uint32 TargetInfoBufferOffset;
s = stream_new(0); s = stream_new(0);
stream_attach(s, buffer->pvBuffer, buffer->cbBuffer); stream_attach(s, buffer->pvBuffer, buffer->cbBuffer);
stream_read(s, signature, 8); stream_read(s, Signature, 8);
stream_read_uint32(s, messageType); stream_read_uint32(s, MessageType);
if (memcmp(signature, NTLM_SIGNATURE, 8) != 0) if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0)
{ {
printf("Unexpected NTLM signature: %s, expected:%s\n", signature, NTLM_SIGNATURE); printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE);
return SEC_E_INVALID_TOKEN; return SEC_E_INVALID_TOKEN;
} }
start_offset = s->p - 12; if (MessageType != MESSAGE_TYPE_CHALLENGE)
return SEC_E_INVALID_TOKEN;
StartOffset = s->p - 12;
/* TargetNameFields (8 bytes) */ /* TargetNameFields (8 bytes) */
stream_read_uint16(s, targetNameLen); /* TargetNameLen (2 bytes) */ stream_read_uint16(s, TargetNameLen); /* TargetNameLen (2 bytes) */
stream_read_uint16(s, targetNameMaxLen); /* TargetNameMaxLen (2 bytes) */ stream_read_uint16(s, TargetNameMaxLen); /* TargetNameMaxLen (2 bytes) */
stream_read_uint32(s, targetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */ stream_read_uint32(s, TargetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */
stream_read_uint32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ stream_read_uint32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */
@ -279,9 +359,9 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* bu
stream_seek(s, 8); /* Reserved (8 bytes), should be ignored */ stream_seek(s, 8); /* Reserved (8 bytes), should be ignored */
/* TargetInfoFields (8 bytes) */ /* TargetInfoFields (8 bytes) */
stream_read_uint16(s, targetInfoLen); /* TargetInfoLen (2 bytes) */ stream_read_uint16(s, TargetInfoLen); /* TargetInfoLen (2 bytes) */
stream_read_uint16(s, targetInfoMaxLen); /* TargetInfoMaxLen (2 bytes) */ stream_read_uint16(s, TargetInfoMaxLen); /* TargetInfoMaxLen (2 bytes) */
stream_read_uint32(s, targetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */ stream_read_uint32(s, TargetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */
/* only present if NTLMSSP_NEGOTIATE_VERSION is set */ /* only present if NTLMSSP_NEGOTIATE_VERSION is set */
@ -291,29 +371,29 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* bu
} }
/* Payload (variable) */ /* Payload (variable) */
payload_offset = s->p; PayloadOffset = s->p;
if (targetNameLen > 0) if (TargetNameLen > 0)
{ {
p = start_offset + targetNameBufferOffset; p = StartOffset + TargetNameBufferOffset;
sspi_SecBufferAlloc(&context->TargetName, targetNameLen); sspi_SecBufferAlloc(&context->TargetName, TargetNameLen);
memcpy(context->TargetName.pvBuffer, p, targetNameLen); memcpy(context->TargetName.pvBuffer, p, TargetNameLen);
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("TargetName (length = %d, offset = %d)\n", targetNameLen, targetNameBufferOffset); printf("TargetName (length = %d, offset = %d)\n", TargetNameLen, TargetNameBufferOffset);
freerdp_hexdump(context->TargetName.pvBuffer, context->TargetName.cbBuffer); freerdp_hexdump(context->TargetName.pvBuffer, context->TargetName.cbBuffer);
printf("\n"); printf("\n");
#endif #endif
} }
if (targetInfoLen > 0) if (TargetInfoLen > 0)
{ {
p = start_offset + targetInfoBufferOffset; p = StartOffset + TargetInfoBufferOffset;
sspi_SecBufferAlloc(&context->TargetInfo, targetInfoLen); sspi_SecBufferAlloc(&context->TargetInfo, TargetInfoLen);
memcpy(context->TargetInfo.pvBuffer, p, targetInfoLen); memcpy(context->TargetInfo.pvBuffer, p, TargetInfoLen);
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("TargetInfo (length = %d, offset = %d)\n", targetInfoLen, targetInfoBufferOffset); printf("TargetInfo (length = %d, offset = %d)\n", TargetInfoLen, TargetInfoBufferOffset);
freerdp_hexdump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); freerdp_hexdump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
printf("\n"); printf("\n");
#endif #endif
@ -325,10 +405,10 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* bu
} }
} }
length = (payload_offset - start_offset) + targetNameLen + targetInfoLen; length = (PayloadOffset - StartOffset) + TargetNameLen + TargetInfoLen;
sspi_SecBufferAlloc(&context->ChallengeMessage, length); sspi_SecBufferAlloc(&context->ChallengeMessage, length);
memcpy(context->ChallengeMessage.pvBuffer, start_offset, length); memcpy(context->ChallengeMessage.pvBuffer, StartOffset, length);
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("CHALLENGE_MESSAGE (length = %d)\n", length); printf("CHALLENGE_MESSAGE (length = %d)\n", length);
@ -409,9 +489,179 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* bu
context->state = NTLM_STATE_AUTHENTICATE; context->state = NTLM_STATE_AUTHENTICATE;
stream_detach(s);
stream_free(s);
return SEC_I_CONTINUE_NEEDED; return SEC_I_CONTINUE_NEEDED;
} }
SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer)
{
STREAM* s;
uint16 TargetNameLen;
uint8* TargetNameBuffer;
uint32 TargetNameBufferOffset;
uint16 TargetInfoLen;
uint8* TargetInfoBuffer;
uint32 TargetInfoBufferOffset;
s = stream_new(0);
stream_attach(s, buffer->pvBuffer, buffer->cbBuffer);
stream_write(s, NTLM_SIGNATURE, 8); /* Signature (8 bytes) */
stream_write_uint32(s, MESSAGE_TYPE_CHALLENGE); /* MessageType */
TargetNameLen = context->TargetName.cbBuffer;
TargetNameBuffer = context->TargetName.pvBuffer;
TargetInfoLen = context->TargetInfo.cbBuffer;
TargetInfoBuffer = context->TargetInfo.pvBuffer;
TargetNameBufferOffset = 56;
TargetInfoBufferOffset = TargetNameBufferOffset + TargetNameLen;
/* TargetNameFields (8 bytes) */
stream_write_uint16(s, TargetNameLen); /* TargetNameLen (2 bytes) */
stream_write_uint16(s, TargetNameLen); /* TargetNameMaxLen (2 bytes) */
stream_write_uint32(s, TargetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */
stream_write_uint32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */
stream_write(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
stream_write_zero(s, 8); /* Reserved (8 bytes), should be ignored */
/* TargetInfoFields (8 bytes) */
stream_write_uint16(s, TargetInfoLen); /* TargetInfoLen (2 bytes) */
stream_write_uint16(s, TargetInfoLen); /* TargetInfoMaxLen (2 bytes) */
stream_write_uint32(s, TargetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */
/* only present if NTLMSSP_NEGOTIATE_VERSION is set */
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{
ntlm_output_version(s); /* Version (8 bytes), can be ignored */
}
/* Payload (variable) */
if (TargetNameLen > 0)
{
stream_write(s, TargetNameBuffer, TargetNameLen);
#ifdef WITH_DEBUG_NTLM
printf("TargetName (length = %d, offset = %d)\n", TargetNameLen, TargetNameBufferOffset);
freerdp_hexdump(TargetNameBuffer, TargetNameLen);
printf("\n");
#endif
}
if (TargetInfoLen > 0)
{
stream_write(s, TargetInfoBuffer, TargetInfoLen);
#ifdef WITH_DEBUG_NTLM
printf("TargetInfo (length = %d, offset = %d)\n", TargetInfoLen, TargetInfoBufferOffset);
freerdp_hexdump(TargetInfoBuffer, TargetInfoLen);
printf("\n");
#endif
}
context->state = NTLM_STATE_AUTHENTICATE;
stream_detach(s);
stream_free(s);
return SEC_I_CONTINUE_NEEDED;
}
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer)
{
STREAM* s;
uint8 Signature[8];
uint32 MessageType;
uint32 NegotiateFlags;
uint16 DomainNameLen;
uint16 DomainNameMaxLen;
uint32 DomainNameBufferOffset;
uint16 UserNameLen;
uint16 UserNameMaxLen;
uint32 UserNameBufferOffset;
uint16 WorkstationLen;
uint16 WorkstationMaxLen;
uint32 WorkstationBufferOffset;
uint16 LmChallengeResponseLen;
uint16 LmChallengeResponseMaxLen;
uint32 LmChallengeResponseBufferOffset;
uint16 NtChallengeResponseLen;
uint16 NtChallengeResponseMaxLen;
uint32 NtChallengeResponseBufferOffset;
uint16 EncryptedRandomSessionKeyLen;
uint16 EncryptedRandomSessionKeyMaxLen;
uint32 EncryptedRandomSessionKeyBufferOffset;
s = stream_new(0);
stream_attach(s, buffer->pvBuffer, buffer->cbBuffer);
stream_read(s, Signature, 8);
stream_read_uint32(s, MessageType);
if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0)
{
printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE);
return SEC_E_INVALID_TOKEN;
}
if (MessageType != MESSAGE_TYPE_AUTHENTICATE)
return SEC_E_INVALID_TOKEN;
/* LmChallengeResponseFields (8 bytes) */
stream_read_uint16(s, LmChallengeResponseLen); /* LmChallengeResponseLen */
stream_read_uint16(s, LmChallengeResponseMaxLen); /* LmChallengeResponseMaxLen */
stream_read_uint32(s, LmChallengeResponseBufferOffset); /* LmChallengeResponseBufferOffset */
/* NtChallengeResponseFields (8 bytes) */
stream_read_uint16(s, NtChallengeResponseLen); /* NtChallengeResponseLen */
stream_read_uint16(s, NtChallengeResponseMaxLen); /* NtChallengeResponseMaxLen */
stream_read_uint32(s, NtChallengeResponseBufferOffset); /* NtChallengeResponseBufferOffset */
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
/* DomainNameFields (8 bytes) */
stream_read_uint16(s, DomainNameLen); /* DomainNameLen */
stream_read_uint16(s, DomainNameMaxLen); /* DomainNameMaxLen */
stream_read_uint32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */
/* UserNameFields (8 bytes) */
stream_read_uint16(s, UserNameLen); /* UserNameLen */
stream_read_uint16(s, UserNameMaxLen); /* UserNameMaxLen */
stream_read_uint32(s, UserNameBufferOffset); /* UserNameBufferOffset */
/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
/* WorkstationFields (8 bytes) */
stream_read_uint16(s, WorkstationLen); /* WorkstationLen */
stream_read_uint16(s, WorkstationMaxLen); /* WorkstationMaxLen */
stream_read_uint32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */
/* EncryptedRandomSessionKeyFields (8 bytes) */
stream_read_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyLen */
stream_read_uint16(s, EncryptedRandomSessionKeyMaxLen); /* EncryptedRandomSessionKeyMaxLen */
stream_read_uint32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */
stream_read_uint32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */
if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
stream_seek(s, 8); /* Version (8 bytes) */
}
context->state = NTLM_STATE_FINAL;
stream_detach(s);
stream_free(s);
return SEC_I_COMPLETE_NEEDED;
}
/** /**
* Send NTLMSSP AUTHENTICATE_MESSAGE.\n * Send NTLMSSP AUTHENTICATE_MESSAGE.\n
* AUTHENTICATE_MESSAGE @msdn{cc236643} * AUTHENTICATE_MESSAGE @msdn{cc236643}
@ -423,8 +673,8 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
{ {
STREAM* s; STREAM* s;
int length; int length;
uint8* mic_offset = NULL; uint8* MicOffset = NULL;
uint32 negotiateFlags = 0; uint32 NegotiateFlags = 0;
uint16 DomainNameLen; uint16 DomainNameLen;
uint16 UserNameLen; uint16 UserNameLen;
@ -470,30 +720,30 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
if (context->ntlm_v2) if (context->ntlm_v2)
{ {
/* observed: 35 82 88 e2 (0xE2888235) */ /* observed: 35 82 88 e2 (0xE2888235) */
negotiateFlags |= NTLMSSP_NEGOTIATE_56; NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
negotiateFlags |= NTLMSSP_NEGOTIATE_128; NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
negotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION;
negotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
negotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
} }
else else
{ {
negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
negotiateFlags |= NTLMSSP_NEGOTIATE_128; NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
negotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
negotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
} }
if (context->ntlm_v2) if (context->ntlm_v2)
@ -501,7 +751,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
else else
PayloadBufferOffset = 64; /* starting buffer offset */ PayloadBufferOffset = 64; /* starting buffer offset */
if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
PayloadBufferOffset += 8; PayloadBufferOffset += 8;
DomainNameBufferOffset = PayloadBufferOffset; DomainNameBufferOffset = PayloadBufferOffset;
@ -548,13 +798,13 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyMaxLen */ stream_write_uint16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyMaxLen */
stream_write_uint32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */ stream_write_uint32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */
stream_write_uint32(s, negotiateFlags); /* NegotiateFlags (4 bytes) */ stream_write_uint32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
ntlm_print_negotiate_flags(negotiateFlags); ntlm_print_negotiate_flags(NegotiateFlags);
#endif #endif
if (negotiateFlags & NTLMSSP_NEGOTIATE_VERSION) if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{ {
/* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */
ntlm_output_version(s); ntlm_output_version(s);
@ -569,7 +819,7 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
if (context->ntlm_v2) if (context->ntlm_v2)
{ {
/* Message Integrity Check */ /* Message Integrity Check */
mic_offset = s->p; MicOffset = s->p;
stream_write_zero(s, 16); stream_write_zero(s, 16);
} }
@ -652,13 +902,13 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
/* Message Integrity Check */ /* Message Integrity Check */
ntlm_compute_message_integrity_check(context); ntlm_compute_message_integrity_check(context);
s->p = mic_offset; s->p = MicOffset;
stream_write(s, context->MessageIntegrityCheck, 16); stream_write(s, context->MessageIntegrityCheck, 16);
s->p = s->data + length; s->p = s->data + length;
#ifdef WITH_DEBUG_NTLM #ifdef WITH_DEBUG_NTLM
printf("MessageIntegrityCheck (length = 16)\n"); printf("MessageIntegrityCheck (length = 16)\n");
freerdp_hexdump(mic_offset, 16); freerdp_hexdump(MicOffset, 16);
printf("\n"); printf("\n");
#endif #endif
} }
@ -671,5 +921,8 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER
context->state = NTLM_STATE_FINAL; context->state = NTLM_STATE_FINAL;
stream_detach(s);
stream_free(s);
return SEC_I_COMPLETE_NEEDED; return SEC_I_COMPLETE_NEEDED;
} }

View File

@ -22,8 +22,11 @@
#include "ntlm.h" #include "ntlm.h"
SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer); SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer); SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer); SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, SEC_BUFFER* buffer);
#endif /* FREERDP_AUTH_NTLM_MESSAGE_H */ #endif /* FREERDP_AUTH_NTLM_MESSAGE_H */