commit
98490b0791
@ -77,8 +77,8 @@ struct _NSC_CONTEXT
|
|||||||
/* color palette allocated by the application */
|
/* color palette allocated by the application */
|
||||||
const BYTE* palette;
|
const BYTE* palette;
|
||||||
|
|
||||||
void (*decode)(NSC_CONTEXT* context);
|
BOOL (*decode)(NSC_CONTEXT* context);
|
||||||
void (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData,
|
BOOL (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData,
|
||||||
UINT32 rowstride);
|
UINT32 rowstride);
|
||||||
|
|
||||||
NSC_CONTEXT_PRIV* priv;
|
NSC_CONTEXT_PRIV* priv;
|
||||||
|
@ -32,34 +32,18 @@
|
|||||||
|
|
||||||
#define ZGFX_SEGMENTED_MAXSIZE 65535
|
#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;
|
typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize,
|
||||||
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
|
BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
||||||
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
|
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);
|
FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush);
|
||||||
|
|
||||||
@ -71,4 +55,4 @@ FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* FREERDP_CODEC_ZGFX_H */
|
#endif /* FREERDP_CODEC_ZGFX_H */
|
||||||
|
|
||||||
|
@ -42,13 +42,24 @@
|
|||||||
#define NSC_INIT_SIMD(_nsc_context) do { } while (0)
|
#define NSC_INIT_SIMD(_nsc_context) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void nsc_decode(NSC_CONTEXT* context)
|
static BOOL nsc_decode(NSC_CONTEXT* context)
|
||||||
{
|
{
|
||||||
UINT16 x;
|
UINT16 x;
|
||||||
UINT16 y;
|
UINT16 y;
|
||||||
UINT16 rw = ROUND_UP_TO(context->width, 8);
|
UINT16 rw;
|
||||||
BYTE shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
|
BYTE shift;
|
||||||
BYTE* bmpdata = context->BitmapData;
|
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++)
|
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 r_val = y_val + co_val - cg_val;
|
||||||
INT16 g_val = y_val + cg_val;
|
INT16 g_val = y_val + cg_val;
|
||||||
INT16 b_val = y_val - co_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(b_val, 0, 0xFF);
|
||||||
*bmpdata++ = MINMAX(g_val, 0, 0xFF);
|
*bmpdata++ = MINMAX(g_val, 0, 0xFF);
|
||||||
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
|
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
|
||||||
@ -90,9 +106,11 @@ static void nsc_decode(NSC_CONTEXT* context)
|
|||||||
aplane++;
|
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 len;
|
||||||
UINT32 left;
|
UINT32 left;
|
||||||
@ -105,6 +123,10 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
|
|||||||
|
|
||||||
if (left == 5)
|
if (left == 5)
|
||||||
{
|
{
|
||||||
|
if (outSize < 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
outSize--;
|
||||||
*out++ = value;
|
*out++ = value;
|
||||||
left--;
|
left--;
|
||||||
}
|
}
|
||||||
@ -124,26 +146,42 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
|
|||||||
in += 4;
|
in += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outSize < len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
outSize -= len;
|
||||||
FillMemory(out, len, value);
|
FillMemory(out, len, value);
|
||||||
out += len;
|
out += len;
|
||||||
left -= len;
|
left -= len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (outSize < 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
outSize--;
|
||||||
*out++ = value;
|
*out++ = value;
|
||||||
left--;
|
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;
|
UINT16 i;
|
||||||
BYTE* rle;
|
BYTE* rle;
|
||||||
UINT32 planeSize;
|
UINT32 planeSize;
|
||||||
UINT32 originalSize;
|
UINT32 originalSize;
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
rle = context->Planes;
|
rle = context->Planes;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
@ -152,14 +190,30 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
|
|||||||
planeSize = context->PlaneByteCount[i];
|
planeSize = context->PlaneByteCount[i];
|
||||||
|
|
||||||
if (planeSize == 0)
|
if (planeSize == 0)
|
||||||
|
{
|
||||||
|
if (context->priv->PlaneBuffersLength < originalSize)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
|
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
|
||||||
|
}
|
||||||
else if (planeSize < originalSize)
|
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
|
else
|
||||||
|
{
|
||||||
|
if (context->priv->PlaneBuffersLength < originalSize)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
|
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
|
||||||
|
}
|
||||||
|
|
||||||
rle += planeSize;
|
rle += planeSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
|
static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
|
||||||
@ -396,13 +450,25 @@ BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* RLE decode */
|
/* RLE decode */
|
||||||
PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data)
|
{
|
||||||
nsc_rle_decompress_data(context);
|
BOOL rc;
|
||||||
PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data)
|
PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data)
|
||||||
|
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 */
|
/* Colorloss recover, Chroma supersample and AYCoCg to ARGB Conversion in one step */
|
||||||
PROFILER_ENTER(context->priv->prof_nsc_decode)
|
{
|
||||||
context->decode(context);
|
BOOL rc;
|
||||||
PROFILER_EXIT(context->priv->prof_nsc_decode)
|
PROFILER_ENTER(context->priv->prof_nsc_decode)
|
||||||
|
rc = context->decode(context);
|
||||||
|
PROFILER_EXIT(context->priv->prof_nsc_decode)
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst,
|
if (!freerdp_image_copy(pDstData, DstFormat, nDstStride, nXDst, nYDst,
|
||||||
width, height, context->BitmapData,
|
width, height, context->BitmapData,
|
||||||
|
@ -51,6 +51,7 @@ static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context)
|
|||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
|
BYTE* tmp = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
|
||||||
|
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ fail:
|
|||||||
return FALSE;
|
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)
|
UINT32 scanline)
|
||||||
{
|
{
|
||||||
UINT16 x;
|
UINT16 x;
|
||||||
@ -104,10 +105,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data,
|
|||||||
INT16 b_val;
|
INT16 b_val;
|
||||||
BYTE a_val;
|
BYTE a_val;
|
||||||
UINT32 tempWidth;
|
UINT32 tempWidth;
|
||||||
|
|
||||||
|
if (!context || data || (scanline == 0))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||||
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
|
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
|
||||||
ccl = context->ColorLossLevel;
|
ccl = context->ColorLossLevel;
|
||||||
|
|
||||||
|
if (context->priv->PlaneBuffersLength < rw * scanline)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (rw < scanline * 2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
for (y = 0; y < context->height; y++)
|
for (y = 0; y < context->height; y++)
|
||||||
{
|
{
|
||||||
src = data + (context->height - 1 - y) * scanline;
|
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(coplane, coplane - rw, rw);
|
||||||
CopyMemory(cgplane, cgplane - 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 x;
|
||||||
UINT16 y;
|
UINT16 y;
|
||||||
BYTE* co_dst;
|
|
||||||
BYTE* cg_dst;
|
|
||||||
INT8* co_src0;
|
|
||||||
INT8* co_src1;
|
|
||||||
INT8* cg_src0;
|
|
||||||
INT8* cg_src1;
|
|
||||||
UINT32 tempWidth;
|
UINT32 tempWidth;
|
||||||
UINT32 tempHeight;
|
UINT32 tempHeight;
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
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++)
|
for (y = 0; y < tempHeight >> 1; y++)
|
||||||
{
|
{
|
||||||
co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
|
BYTE* co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
|
||||||
cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
|
BYTE* cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
|
||||||
co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
|
const INT8* co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
|
||||||
co_src1 = co_src0 + tempWidth;
|
const INT8* co_src1 = co_src0 + tempWidth;
|
||||||
cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
|
const INT8* cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
|
||||||
cg_src1 = cg_src0 + tempWidth;
|
const INT8* cg_src1 = cg_src0 + tempWidth;
|
||||||
|
|
||||||
for (x = 0; x < tempWidth >> 1; x++)
|
for (x = 0; x < tempWidth >> 1; x++)
|
||||||
{
|
{
|
||||||
@ -280,19 +297,28 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
|
|||||||
cg_src1 += 2;
|
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)
|
if (context->ChromaSubsamplingLevel)
|
||||||
{
|
{
|
||||||
nsc_encode_subsampling(context);
|
if (!nsc_encode_subsampling(context))
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize)
|
static UINT32 nsc_rle_encode(const BYTE* in, BYTE* out, UINT32 originalSize)
|
||||||
{
|
{
|
||||||
UINT32 left;
|
UINT32 left;
|
||||||
UINT32 runlength = 1;
|
UINT32 runlength = 1;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include <freerdp/api.h>
|
#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);
|
UINT32 rowstride);
|
||||||
|
|
||||||
#endif /* FREERDP_LIB_CODEC_NSC_ENCODE_H */
|
#endif /* FREERDP_LIB_CODEC_NSC_ENCODE_H */
|
||||||
|
@ -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)
|
UINT32 scanline)
|
||||||
{
|
{
|
||||||
nsc_encode_argb_to_aycocg_sse2(context, data, 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);
|
nsc_encode_subsampling_sse2(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsc_init_sse2(NSC_CONTEXT* context)
|
void nsc_init_sse2(NSC_CONTEXT* context)
|
||||||
|
@ -44,14 +44,34 @@
|
|||||||
|
|
||||||
struct _ZGFX_TOKEN
|
struct _ZGFX_TOKEN
|
||||||
{
|
{
|
||||||
int prefixLength;
|
UINT32 prefixLength;
|
||||||
int prefixCode;
|
UINT32 prefixCode;
|
||||||
int valueBits;
|
UINT32 valueBits;
|
||||||
int tokenType;
|
UINT32 tokenType;
|
||||||
UINT32 valueBase;
|
UINT32 valueBase;
|
||||||
};
|
};
|
||||||
typedef struct _ZGFX_TOKEN ZGFX_TOKEN;
|
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[] =
|
static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
|
||||||
{
|
{
|
||||||
// len code vbits type vbase
|
// len code vbits type vbase
|
||||||
@ -98,17 +118,27 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
|
|||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define zgfx_GetBits(_zgfx, _nbits) \
|
static INLINE BOOL zgfx_GetBits(ZGFX_CONTEXT* _zgfx, UINT32 _nbits)
|
||||||
while (_zgfx->cBitsCurrent < _nbits) { \
|
{
|
||||||
_zgfx->BitsCurrent <<= 8; \
|
if (!_zgfx)
|
||||||
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \
|
return FALSE;
|
||||||
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \
|
|
||||||
_zgfx->cBitsCurrent += 8; \
|
while (_zgfx->cBitsCurrent < _nbits)
|
||||||
} \
|
{
|
||||||
_zgfx->cBitsRemaining -= _nbits; \
|
_zgfx->BitsCurrent <<= 8;
|
||||||
_zgfx->cBitsCurrent -= _nbits; \
|
|
||||||
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
|
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);
|
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count)
|
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 c;
|
||||||
BYTE flags;
|
BYTE flags;
|
||||||
int extra;
|
UINT32 extra = 0;
|
||||||
int opIndex;
|
int opIndex;
|
||||||
int haveBits;
|
int haveBits;
|
||||||
int inPrefix;
|
int inPrefix;
|
||||||
UINT32 count;
|
UINT32 count;
|
||||||
UINT32 distance;
|
UINT32 distance;
|
||||||
BYTE* pbSegment;
|
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;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT8(stream, flags); /* header (1 byte) */
|
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))
|
if (!(flags & PACKET_COMPRESSED))
|
||||||
{
|
{
|
||||||
zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment);
|
zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment);
|
||||||
|
|
||||||
|
if (cbSegment > sizeof(zgfx->OutputBuffer))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment);
|
CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment);
|
||||||
zgfx->OutputCount = cbSegment;
|
zgfx->OutputCount = cbSegment;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -251,6 +291,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
|
|||||||
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||||
zgfx->HistoryIndex = 0;
|
zgfx->HistoryIndex = 0;
|
||||||
|
|
||||||
|
if (zgfx->OutputCount >= sizeof(zgfx->OutputBuffer))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
|
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -284,6 +327,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
|
|||||||
count += zgfx->bits;
|
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_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
|
||||||
zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
|
zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count);
|
||||||
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->cBitsRemaining -= zgfx->cBitsCurrent;
|
||||||
zgfx->cBitsCurrent = 0;
|
zgfx->cBitsCurrent = 0;
|
||||||
zgfx->BitsCurrent = 0;
|
zgfx->BitsCurrent = 0;
|
||||||
|
|
||||||
|
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count);
|
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count);
|
||||||
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);
|
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);
|
||||||
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;
|
int status = -1;
|
||||||
BYTE descriptor;
|
BYTE descriptor;
|
||||||
|
|
||||||
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
|
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
|
||||||
|
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -333,6 +383,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
*ppDstData = NULL;
|
*ppDstData = NULL;
|
||||||
|
|
||||||
if (zgfx->OutputCount > 0)
|
if (zgfx->OutputCount > 0)
|
||||||
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
|
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
|
||||||
|
|
||||||
@ -349,6 +400,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
|
|||||||
UINT16 segmentCount;
|
UINT16 segmentCount;
|
||||||
UINT32 uncompressedSize;
|
UINT32 uncompressedSize;
|
||||||
BYTE* pConcatenated;
|
BYTE* pConcatenated;
|
||||||
|
size_t used = 0;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(stream) < 6)
|
if (Stream_GetRemainingLength(stream) < 6)
|
||||||
goto fail;
|
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))
|
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (zgfx->OutputCount > UINT32_MAX - used)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (used + zgfx->OutputCount > uncompressedSize)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
|
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||||
pConcatenated += zgfx->OutputCount;
|
pConcatenated += zgfx->OutputCount;
|
||||||
|
used += zgfx->OutputCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -208,11 +208,9 @@ BITMAP_UPDATE* update_read_bitmap_update(rdpUpdate* update, wStream* s)
|
|||||||
|
|
||||||
if (bitmapUpdate->number > bitmapUpdate->count)
|
if (bitmapUpdate->number > bitmapUpdate->count)
|
||||||
{
|
{
|
||||||
UINT16 count;
|
UINT32 count = bitmapUpdate->number * 2;
|
||||||
BITMAP_DATA* newdata;
|
BITMAP_DATA* newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
|
||||||
count = bitmapUpdate->number * 2;
|
sizeof(BITMAP_DATA) * count);
|
||||||
newdata = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
|
|
||||||
sizeof(BITMAP_DATA) * count);
|
|
||||||
|
|
||||||
if (!newdata)
|
if (!newdata)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -141,9 +141,17 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
|||||||
{
|
{
|
||||||
UINT32 SrcSize = length;
|
UINT32 SrcSize = length;
|
||||||
rdpGdi* gdi = context->gdi;
|
rdpGdi* gdi = context->gdi;
|
||||||
|
UINT32 size = DstWidth * DstHeight;
|
||||||
bitmap->compressed = FALSE;
|
bitmap->compressed = FALSE;
|
||||||
bitmap->format = gdi->dstFormat;
|
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);
|
bitmap->data = (BYTE*) _aligned_malloc(bitmap->length, 16);
|
||||||
|
|
||||||
if (!bitmap->data)
|
if (!bitmap->data)
|
||||||
|
@ -147,6 +147,7 @@ struct _NTLMv2_CLIENT_CHALLENGE
|
|||||||
BYTE ClientChallenge[8];
|
BYTE ClientChallenge[8];
|
||||||
UINT32 Reserved3;
|
UINT32 Reserved3;
|
||||||
NTLM_AV_PAIR* AvPairs;
|
NTLM_AV_PAIR* AvPairs;
|
||||||
|
UINT32 cbAvPairs;
|
||||||
};
|
};
|
||||||
typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE;
|
typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "../../log.h"
|
#include "../../log.h"
|
||||||
#define TAG WINPR_TAG("sspi.NTLM")
|
#define TAG WINPR_TAG("sspi.NTLM")
|
||||||
|
|
||||||
const char* const AV_PAIR_STRINGS[] =
|
static const char* const AV_PAIR_STRINGS[] =
|
||||||
{
|
{
|
||||||
"MsvAvEOL",
|
"MsvAvEOL",
|
||||||
"MsvAvNbComputerName",
|
"MsvAvNbComputerName",
|
||||||
@ -54,14 +54,42 @@ const char* const AV_PAIR_STRINGS[] =
|
|||||||
"MsvChannelBindings"
|
"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;
|
Data_Write_UINT16(&pAvPair->AvId, id);
|
||||||
ntlm_av_pair_set_id(pAvPair, MsvAvEOL);
|
|
||||||
ntlm_av_pair_set_len(pAvPair, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
ULONG length;
|
||||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
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)
|
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);
|
length = (pAvPair - pAvPairList) + sizeof(NTLM_AV_PAIR);
|
||||||
return length;
|
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;
|
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"",
|
WLog_INFO(TAG, "\t%s AvId: %"PRIu16" AvLen: %"PRIu16"",
|
||||||
AV_PAIR_STRINGS[ntlm_av_pair_get_id(pAvPair)],
|
AV_PAIR_STRINGS[ntlm_av_pair_get_id(pAvPair)],
|
||||||
ntlm_av_pair_get_id(pAvPair),
|
ntlm_av_pair_get_id(pAvPair),
|
||||||
ntlm_av_pair_get_len(pAvPair));
|
ntlm_av_pair_get_len(pAvPair, cbAvPairList));
|
||||||
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair),
|
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair, cbAvPairList),
|
||||||
ntlm_av_pair_get_len(pAvPair));
|
ntlm_av_pair_get_len(pAvPair, cbAvPairList));
|
||||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
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 */
|
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
|
||||||
return ((AvPairsCount + 1) * 4) + AvPairsValueLength;
|
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)];
|
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;
|
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||||
|
|
||||||
if (!pAvPair)
|
if (pcbAvPairListRemainingLength)
|
||||||
return NULL;
|
*pcbAvPairListRemainingLength = 0;
|
||||||
|
|
||||||
while (1)
|
while (pAvPair)
|
||||||
{
|
{
|
||||||
if (ntlm_av_pair_get_id(pAvPair) == AvId)
|
if (ntlm_av_pair_get_id(pAvPair) == AvId)
|
||||||
|
{
|
||||||
|
if (pcbAvPairListRemainingLength)
|
||||||
|
*pcbAvPairListRemainingLength = avPairListLength;
|
||||||
|
|
||||||
return pAvPair;
|
return pAvPair;
|
||||||
|
}
|
||||||
|
|
||||||
if (ntlm_av_pair_get_id(pAvPair) == MsvAvEOL)
|
if (ntlm_av_pair_get_id(pAvPair) == MsvAvEOL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair, &avPairListLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
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,
|
||||||
UINT16 AvLen)
|
NTLM_AV_ID AvId, PBYTE Value,
|
||||||
|
UINT16 AvLen)
|
||||||
{
|
{
|
||||||
|
size_t cbAvPair;
|
||||||
NTLM_AV_PAIR* pAvPair;
|
NTLM_AV_PAIR* pAvPair;
|
||||||
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
|
pAvPair = ntlm_av_pair_get(pAvPairList, cbAvPairListLength, MsvAvEOL, &cbAvPair);
|
||||||
|
|
||||||
if (!pAvPair)
|
if (!pAvPair)
|
||||||
return NULL;
|
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);
|
assert(Value != NULL);
|
||||||
ntlm_av_pair_set_id(pAvPair, AvId);
|
ntlm_av_pair_set_id(pAvPair, AvId);
|
||||||
ntlm_av_pair_set_len(pAvPair, AvLen);
|
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;
|
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;
|
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)
|
if (!pAvPairCopy)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
CopyMemory(&pAvPairCopy->AvId, &pAvPair->AvId, 2);
|
CopyMemory(&pAvPairCopy->AvId, &pAvPair->AvId, 2);
|
||||||
CopyMemory(&pAvPairCopy->AvLen, &pAvPair->AvLen, 2);
|
CopyMemory(&pAvPairCopy->AvLen, &pAvPair->AvLen, 2);
|
||||||
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy),
|
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy, cbAvPairCopy),
|
||||||
ntlm_av_pair_get_value_pointer(pAvPair),
|
ntlm_av_pair_get_value_pointer(pAvPair, cbAvPair),
|
||||||
ntlm_av_pair_get_len(pAvPair));
|
ntlm_av_pair_get_len(pAvPair, cbAvPair));
|
||||||
return pAvPairCopy;
|
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;
|
char* name;
|
||||||
int status;
|
int status;
|
||||||
@ -219,7 +288,7 @@ int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT ty
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ntlm_free_unicode_string(PUNICODE_STRING string)
|
static void ntlm_free_unicode_string(PUNICODE_STRING string)
|
||||||
{
|
{
|
||||||
if (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);
|
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;
|
WINPR_DIGEST_CTX* md5;
|
||||||
BYTE* ChannelBindingToken;
|
BYTE* ChannelBindingToken;
|
||||||
@ -317,7 +386,7 @@ out:
|
|||||||
winpr_Digest_Free(md5);
|
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
|
* 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 ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
|
||||||
{
|
{
|
||||||
|
int rc = -1;
|
||||||
int length;
|
int length;
|
||||||
ULONG AvPairsCount;
|
ULONG AvPairsCount;
|
||||||
ULONG AvPairsLength;
|
ULONG AvPairsLength;
|
||||||
NTLM_AV_PAIR* pAvPairList;
|
NTLM_AV_PAIR* pAvPairList;
|
||||||
UNICODE_STRING NbDomainName;
|
size_t cbAvPairList;
|
||||||
UNICODE_STRING NbComputerName;
|
UNICODE_STRING NbDomainName = { 0 };
|
||||||
UNICODE_STRING DnsDomainName;
|
UNICODE_STRING NbComputerName = { 0 };
|
||||||
UNICODE_STRING DnsComputerName;
|
UNICODE_STRING DnsDomainName = { 0 };
|
||||||
NbDomainName.Buffer = NULL;
|
UNICODE_STRING DnsComputerName = { 0 };
|
||||||
|
|
||||||
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
|
if (ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS) < 0)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
NbComputerName.Buffer = NULL;
|
NbComputerName.Buffer = NULL;
|
||||||
|
|
||||||
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
|
if (ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS) < 0)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
DnsDomainName.Buffer = NULL;
|
DnsDomainName.Buffer = NULL;
|
||||||
|
|
||||||
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
|
if (ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain) < 0)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
DnsComputerName.Buffer = NULL;
|
DnsComputerName.Buffer = NULL;
|
||||||
|
|
||||||
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
|
if (ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname) < 0)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
AvPairsCount = 5;
|
AvPairsCount = 5;
|
||||||
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
|
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);
|
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
|
||||||
|
|
||||||
if (!sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length))
|
if (!sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length))
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
|
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
|
||||||
ntlm_av_pair_list_init(pAvPairList);
|
cbAvPairList = context->ChallengeTargetInfo.cbBuffer;
|
||||||
ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer, NbDomainName.Length);
|
|
||||||
ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, (PBYTE) NbComputerName.Buffer,
|
if (!ntlm_av_pair_list_init(pAvPairList, cbAvPairList))
|
||||||
NbComputerName.Length);
|
goto fail;
|
||||||
ntlm_av_pair_add(pAvPairList, MsvAvDnsDomainName, (PBYTE) DnsDomainName.Buffer,
|
|
||||||
DnsDomainName.Length);
|
if (ntlm_av_pair_add(pAvPairList, cbAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer,
|
||||||
ntlm_av_pair_add(pAvPairList, MsvAvDnsComputerName, (PBYTE) DnsComputerName.Buffer,
|
NbDomainName.Length) == NULL)
|
||||||
DnsComputerName.Length);
|
goto fail;
|
||||||
ntlm_av_pair_add(pAvPairList, MsvAvTimestamp, context->Timestamp, sizeof(context->Timestamp));
|
|
||||||
|
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(&NbDomainName);
|
||||||
ntlm_free_unicode_string(&NbComputerName);
|
ntlm_free_unicode_string(&NbComputerName);
|
||||||
ntlm_free_unicode_string(&DnsDomainName);
|
ntlm_free_unicode_string(&DnsDomainName);
|
||||||
ntlm_free_unicode_string(&DnsComputerName);
|
ntlm_free_unicode_string(&DnsComputerName);
|
||||||
return 1;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
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* AvDnsTreeName;
|
||||||
NTLM_AV_PAIR* ChallengeTargetInfo;
|
NTLM_AV_PAIR* ChallengeTargetInfo;
|
||||||
NTLM_AV_PAIR* AuthenticateTargetInfo;
|
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;
|
AvPairsCount = 1;
|
||||||
AvPairsValueLength = 0;
|
AvPairsValueLength = 0;
|
||||||
ChallengeTargetInfo = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
|
ChallengeTargetInfo = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
|
||||||
AvNbDomainName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvNbDomainName);
|
cbChallengeTargetInfo = context->ChallengeTargetInfo.cbBuffer;
|
||||||
AvNbComputerName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvNbComputerName);
|
AvNbDomainName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvNbDomainName,
|
||||||
AvDnsDomainName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsDomainName);
|
&cbAvNbDomainName);
|
||||||
AvDnsComputerName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsComputerName);
|
AvNbComputerName = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvNbComputerName,
|
||||||
AvDnsTreeName = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvDnsTreeName);
|
&cbAvNbComputerName);
|
||||||
AvTimestamp = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvTimestamp);
|
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)
|
if (AvNbDomainName)
|
||||||
{
|
{
|
||||||
AvPairsCount++; /* MsvAvNbDomainName */
|
AvPairsCount++; /* MsvAvNbDomainName */
|
||||||
AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName);
|
AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName, cbAvNbDomainName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvNbComputerName)
|
if (AvNbComputerName)
|
||||||
{
|
{
|
||||||
AvPairsCount++; /* MsvAvNbComputerName */
|
AvPairsCount++; /* MsvAvNbComputerName */
|
||||||
AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName);
|
AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName, cbAvNbComputerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvDnsDomainName)
|
if (AvDnsDomainName)
|
||||||
{
|
{
|
||||||
AvPairsCount++; /* MsvAvDnsDomainName */
|
AvPairsCount++; /* MsvAvDnsDomainName */
|
||||||
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName);
|
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName, cbAvDnsDomainName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvDnsComputerName)
|
if (AvDnsComputerName)
|
||||||
{
|
{
|
||||||
AvPairsCount++; /* MsvAvDnsComputerName */
|
AvPairsCount++; /* MsvAvDnsComputerName */
|
||||||
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName);
|
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName, cbAvDnsComputerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvDnsTreeName)
|
if (AvDnsTreeName)
|
||||||
{
|
{
|
||||||
AvPairsCount++; /* MsvAvDnsTreeName */
|
AvPairsCount++; /* MsvAvDnsTreeName */
|
||||||
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName);
|
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName, cbAvDnsTreeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvPairsCount++; /* MsvAvTimestamp */
|
AvPairsCount++; /* MsvAvTimestamp */
|
||||||
@ -489,56 +594,96 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
AuthenticateTargetInfo = (NTLM_AV_PAIR*) context->AuthenticateTargetInfo.pvBuffer;
|
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)
|
if (AvNbDomainName)
|
||||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
|
{
|
||||||
|
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvNbDomainName,
|
||||||
|
cbAvNbDomainName) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (AvNbComputerName)
|
if (AvNbComputerName)
|
||||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
|
{
|
||||||
|
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
|
||||||
|
AvNbComputerName, cbAvNbComputerName) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (AvDnsDomainName)
|
if (AvDnsDomainName)
|
||||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
|
{
|
||||||
|
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
|
||||||
|
AvDnsDomainName, cbAvDnsDomainName) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (AvDnsComputerName)
|
if (AvDnsComputerName)
|
||||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
|
{
|
||||||
|
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
|
||||||
|
AvDnsComputerName, cbAvDnsComputerName) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (AvDnsTreeName)
|
if (AvDnsTreeName)
|
||||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
|
{
|
||||||
|
if (ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsTreeName,
|
||||||
|
cbAvDnsTreeName) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (AvTimestamp)
|
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)
|
if (context->UseMIC)
|
||||||
{
|
{
|
||||||
UINT32 flags;
|
UINT32 flags;
|
||||||
Data_Write_UINT32(&flags, MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK);
|
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)
|
if (context->SendSingleHostData)
|
||||||
{
|
{
|
||||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvSingleHost,
|
if (ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvSingleHost,
|
||||||
(PBYTE) &context->SingleHostData, context->SingleHostData.Size);
|
(PBYTE) &context->SingleHostData, context->SingleHostData.Size) == NULL)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context->SuppressExtendedProtection)
|
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)
|
if (context->ServicePrincipalName.Length > 0)
|
||||||
{
|
{
|
||||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvTargetName,
|
if (ntlm_av_pair_add(AuthenticateTargetInfo,
|
||||||
(PBYTE) context->ServicePrincipalName.Buffer,
|
cbAuthenticateTargetInfo,
|
||||||
context->ServicePrincipalName.Length);
|
MsvAvTargetName,
|
||||||
|
(PBYTE) context->ServicePrincipalName.Buffer,
|
||||||
|
context->ServicePrincipalName.Length) == NULL)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->NTLMv2)
|
if (context->NTLMv2)
|
||||||
{
|
{
|
||||||
NTLM_AV_PAIR* AvEOL;
|
NTLM_AV_PAIR* AvEOL;
|
||||||
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
|
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvEOL, NULL);
|
||||||
ZeroMemory((void*) AvEOL, 4);
|
|
||||||
|
if (!AvEOL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ZeroMemory(AvEOL, sizeof(NTLM_AV_PAIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -24,33 +24,11 @@
|
|||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList);
|
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairListMaxLength);
|
||||||
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList);
|
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList);
|
||||||
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList);
|
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair, size_t cbAvPairListMaxLength);
|
||||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength);
|
NTLM_AV_PAIR* ntlm_av_pair_get(void* pAvPairList, size_t avPairListLength, NTLM_AV_ID AvId,
|
||||||
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair);
|
size_t* pcbAvPairListRemainingLength);
|
||||||
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)
|
|
||||||
|
|
||||||
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
|
int ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
|
||||||
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
|
int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
|
||||||
|
@ -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(s, challenge->ClientChallenge, 8);
|
||||||
Stream_Read_UINT32(s, challenge->Reserved3);
|
Stream_Read_UINT32(s, challenge->Reserved3);
|
||||||
size = Stream_Length(s) - Stream_GetPosition(s);
|
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)
|
if (!challenge->AvPairs)
|
||||||
return -1;
|
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->Timestamp, 8);
|
||||||
Stream_Write(s, challenge->ClientChallenge, 8);
|
Stream_Write(s, challenge->ClientChallenge, 8);
|
||||||
Stream_Write_UINT32(s, challenge->Reserved3);
|
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);
|
Stream_Write(s, challenge->AvPairs, length);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ static const char* const NTLM_NEGOTIATE_STRINGS[] =
|
|||||||
"NTLMSSP_NEGOTIATE_UNICODE"
|
"NTLMSSP_NEGOTIATE_UNICODE"
|
||||||
};
|
};
|
||||||
|
|
||||||
void ntlm_print_negotiate_flags(UINT32 flags)
|
static void ntlm_print_negotiate_flags(UINT32 flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char* str;
|
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)
|
if (Stream_GetRemainingLength(s) < 12)
|
||||||
return -1;
|
return -1;
|
||||||
@ -104,19 +104,19 @@ int ntlm_read_message_header(wStream* s, NTLM_MESSAGE_HEADER* header)
|
|||||||
return 1;
|
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(s, header->Signature, sizeof(NTLM_SIGNATURE));
|
||||||
Stream_Write_UINT32(s, header->MessageType);
|
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));
|
CopyMemory(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));
|
||||||
header->MessageType = MessageType;
|
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)
|
if (Stream_GetRemainingLength(s) < 8)
|
||||||
return -1;
|
return -1;
|
||||||
@ -127,7 +127,7 @@ int ntlm_read_message_fields(wStream* s, NTLM_MESSAGE_FIELDS* fields)
|
|||||||
return 1;
|
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)
|
if (fields->MaxLen < 1)
|
||||||
fields->MaxLen = fields->Len;
|
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) */
|
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->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;
|
return -1;
|
||||||
|
|
||||||
fields->Buffer = (PBYTE) malloc(fields->Len);
|
fields->Buffer = (PBYTE) malloc(fields->Len);
|
||||||
@ -156,7 +161,7 @@ int ntlm_read_message_fields_buffer(wStream* s, NTLM_MESSAGE_FIELDS* fields)
|
|||||||
return 1;
|
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)
|
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)
|
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")",
|
WLog_DBG(TAG, "%s (Len: %"PRIu16" MaxLen: %"PRIu16" BufferOffset: %"PRIu32")",
|
||||||
name, fields->Len, fields->MaxLen, fields->BufferOffset);
|
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)
|
if (message->TargetInfo.Len > 0)
|
||||||
{
|
{
|
||||||
|
size_t cbAvTimestamp;
|
||||||
|
|
||||||
if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
|
if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
|
||||||
{
|
{
|
||||||
Stream_Free(s, FALSE);
|
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.pvBuffer = message->TargetInfo.Buffer;
|
||||||
context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
|
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)
|
if (AvTimestamp)
|
||||||
{
|
{
|
||||||
|
PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp, cbAvTimestamp);
|
||||||
|
|
||||||
|
if (!ptr)
|
||||||
|
return SEC_E_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (context->NTLMv2)
|
if (context->NTLMv2)
|
||||||
context->UseMIC = TRUE;
|
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)
|
if (message->NtChallengeResponse.Len > 0)
|
||||||
{
|
{
|
||||||
|
size_t cbAvFlags;
|
||||||
wStream* snt = Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
|
wStream* snt = Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
|
||||||
|
|
||||||
if (!snt)
|
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.pvBuffer = (void*) context->NTLMv2Response.Challenge.AvPairs;
|
||||||
context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
|
context->ChallengeTargetInfo.cbBuffer = message->NtChallengeResponse.Len - (28 + 16);
|
||||||
CopyMemory(context->ClientChallenge, context->NTLMv2Response.Challenge.ClientChallenge, 8);
|
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)
|
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,
|
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)
|
SECURITY_STATUS ntlm_server_AuthenticateComplete(NTLM_CONTEXT* context)
|
||||||
{
|
{
|
||||||
UINT32 flags = 0;
|
UINT32 flags = 0;
|
||||||
|
size_t cbAvFlags;
|
||||||
NTLM_AV_PAIR* AvFlags = NULL;
|
NTLM_AV_PAIR* AvFlags = NULL;
|
||||||
NTLM_AUTHENTICATE_MESSAGE* message;
|
NTLM_AUTHENTICATE_MESSAGE* message;
|
||||||
BYTE messageIntegrityCheck[16];
|
BYTE messageIntegrityCheck[16];
|
||||||
|
|
||||||
|
if (!context)
|
||||||
|
return SEC_E_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (context->state != NTLM_STATE_COMPLETION)
|
if (context->state != NTLM_STATE_COMPLETION)
|
||||||
return SEC_E_OUT_OF_SEQUENCE;
|
return SEC_E_OUT_OF_SEQUENCE;
|
||||||
|
|
||||||
message = &context->AUTHENTICATE_MESSAGE;
|
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)
|
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 */
|
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
|
||||||
return SEC_E_INTERNAL_ERROR;
|
return SEC_E_INTERNAL_ERROR;
|
||||||
|
Loading…
Reference in New Issue
Block a user