Merge pull request #5031 from akallabeth/cve_fixes_final

Cve fixes
This commit is contained in:
Bernhard Miklautz 2018-11-20 10:20:43 +00:00 committed by GitHub
commit 98490b0791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 507 additions and 212 deletions

View File

@ -77,8 +77,8 @@ struct _NSC_CONTEXT
/* color palette allocated by the application */
const BYTE* palette;
void (*decode)(NSC_CONTEXT* context);
void (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData,
BOOL (*decode)(NSC_CONTEXT* context);
BOOL (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData,
UINT32 rowstride);
NSC_CONTEXT_PRIV* priv;

View File

@ -32,34 +32,18 @@
#define ZGFX_SEGMENTED_MAXSIZE 65535
struct _ZGFX_CONTEXT
{
BOOL Compressor;
const BYTE* pbInputCurrent;
const BYTE* pbInputEnd;
UINT32 bits;
UINT32 cBitsRemaining;
UINT32 BitsCurrent;
UINT32 cBitsCurrent;
BYTE OutputBuffer[65536];
UINT32 OutputCount;
BYTE HistoryBuffer[2500000];
UINT32 HistoryIndex;
UINT32 HistoryBufferSize;
};
typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst,
const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush);

View File

@ -42,13 +42,24 @@
#define NSC_INIT_SIMD(_nsc_context) do { } while (0)
#endif
static void nsc_decode(NSC_CONTEXT* context)
static BOOL nsc_decode(NSC_CONTEXT* context)
{
UINT16 x;
UINT16 y;
UINT16 rw = ROUND_UP_TO(context->width, 8);
BYTE shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
BYTE* bmpdata = context->BitmapData;
UINT16 rw;
BYTE shift;
BYTE* bmpdata;
size_t pos = 0;
if (!context)
return FALSE;
rw = ROUND_UP_TO(context->width, 8);
shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
bmpdata = context->BitmapData;
if (!bmpdata)
return FALSE;
for (y = 0; y < context->height; y++)
{
@ -80,6 +91,11 @@ static void nsc_decode(NSC_CONTEXT* context)
INT16 r_val = y_val + co_val - cg_val;
INT16 g_val = y_val + cg_val;
INT16 b_val = y_val - co_val - cg_val;
if (pos + 4 > context->BitmapDataLength)
return FALSE;
pos += 4;
*bmpdata++ = MINMAX(b_val, 0, 0xFF);
*bmpdata++ = MINMAX(g_val, 0, 0xFF);
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
@ -90,9 +106,11 @@ static void nsc_decode(NSC_CONTEXT* context)
aplane++;
}
}
return TRUE;
}
static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize)
{
UINT32 len;
UINT32 left;
@ -105,6 +123,10 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
if (left == 5)
{
if (outSize < 1)
return FALSE;
outSize--;
*out++ = value;
left--;
}
@ -124,26 +146,42 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
in += 4;
}
if (outSize < len)
return FALSE;
outSize -= len;
FillMemory(out, len, value);
out += len;
left -= len;
}
else
{
if (outSize < 1)
return FALSE;
outSize--;
*out++ = value;
left--;
}
}
*((UINT32*)out) = *((UINT32*)in);
if ((outSize < 4) || (left < 4))
return FALSE;
memcpy(out, in, 4);
return TRUE;
}
static void nsc_rle_decompress_data(NSC_CONTEXT* context)
static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context)
{
UINT16 i;
BYTE* rle;
UINT32 planeSize;
UINT32 originalSize;
if (!context)
return FALSE;
rle = context->Planes;
for (i = 0; i < 4; i++)
@ -152,14 +190,30 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
planeSize = context->PlaneByteCount[i];
if (planeSize == 0)
{
if (context->priv->PlaneBuffersLength < originalSize)
return FALSE;
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
}
else if (planeSize < originalSize)
nsc_rle_decode(rle, context->priv->PlaneBuffers[i], originalSize);
{
if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i], context->priv->PlaneBuffersLength,
originalSize))
return FALSE;
}
else
{
if (context->priv->PlaneBuffersLength < originalSize)
return FALSE;
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
}
rle += planeSize;
}
return TRUE;
}
static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
@ -396,14 +450,26 @@ BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp,
return FALSE;
/* RLE decode */
{
BOOL rc;
PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data)
nsc_rle_decompress_data(context);
rc = nsc_rle_decompress_data(context);
PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data)
if (!rc)
return FALSE;
}
/* Colorloss recover, Chroma supersample and AYCoCg to ARGB Conversion in one step */
{
BOOL rc;
PROFILER_ENTER(context->priv->prof_nsc_decode)
context->decode(context);
rc = context->decode(context);
PROFILER_EXIT(context->priv->prof_nsc_decode)
if (!rc)
return FALSE;
}
if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst,
width, height, context->BitmapData,
PIXEL_FORMAT_BGRA32, 0, 0, 0, NULL, flip))

