libwinpr-sspi: even more code hardening

This commit is contained in:
Marc-André Moreau 2014-06-07 00:17:11 -04:00
parent 220f885774
commit 1b5a2340d2
9 changed files with 364 additions and 220 deletions

View File

@ -1000,7 +1000,7 @@ extern "C" {
WINPR_API void sspi_GlobalInit(void);
WINPR_API void sspi_GlobalFinish(void);
WINPR_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size);
WINPR_API void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size);
WINPR_API void sspi_SecBufferFree(PSecBuffer SecBuffer);
WINPR_API int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* domain, char* password);

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -173,34 +173,45 @@ NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAv
return pAvPairCopy;
}
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
{
char* name;
int length;
int status;
DWORD nSize = 0;
GetComputerNameExA(type, NULL, &nSize);
name = malloc(nSize);
GetComputerNameExA(type, name, &nSize);
name = (char*) malloc(nSize);
if (!name)
return -1;
if (!GetComputerNameExA(type, name, &nSize))
return -1;
if (type == ComputerNameNetBIOS)
CharUpperA(name);
length = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0);
status = ConvertToUnicode(CP_UTF8, 0, name, -1, &pName->Buffer, 0);
pName->Length = (length - 1) * 2;
if (status <= 0)
return status;
pName->Length = (USHORT) ((status - 1) * 2);
pName->MaximumLength = pName->Length;
free(name);
return 1;
}
void ntlm_free_unicode_string(PUNICODE_STRING string)
{
if (string != NULL)
if (string)
{
if (string->Length > 0)
{
if (string->Buffer != NULL)
if (string->Buffer)
free(string->Buffer);
string->Buffer = NULL;
@ -297,7 +308,7 @@ void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
FillMemory(context->SingleHostData.MachineID, 32, 0xAA);
}
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
{
int length;
ULONG AvPairsCount;
@ -310,16 +321,24 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
UNICODE_STRING DnsComputerName;
NbDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
return -1;
NbComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
return -1;
DnsDomainName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
return -1;
DnsComputerName.Buffer = NULL;
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
return -1;
AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
@ -342,9 +361,11 @@ void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
ntlm_free_unicode_string(&NbComputerName);
ntlm_free_unicode_string(&DnsDomainName);
ntlm_free_unicode_string(&DnsComputerName);
return 1;
}
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
{
ULONG size;
ULONG AvPairsCount;
@ -369,31 +390,31 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
{
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += AvNbDomainName->AvLen;
}
if (AvNbComputerName != NULL)
if (AvNbComputerName)
{
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += AvNbComputerName->AvLen;
}
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
{
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += AvDnsDomainName->AvLen;
}
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
{
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += AvDnsComputerName->AvLen;
}
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
{
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += AvDnsTreeName->AvLen;
@ -448,22 +469,22 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
ntlm_av_pair_list_init(AuthenticateTargetInfo);
if (AvNbDomainName != NULL)
if (AvNbDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
if (AvNbComputerName != NULL)
if (AvNbComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
if (AvDnsDomainName != NULL)
if (AvDnsDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
if (AvDnsComputerName != NULL)
if (AvDnsComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
if (AvDnsTreeName != NULL)
if (AvDnsTreeName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
if (AvTimestamp != NULL)
if (AvTimestamp)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
if (context->UseMIC)
@ -497,4 +518,6 @@ void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 4);
}
return 1;
}

View File

@ -35,7 +35,7 @@ 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_challenge_target_info(NTLM_CONTEXT* context);
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
#endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */

View File

@ -32,12 +32,12 @@
#include "ntlm_compute.h"
const char lm_magic[] = "KGS!@#$%";
const char LM_MAGIC[] = "KGS!@#$%";
static const char client_sign_magic[] = "session key to client-to-server signing key magic constant";
static const char server_sign_magic[] = "session key to server-to-client signing key magic constant";
static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant";
static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant";
static const char NTLM_CLIENT_SIGN_MAGIC[] = "session key to client-to-server signing key magic constant";
static const char NTLM_SERVER_SIGN_MAGIC[] = "session key to server-to-client signing key magic constant";
static const char NTLM_CLIENT_SEAL_MAGIC[] = "session key to client-to-server sealing key magic constant";
static const char NTLM_SERVER_SEAL_MAGIC[] = "session key to server-to-client sealing key magic constant";
/**
* Populate VERSION structure.\n
@ -66,13 +66,18 @@ void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
* @param s
*/
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo)
{
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
Stream_Read_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
Stream_Read_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
Stream_Read(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
Stream_Read_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
return 1;
}
/**
@ -107,7 +112,7 @@ void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
fprintf(stderr, "\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
}
void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
int ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{
size_t size;
@ -121,10 +126,16 @@ void ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* cha
size = Stream_Length(s) - Stream_GetPosition(s);
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
if (!challenge->AvPairs)
return -1;
Stream_Read(s, challenge->AvPairs, size);
return 1;
}
void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
int ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* challenge)
{
ULONG length;
@ -138,57 +149,22 @@ void ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* ch
length = ntlm_av_pair_list_length(challenge->AvPairs);
Stream_Write(s, challenge->AvPairs, length);
return 1;
}
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{
Stream_Read(s, response->Response, 16);
ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
return ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
}
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
int ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response)
{
Stream_Write(s, response->Response, 16);
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
return ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
}
#if 0
/**
* Output Restriction_Encoding.\n
* Restriction_Encoding @msdn{cc236647}
* @param NTLM context
*/
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context)
{
wStream* s;
AV_PAIR* restrictions = &context->av_pairs->Restrictions;
BYTE machineID[32] =
"\x3A\x15\x8E\xA6\x75\x82\xD8\xF7\x3E\x06\xFA\x7A\xB4\xDF\xFD\x43"
"\x84\x6C\x02\x3A\xFD\x5A\x94\xFE\xCF\x97\x0F\x3D\x19\x2C\x38\x20";
restrictions->value = malloc(48);
restrictions->length = 48;
s = PStreamAllocAttach(restrictions->value, restrictions->length);
Stream_Write_UINT32(s, 48); /* Size */
Stream_Zero(s, 4); /* Z4 (set to zero) */
/* IntegrityLevel (bit 31 set to 1) */
Stream_Write_UINT8(s, 1);
Stream_Zero(s, 3);
Stream_Write_UINT32(s, 0x00002000); /* SubjectIntegrityLevel */
Stream_Write(s, machineID, 32); /* MachineID */
PStreamFreeDetach(s);
}
#endif
/**
* Get current time, in tenths of microseconds since midnight of January 1, 1601.
* @param[out] timestamp 64-bit little-endian timestamp
@ -224,20 +200,21 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context)
ntlm_current_time(context->Timestamp);
}
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
int ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{
WINPR_SAM* sam;
WINPR_SAM_ENTRY* entry;
sam = SamOpen(1);
if (sam == NULL)
return;
sam = SamOpen(TRUE);
if (!sam)
return -1;
entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2);
if (entry != NULL)
if (entry)
{
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n");
@ -252,13 +229,13 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
entry = SamLookupUserW(sam,
(LPWSTR) context->identity.User, context->identity.UserLength * 2, NULL, 0);
if (entry != NULL)
if (entry)
{
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "NTLM Hash:\n");
@ -273,17 +250,22 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
SamFreeEntry(sam, entry);
SamClose(sam);
return;
return 1;
}
else
{
fprintf(stderr, "Error: Could not find user in SAM database\n");
}
SamClose(sam);
return 0;
}
void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
SamClose(sam);
return 1;
}
int ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
{
int status;
int i, hn, ln;
char* PasswordHash = NULL;
UINT32 PasswordHashLength = 0;
@ -291,7 +273,12 @@ void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
/* Password contains a password hash of length (PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR) */
PasswordHashLength = context->identity.PasswordLength / SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
ConvertFromUnicode(CP_UTF8, 0, context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
status = ConvertFromUnicode(CP_UTF8, 0, (LPCWSTR) context->identity.Password, PasswordHashLength, &PasswordHash, 0, NULL, NULL);
if (status <= 0)
return -1;
CharUpperBuffA(PasswordHash, PasswordHashLength);
for (i = 0; i < 32; i += 2)
@ -302,16 +289,20 @@ void ntlm_convert_password_hash(NTLM_CONTEXT* context, BYTE* hash)
}
free(PasswordHash);
return 1;
}
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{
if (context->identity.PasswordLength > 256)
{
BYTE PasswordHash[16];
/* Special case for WinPR: password hash */
ntlm_convert_password_hash(context, PasswordHash);
if (ntlm_convert_password_hash(context, PasswordHash) < 0)
return -1;
NTOWFv2FromHashW(PasswordHash,
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
@ -328,9 +319,11 @@ void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
{
ntlm_fetch_ntlm_v2_hash(context, hash);
}
return 1;
}
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
{
char* response;
char value[16];
@ -338,19 +331,26 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
if (context->LmCompatibilityLevel < 2)
{
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
return;
return 1;
}
/* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash) < 0)
return -1;
/* Concatenate the server and client challenges */
CopyMemory(value, context->ServerChallenge, 8);
CopyMemory(&value[8], context->ClientChallenge, 8);
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24))
return -1;
response = (char*) context->LmChallengeResponse.pvBuffer;
/* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */
@ -358,6 +358,8 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
/* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */
CopyMemory(&response[16], context->ClientChallenge, 8);
return 1;
}
/**
@ -367,7 +369,7 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
* @param NTLM context
*/
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
{
BYTE* blob;
BYTE ntlm_v2_hash[16];
@ -378,13 +380,16 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
TargetInfo = &context->ChallengeTargetInfo;
sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28);
if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28))
return -1;
ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
blob = (BYTE*) ntlm_v2_temp.pvBuffer;
/* Compute the NTLMv2 hash */
ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash);
if (ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash) < 0)
return -1;
#ifdef WITH_DEBUG_NTLM
fprintf(stderr, "Password (length = %d)\n", context->identity.PasswordLength * 2);
@ -425,16 +430,22 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
#endif
/* Concatenate server challenge with temp */
sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8);
if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8))
return -1;
blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer;
CopyMemory(blob, context->ServerChallenge, 8);
CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer,
HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer,
ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL);
/* NtChallengeResponse, Concatenate NTProofStr with temp */
sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16);
if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16))
return -1;
blob = (BYTE*) context->NtChallengeResponse.pvBuffer;
CopyMemory(blob, nt_proof_str, 16);
CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
@ -444,6 +455,8 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
sspi_SecBufferFree(&ntlm_v2_temp);
sspi_SecBufferFree(&ntlm_v2_temp_chal);
return 1;
}
/**
@ -548,7 +561,7 @@ void ntlm_decrypt_random_session_key(NTLM_CONTEXT* context)
* @param signing_key Destination signing key
*/
void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key)
int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* signing_key)
{
int length;
BYTE* value;
@ -557,6 +570,9 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
length = 16 + sign_magic->cbBuffer;
value = (BYTE*) malloc(length);
if (!value)
return -1;
/* Concatenate ExportedSessionKey with sign magic */
CopyMemory(value, exported_session_key, 16);
CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer);
@ -566,6 +582,8 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
MD5_Final(signing_key, &md5);
free(value);
return 1;
}
/**
@ -576,10 +594,12 @@ void ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic
void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) client_sign_magic;
sign_magic.cbBuffer = sizeof(client_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ClientSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_CLIENT_SIGN_MAGIC;
signMagic.cbBuffer = sizeof(NTLM_CLIENT_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ClientSigningKey);
}
/**
@ -590,10 +610,12 @@ void ntlm_generate_client_signing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
{
SecBuffer sign_magic;
sign_magic.pvBuffer = (void*) server_sign_magic;
sign_magic.cbBuffer = sizeof(server_sign_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &sign_magic, context->ServerSigningKey);
SecBuffer signMagic;
signMagic.pvBuffer = (void*) NTLM_SERVER_SIGN_MAGIC;
signMagic.cbBuffer = sizeof(NTLM_SERVER_SIGN_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &signMagic, context->ServerSigningKey);
}
/**
@ -604,13 +626,15 @@ void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
* @param sealing_key Destination sealing key
*/
void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
{
BYTE* p;
MD5_CTX md5;
SecBuffer buffer;
sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer);
if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer))
return -1;
p = (BYTE*) buffer.pvBuffer;
/* Concatenate ExportedSessionKey with seal magic */
@ -622,6 +646,8 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
MD5_Final(sealing_key, &md5);
sspi_SecBufferFree(&buffer);
return 1;
}
/**
@ -632,10 +658,12 @@ void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic
void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) client_seal_magic;
seal_magic.cbBuffer = sizeof(client_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ClientSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_CLIENT_SEAL_MAGIC;
sealMagic.cbBuffer = sizeof(NTLM_CLIENT_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ClientSealingKey);
}
/**
@ -646,10 +674,12 @@ void ntlm_generate_client_sealing_key(NTLM_CONTEXT* context)
void ntlm_generate_server_sealing_key(NTLM_CONTEXT* context)
{
SecBuffer seal_magic;
seal_magic.pvBuffer = (void*) server_seal_magic;
seal_magic.cbBuffer = sizeof(server_seal_magic);
ntlm_generate_signing_key(context->ExportedSessionKey, &seal_magic, context->ServerSealingKey);
SecBuffer sealMagic;
sealMagic.pvBuffer = (void*) NTLM_SERVER_SEAL_MAGIC;
sealMagic.cbBuffer = sizeof(NTLM_SERVER_SEAL_MAGIC);
ntlm_generate_signing_key(context->ExportedSessionKey, &sealMagic, context->ServerSealingKey);
}
/**
@ -690,9 +720,9 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context)
HMAC_CTX_init(&hmac_ctx);
HMAC_Init_ex(&hmac_ctx, context->ExportedSessionKey, 16, EVP_md5(), NULL);
HMAC_Update(&hmac_ctx, context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
HMAC_Update(&hmac_ctx, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
HMAC_Final(&hmac_ctx, context->MessageIntegrityCheck, NULL);
HMAC_CTX_cleanup(&hmac_ctx);
}

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (Compute)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,24 +25,22 @@
#include "ntlm_av_pairs.h"
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
int ntlm_read_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_write_version_info(wStream* s, NTLM_VERSION_INFO* versionInfo);
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo);
void ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_write_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response);
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
void ntlm_output_target_name(NTLM_CONTEXT* context);
void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
void ntlm_current_time(BYTE* timestamp);
void ntlm_generate_timestamp(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash);
void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash);
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash);
int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context);
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context);
void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext);
void ntlm_generate_client_challenge(NTLM_CONTEXT* context);

View File

@ -33,7 +33,7 @@
#include "ntlm_message.h"
static const char NTLM_SIGNATURE[8] = "NTLMSSP\0";
static const char NTLM_SIGNATURE[8] = { 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' };
static const char* const NTLM_NEGOTIATE_STRINGS[] =
{
@ -90,10 +90,15 @@ void ntlm_print_negotiate_flags(UINT32 flags)
fprintf(stderr, "}\n");
}
void ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
{
if (Stream_GetRemainingLength(s) < 12)
return -1;
Stream_Read(s, header->Signature, sizeof(NTLM_SIGNATURE));
Stream_Read_UINT32(s, header->MessageType);
return 1;
}
void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
@ -125,11 +130,16 @@ BOOL ntlm_validate_message_header(wStream* s, NTLM_MESSAGE_HEADER* header, UINT3
return TRUE;
}
void ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT16(s, fields->Len); /* Len (2 bytes) */
Stream_Read_UINT16(s, fields->MaxLen); /* MaxLen (2 bytes) */
Stream_Read_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
return 1;
}
void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
@ -142,14 +152,20 @@ void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Stream_Write_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
}
void ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (fields->Len > 0)
{
fields->Buffer = malloc(fields->Len);
fields->Buffer = (PBYTE) malloc(fields->Len);
if (!fields->Buffer)
return -1;
Stream_SetPosition(s, fields->BufferOffset);
Stream_Read(s, fields->Buffer, fields->Len);
}
return 1;
}
void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
@ -163,9 +179,9 @@ void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields)
{
if (fields != NULL)
if (fields)
{
if (fields->Buffer != NULL)
if (fields->Buffer)
{
free(fields->Buffer);
@ -197,9 +213,13 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
message = &context->NEGOTIATE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message);
if (!s)
return SEC_E_INTERNAL_ERROR;
if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message) < 0)
return SEC_E_INVALID_TOKEN;
if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) message, MESSAGE_TYPE_NEGOTIATE))
{
@ -222,21 +242,26 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
/* DomainNameFields (8 bytes) */
ntlm_read_message_fields(s, &(message->DomainName));
if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
/* WorkstationFields (8 bytes) */
ntlm_read_message_fields(s, &(message->Workstation));
if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_read_version_info(s, &(message->Version)); /* Version (8 bytes) */
{
if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
return SEC_E_INVALID_TOKEN;
}
length = Stream_GetPosition(s);
buffer->cbBuffer = length;
sspi_SecBufferAlloc(&context->NegotiateMessage, length);
if (!sspi_SecBufferAlloc(&context->NegotiateMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
context->NegotiateMessage.BufferType = buffer->BufferType;
@ -267,7 +292,10 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
message = &context->NEGOTIATE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_NEGOTIATE_MESSAGE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
if (!s)
return SEC_E_INTERNAL_ERROR;
ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) message, MESSAGE_TYPE_NEGOTIATE);
@ -320,7 +348,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
length = Stream_GetPosition(s);
buffer->cbBuffer = length;
sspi_SecBufferAlloc(&context->NegotiateMessage, length);
if (!sspi_SecBufferAlloc(&context->NegotiateMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->NegotiateMessage.pvBuffer, buffer->pvBuffer, buffer->cbBuffer);
context->NegotiateMessage.BufferType = buffer->BufferType;
@ -354,11 +384,15 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
message = &context->CHALLENGE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
if (!s)
return SEC_E_INTERNAL_ERROR;
StartOffset = Stream_Pointer(s);
ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message);
if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message) < 0)
return SEC_E_INVALID_TOKEN;
if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) message, MESSAGE_TYPE_CHALLENGE))
{
@ -366,39 +400,55 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
return SEC_E_INVALID_TOKEN;
}
/* TargetNameFields (8 bytes) */
ntlm_read_message_fields(s, &(message->TargetName));
if (ntlm_read_message_fields(s, &(message->TargetName)) < 0) /* TargetNameFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
if (Stream_GetRemainingLength(s) < 4)
return SEC_E_INVALID_TOKEN;
Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
context->NegotiateFlags = message->NegotiateFlags;
if (Stream_GetRemainingLength(s) < 8)
return SEC_E_INVALID_TOKEN;
Stream_Read(s, message->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
CopyMemory(context->ServerChallenge, message->ServerChallenge, 8);
if (Stream_GetRemainingLength(s) < 8)
return SEC_E_INVALID_TOKEN;
Stream_Read(s, message->Reserved, 8); /* Reserved (8 bytes), should be ignored */
/* TargetInfoFields (8 bytes) */
ntlm_read_message_fields(s, &(message->TargetInfo));
if (ntlm_read_message_fields(s, &(message->TargetInfo)) < 0) /* TargetInfoFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_read_version_info(s, &(message->Version)); /* Version (8 bytes) */
{
if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
return SEC_E_INVALID_TOKEN;
}
/* Payload (variable) */
PayloadOffset = Stream_Pointer(s);
if (message->TargetName.Len > 0)
ntlm_read_message_fields_buffer(s, &(message->TargetName));
{
if (ntlm_read_message_fields_buffer(s, &(message->TargetName)) < 0)
return SEC_E_INTERNAL_ERROR;
}
if (message->TargetInfo.Len > 0)
{
ntlm_read_message_fields_buffer(s, &(message->TargetInfo));
if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
return SEC_E_INTERNAL_ERROR;
context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer;
context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
AvTimestamp = ntlm_av_pair_get((NTLM_AV_PAIR*) message->TargetInfo.Buffer, MsvAvTimestamp);
if (AvTimestamp != NULL)
if (AvTimestamp)
{
if (context->NTLMv2)
context->UseMIC = TRUE;
@ -409,7 +459,9 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
length = (PayloadOffset - StartOffset) + message->TargetName.Len + message->TargetInfo.Len;
sspi_SecBufferAlloc(&context->ChallengeMessage, length);
if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->ChallengeMessage.pvBuffer, StartOffset, length);
#ifdef WITH_DEBUG_NTLM
@ -435,32 +487,29 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
if (context->NTLMv2)
{
ntlm_construct_authenticate_target_info(context);
if (ntlm_construct_authenticate_target_info(context) < 0)
return SEC_E_INTERNAL_ERROR;
sspi_SecBufferFree(&context->ChallengeTargetInfo);
context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer;
context->ChallengeTargetInfo.cbBuffer = context->AuthenticateTargetInfo.cbBuffer;
}
/* Timestamp */
ntlm_generate_timestamp(context);
ntlm_generate_timestamp(context); /* Timestamp */
/* LmChallengeResponse */
ntlm_compute_lm_v2_response(context);
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* NtChallengeResponse */
ntlm_compute_ntlm_v2_response(context);
if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* KeyExchangeKey */
ntlm_generate_key_exchange_key(context);
ntlm_generate_key_exchange_key(context); /* KeyExchangeKey */
/* RandomSessionKey */
ntlm_generate_random_session_key(context);
ntlm_generate_random_session_key(context); /* RandomSessionKey */
/* ExportedSessionKey */
ntlm_generate_exported_session_key(context);
ntlm_generate_exported_session_key(context); /* ExportedSessionKey */
/* EncryptedRandomSessionKey */
ntlm_encrypt_random_session_key(context);
ntlm_encrypt_random_session_key(context); /* EncryptedRandomSessionKey */
/* Generate signing keys */
ntlm_generate_client_signing_key(context);
@ -538,22 +587,21 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
message = &context->CHALLENGE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
/* Version */
ntlm_get_version_info(&(message->Version));
if (!s)
return SEC_E_INTERNAL_ERROR;
/* Server Challenge */
ntlm_generate_server_challenge(context);
ntlm_get_version_info(&(message->Version)); /* Version */
/* Timestamp */
ntlm_generate_timestamp(context);
ntlm_generate_server_challenge(context); /* Server Challenge */
/* TargetInfo */
ntlm_construct_challenge_target_info(context);
ntlm_generate_timestamp(context); /* Timestamp */
/* ServerChallenge */
CopyMemory(message->ServerChallenge, context->ServerChallenge, 8);
if (ntlm_construct_challenge_target_info(context) < 0) /* TargetInfo */
return SEC_E_INTERNAL_ERROR;
CopyMemory(message->ServerChallenge, context->ServerChallenge, 8); /* ServerChallenge */
message->NegotiateFlags = context->NegotiateFlags;
@ -565,7 +613,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
if (message->NegotiateFlags & NTLMSSP_REQUEST_TARGET)
{
message->TargetName.Len = (UINT16) context->TargetName.cbBuffer;
message->TargetName.Buffer = context->TargetName.pvBuffer;
message->TargetName.Buffer = (PBYTE) context->TargetName.pvBuffer;
}
message->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
@ -573,7 +621,7 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO)
{
message->TargetInfo.Len = (UINT16) context->ChallengeTargetInfo.cbBuffer;
message->TargetInfo.Buffer = context->ChallengeTargetInfo.pvBuffer;
message->TargetInfo.Buffer = (PBYTE) context->ChallengeTargetInfo.pvBuffer;
}
PayloadOffset = 48;
@ -609,7 +657,9 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
length = Stream_GetPosition(s);
buffer->cbBuffer = length;
sspi_SecBufferAlloc(&context->ChallengeMessage, length);
if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s), length);
#ifdef WITH_DEBUG_NTLM
@ -652,9 +702,13 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
ZeroMemory(&response, sizeof(NTLMv2_RESPONSE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message);
if (!s)
return SEC_E_INTERNAL_ERROR;
if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) message) < 0)
return SEC_E_INVALID_TOKEN;
if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) message, MESSAGE_TYPE_AUTHENTICATE))
{
@ -662,44 +716,63 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
return SEC_E_INVALID_TOKEN;
}
ntlm_read_message_fields(s, &(message->LmChallengeResponse)); /* LmChallengeResponseFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) < 0) /* LmChallengeResponseFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
ntlm_read_message_fields(s, &(message->NtChallengeResponse)); /* NtChallengeResponseFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) < 0) /* NtChallengeResponseFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
/* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */
ntlm_read_message_fields(s, &(message->DomainName)); /* DomainNameFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
ntlm_read_message_fields(s, &(message->UserName)); /* UserNameFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
/* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */
ntlm_read_message_fields(s, &(message->Workstation)); /* WorkstationFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)); /* EncryptedRandomSessionKeyFields (8 bytes) */
if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) < 0) /* EncryptedRandomSessionKeyFields (8 bytes) */
return SEC_E_INVALID_TOKEN;
Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
ntlm_read_version_info(s, &(message->Version)); /* Version (8 bytes) */
{
if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
return SEC_E_INVALID_TOKEN;
}
PayloadBufferOffset = Stream_GetPosition(s);
ntlm_read_message_fields_buffer(s, &(message->DomainName)); /* DomainName */
if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */
return SEC_E_INTERNAL_ERROR;
ntlm_read_message_fields_buffer(s, &(message->UserName)); /* UserName */
if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */
return SEC_E_INTERNAL_ERROR;
ntlm_read_message_fields_buffer(s, &(message->Workstation)); /* Workstation */
if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */
return SEC_E_INTERNAL_ERROR;
ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)); /* LmChallengeResponse */
if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) < 0) /* LmChallengeResponse */
return SEC_E_INTERNAL_ERROR;
ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)); /* NtChallengeResponse */
if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) < 0) /* NtChallengeResponse */
return SEC_E_INTERNAL_ERROR;
if (message->NtChallengeResponse.Len > 0)
{
wStream* s = Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
ntlm_read_ntlm_v2_response(s, &response);
Stream_Free(s, FALSE);
wStream* snt = Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
if (!snt)
return SEC_E_INTERNAL_ERROR;
ntlm_read_ntlm_v2_response(snt, &response);
Stream_Free(snt, FALSE);
context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer;
context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
@ -711,16 +784,20 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags);
if (AvFlags != NULL)
if (AvFlags)
flags = *((UINT32*) ntlm_av_pair_get_value_pointer(AvFlags));
}
/* EncryptedRandomSessionKey */
ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey));
if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) < 0) /* EncryptedRandomSessionKey */
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer, 16);
length = Stream_GetPosition(s);
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
buffer->cbBuffer = length;
@ -760,6 +837,10 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (message->UserName.Len > 0)
{
context->identity.User = (UINT16*) malloc(message->UserName.Len);
if (!context->identity.User)
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->identity.User, message->UserName.Buffer, message->UserName.Len);
context->identity.UserLength = message->UserName.Len / 2;
}
@ -767,15 +848,19 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (message->DomainName.Len > 0)
{
context->identity.Domain = (UINT16*) malloc(message->DomainName.Len);
if (!context->identity.Domain)
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->identity.Domain, message->DomainName.Buffer, message->DomainName.Len);
context->identity.DomainLength = message->DomainName.Len / 2;
}
/* LmChallengeResponse */
ntlm_compute_lm_v2_response(context);
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* NtChallengeResponse */
ntlm_compute_ntlm_v2_response(context);
if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
return SEC_E_INTERNAL_ERROR;
/* KeyExchangeKey */
ntlm_generate_key_exchange_key(context);
@ -895,7 +980,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
message = &context->AUTHENTICATE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
s = Stream_New(buffer->pvBuffer, buffer->cbBuffer);
s = Stream_New((BYTE*) buffer->pvBuffer, buffer->cbBuffer);
if (!s)
return SEC_E_INTERNAL_ERROR;
if (context->NTLMv2)
{
@ -947,9 +1035,6 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
message->LmChallengeResponse.Len = (UINT16) context->LmChallengeResponse.cbBuffer;
message->LmChallengeResponse.Buffer = (BYTE*) context->LmChallengeResponse.pvBuffer;
//if (context->NTLMv2)
// ZeroMemory(message->LmChallengeResponse.Buffer, message->LmChallengeResponse.Len);
message->NtChallengeResponse.Len = (UINT16) context->NtChallengeResponse.cbBuffer;
message->NtChallengeResponse.Buffer = (BYTE*) context->NtChallengeResponse.pvBuffer;
@ -1017,7 +1102,10 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
ntlm_write_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)); /* EncryptedRandomSessionKey */
length = Stream_GetPosition(s);
sspi_SecBufferAlloc(&context->AuthenticateMessage, length);
if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
return SEC_E_INTERNAL_ERROR;
CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
buffer->cbBuffer = length;

View File

@ -2,7 +2,7 @@
* WinPR: Windows Portable Runtime
* NTLM Security Package (Message)
*
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -223,10 +223,15 @@ void sspi_CredentialsFree(CREDENTIALS* credentials)
free(credentials);
}
void sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
{
if (!SecBuffer)
return NULL;
SecBuffer->cbBuffer = size;
SecBuffer->pvBuffer = calloc(1, size);
return SecBuffer->pvBuffer;
}
void sspi_SecBufferFree(PSecBuffer SecBuffer)