View File

@ -51,6 +51,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context)
for (i = 0; i < 5; i++)
{
BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
if (!tmp)
goto fail;
@ -87,7 +88,7 @@ fail:
return FALSE;
}
static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
UINT32 scanline)
{
UINT16 x;
@ -104,10 +105,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
INT16 b_val;
BYTE a_val;
UINT32 tempWidth;
if (!context || data || (scanline == 0))
return FALSE;
tempWidth = ROUND_UP_TO(context->width, 8);
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
ccl = context->ColorLossLevel;
if (context->priv->PlaneBuffersLength < rw * scanline)
return FALSE;
if (rw < scanline * 2)
return FALSE;
for (y = 0; y < context->height; y++)
{
src = data + (context->height - 1 - y) * scanline;
@ -242,31 +253,37 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
CopyMemory(coplane, coplane - rw, rw);
CopyMemory(cgplane, cgplane - rw, rw);
}
return TRUE;
}
static void nsc_encode_subsampling(NSC_CONTEXT* context)
static BOOL nsc_encode_subsampling(NSC_CONTEXT* context)
{
UINT16 x;
UINT16 y;
BYTE* co_dst;
BYTE* cg_dst;
INT8* co_src0;
INT8* co_src1;
INT8* cg_src0;
INT8* cg_src1;
UINT32 tempWidth;
UINT32 tempHeight;
if (!context)
return FALSE;
tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2);
if (tempHeight == 0)
return FALSE;
if (tempWidth > context->priv->PlaneBuffersLength / tempHeight)
return FALSE;
for (y = 0; y < tempHeight >> 1; y++)
{
co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
co_src1 = co_src0 + tempWidth;
cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
cg_src1 = cg_src0 + tempWidth;
BYTE* co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
BYTE* cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
const INT8* co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
const INT8* co_src1 = co_src0 + tempWidth;
const INT8* cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
const INT8* cg_src1 = cg_src0 + tempWidth;
for (x = 0; x < tempWidth >> 1; x++)
{
@ -280,19 +297,28 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
cg_src1 += 2;
}
}
return TRUE;
}
void nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride)
BOOL nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata, UINT32 rowstride)
{
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
if (!context || !bmpdata || (rowstride == 0))
return FALSE;
if (!nsc_encode_argb_to_aycocg(context, bmpdata, rowstride))
return FALSE;
if (context->ChromaSubsamplingLevel)
{
nsc_encode_subsampling(context);
}
if (!nsc_encode_subsampling(context))
return FALSE;
}
static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize)
return TRUE;
}
static UINT32 nsc_rle_encode(const BYTE* in, BYTE* out, UINT32 originalSize)
{
UINT32 left;
UINT32 runlength = 1;

View File

@ -24,7 +24,7 @@
#include <freerdp/api.h>
FREERDP_LOCAL void nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata,
FREERDP_LOCAL BOOL nsc_encode(NSC_CONTEXT* context, const BYTE* bmpdata,
UINT32 rowstride);
#endif /* FREERDP_LIB_CODEC_NSC_ENCODE_H */

View File

@ -385,7 +385,7 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context)
}
}
static void nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data,
static BOOL nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data,
UINT32 scanline)
{
nsc_encode_argb_to_aycocg_sse2(context, data, scanline);
@ -394,6 +394,8 @@ static void nsc_encode_sse2(NSC_CONTEXT* context, const BYTE* data,
{
nsc_encode_subsampling_sse2(context);
}
return TRUE;
}
void nsc_init_sse2(NSC_CONTEXT* context)

View File

@ -44,14 +44,34 @@
struct _ZGFX_TOKEN
{
int prefixLength;
int prefixCode;
int valueBits;
int tokenType;
UINT32 prefixLength;
UINT32 prefixCode;
UINT32 valueBits;
UINT32 tokenType;
UINT32 valueBase;
};
typedef struct _ZGFX_TOKEN ZGFX_TOKEN;
struct _ZGFX_CONTEXT
{
BOOL Compressor;
const BYTE* pbInputCurrent;
const BYTE* pbInputEnd;
UINT32 bits;
UINT32 cBitsRemaining;
UINT32 BitsCurrent;
UINT32 cBitsCurrent;
BYTE OutputBuffer[65536];
UINT32 OutputCount;
BYTE HistoryBuffer[2500000];
UINT32 HistoryIndex;
UINT32 HistoryBufferSize;
};
static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
{
// len code vbits type vbase
@ -98,17 +118,27 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
{ 0 }
};
#define zgfx_GetBits(_zgfx, _nbits) \
while (_zgfx->cBitsCurrent < _nbits) { \
_zgfx->BitsCurrent <<= 8; \
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \
_zgfx->cBitsCurrent += 8; \
} \
_zgfx->cBitsRemaining -= _nbits; \
_zgfx->cBitsCurrent -= _nbits; \
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
static INLINE BOOL zgfx_GetBits(ZGFX_CONTEXT* _zgfx, UINT32 _nbits)
{
if (!_zgfx)
return FALSE;
while (_zgfx->cBitsCurrent < _nbits)
{
_zgfx->BitsCurrent <<= 8;
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd)
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++;
_zgfx->cBitsCurrent += 8;
}
_zgfx->cBitsRemaining -= _nbits;
_zgfx->cBitsCurrent -= _nbits;
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent;
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
return TRUE;
}
static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count)
{
@ -193,16 +223,22 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
{
BYTE c;
BYTE flags;
int extra;
UINT32 extra = 0;
int opIndex;
int haveBits;
int inPrefix;
UINT32 count;
UINT32 distance;
BYTE* pbSegment;
size_t cbSegment = segmentSize - 1;
size_t cbSegment;
if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1))
if (!zgfx || !stream)
return FALSE;
cbSegment = segmentSize - 1;
if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) ||
(segmentSize > UINT32_MAX))
return FALSE;
Stream_Read_UINT8(stream, flags); /* header (1 byte) */
@ -213,6 +249,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (!(flags & PACKET_COMPRESSED))
{
zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment);
if (cbSegment > sizeof(zgfx->OutputBuffer))
return FALSE;
CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment);
zgfx->OutputCount = cbSegment;
return TRUE;
@ -251,6 +291,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
zgfx->HistoryIndex = 0;
if (zgfx->OutputCount >= sizeof(zgfx->OutputBuffer))
return FALSE;
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
}
else
@ -284,6 +327,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
count += zgfx->bits;
}
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
zgfx->OutputCount += count;
@ -296,6 +342,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
zgfx->cBitsRemaining -= zgfx->cBitsCurrent;
zgfx->cBitsCurrent = 0;
zgfx->BitsCurrent = 0;
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count);
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);
zgfx->pbInputCurrent += count;
@ -317,8 +367,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
{
int status = -1;
BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
if (!stream)
return -1;
@ -333,6 +383,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
goto fail;
*ppDstData = NULL;
if (zgfx->OutputCount > 0)
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
@ -349,6 +400,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
UINT16 segmentCount;
UINT32 uncompressedSize;
BYTE* pConcatenated;
size_t used = 0;
if (Stream_GetRemainingLength(stream) < 6)
goto fail;
@ -377,8 +429,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
goto fail;
if (zgfx->OutputCount > UINT32_MAX - used)
goto fail;
if (used + zgfx->OutputCount > uncompressedSize)
goto fail;
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
pConcatenated += zgfx->OutputCount;
used += zgfx->OutputCount;
}
}
else

View File

@ -208,10 +208,8 @@ BITMAP_UPDATE* update_read_bitmap_update(rdpUpdate* update, wStream* s)
if (bitmapUpdate->number > bitmapUpdate->count)
{
UINT16 count;
BITMAP_DATA* newdata;
count = bitmapUpdate->number * 2;
newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
UINT32 count = bitmapUpdate->number * 2;
BITMAP_DATA* newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
sizeof(BITMAP_DATA) * count);
if (!newdata)

View File

@ -141,9 +141,17 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
{
UINT32 SrcSize = length;
rdpGdi* gdi = context->gdi;
UINT32 size = DstWidth * DstHeight;
bitmap->compressed = FALSE;
bitmap->format = gdi->dstFormat;
bitmap->length = DstWidth * DstHeight * GetBytesPerPixel(bitmap->format);
if ((GetBytesPerPixel(bitmap->format) == 0) ||
(DstWidth == 0) || (DstHeight == 0) || (DstWidth > UINT32_MAX / DstHeight) ||
(size > (UINT32_MAX / GetBytesPerPixel(bitmap->format))))
return FALSE;
size *= GetBytesPerPixel(bitmap->format);
bitmap->length = size;
bitmap->data = (BYTE*) _aligned_malloc(bitmap->length, 16);
if (!bitmap->data)

View File

@ -147,6 +147,7 @@ struct _NTLMv2_CLIENT_CHALLENGE
BYTE ClientChallenge[8];
UINT32 Reserved3;
NTLM_AV_PAIR* AvPairs;
UINT32 cbAvPairs;
};
typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE;

View File

@ -39,7 +39,7 @@
#include "../../log.h"
#define TAG WINPR_TAG("sspi.NTLM")
const char* const AV_PAIR_STRINGS[] =
static const char* const AV_PAIR_STRINGS[] =
{
"MsvAvEOL",
"MsvAvNbComputerName",
@ -54,14 +54,42 @@ const char* const AV_PAIR_STRINGS[] =
"MsvChannelBindings"
};
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList)
static NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair);
static void ntlm_av_pair_set_id(NTLM_AV_PAIR* pAvPair, UINT16 id)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
ntlm_av_pair_set_id(pAvPair, MsvAvEOL);
ntlm_av_pair_set_len(pAvPair, 0);
Data_Write_UINT16(&pAvPair->AvId, id);
}
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList)
static void ntlm_av_pair_set_len(NTLM_AV_PAIR* pAvPair, UINT16 len)
{
Data_Write_UINT16(&pAvPair->AvLen, len);
}
static BOOL ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
if (!pAvPair || (cbAvPairList < sizeof(NTLM_AV_PAIR)))
return FALSE;
ntlm_av_pair_set_id(pAvPair, MsvAvEOL);
ntlm_av_pair_set_len(pAvPair, 0);
return TRUE;
}
static INLINE UINT16 ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair)
{
UINT16 AvId;
if (!pAvPair)
return MsvAvEOL;
Data_Read_UINT16(&pAvPair->AvId, AvId);
return AvId;
}
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairListMaxLength)
{
ULONG length;
NTLM_AV_PAIR* pAvPair = pAvPairList;
@ -71,14 +99,29 @@ ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList)
while (ntlm_av_pair_get_id(pAvPair) != MsvAvEOL)
{
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair, &cbAvPairListMaxLength);
}
length = (pAvPair - pAvPairList) + sizeof(NTLM_AV_PAIR);
return length;
}
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList)
static INLINE SSIZE_T ntlm_av_pair_get_len(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair)
{
UINT16 AvLen;
if (!pAvPair || (cbAvPair < sizeof(NTLM_AV_PAIR)))
return -1;
Data_Read_UINT16(&pAvPair->AvLen, AvLen);
if (cbAvPair < sizeof(NTLM_AV_PAIR) + pAvPair->AvLen)
return -1;
return AvLen;
}
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
@ -92,60 +135,84 @@ void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList)
WLog_INFO(TAG, "\t%s AvId: %"PRIu16" AvLen: %"PRIu16"",
AV_PAIR_STRINGS[ntlm_av_pair_get_id(pAvPair)],
ntlm_av_pair_get_id(pAvPair),
ntlm_av_pair_get_len(pAvPair));
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair),
ntlm_av_pair_get_len(pAvPair));
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
ntlm_av_pair_get_len(pAvPair, cbAvPairList));
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair, cbAvPairList),
ntlm_av_pair_get_len(pAvPair, cbAvPairList));
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair, &cbAvPairList);
}
}
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
static ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
{
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
return ((AvPairsCount + 1) * 4) + AvPairsValueLength;
}
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair)
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair, size_t cbAvPairListMaxLength)
{
if (cbAvPairListMaxLength < 2 * sizeof(NTLM_AV_PAIR))
return NULL;
return &((PBYTE) pAvPair)[sizeof(NTLM_AV_PAIR)];
}
int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair)
static SSIZE_T ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair, size_t cbAvPairListMaxLength)
{
return ntlm_av_pair_get_len(pAvPair) + sizeof(NTLM_AV_PAIR);
return ntlm_av_pair_get_len(pAvPair, cbAvPairListMaxLength) + sizeof(NTLM_AV_PAIR);
}
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair)
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair)
{
return (NTLM_AV_PAIR*)((PBYTE) pAvPair + ntlm_av_pair_get_next_offset(pAvPair));
SSIZE_T offset;
if (!pAvPair || !pcbAvPair)
return NULL;
offset = ntlm_av_pair_get_next_offset(pAvPair, *pcbAvPair);
if ((offset <= 0) || (offset > *pcbAvPair))
return NULL;
*pcbAvPair -= offset;
return (NTLM_AV_PAIR*)((PBYTE) pAvPair + offset);
}
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId)
NTLM_AV_PAIR* ntlm_av_pair_get(void* pAvPairList,
size_t avPairListLength,
NTLM_AV_ID AvId,
size_t* pcbAvPairListRemainingLength)
{
NTLM_AV_PAIR* pAvPair = pAvPairList;
if (!pAvPair)
return NULL;
if (pcbAvPairListRemainingLength)
*pcbAvPairListRemainingLength = 0;
while (1)
while (pAvPair)
{
if (ntlm_av_pair_get_id(pAvPair) == AvId)
{
if (pcbAvPairListRemainingLength)
*pcbAvPairListRemainingLength = avPairListLength;
return pAvPair;
}
if (ntlm_av_pair_get_id(pAvPair) == MsvAvEOL)
return NULL;
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair, &avPairListLength);
}
return NULL;
}
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value,
static NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairListLength,
NTLM_AV_ID AvId, PBYTE Value,
UINT16 AvLen)
{
size_t cbAvPair;
NTLM_AV_PAIR* pAvPair;
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
pAvPair = ntlm_av_pair_get(pAvPairList, cbAvPairListLength, MsvAvEOL, &cbAvPair);
if (!pAvPair)
return NULL;
@ -153,27 +220,29 @@ NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE
assert(Value != NULL);
ntlm_av_pair_set_id(pAvPair, AvId);
ntlm_av_pair_set_len(pAvPair, AvLen);
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), Value, AvLen);
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair, cbAvPair), Value, AvLen);
return pAvPair;
}
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair)
static NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairListLength,
NTLM_AV_PAIR* pAvPair, size_t cbAvPair)
{
NTLM_AV_PAIR* pAvPairCopy;
pAvPairCopy = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
size_t cbAvPairCopy;
pAvPairCopy = ntlm_av_pair_get(pAvPairList, cbAvPairListLength, MsvAvEOL, &cbAvPairCopy);
if (!pAvPairCopy)
return NULL;
CopyMemory(&pAvPairCopy->AvId, &pAvPair->AvId, 2);
CopyMemory(&pAvPairCopy->AvLen, &pAvPair->AvLen, 2);
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy),
ntlm_av_pair_get_value_pointer(pAvPair),
ntlm_av_pair_get_len(pAvPair));
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy, cbAvPairCopy),
ntlm_av_pair_get_value_pointer(pAvPair, cbAvPair),
ntlm_av_pair_get_len(pAvPair, cbAvPair));
return pAvPairCopy;
}
int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
static int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
{
char* name;
int status;
@ -219,7 +288,7 @@ int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT ty
return 1;
}
void ntlm_free_unicode_string(PUNICODE_STRING string)
static void ntlm_free_unicode_string(PUNICODE_STRING string)
{
if (string)
{
@ -271,7 +340,7 @@ static BOOL ntlm_md5_update_uint32_be(WINPR_DIGEST_CTX* md5, UINT32 num)
return winpr_Digest_Update(md5, be32, 4);
}
void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
static void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
{
WINPR_DIGEST_CTX* md5;
BYTE* ChannelBindingToken;
@ -317,7 +386,7 @@ out:
winpr_Digest_Free(md5);
}
void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
static void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
{
/**
* The Single_Host_Data structure allows a client to send machine-specific information
@ -336,33 +405,34 @@ void ntlm_compute_single_host_data(NTLM_CONTEXT* context)
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
{
int rc = -1;
int length;
ULONG AvPairsCount;
ULONG AvPairsLength;
NTLM_AV_PAIR* pAvPairList;
UNICODE_STRING NbDomainName;
UNICODE_STRING NbComputerName;
UNICODE_STRING DnsDomainName;
UNICODE_STRING DnsComputerName;
NbDomainName.Buffer = NULL;
size_t cbAvPairList;
UNICODE_STRING NbDomainName = { 0 };
UNICODE_STRING NbComputerName = { 0 };
UNICODE_STRING DnsDomainName = { 0 };
UNICODE_STRING DnsComputerName = { 0 };
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
return -1;
goto fail;
NbComputerName.Buffer = NULL;
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
return -1;
goto fail;
DnsDomainName.Buffer = NULL;
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
return -1;
goto fail;
DnsComputerName.Buffer = NULL;
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
return -1;
goto fail;
AvPairsCount = 5;
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
@ -370,23 +440,42 @@ int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
if (!sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length))
return -1;
goto fail;
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
ntlm_av_pair_list_init(pAvPairList);
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));
cbAvPairList = context->ChallengeTargetInfo.cbBuffer;
if (!ntlm_av_pair_list_init(pAvPairList, cbAvPairList))
goto fail;
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer,
NbDomainName.Length) == NULL)
goto fail;
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvNbComputerName, (PBYTE) NbComputerName.Buffer,
NbComputerName.Length) == NULL)
goto fail;
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvDnsDomainName, (PBYTE) DnsDomainName.Buffer,
DnsDomainName.Length) == NULL)
goto fail;
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvDnsComputerName,
(PBYTE) DnsComputerName.Buffer,
DnsComputerName.Length) == NULL)
goto fail;
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvTimestamp, context->Timestamp,
sizeof(context->Timestamp)) == NULL)
goto fail;
rc = 1;
fail:
ntlm_free_unicode_string(&NbDomainName);
ntlm_free_unicode_string(&NbComputerName);
ntlm_free_unicode_string(&DnsDomainName);
ntlm_free_unicode_string(&DnsComputerName);
return 1;
return rc;
}
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
@ -402,44 +491,60 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
NTLM_AV_PAIR* AvDnsTreeName;
NTLM_AV_PAIR* ChallengeTargetInfo;
NTLM_AV_PAIR* AuthenticateTargetInfo;
size_t cbAvTimestamp;
size_t cbAvNbDomainName;
size_t cbAvNbComputerName;
size_t cbAvDnsDomainName;
size_t cbAvDnsComputerName;
size_t cbAvDnsTreeName;
size_t cbChallengeTargetInfo;
size_t cbAuthenticateTargetInfo;
AvPairsCount = 1;
AvPairsValueLength = 0;
ChallengeTargetInfo = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
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);
cbChallengeTargetInfo = context->ChallengeTargetInfo.cbBuffer;
AvNbDomainName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvNbDomainName,
&cbAvNbDomainName);
AvNbComputerName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvNbComputerName,
&cbAvNbComputerName);
AvDnsDomainName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvDnsDomainName,
&cbAvDnsDomainName);
AvDnsComputerName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo,
MsvAvDnsComputerName,
&cbAvDnsComputerName);
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvDnsTreeName,
&cbAvDnsTreeName);
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvTimestamp,
&cbAvTimestamp);
if (AvNbDomainName)
{
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName);
AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName, cbAvNbDomainName);
}
if (AvNbComputerName)
{
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName);
AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName, cbAvNbComputerName);
}
if (AvDnsDomainName)
{
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName);
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName, cbAvDnsDomainName);
}
if (AvDnsComputerName)
{
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName);
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName, cbAvDnsComputerName);
}
if (AvDnsTreeName)
{
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName);
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName, cbAvDnsTreeName);
}
AvPairsCount++; /* MsvAvTimestamp */
@ -489,56 +594,96 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
return -1;
AuthenticateTargetInfo = (NTLM_AV_PAIR*) context->AuthenticateTargetInfo.pvBuffer;
ntlm_av_pair_list_init(AuthenticateTargetInfo);
cbAuthenticateTargetInfo = context->AuthenticateTargetInfo.cbBuffer;
if (!ntlm_av_pair_list_init(AuthenticateTargetInfo, cbAuthenticateTargetInfo))
return -1;
if (AvNbDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvNbDomainName,
cbAvNbDomainName) == NULL)
return -1;
}
if (AvNbComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvNbComputerName, cbAvNbComputerName) == NULL)
return -1;
}
if (AvDnsDomainName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvDnsDomainName, cbAvDnsDomainName) == NULL)
return -1;
}
if (AvDnsComputerName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvDnsComputerName, cbAvDnsComputerName) == NULL)
return -1;
}
if (AvDnsTreeName)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsTreeName,
cbAvDnsTreeName) == NULL)
return -1;
}
if (AvTimestamp)
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
{
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvTimestamp,
cbAvTimestamp) == NULL)
return -1;
}
if (context->UseMIC)
{
UINT32 flags;
Data_Write_UINT32(&flags, MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK);
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvFlags, (PBYTE) &flags, 4);
if (ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvFlags, (PBYTE) &flags,
4) == NULL)
return -1;
}
if (context->SendSingleHostData)
{
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvSingleHost,
(PBYTE) &context->SingleHostData, context->SingleHostData.Size);
if (ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvSingleHost,
(PBYTE) &context->SingleHostData, context->SingleHostData.Size) == NULL)
return -1;
}
if (!context->SuppressExtendedProtection)
{
ntlm_av_pair_add(AuthenticateTargetInfo, MsvChannelBindings, context->ChannelBindingsHash, 16);
if (ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvChannelBindings,
context->ChannelBindingsHash, 16) == NULL)
return -1;
if (context->ServicePrincipalName.Length > 0)
{
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvTargetName,
if (ntlm_av_pair_add(AuthenticateTargetInfo,
cbAuthenticateTargetInfo,
MsvAvTargetName,
(PBYTE) context->ServicePrincipalName.Buffer,
context->ServicePrincipalName.Length);
context->ServicePrincipalName.Length) == NULL)
return -1;
}
}
if (context->NTLMv2)
{
NTLM_AV_PAIR* AvEOL;
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
ZeroMemory((void*) AvEOL, 4);
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvEOL, NULL);
if (!AvEOL)
return -1;
ZeroMemory(AvEOL, sizeof(NTLM_AV_PAIR));
}
return 1;

View File

@ -24,33 +24,11 @@
#include <winpr/stream.h>
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList);
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList);
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList);
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength);
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair);
int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair);
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair);
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, 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);
static INLINE UINT16 ntlm_av_pair_get_id(NTLM_AV_PAIR* pAvPair)
{
UINT16 AvId;
Data_Read_UINT16(&pAvPair->AvId, AvId);
return AvId;
}
static INLINE UINT16 ntlm_av_pair_get_len(NTLM_AV_PAIR* pAvPair)
{
UINT16 AvLen;
Data_Read_UINT16(&pAvPair->AvLen, AvLen);
return AvLen;
}
#define ntlm_av_pair_set_id(pAvPair, id) Data_Write_UINT16(&pAvPair->AvId, id)
#define ntlm_av_pair_set_len(pAvPair, len) Data_Write_UINT16(&pAvPair->AvLen, len)
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairListMaxLength);
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList);
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair, size_t cbAvPairListMaxLength);
NTLM_AV_PAIR* ntlm_av_pair_get(void* pAvPairList, size_t avPairListLength, NTLM_AV_ID AvId,
size_t* pcbAvPairListRemainingLength);
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);

View File

@ -132,7 +132,12 @@ int ntlm_read_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* chal
Stream_Read(s, challenge->ClientChallenge, 8);
Stream_Read_UINT32(s, challenge->Reserved3);
size = Stream_Length(s) - Stream_GetPosition(s);
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
if (size > UINT32_MAX)
return -1;
challenge->cbAvPairs = size;
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(challenge->cbAvPairs);
if (!challenge->AvPairs)
return -1;
@ -151,7 +156,7 @@ int ntlm_write_ntlm_v2_client_challenge(wStream* s, NTLMv2_CLIENT_CHALLENGE* cha
Stream_Write(s, challenge->Timestamp, 8);
Stream_Write(s, challenge->ClientChallenge, 8);
Stream_Write_UINT32(s, challenge->Reserved3);
length = ntlm_av_pair_list_length(challenge->AvPairs);
length = ntlm_av_pair_list_length(challenge->AvPairs, challenge->cbAvPairs);
Stream_Write(s, challenge->AvPairs, length);
return 1;
}

View File

@ -74,7 +74,7 @@ static const char* const NTLM_NEGOTIATE_STRINGS[] =
"NTLMSSP_NEGOTIATE_UNICODE"
};
void ntlm_print_negotiate_flags(UINT32 flags)
static void ntlm_print_negotiate_flags(UINT32 flags)
{
int i;
const char* str;
@ -90,7 +90,7 @@ void ntlm_print_negotiate_flags(UINT32 flags)
}
}
int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
static int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
{
if (Stream_GetRemainingLength(s) < 12)
return -1;
@ -104,19 +104,19 @@ int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
return 1;
}
void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
static void ntlm_write_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
{
Stream_Write(s, header->Signature, sizeof(NTLM_SIGNATURE));
Stream_Write_UINT32(s, header->MessageType);
}
void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType)
static void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType)
{
CopyMemory(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));
header->MessageType = MessageType;
}
int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
static int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (Stream_GetRemainingLength(s) < 8)
return -1;
@ -127,7 +127,7 @@ int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
return 1;
}
void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
static void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (fields->MaxLen < 1)
fields->MaxLen = fields->Len;
@ -137,11 +137,16 @@ void ntlm_write_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
Stream_Write_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */
}
int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
static int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (fields->Len > 0)
{
if ((fields->BufferOffset + fields->Len) > Stream_Length(s))
const UINT32 offset = fields->BufferOffset + fields->Len;
if (fields->BufferOffset > UINT32_MAX - fields->Len)
return -1;
if (offset > Stream_Length(s))
return -1;
fields->Buffer = (PBYTE) malloc(fields->Len);
@ -156,7 +161,7 @@ int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
return 1;
}
void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
static void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
{
if (fields->Len > 0)
{
@ -165,7 +170,7 @@ void ntlm_write_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
}
}
void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields)
static void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields)
{
if (fields)
{
@ -180,7 +185,7 @@ void ntlm_free_message_fields_buffer(NTLM_MESSAGE_FIELDS* fields)
}
}
void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name)
static void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name)
{
WLog_DBG(TAG, "%s (Len: %"PRIu16" MaxLen: %"PRIu16" BufferOffset: %"PRIu32")",
name, fields->Len, fields->MaxLen, fields->BufferOffset);
@ -445,6 +450,8 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
if (message->TargetInfo.Len > 0)
{
size_t cbAvTimestamp;
if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
{
Stream_Free(s, FALSE);
@ -453,14 +460,21 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer;
context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
AvTimestamp = ntlm_av_pair_get((NTLM_AV_PAIR*) message->TargetInfo.Buffer, MsvAvTimestamp);
AvTimestamp = ntlm_av_pair_get(message->TargetInfo.Buffer,
message->TargetInfo.Len,
MsvAvTimestamp, &cbAvTimestamp);
if (AvTimestamp)
{
PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp, cbAvTimestamp);
if (!ptr)
return SEC_E_INTERNAL_ERROR;
if (context->NTLMv2)
context->UseMIC = TRUE;
CopyMemory(context->ChallengeTimestamp, ntlm_av_pair_get_value_pointer(AvTimestamp), 8);
CopyMemory(context->ChallengeTimestamp, ptr, 8);
}
}
@ -784,6 +798,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
if (message->NtChallengeResponse.Len > 0)
{
size_t cbAvFlags;
wStream* snt = Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
if (!snt)
@ -806,10 +821,12 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
context->ChallengeTargetInfo.pvBuffer = (void*) context->NTLMv2Response.Challenge.AvPairs;
context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
CopyMemory(context->ClientChallenge, context->NTLMv2Response.Challenge.ClientChallenge, 8);
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs, MsvAvFlags);
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs,
context->NTLMv2Response.Challenge.cbAvPairs,
MsvAvFlags, &cbAvFlags);
if (AvFlags)
Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags), flags);
Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags, cbAvFlags), flags);
}
if (ntlm_read_message_fields_buffer(s,
@ -1101,18 +1118,24 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context)
{
UINT32 flags = 0;
size_t cbAvFlags;
NTLM_AV_PAIR* AvFlags = NULL;
NTLM_AUTHENTICATE_MESSAGE* message;
BYTE messageIntegrityCheck[16];
if (!context)
return SEC_E_INVALID_PARAMETER;
if (context->state != NTLM_STATE_COMPLETION)
return SEC_E_OUT_OF_SEQUENCE;
message = &context->AUTHENTICATE_MESSAGE;
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs, MsvAvFlags);
AvFlags = ntlm_av_pair_get(context->NTLMv2Response.Challenge.AvPairs,
context->NTLMv2Response.Challenge.cbAvPairs,
MsvAvFlags, &cbAvFlags);
if (AvFlags)
Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags), flags);
Data_Read_UINT32(ntlm_av_pair_get_value_pointer(AvFlags, cbAvFlags), flags);
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
return SEC_E_INTERNAL_ERROR;