commit
5da865a120
@ -26,10 +26,10 @@
|
||||
|
||||
struct stream
|
||||
{
|
||||
BYTE* p;
|
||||
BYTE* end;
|
||||
BYTE* data;
|
||||
BYTE* pointer;
|
||||
BYTE* buffer;
|
||||
size_t size;
|
||||
size_t length;
|
||||
};
|
||||
typedef struct stream Stream;
|
||||
typedef struct stream* PStream;
|
||||
@ -37,74 +37,74 @@ typedef struct stream* PStream;
|
||||
WINPR_API PStream PStreamAlloc(size_t size);
|
||||
WINPR_API void StreamAlloc(PStream s, size_t size);
|
||||
WINPR_API void StreamReAlloc(PStream s, size_t size);
|
||||
WINPR_API PStream PStreamAllocAttach(BYTE* data, size_t size);
|
||||
WINPR_API void StreamAllocAttach(PStream s, BYTE* data, size_t size);
|
||||
WINPR_API PStream PStreamAllocAttach(BYTE* buffer, size_t size);
|
||||
WINPR_API void StreamAllocAttach(PStream s, BYTE* buffer, size_t size);
|
||||
WINPR_API void PStreamFree(PStream s);
|
||||
WINPR_API void StreamFree(PStream s);
|
||||
WINPR_API void PStreamFreeDetach(PStream s);
|
||||
WINPR_API void StreamFreeDetach(PStream s);
|
||||
WINPR_API void StreamAttach(PStream s, BYTE* data, size_t size);
|
||||
WINPR_API void StreamAttach(PStream s, BYTE* buffer, size_t size);
|
||||
WINPR_API void StreamDetach(PStream s);
|
||||
|
||||
#define StreamRead_UINT8(_s, _v) do { _v = \
|
||||
*_s->p++; } while (0)
|
||||
*_s->pointer++; } while (0)
|
||||
|
||||
#define StreamRead_UINT16(_s, _v) do { _v = \
|
||||
(UINT16)(*_s->p) + \
|
||||
(((UINT16)(*(_s->p + 1))) << 8); \
|
||||
_s->p += 2; } while (0)
|
||||
(UINT16)(*_s->pointer) + \
|
||||
(((UINT16)(*(_s->pointer + 1))) << 8); \
|
||||
_s->pointer += 2; } while (0)
|
||||
|
||||
#define StreamRead_UINT16_BE(_s, _v) do { _v = \
|
||||
(((UINT16)(*_s->p)) << 8) + \
|
||||
(UINT16)(*(_s->p + 1)); \
|
||||
_s->p += 2; } while (0)
|
||||
(((UINT16)(*_s->pointer)) << 8) + \
|
||||
(UINT16)(*(_s->pointer + 1)); \
|
||||
_s->pointer += 2; } while (0)
|
||||
|
||||
#define StreamRead_UINT32(_s, _v) do { _v = \
|
||||
(UINT32)(*_s->p) + \
|
||||
(((UINT32)(*(_s->p + 1))) << 8) + \
|
||||
(((UINT32)(*(_s->p + 2))) << 16) + \
|
||||
(((UINT32)(*(_s->p + 3))) << 24); \
|
||||
_s->p += 4; } while (0)
|
||||
(UINT32)(*_s->pointer) + \
|
||||
(((UINT32)(*(_s->pointer + 1))) << 8) + \
|
||||
(((UINT32)(*(_s->pointer + 2))) << 16) + \
|
||||
(((UINT32)(*(_s->pointer + 3))) << 24); \
|
||||
_s->pointer += 4; } while (0)
|
||||
|
||||
#define StreamRead_UINT32_BE(_s, _v) do { _v = \
|
||||
(((uint32)(*(_s->p))) << 24) + \
|
||||
(((uint32)(*(_s->p + 1))) << 16) + \
|
||||
(((uint32)(*(_s->p + 2))) << 8) + \
|
||||
(((uint32)(*(_s->p + 3)))); \
|
||||
_s->p += 4; } while (0)
|
||||
(((uint32)(*(_s->pointer))) << 24) + \
|
||||
(((uint32)(*(_s->pointer + 1))) << 16) + \
|
||||
(((uint32)(*(_s->pointer + 2))) << 8) + \
|
||||
(((uint32)(*(_s->pointer + 3)))); \
|
||||
_s->pointer += 4; } while (0)
|
||||
|
||||
#define StreamRead_UINT64(_s, _v) do { _v = \
|
||||
(UINT64)(*_s->p) + \
|
||||
(((UINT64)(*(_s->p + 1))) << 8) + \
|
||||
(((UINT64)(*(_s->p + 2))) << 16) + \
|
||||
(((UINT64)(*(_s->p + 3))) << 24) + \
|
||||
(((UINT64)(*(_s->p + 4))) << 32) + \
|
||||
(((UINT64)(*(_s->p + 5))) << 40) + \
|
||||
(((UINT64)(*(_s->p + 6))) << 48) + \
|
||||
(((UINT64)(*(_s->p + 7))) << 56); \
|
||||
_s->p += 8; } while (0)
|
||||
(UINT64)(*_s->pointer) + \
|
||||
(((UINT64)(*(_s->pointer + 1))) << 8) + \
|
||||
(((UINT64)(*(_s->pointer + 2))) << 16) + \
|
||||
(((UINT64)(*(_s->pointer + 3))) << 24) + \
|
||||
(((UINT64)(*(_s->pointer + 4))) << 32) + \
|
||||
(((UINT64)(*(_s->pointer + 5))) << 40) + \
|
||||
(((UINT64)(*(_s->pointer + 6))) << 48) + \
|
||||
(((UINT64)(*(_s->pointer + 7))) << 56); \
|
||||
_s->pointer += 8; } while (0)
|
||||
|
||||
#define StreamRead(_s, _b, _n) do { \
|
||||
memcpy(_b, (_s->p), (_n)); \
|
||||
_s->p += (_n); \
|
||||
memcpy(_b, (_s->pointer), (_n)); \
|
||||
_s->pointer += (_n); \
|
||||
} while (0)
|
||||
|
||||
#define StreamWrite_UINT8(_s, _v) do { \
|
||||
*_s->p++ = (UINT8)(_v); } while (0)
|
||||
*_s->pointer++ = (UINT8)(_v); } while (0)
|
||||
|
||||
#define StreamWrite_UINT16(_s, _v) do { \
|
||||
*_s->p++ = (_v) & 0xFF; \
|
||||
*_s->p++ = ((_v) >> 8) & 0xFF; } while (0)
|
||||
*_s->pointer++ = (_v) & 0xFF; \
|
||||
*_s->pointer++ = ((_v) >> 8) & 0xFF; } while (0)
|
||||
|
||||
#define StreamWrite_UINT16_BE(_s, _v) do { \
|
||||
*_s->p++ = ((_v) >> 8) & 0xFF; \
|
||||
*_s->p++ = (_v) & 0xFF; } while (0)
|
||||
*_s->pointer++ = ((_v) >> 8) & 0xFF; \
|
||||
*_s->pointer++ = (_v) & 0xFF; } while (0)
|
||||
|
||||
#define StreamWrite_UINT32(_s, _v) do { \
|
||||
*_s->p++ = (_v) & 0xFF; \
|
||||
*_s->p++ = ((_v) >> 8) & 0xFF; \
|
||||
*_s->p++ = ((_v) >> 16) & 0xFF; \
|
||||
*_s->p++ = ((_v) >> 24) & 0xFF; } while (0)
|
||||
*_s->pointer++ = (_v) & 0xFF; \
|
||||
*_s->pointer++ = ((_v) >> 8) & 0xFF; \
|
||||
*_s->pointer++ = ((_v) >> 16) & 0xFF; \
|
||||
*_s->pointer++ = ((_v) >> 24) & 0xFF; } while (0)
|
||||
|
||||
#define StreamWrite_UINT32_BE(_s, _v) do { \
|
||||
StreamWrite_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); \
|
||||
@ -112,52 +112,52 @@ WINPR_API void StreamDetach(PStream s);
|
||||
} while (0)
|
||||
|
||||
#define StreamWrite_UINT64(_s, _v) do { \
|
||||
*_s->p++ = (UINT64)(_v) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 8) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 16) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 24) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 32) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 40) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 48) & 0xFF; \
|
||||
*_s->p++ = ((UINT64)(_v) >> 56) & 0xFF; } while (0)
|
||||
*_s->pointer++ = (UINT64)(_v) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; \
|
||||
*_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; } while (0)
|
||||
|
||||
#define StreamWrite(_s, _b, _n) do { \
|
||||
memcpy(_s->p, (_b), (_n)); \
|
||||
_s->p += (_n); \
|
||||
memcpy(_s->pointer, (_b), (_n)); \
|
||||
_s->pointer += (_n); \
|
||||
} while (0)
|
||||
|
||||
#define StreamPeek_UINT8(_s, _v) do { _v = \
|
||||
*_s->p; } while (0)
|
||||
*_s->pointer; } while (0)
|
||||
|
||||
#define StreamPeek_UINT16(_s, _v) do { _v = \
|
||||
(UINT16)(*_s->p) + \
|
||||
(((UINT16)(*(_s->p + 1))) << 8); \
|
||||
(UINT16)(*_s->pointer) + \
|
||||
(((UINT16)(*(_s->pointer + 1))) << 8); \
|
||||
} while (0)
|
||||
|
||||
#define StreamPeek_UINT32(_s, _v) do { _v = \
|
||||
(UINT32)(*_s->p) + \
|
||||
(((UINT32)(*(_s->p + 1))) << 8) + \
|
||||
(((UINT32)(*(_s->p + 2))) << 16) + \
|
||||
(((UINT32)(*(_s->p + 3))) << 24); \
|
||||
(UINT32)(*_s->pointer) + \
|
||||
(((UINT32)(*(_s->pointer + 1))) << 8) + \
|
||||
(((UINT32)(*(_s->pointer + 2))) << 16) + \
|
||||
(((UINT32)(*(_s->pointer + 3))) << 24); \
|
||||
} while (0)
|
||||
|
||||
#define StreamPeek_UINT64(_s, _v) do { _v = \
|
||||
(UINT64)(*_s->p) + \
|
||||
(((UINT64)(*(_s->p + 1))) << 8) + \
|
||||
(((UINT64)(*(_s->p + 2))) << 16) + \
|
||||
(((UINT64)(*(_s->p + 3))) << 24) + \
|
||||
(((UINT64)(*(_s->p + 4))) << 32) + \
|
||||
(((UINT64)(*(_s->p + 5))) << 40) + \
|
||||
(((UINT64)(*(_s->p + 6))) << 48) + \
|
||||
(((UINT64)(*(_s->p + 7))) << 56); \
|
||||
(UINT64)(*_s->pointer) + \
|
||||
(((UINT64)(*(_s->pointer + 1))) << 8) + \
|
||||
(((UINT64)(*(_s->pointer + 2))) << 16) + \
|
||||
(((UINT64)(*(_s->pointer + 3))) << 24) + \
|
||||
(((UINT64)(*(_s->pointer + 4))) << 32) + \
|
||||
(((UINT64)(*(_s->pointer + 5))) << 40) + \
|
||||
(((UINT64)(*(_s->pointer + 6))) << 48) + \
|
||||
(((UINT64)(*(_s->pointer + 7))) << 56); \
|
||||
} while (0)
|
||||
|
||||
#define StreamPeek(_s, _b, _n) do { \
|
||||
memcpy(_b, (_s->p), (_n)); \
|
||||
memcpy(_b, (_s->pointer), (_n)); \
|
||||
} while (0)
|
||||
|
||||
#define StreamSeek(_s,_offset) _s->p += (_offset)
|
||||
#define StreamRewind(_s,_offset) _s->p -= (_offset)
|
||||
#define StreamSeek(_s,_offset) _s->pointer += (_offset)
|
||||
#define StreamRewind(_s,_offset) _s->pointer -= (_offset)
|
||||
|
||||
#define StreamSeek_UINT8(_s) StreamSeek(_s, 1)
|
||||
#define StreamSeek_UINT16(_s) StreamSeek(_s, 2)
|
||||
@ -170,37 +170,33 @@ WINPR_API void StreamDetach(PStream s);
|
||||
#define StreamRewind_UINT64(_s) StreamRewind(_s, 8)
|
||||
|
||||
#define StreamZero(_s, _n) do { \
|
||||
memset(_s->p, '\0', (_n)); \
|
||||
_s->p += (_n); \
|
||||
memset(_s->pointer, '\0', (_n)); \
|
||||
_s->pointer += (_n); \
|
||||
} while (0)
|
||||
|
||||
#define StreamFill(_s, _v, _n) do { \
|
||||
memset(_s->p, _v, (_n)); \
|
||||
_s->p += (_n); \
|
||||
memset(_s->pointer, _v, (_n)); \
|
||||
_s->pointer += (_n); \
|
||||
} while (0)
|
||||
|
||||
#define StreamCopy(_dst, _src, _n) do { \
|
||||
memcpy(_dst->p, _src->p, _n); \
|
||||
_dst->p += _n; \
|
||||
_src->p += _n; \
|
||||
memcpy(_dst->pointer, _src->pointer, _n); \
|
||||
_dst->pointer += _n; \
|
||||
_src->pointer += _n; \
|
||||
} while (0)
|
||||
|
||||
#define StreamGetOffset(_s) (_s->p - _s->data)
|
||||
#define StreamSetOffset(_s, _m) _s->p = _s->data + (_m)
|
||||
#define StreamGetPointer(_s, _p) _p = _s->pointer
|
||||
#define StreamSetPointer(_s, _p) _s->pointer = _p
|
||||
|
||||
#define StreamSeal(_s) _s->end = (_s->p - _s->data)
|
||||
#define StreamGetPosition(_s) (_s->pointer - _s->buffer)
|
||||
#define StreamSetPosition(_s, _p) _s->pointer = _s->buffer + (_p)
|
||||
|
||||
#define StreamGetMark(_s, _m) _m = _s->p
|
||||
#define StreamSetMark(_s, _m) _s->p = _m
|
||||
#define StreamPointer(_s) _s->pointer
|
||||
#define StreamBuffer(_s) _s->buffer
|
||||
#define StreamSize(_s) _s->size
|
||||
#define StreamLength(_s) _s->length
|
||||
|
||||
#define StreamGetData(_s) _s->data
|
||||
#define StreamGetPointer(_s) _s->p
|
||||
#define StreamSetPointer(_s, _m) _s->p = _m
|
||||
#define StreamGetEnd(_s) _s->end
|
||||
#define StreamGetSize(_s) _s->size
|
||||
|
||||
#define StreamSize(_s) (_s->p - _s->data)
|
||||
#define StreamSealedSize(_s) (_s->end - _s->data)
|
||||
#define StreamRemainingSize(_s) (_s->size - (_s->p - _s->data))
|
||||
#define StreamRemainingSize(_s) (_s->size - (_s->pointer - _s->buffer))
|
||||
#define StreamRemainingLength(_s) (_s->length - (_s->pointer - _s->buffer))
|
||||
|
||||
#endif /* WINPR_UTILS_STREAM_H */
|
||||
|
@ -145,6 +145,8 @@ WINPR_API BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation);
|
||||
#define GetVersionEx GetVersionExA
|
||||
#endif
|
||||
|
||||
WINPR_API VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_SYSINFO_H */
|
||||
|
@ -54,6 +54,14 @@ typedef float FLOAT;
|
||||
typedef unsigned char UCHAR, *PUCHAR;
|
||||
typedef short SHORT;
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
typedef void* HANDLE, *LPHANDLE;
|
||||
typedef DWORD HCALL;
|
||||
typedef int INT, *LPINT;
|
||||
@ -135,6 +143,23 @@ typedef LPSTR LPTSTR;
|
||||
typedef LPCSTR LPCTSTR;
|
||||
#endif
|
||||
|
||||
typedef union _ULARGE_INTEGER
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
} u;
|
||||
|
||||
ULONGLONG QuadPart;
|
||||
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
||||
|
||||
typedef struct _FILETIME
|
||||
{
|
||||
DWORD dwLowDateTime;
|
||||
|
@ -537,6 +537,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
|
||||
status = SEC_I_CONTINUE_NEEDED;
|
||||
}
|
||||
|
||||
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
|
||||
{
|
||||
printf("AcceptSecurityContext status: 0x%08X\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send authentication token */
|
||||
|
||||
#ifdef WITH_DEBUG_CREDSSP
|
||||
|
@ -47,15 +47,23 @@ void ntlm_SetContextWorkstation(NTLM_CONTEXT* context, char* Workstation)
|
||||
GetComputerNameExA(ComputerNameNetBIOS, Workstation, &nSize);
|
||||
}
|
||||
|
||||
context->WorkstationLength = strlen(Workstation) * 2;
|
||||
context->Workstation = (UINT16*) malloc(context->WorkstationLength);
|
||||
context->Workstation.Length = strlen(Workstation) * 2;
|
||||
context->Workstation.Buffer = (PWSTR) malloc(context->Workstation.Length);
|
||||
MultiByteToWideChar(CP_ACP, 0, Workstation, strlen(Workstation),
|
||||
(LPWSTR) context->Workstation, context->WorkstationLength / 2);
|
||||
context->Workstation.Buffer, context->Workstation.Length / 2);
|
||||
|
||||
if (nSize > 0)
|
||||
free(Workstation);
|
||||
}
|
||||
|
||||
void ntlm_SetContextServicePrincipalName(NTLM_CONTEXT* context, char* ServicePrincipalName)
|
||||
{
|
||||
context->ServicePrincipalName.Length = strlen(ServicePrincipalName) * 2;
|
||||
context->ServicePrincipalName.Buffer = (PWSTR) malloc(context->ServicePrincipalName.Length);
|
||||
MultiByteToWideChar(CP_ACP, 0, ServicePrincipalName, strlen(ServicePrincipalName),
|
||||
context->ServicePrincipalName.Buffer, context->ServicePrincipalName.Length / 2);
|
||||
}
|
||||
|
||||
void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
|
||||
{
|
||||
DWORD nSize = 0;
|
||||
@ -65,6 +73,7 @@ void ntlm_SetContextTargetName(NTLM_CONTEXT* context, char* TargetName)
|
||||
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
|
||||
TargetName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsHostname, TargetName, &nSize);
|
||||
CharUpperA(TargetName);
|
||||
}
|
||||
|
||||
context->TargetName.cbBuffer = strlen(TargetName) * 2;
|
||||
@ -85,14 +94,17 @@ NTLM_CONTEXT* ntlm_ContextNew()
|
||||
|
||||
if (context != NULL)
|
||||
{
|
||||
context->ntlm_v2 = 0;
|
||||
context->NTLMv2 = TRUE;
|
||||
context->UseMIC = FALSE;
|
||||
context->NegotiateFlags = 0;
|
||||
context->SendVersionInfo = 0;
|
||||
context->SendVersionInfo = TRUE;
|
||||
context->LmCompatibilityLevel = 3;
|
||||
context->state = NTLM_STATE_INITIAL;
|
||||
context->SuppressExtendedProtection = 1;
|
||||
context->av_pairs = (AV_PAIRS*) malloc(sizeof(AV_PAIRS));
|
||||
ZeroMemory(context->av_pairs, sizeof(AV_PAIRS));
|
||||
context->SuppressExtendedProtection = FALSE;
|
||||
memset(context->MachineID, 0xAA, sizeof(context->MachineID));
|
||||
|
||||
if (context->NTLMv2)
|
||||
context->UseMIC = TRUE;
|
||||
}
|
||||
|
||||
return context;
|
||||
@ -106,7 +118,7 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
|
||||
sspi_SecBufferFree(&context->NegotiateMessage);
|
||||
sspi_SecBufferFree(&context->ChallengeMessage);
|
||||
sspi_SecBufferFree(&context->AuthenticateMessage);
|
||||
sspi_SecBufferFree(&context->TargetInfo);
|
||||
sspi_SecBufferFree(&context->ChallengeTargetInfo);
|
||||
sspi_SecBufferFree(&context->TargetName);
|
||||
sspi_SecBufferFree(&context->NtChallengeResponse);
|
||||
sspi_SecBufferFree(&context->LmChallengeResponse);
|
||||
@ -114,9 +126,7 @@ void ntlm_ContextFree(NTLM_CONTEXT* context)
|
||||
free(context->identity.User);
|
||||
free(context->identity.Password);
|
||||
free(context->identity.Domain);
|
||||
free(context->Workstation);
|
||||
free(context->av_pairs->Timestamp.value);
|
||||
free(context->av_pairs);
|
||||
free(context->Workstation.Buffer);
|
||||
free(context);
|
||||
}
|
||||
|
||||
@ -372,8 +382,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti
|
||||
|
||||
credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
|
||||
|
||||
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
|
||||
ntlm_SetContextWorkstation(context, NULL);
|
||||
ntlm_SetContextServicePrincipalName(context, pszTargetName);
|
||||
sspi_CopyAuthIdentity(&context->identity, &credentials->identity);
|
||||
|
||||
sspi_SecureHandleSetLowerPointer(phNewContext, context);
|
||||
sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NTLM_PACKAGE_NAME);
|
||||
|
@ -34,6 +34,43 @@
|
||||
|
||||
#include "../sspi.h"
|
||||
|
||||
#define MESSAGE_TYPE_NEGOTIATE 1
|
||||
#define MESSAGE_TYPE_CHALLENGE 2
|
||||
#define MESSAGE_TYPE_AUTHENTICATE 3
|
||||
|
||||
#define NTLMSSP_NEGOTIATE_56 0x80000000 /* W (0) */
|
||||
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 /* V (1) */
|
||||
#define NTLMSSP_NEGOTIATE_128 0x20000000 /* U (2) */
|
||||
#define NTLMSSP_RESERVED1 0x10000000 /* r1 (3) */
|
||||
#define NTLMSSP_RESERVED2 0x08000000 /* r2 (4) */
|
||||
#define NTLMSSP_RESERVED3 0x04000000 /* r3 (5) */
|
||||
#define NTLMSSP_NEGOTIATE_VERSION 0x02000000 /* T (6) */
|
||||
#define NTLMSSP_RESERVED4 0x01000000 /* r4 (7) */
|
||||
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000 /* S (8) */
|
||||
#define NTLMSSP_REQUEST_NON_NT_SESSION_KEY 0x00400000 /* R (9) */
|
||||
#define NTLMSSP_RESERVED5 0x00200000 /* r5 (10) */
|
||||
#define NTLMSSP_NEGOTIATE_IDENTIFY 0x00100000 /* Q (11) */
|
||||
#define NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY 0x00080000 /* P (12) */
|
||||
#define NTLMSSP_RESERVED6 0x00040000 /* r6 (13) */
|
||||
#define NTLMSSP_TARGET_TYPE_SERVER 0x00020000 /* O (14) */
|
||||
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000 /* N (15) */
|
||||
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000 /* M (16) */
|
||||
#define NTLMSSP_RESERVED7 0x00004000 /* r7 (17) */
|
||||
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000 /* L (18) */
|
||||
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000 /* K (19) */
|
||||
#define NTLMSSP_NEGOTIATE_ANONYMOUS 0x00000800 /* J (20) */
|
||||
#define NTLMSSP_RESERVED8 0x00000400 /* r8 (21) */
|
||||
#define NTLMSSP_NEGOTIATE_NTLM 0x00000200 /* H (22) */
|
||||
#define NTLMSSP_RESERVED9 0x00000100 /* r9 (23) */
|
||||
#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080 /* G (24) */
|
||||
#define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040 /* F (25) */
|
||||
#define NTLMSSP_NEGOTIATE_SEAL 0x00000020 /* E (26) */
|
||||
#define NTLMSSP_NEGOTIATE_SIGN 0x00000010 /* D (27) */
|
||||
#define NTLMSSP_RESERVED10 0x00000008 /* r10 (28) */
|
||||
#define NTLMSSP_REQUEST_TARGET 0x00000004 /* C (29) */
|
||||
#define NTLMSSP_NEGOTIATE_OEM 0x00000002 /* B (30) */
|
||||
#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001 /* A (31) */
|
||||
|
||||
enum _NTLM_STATE
|
||||
{
|
||||
NTLM_STATE_INITIAL,
|
||||
@ -44,29 +81,7 @@ enum _NTLM_STATE
|
||||
};
|
||||
typedef enum _NTLM_STATE NTLM_STATE;
|
||||
|
||||
struct _AV_PAIR
|
||||
{
|
||||
UINT16 length;
|
||||
BYTE* value;
|
||||
};
|
||||
typedef struct _AV_PAIR AV_PAIR;
|
||||
|
||||
struct _AV_PAIRS
|
||||
{
|
||||
AV_PAIR NbComputerName;
|
||||
AV_PAIR NbDomainName;
|
||||
AV_PAIR DnsComputerName;
|
||||
AV_PAIR DnsDomainName;
|
||||
AV_PAIR DnsTreeName;
|
||||
AV_PAIR Timestamp;
|
||||
AV_PAIR Restrictions;
|
||||
AV_PAIR TargetName;
|
||||
AV_PAIR ChannelBindings;
|
||||
UINT32 Flags;
|
||||
};
|
||||
typedef struct _AV_PAIRS AV_PAIRS;
|
||||
|
||||
enum _AV_ID
|
||||
enum _NTLM_AV_ID
|
||||
{
|
||||
MsvAvEOL,
|
||||
MsvAvNbComputerName,
|
||||
@ -80,16 +95,138 @@ enum _AV_ID
|
||||
MsvAvTargetName,
|
||||
MsvChannelBindings
|
||||
};
|
||||
typedef enum _AV_ID AV_ID;
|
||||
typedef enum _NTLM_AV_ID NTLM_AV_ID;
|
||||
|
||||
struct _NTLM_AV_PAIR
|
||||
{
|
||||
UINT16 AvId;
|
||||
UINT16 AvLen;
|
||||
};
|
||||
typedef struct _NTLM_AV_PAIR NTLM_AV_PAIR;
|
||||
|
||||
#define MSV_AV_FLAGS_AUTHENTICATION_CONSTRAINED 0x00000001
|
||||
#define MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK 0x00000002
|
||||
#define MSV_AV_FLAGS_TARGET_SPN_UNTRUSTED_SOURCE 0x00000004
|
||||
|
||||
#define WINDOWS_MAJOR_VERSION_5 0x05
|
||||
#define WINDOWS_MAJOR_VERSION_6 0x06
|
||||
#define WINDOWS_MINOR_VERSION_0 0x00
|
||||
#define WINDOWS_MINOR_VERSION_1 0x01
|
||||
#define WINDOWS_MINOR_VERSION_2 0x02
|
||||
#define NTLMSSP_REVISION_W2K3 0x0F
|
||||
|
||||
struct _NTLM_VERSION_INFO
|
||||
{
|
||||
UINT8 ProductMajorVersion;
|
||||
UINT8 ProductMinorVersion;
|
||||
UINT16 ProductBuild;
|
||||
BYTE Reserved[3];
|
||||
UINT8 NTLMRevisionCurrent;
|
||||
};
|
||||
typedef struct _NTLM_VERSION_INFO NTLM_VERSION_INFO;
|
||||
|
||||
struct _NTLM_RESTRICTION_ENCODING
|
||||
{
|
||||
UINT32 Size;
|
||||
UINT32 Z4;
|
||||
UINT32 IntegrityLevel;
|
||||
UINT32 SubjectIntegrityLevel;
|
||||
BYTE MachineID[32];
|
||||
};
|
||||
typedef struct _NTLM_RESTRICTION_ENCODING NTLM_RESTRICTION_ENCODING;
|
||||
|
||||
struct _NTLM_RESPONSE
|
||||
{
|
||||
BYTE Response[24];
|
||||
};
|
||||
typedef struct _NTLM_RESPONSE NTLM_RESPONSE;
|
||||
|
||||
struct _NTLMv2_CLIENT_CHALLENGE
|
||||
{
|
||||
UINT8 RespType;
|
||||
UINT8 HiRespType;
|
||||
UINT16 Reserved1;
|
||||
UINT32 Reserved2;
|
||||
BYTE Timestamp[8];
|
||||
BYTE ClientChallenge[8];
|
||||
UINT32 Reserved3;
|
||||
NTLM_AV_PAIR* AvPairs;
|
||||
};
|
||||
typedef struct _NTLMv2_CLIENT_CHALLENGE NTLMv2_CLIENT_CHALLENGE;
|
||||
|
||||
struct _NTLMv2_RESPONSE
|
||||
{
|
||||
BYTE Response[16];
|
||||
NTLMv2_CLIENT_CHALLENGE Challenge;
|
||||
};
|
||||
typedef struct _NTLMv2_RESPONSE NTLMv2_RESPONSE;
|
||||
|
||||
struct _NTLM_MESSAGE_FIELDS
|
||||
{
|
||||
UINT16 Len;
|
||||
UINT16 MaxLen;
|
||||
PBYTE Buffer;
|
||||
UINT32 BufferOffset;
|
||||
};
|
||||
typedef struct _NTLM_MESSAGE_FIELDS NTLM_MESSAGE_FIELDS;
|
||||
|
||||
struct _NTLM_MESSAGE_HEADER
|
||||
{
|
||||
BYTE Signature[8];
|
||||
UINT32 MessageType;
|
||||
};
|
||||
typedef struct _NTLM_MESSAGE_HEADER NTLM_MESSAGE_HEADER;
|
||||
|
||||
struct _NTLM_NEGOTIATE_MESSAGE
|
||||
{
|
||||
BYTE Signature[8];
|
||||
UINT32 MessageType;
|
||||
UINT32 NegotiateFlags;
|
||||
NTLM_VERSION_INFO Version;
|
||||
NTLM_MESSAGE_FIELDS DomainName;
|
||||
NTLM_MESSAGE_FIELDS Workstation;
|
||||
};
|
||||
typedef struct _NTLM_NEGOTIATE_MESSAGE NTLM_NEGOTIATE_MESSAGE;
|
||||
|
||||
struct _NTLM_CHALLENGE_MESSAGE
|
||||
{
|
||||
BYTE Signature[8];
|
||||
UINT32 MessageType;
|
||||
UINT32 NegotiateFlags;
|
||||
BYTE ServerChallenge[8];
|
||||
BYTE Reserved[8];
|
||||
NTLM_VERSION_INFO Version;
|
||||
NTLM_MESSAGE_FIELDS TargetName;
|
||||
NTLM_MESSAGE_FIELDS TargetInfo;
|
||||
};
|
||||
typedef struct _NTLM_CHALLENGE_MESSAGE NTLM_CHALLENGE_MESSAGE;
|
||||
|
||||
struct _NTLM_AUTHENTICATE_MESSAGE
|
||||
{
|
||||
BYTE Signature[8];
|
||||
UINT32 MessageType;
|
||||
UINT32 NegotiateFlags;
|
||||
NTLM_VERSION_INFO Version;
|
||||
NTLM_MESSAGE_FIELDS DomainName;
|
||||
NTLM_MESSAGE_FIELDS UserName;
|
||||
NTLM_MESSAGE_FIELDS Workstation;
|
||||
NTLM_MESSAGE_FIELDS LmChallengeResponse;
|
||||
NTLM_MESSAGE_FIELDS NtChallengeResponse;
|
||||
NTLM_MESSAGE_FIELDS EncryptedRandomSessionKey;
|
||||
BYTE MessageIntegrityCheck[16];
|
||||
};
|
||||
typedef struct _NTLM_AUTHENTICATE_MESSAGE NTLM_AUTHENTICATE_MESSAGE;
|
||||
|
||||
struct _NTLM_CONTEXT
|
||||
{
|
||||
BOOL server;
|
||||
BOOL ntlm_v2;
|
||||
BOOL NTLMv2;
|
||||
BOOL UseMIC;
|
||||
NTLM_STATE state;
|
||||
int SendSeqNum;
|
||||
int RecvSeqNum;
|
||||
int SendVersionInfo;
|
||||
BYTE MachineID[32];
|
||||
BOOL SendVersionInfo;
|
||||
BOOL confidentiality;
|
||||
RC4_KEY SendRc4Seal;
|
||||
RC4_KEY RecvRc4Seal;
|
||||
@ -97,21 +234,22 @@ struct _NTLM_CONTEXT
|
||||
BYTE* RecvSigningKey;
|
||||
BYTE* SendSealingKey;
|
||||
BYTE* RecvSealingKey;
|
||||
AV_PAIRS* av_pairs;
|
||||
UINT32 NegotiateFlags;
|
||||
UINT16* Workstation;
|
||||
UINT32 WorkstationLength;
|
||||
int LmCompatibilityLevel;
|
||||
int SuppressExtendedProtection;
|
||||
UNICODE_STRING Workstation;
|
||||
UNICODE_STRING ServicePrincipalName;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
SecBuffer NegotiateMessage;
|
||||
SecBuffer ChallengeMessage;
|
||||
SecBuffer AuthenticateMessage;
|
||||
SecBuffer TargetInfo;
|
||||
SecBuffer ChallengeTargetInfo;
|
||||
SecBuffer AuthenticateTargetInfo;
|
||||
SecBuffer TargetName;
|
||||
SecBuffer NtChallengeResponse;
|
||||
SecBuffer LmChallengeResponse;
|
||||
BYTE Timestamp[8];
|
||||
BYTE ChallengeTimestamp[8];
|
||||
BYTE ServerChallenge[8];
|
||||
BYTE ClientChallenge[8];
|
||||
BYTE SessionBaseKey[16];
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "ntlm_av_pairs.h"
|
||||
|
||||
const char* const AV_PAIRS_STRINGS[] =
|
||||
const char* const AV_PAIR_STRINGS[] =
|
||||
{
|
||||
"MsvAvEOL",
|
||||
"MsvAvNbComputerName",
|
||||
@ -43,463 +43,323 @@ const char* const AV_PAIRS_STRINGS[] =
|
||||
"MsvChannelBindings"
|
||||
};
|
||||
|
||||
/**
|
||||
* Input array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s)
|
||||
void ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList)
|
||||
{
|
||||
AV_ID AvId;
|
||||
UINT16 AvLen;
|
||||
BYTE* value;
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("AV_PAIRS = {\n");
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
value = NULL;
|
||||
StreamRead_UINT16(s, AvId);
|
||||
StreamRead_UINT16(s, AvLen);
|
||||
|
||||
if (AvLen > 0)
|
||||
{
|
||||
if (AvId != MsvAvFlags)
|
||||
{
|
||||
value = malloc(AvLen);
|
||||
StreamRead(s, value, AvLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
StreamRead_UINT32(s, av_pairs->Flags);
|
||||
}
|
||||
}
|
||||
|
||||
switch (AvId)
|
||||
{
|
||||
case MsvAvNbComputerName:
|
||||
av_pairs->NbComputerName.length = AvLen;
|
||||
av_pairs->NbComputerName.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvNbDomainName:
|
||||
av_pairs->NbDomainName.length = AvLen;
|
||||
av_pairs->NbDomainName.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvDnsComputerName:
|
||||
av_pairs->DnsComputerName.length = AvLen;
|
||||
av_pairs->DnsComputerName.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvDnsDomainName:
|
||||
av_pairs->DnsDomainName.length = AvLen;
|
||||
av_pairs->DnsDomainName.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvDnsTreeName:
|
||||
av_pairs->DnsTreeName.length = AvLen;
|
||||
av_pairs->DnsTreeName.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvTimestamp:
|
||||
av_pairs->Timestamp.length = AvLen;
|
||||
av_pairs->Timestamp.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvRestrictions:
|
||||
av_pairs->Restrictions.length = AvLen;
|
||||
av_pairs->Restrictions.value = value;
|
||||
break;
|
||||
|
||||
case MsvAvTargetName:
|
||||
av_pairs->TargetName.length = AvLen;
|
||||
av_pairs->TargetName.value = value;
|
||||
break;
|
||||
|
||||
case MsvChannelBindings:
|
||||
av_pairs->ChannelBindings.length = AvLen;
|
||||
av_pairs->ChannelBindings.value = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
if (AvId < 10)
|
||||
printf("\tAvId: %s, AvLen: %d\n", AV_PAIRS_STRINGS[AvId], AvLen);
|
||||
else
|
||||
printf("\tAvId: %s, AvLen: %d\n", "Unknown", AvLen);
|
||||
|
||||
winpr_HexDump(value, AvLen);
|
||||
#endif
|
||||
}
|
||||
while (AvId != MsvAvEOL);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("}\n");
|
||||
#endif
|
||||
pAvPair->AvId = MsvAvEOL;
|
||||
pAvPair->AvLen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_output_av_pairs(NTLM_CONTEXT* context, PSecBuffer buffer)
|
||||
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList)
|
||||
{
|
||||
PStream s;
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
ULONG length;
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer);
|
||||
if (!pAvPair)
|
||||
return 0;
|
||||
|
||||
if (av_pairs->NbDomainName.length > 0)
|
||||
while (pAvPair->AvId != MsvAvEOL)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvNbDomainName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->NbDomainName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->NbDomainName.value, av_pairs->NbDomainName.length); /* Value */
|
||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||
}
|
||||
|
||||
if (av_pairs->NbComputerName.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvNbComputerName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->NbComputerName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->NbComputerName.value, av_pairs->NbComputerName.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->DnsDomainName.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvDnsDomainName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->DnsDomainName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->DnsComputerName.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvDnsComputerName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->DnsComputerName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->DnsTreeName.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvDnsTreeName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->DnsTreeName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->Timestamp.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvTimestamp); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->Timestamp.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->Timestamp.value, av_pairs->Timestamp.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->Flags > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvFlags); /* AvId */
|
||||
StreamWrite_UINT16(s, 4); /* AvLen */
|
||||
StreamWrite_UINT32(s, av_pairs->Flags); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->Restrictions.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvRestrictions); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->Restrictions.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->Restrictions.value, av_pairs->Restrictions.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->ChannelBindings.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvChannelBindings); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->ChannelBindings.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length); /* Value */
|
||||
}
|
||||
|
||||
if (av_pairs->TargetName.length > 0)
|
||||
{
|
||||
StreamWrite_UINT16(s, MsvAvTargetName); /* AvId */
|
||||
StreamWrite_UINT16(s, av_pairs->TargetName.length); /* AvLen */
|
||||
StreamWrite(s, av_pairs->TargetName.value, av_pairs->TargetName.length); /* Value */
|
||||
}
|
||||
|
||||
/* This indicates the end of the AV_PAIR array */
|
||||
StreamWrite_UINT16(s, MsvAvEOL); /* AvId */
|
||||
StreamWrite_UINT16(s, 0); /* AvLen */
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
StreamZero(s, 8);
|
||||
}
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute AV_PAIRs length.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
int ntlm_compute_av_pairs_length(NTLM_CONTEXT* context)
|
||||
{
|
||||
int length = 0;
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
|
||||
if (av_pairs->NbDomainName.length > 0)
|
||||
length += av_pairs->NbDomainName.length + 4;
|
||||
|
||||
if (av_pairs->NbComputerName.length > 0)
|
||||
length += av_pairs->NbComputerName.length + 4;
|
||||
|
||||
if (av_pairs->DnsDomainName.length > 0)
|
||||
length += av_pairs->DnsDomainName.length + 4;
|
||||
|
||||
if (av_pairs->DnsComputerName.length > 0)
|
||||
length += av_pairs->DnsComputerName.length + 4;
|
||||
|
||||
if (av_pairs->DnsTreeName.length > 0)
|
||||
length += av_pairs->DnsTreeName.length + 4;
|
||||
|
||||
if (av_pairs->Timestamp.length > 0)
|
||||
length += av_pairs->Timestamp.length;
|
||||
|
||||
if (av_pairs->Flags > 0)
|
||||
length += 4 + 4;
|
||||
|
||||
if (av_pairs->Restrictions.length > 0)
|
||||
length += av_pairs->Restrictions.length + 4;
|
||||
|
||||
if (av_pairs->ChannelBindings.length > 0)
|
||||
length += av_pairs->ChannelBindings.length + 4;
|
||||
|
||||
if (av_pairs->TargetName.length > 0)
|
||||
length += av_pairs->TargetName.length + 4;
|
||||
|
||||
length += 4;
|
||||
|
||||
if (context->ntlm_v2)
|
||||
length += 8;
|
||||
length = (pAvPair - pAvPairList) + sizeof(NTLM_AV_PAIR);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_populate_av_pairs(NTLM_CONTEXT* context)
|
||||
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList)
|
||||
{
|
||||
int length;
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
/* MsvAvFlags */
|
||||
av_pairs->Flags = 0x00000002; /* Indicates the present of a Message Integrity Check (MIC) */
|
||||
if (!pAvPair)
|
||||
return;
|
||||
|
||||
/* Restriction_Encoding */
|
||||
ntlm_output_restriction_encoding(context);
|
||||
printf("AV_PAIRs =\n{\n");
|
||||
|
||||
/* TargetName */
|
||||
ntlm_output_target_name(context);
|
||||
|
||||
/* ChannelBindings */
|
||||
ntlm_output_channel_bindings(context);
|
||||
|
||||
length = ntlm_compute_av_pairs_length(context);
|
||||
sspi_SecBufferAlloc(&context->TargetInfo, length);
|
||||
ntlm_output_av_pairs(context, &context->TargetInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate array of AV_PAIRs (server).\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context)
|
||||
{
|
||||
int length;
|
||||
DWORD nSize;
|
||||
AV_PAIRS* av_pairs;
|
||||
char* NbDomainName;
|
||||
char* NbComputerName;
|
||||
char* DnsDomainName;
|
||||
char* DnsComputerName;
|
||||
|
||||
av_pairs = context->av_pairs;
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
|
||||
NbDomainName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NbDomainName, &nSize);
|
||||
CharUpperA(NbDomainName);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize);
|
||||
NbComputerName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameNetBIOS, NbComputerName, &nSize);
|
||||
CharUpperA(NbComputerName);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameDnsDomain, NULL, &nSize);
|
||||
DnsDomainName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsDomain, DnsDomainName, &nSize);
|
||||
|
||||
nSize = 0;
|
||||
GetComputerNameExA(ComputerNameDnsHostname, NULL, &nSize);
|
||||
DnsComputerName = malloc(nSize);
|
||||
GetComputerNameExA(ComputerNameDnsHostname, DnsComputerName, &nSize);
|
||||
|
||||
av_pairs->NbDomainName.length = strlen(NbDomainName) * 2;
|
||||
av_pairs->NbDomainName.value = (BYTE*) malloc(av_pairs->NbDomainName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, NbDomainName, strlen(NbDomainName),
|
||||
(LPWSTR) av_pairs->NbDomainName.value, av_pairs->NbDomainName.length / 2);
|
||||
|
||||
av_pairs->NbComputerName.length = strlen(NbDomainName) * 2;
|
||||
av_pairs->NbComputerName.value = (BYTE*) malloc(av_pairs->NbComputerName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, NbComputerName, strlen(NbComputerName),
|
||||
(LPWSTR) av_pairs->NbComputerName.value, av_pairs->NbComputerName.length / 2);
|
||||
|
||||
av_pairs->DnsDomainName.length = strlen(DnsDomainName) * 2;
|
||||
av_pairs->DnsDomainName.value = (BYTE*) malloc(av_pairs->DnsDomainName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, DnsDomainName, strlen(DnsDomainName),
|
||||
(LPWSTR) av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length / 2);
|
||||
|
||||
av_pairs->DnsComputerName.length = strlen(DnsComputerName) * 2;
|
||||
av_pairs->DnsComputerName.value = (BYTE*) malloc(av_pairs->DnsComputerName.length);
|
||||
MultiByteToWideChar(CP_ACP, 0, DnsComputerName, strlen(DnsComputerName),
|
||||
(LPWSTR) av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length / 2);
|
||||
|
||||
length = ntlm_compute_av_pairs_length(context) + 4;
|
||||
sspi_SecBufferAlloc(&context->TargetInfo, length);
|
||||
ntlm_output_av_pairs(context, &context->TargetInfo);
|
||||
|
||||
free(NbDomainName);
|
||||
free(NbComputerName);
|
||||
free(DnsDomainName);
|
||||
free(DnsComputerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_print_av_pairs(NTLM_CONTEXT* context)
|
||||
{
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
|
||||
printf("AV_PAIRS = {\n");
|
||||
|
||||
if (av_pairs->NbDomainName.length > 0)
|
||||
while (pAvPair->AvId != MsvAvEOL)
|
||||
{
|
||||
printf("\tAvId: MsvAvNbDomainName AvLen: %d\n", av_pairs->NbDomainName.length);
|
||||
winpr_HexDump(av_pairs->NbDomainName.value, av_pairs->NbDomainName.length);
|
||||
}
|
||||
printf("\t%s AvId: %d AvLen: %d\n",
|
||||
AV_PAIR_STRINGS[pAvPair->AvId],
|
||||
pAvPair->AvId, pAvPair->AvLen);
|
||||
|
||||
if (av_pairs->NbComputerName.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvNbComputerName AvLen: %d\n", av_pairs->NbComputerName.length);
|
||||
winpr_HexDump(av_pairs->NbComputerName.value, av_pairs->NbComputerName.length);
|
||||
}
|
||||
winpr_HexDump(ntlm_av_pair_get_value_pointer(pAvPair), pAvPair->AvLen);
|
||||
|
||||
if (av_pairs->DnsDomainName.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvDnsDomainName AvLen: %d\n", av_pairs->DnsDomainName.length);
|
||||
winpr_HexDump(av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length);
|
||||
}
|
||||
|
||||
if (av_pairs->DnsComputerName.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvDnsComputerName AvLen: %d\n", av_pairs->DnsComputerName.length);
|
||||
winpr_HexDump(av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length);
|
||||
}
|
||||
|
||||
if (av_pairs->DnsTreeName.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvDnsTreeName AvLen: %d\n", av_pairs->DnsTreeName.length);
|
||||
winpr_HexDump(av_pairs->DnsTreeName.value, av_pairs->DnsTreeName.length);
|
||||
}
|
||||
|
||||
if (av_pairs->Timestamp.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvTimestamp AvLen: %d\n", av_pairs->Timestamp.length);
|
||||
winpr_HexDump(av_pairs->Timestamp.value, av_pairs->Timestamp.length);
|
||||
}
|
||||
|
||||
if (av_pairs->Flags > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvFlags AvLen: %d\n", 4);
|
||||
printf("0x%08X\n", av_pairs->Flags);
|
||||
}
|
||||
|
||||
if (av_pairs->Restrictions.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvRestrictions AvLen: %d\n", av_pairs->Restrictions.length);
|
||||
winpr_HexDump(av_pairs->Restrictions.value, av_pairs->Restrictions.length);
|
||||
}
|
||||
|
||||
if (av_pairs->ChannelBindings.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvChannelBindings AvLen: %d\n", av_pairs->ChannelBindings.length);
|
||||
winpr_HexDump(av_pairs->ChannelBindings.value, av_pairs->ChannelBindings.length);
|
||||
}
|
||||
|
||||
if (av_pairs->TargetName.length > 0)
|
||||
{
|
||||
printf("\tAvId: MsvAvTargetName AvLen: %d\n", av_pairs->TargetName.length);
|
||||
winpr_HexDump(av_pairs->TargetName.value, av_pairs->TargetName.length);
|
||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||
}
|
||||
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Free array of AV_PAIRs.\n
|
||||
* AV_PAIR @msdn{cc236646}
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_free_av_pairs(NTLM_CONTEXT* context)
|
||||
ULONG ntlm_av_pair_list_size(ULONG AvPairsCount, ULONG AvPairsValueLength)
|
||||
{
|
||||
AV_PAIRS* av_pairs = context->av_pairs;
|
||||
/* size of headers + value lengths + terminating MsvAvEOL AV_PAIR */
|
||||
return (AvPairsCount + 1) * sizeof(NTLM_AV_PAIR) + AvPairsValueLength;
|
||||
}
|
||||
|
||||
if (av_pairs != NULL)
|
||||
PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return &((PBYTE) pAvPair)[sizeof(NTLM_AV_PAIR)];
|
||||
}
|
||||
|
||||
int ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return pAvPair->AvLen + sizeof(NTLM_AV_PAIR);
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get_next_pointer(NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
return (NTLM_AV_PAIR*) ((PBYTE) pAvPair + ntlm_av_pair_get_next_offset(pAvPair));
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPair = pAvPairList;
|
||||
|
||||
if (!pAvPair)
|
||||
return NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (av_pairs->NbComputerName.value != NULL)
|
||||
free(av_pairs->NbComputerName.value);
|
||||
if (av_pairs->NbDomainName.value != NULL)
|
||||
free(av_pairs->NbDomainName.value);
|
||||
if (av_pairs->DnsComputerName.value != NULL)
|
||||
free(av_pairs->DnsComputerName.value);
|
||||
if (av_pairs->DnsDomainName.value != NULL)
|
||||
free(av_pairs->DnsDomainName.value);
|
||||
if (av_pairs->DnsTreeName.value != NULL)
|
||||
free(av_pairs->DnsTreeName.value);
|
||||
if (av_pairs->Timestamp.value != NULL)
|
||||
free(av_pairs->Timestamp.value);
|
||||
if (av_pairs->Restrictions.value != NULL)
|
||||
free(av_pairs->Restrictions.value);
|
||||
if (av_pairs->TargetName.value != NULL)
|
||||
free(av_pairs->TargetName.value);
|
||||
if (av_pairs->ChannelBindings.value != NULL)
|
||||
free(av_pairs->ChannelBindings.value);
|
||||
if (pAvPair->AvId == AvId)
|
||||
return pAvPair;
|
||||
|
||||
free(av_pairs);
|
||||
if (pAvPair->AvId == MsvAvEOL)
|
||||
return NULL;
|
||||
|
||||
pAvPair = ntlm_av_pair_get_next_pointer(pAvPair);
|
||||
}
|
||||
|
||||
context->av_pairs = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, NTLM_AV_ID AvId, PBYTE Value, UINT16 AvLen)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPair;
|
||||
|
||||
pAvPair = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
|
||||
|
||||
if (!pAvPair)
|
||||
return NULL;
|
||||
|
||||
pAvPair->AvId = AvId;
|
||||
pAvPair->AvLen = AvLen;
|
||||
|
||||
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPair), Value, AvLen);
|
||||
|
||||
return pAvPair;
|
||||
}
|
||||
|
||||
NTLM_AV_PAIR* ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, NTLM_AV_PAIR* pAvPair)
|
||||
{
|
||||
NTLM_AV_PAIR* pAvPairCopy;
|
||||
|
||||
pAvPairCopy = ntlm_av_pair_get(pAvPairList, MsvAvEOL);
|
||||
|
||||
if (!pAvPairCopy)
|
||||
return NULL;
|
||||
|
||||
pAvPairCopy->AvId = pAvPair->AvId;
|
||||
pAvPairCopy->AvLen = pAvPair->AvLen;
|
||||
|
||||
CopyMemory(ntlm_av_pair_get_value_pointer(pAvPairCopy),
|
||||
ntlm_av_pair_get_value_pointer(pAvPair), pAvPair->AvLen);
|
||||
|
||||
return pAvPairCopy;
|
||||
}
|
||||
|
||||
void ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
|
||||
{
|
||||
char* name;
|
||||
DWORD nSize = 0;
|
||||
|
||||
GetComputerNameExA(type, NULL, &nSize);
|
||||
name = malloc(nSize);
|
||||
GetComputerNameExA(type, name, &nSize);
|
||||
|
||||
if (type == ComputerNameNetBIOS)
|
||||
CharUpperA(name);
|
||||
|
||||
pName->Length = strlen(name) * 2;
|
||||
pName->Buffer = (PWSTR) malloc(pName->Length);
|
||||
MultiByteToWideChar(CP_ACP, 0, name, strlen(name),
|
||||
(LPWSTR) pName->Buffer, pName->Length / 2);
|
||||
|
||||
pName->MaximumLength = pName->Length;
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context)
|
||||
{
|
||||
int length;
|
||||
ULONG AvPairsCount;
|
||||
ULONG AvPairsLength;
|
||||
LONG AvPairListSize;
|
||||
NTLM_AV_PAIR* pAvPairList;
|
||||
UNICODE_STRING NbDomainName;
|
||||
UNICODE_STRING NbComputerName;
|
||||
UNICODE_STRING DnsDomainName;
|
||||
UNICODE_STRING DnsComputerName;
|
||||
|
||||
ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS);
|
||||
ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS);
|
||||
ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain);
|
||||
ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname);
|
||||
|
||||
AvPairsCount = 5;
|
||||
AvPairsLength = NbDomainName.Length + NbComputerName.Length +
|
||||
DnsDomainName.Length + DnsComputerName.Length + 8;
|
||||
|
||||
length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength);
|
||||
sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length);
|
||||
|
||||
pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer;
|
||||
AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
|
||||
{
|
||||
ULONG size;
|
||||
ULONG AvPairsCount;
|
||||
ULONG AvPairsValueLength;
|
||||
NTLM_AV_PAIR* AvTimestamp;
|
||||
NTLM_AV_PAIR* AvNbDomainName;
|
||||
NTLM_AV_PAIR* AvNbComputerName;
|
||||
NTLM_AV_PAIR* AvDnsDomainName;
|
||||
NTLM_AV_PAIR* AvDnsComputerName;
|
||||
NTLM_AV_PAIR* AvDnsTreeName;
|
||||
NTLM_AV_PAIR* ChallengeTargetInfo;
|
||||
NTLM_AV_PAIR* AuthenticateTargetInfo;
|
||||
|
||||
AvPairsCount = 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);
|
||||
|
||||
if (AvNbDomainName != NULL)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvNbDomainName */
|
||||
AvPairsValueLength += AvNbDomainName->AvLen;
|
||||
}
|
||||
|
||||
if (AvNbComputerName != NULL)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvNbComputerName */
|
||||
AvPairsValueLength += AvNbComputerName->AvLen;
|
||||
}
|
||||
|
||||
if (AvDnsDomainName != NULL)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvDnsDomainName */
|
||||
AvPairsValueLength += AvDnsDomainName->AvLen;
|
||||
}
|
||||
|
||||
if (AvDnsComputerName != NULL)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvDnsComputerName */
|
||||
AvPairsValueLength += AvDnsComputerName->AvLen;
|
||||
}
|
||||
|
||||
if (AvDnsTreeName != NULL)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvDnsTreeName */
|
||||
AvPairsValueLength += AvDnsTreeName->AvLen;
|
||||
}
|
||||
|
||||
AvPairsCount++; /* MsvAvTimestamp */
|
||||
AvPairsValueLength += 8;
|
||||
|
||||
if (context->UseMIC)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvFlags */
|
||||
AvPairsValueLength += 4;
|
||||
}
|
||||
|
||||
//AvPairsCount++; /* MsvAvRestrictions */
|
||||
//AvPairsValueLength += 48;
|
||||
|
||||
if (!context->SuppressExtendedProtection)
|
||||
{
|
||||
AvPairsCount++; /* MsvChannelBindings */
|
||||
AvPairsValueLength += 16;
|
||||
|
||||
if (context->ServicePrincipalName.Length > 0)
|
||||
{
|
||||
AvPairsCount++; /* MsvAvTargetName */
|
||||
AvPairsValueLength += context->ServicePrincipalName.Length;
|
||||
}
|
||||
}
|
||||
|
||||
size = ntlm_av_pair_list_size(AvPairsCount, AvPairsValueLength);
|
||||
|
||||
if (context->NTLMv2)
|
||||
size += 8; /* unknown 8-byte padding */
|
||||
|
||||
sspi_SecBufferAlloc(&context->AuthenticateTargetInfo, size);
|
||||
AuthenticateTargetInfo = (NTLM_AV_PAIR*) context->AuthenticateTargetInfo.pvBuffer;
|
||||
|
||||
ntlm_av_pair_list_init(AuthenticateTargetInfo);
|
||||
|
||||
if (AvNbDomainName != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbDomainName);
|
||||
|
||||
if (AvNbComputerName != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvNbComputerName);
|
||||
|
||||
if (AvDnsDomainName != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsDomainName);
|
||||
|
||||
if (AvDnsComputerName != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsComputerName);
|
||||
|
||||
if (AvDnsTreeName != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvDnsTreeName);
|
||||
|
||||
if (AvTimestamp != NULL)
|
||||
ntlm_av_pair_add_copy(AuthenticateTargetInfo, AvTimestamp);
|
||||
|
||||
if (context->UseMIC)
|
||||
{
|
||||
UINT32 flags = MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK;
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvFlags, (PBYTE) &flags, 4);
|
||||
}
|
||||
|
||||
if (!context->SuppressExtendedProtection)
|
||||
{
|
||||
BYTE ChannelBindingToken[16];
|
||||
|
||||
ZeroMemory(ChannelBindingToken, 16);
|
||||
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvChannelBindings,
|
||||
ChannelBindingToken, sizeof(ChannelBindingToken));
|
||||
|
||||
if (context->ServicePrincipalName.Length > 0)
|
||||
{
|
||||
ntlm_av_pair_add(AuthenticateTargetInfo, MsvAvTargetName,
|
||||
(PBYTE) context->ServicePrincipalName.Buffer,
|
||||
context->ServicePrincipalName.Length);
|
||||
}
|
||||
}
|
||||
|
||||
if (context->NTLMv2)
|
||||
{
|
||||
NTLM_AV_PAIR* AvEOL;
|
||||
|
||||
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, MsvAvEOL);
|
||||
ZeroMemory((void*) AvEOL, 12);
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,18 @@
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
void ntlm_input_av_pairs(NTLM_CONTEXT* context, PStream s);
|
||||
void ntlm_output_av_pairs(NTLM_CONTEXT* context, PSecBuffer buffer);
|
||||
void ntlm_populate_av_pairs(NTLM_CONTEXT* context);
|
||||
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context);
|
||||
void ntlm_print_av_pairs(NTLM_CONTEXT* context);
|
||||
void ntlm_free_av_pairs(NTLM_CONTEXT* context);
|
||||
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);
|
||||
|
||||
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context);
|
||||
void ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context);
|
||||
|
||||
#endif /* WINPR_SSPI_NTLM_AV_PAIRS_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <winpr/sam.h>
|
||||
#include <winpr/ntlm.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include "ntlm_compute.h"
|
||||
|
||||
@ -34,6 +35,121 @@ static const char server_sign_magic[] = "session key to server-to-client signing
|
||||
static const char client_seal_magic[] = "session key to client-to-server sealing key magic constant";
|
||||
static const char server_seal_magic[] = "session key to server-to-client sealing key magic constant";
|
||||
|
||||
/**
|
||||
* Populate VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
OSVERSIONINFOA osVersionInfo;
|
||||
|
||||
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||
|
||||
GetVersionExA(&osVersionInfo);
|
||||
|
||||
versionInfo->ProductMajorVersion = osVersionInfo.dwMajorVersion;
|
||||
versionInfo->ProductMinorVersion = osVersionInfo.dwMinorVersion;
|
||||
versionInfo->ProductBuild = osVersionInfo.dwBuildNumber;
|
||||
ZeroMemory(versionInfo->Reserved, sizeof(versionInfo->Reserved));
|
||||
versionInfo->NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
StreamRead_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
|
||||
StreamRead_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
|
||||
StreamRead_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
|
||||
StreamRead(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
|
||||
StreamRead_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Write VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
StreamWrite_UINT8(s, versionInfo->ProductMajorVersion); /* ProductMajorVersion (1 byte) */
|
||||
StreamWrite_UINT8(s, versionInfo->ProductMinorVersion); /* ProductMinorVersion (1 byte) */
|
||||
StreamWrite_UINT16(s, versionInfo->ProductBuild); /* ProductBuild (2 bytes) */
|
||||
StreamWrite(s, versionInfo->Reserved, sizeof(versionInfo->Reserved)); /* Reserved (3 bytes) */
|
||||
StreamWrite_UINT8(s, versionInfo->NTLMRevisionCurrent); /* NTLMRevisionCurrent (1 byte) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Print VERSION structure.\n
|
||||
* VERSION @msdn{cc236654}
|
||||
* @param s
|
||||
*/
|
||||
|
||||
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo)
|
||||
{
|
||||
printf("VERSION =\n{\n");
|
||||
printf("\tProductMajorVersion: %d\n", versionInfo->ProductMajorVersion);
|
||||
printf("\tProductMinorVersion: %d\n", versionInfo->ProductMinorVersion);
|
||||
printf("\tProductBuild: %d\n", versionInfo->ProductBuild);
|
||||
printf("\tReserved: 0x%02X%02X%02X\n", versionInfo->Reserved[0],
|
||||
versionInfo->Reserved[1], versionInfo->Reserved[2]);
|
||||
printf("\tNTLMRevisionCurrent: 0x%02X\n", versionInfo->NTLMRevisionCurrent);
|
||||
}
|
||||
|
||||
void ntlm_read_ntlm_v2_client_challenge(PStream s, NTLMv2_CLIENT_CHALLENGE* challenge)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
StreamRead_UINT8(s, challenge->RespType);
|
||||
StreamRead_UINT8(s, challenge->HiRespType);
|
||||
StreamRead_UINT16(s, challenge->Reserved1);
|
||||
StreamRead_UINT32(s, challenge->Reserved2);
|
||||
StreamRead(s, challenge->Timestamp, 8);
|
||||
StreamRead(s, challenge->ClientChallenge, 8);
|
||||
StreamRead_UINT32(s, challenge->Reserved3);
|
||||
|
||||
size = StreamRemainingSize(s);
|
||||
challenge->AvPairs = (NTLM_AV_PAIR*) malloc(size);
|
||||
StreamRead(s, challenge->AvPairs, size);
|
||||
}
|
||||
|
||||
void ntlm_write_ntlm_v2_client_challenge(PStream s, NTLMv2_CLIENT_CHALLENGE* challenge)
|
||||
{
|
||||
ULONG length;
|
||||
|
||||
StreamWrite_UINT8(s, challenge->RespType);
|
||||
StreamWrite_UINT8(s, challenge->HiRespType);
|
||||
StreamWrite_UINT16(s, challenge->Reserved1);
|
||||
StreamWrite_UINT32(s, challenge->Reserved2);
|
||||
StreamWrite(s, challenge->Timestamp, 8);
|
||||
StreamWrite(s, challenge->ClientChallenge, 8);
|
||||
StreamWrite_UINT32(s, challenge->Reserved3);
|
||||
|
||||
length = ntlm_av_pair_list_length(challenge->AvPairs);
|
||||
StreamWrite(s, challenge->AvPairs, length);
|
||||
}
|
||||
|
||||
void ntlm_read_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response)
|
||||
{
|
||||
StreamRead(s, response->Response, 16);
|
||||
ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge));
|
||||
}
|
||||
|
||||
void ntlm_write_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response)
|
||||
{
|
||||
StreamWrite(s, response->Response, 16);
|
||||
ntlm_write_ntlm_v2_client_challenge(s, &(response->Challenge));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* Output Restriction_Encoding.\n
|
||||
* Restriction_Encoding @msdn{cc236647}
|
||||
@ -67,54 +183,7 @@ void ntlm_output_restriction_encoding(NTLM_CONTEXT* context)
|
||||
PStreamFreeDetach(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output TargetName.\n
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_output_target_name(NTLM_CONTEXT* context)
|
||||
{
|
||||
PStream s;
|
||||
AV_PAIR* TargetName = &context->av_pairs->TargetName;
|
||||
|
||||
/*
|
||||
* TODO: No idea what should be set here (observed MsvAvTargetName = MsvAvDnsComputerName or
|
||||
* MsvAvTargetName should be the name of the service be accessed after authentication)
|
||||
* here used: "TERMSRV/192.168.0.123" in unicode (Dmitrij Jasnov)
|
||||
*/
|
||||
BYTE name[42] =
|
||||
"\x54\x00\x45\x00\x52\x00\x4d\x00\x53\x00\x52\x00\x56\x00\x2f\x00\x31\x00\x39\x00\x32"
|
||||
"\x00\x2e\x00\x31\x00\x36\x00\x38\x00\x2e\x00\x30\x00\x2e\x00\x31\x00\x32\x00\x33\x00";
|
||||
|
||||
TargetName->length = 42;
|
||||
TargetName->value = (BYTE*) malloc(TargetName->length);
|
||||
|
||||
s = PStreamAllocAttach(TargetName->value, TargetName->length);
|
||||
|
||||
StreamWrite(s, name, TargetName->length);
|
||||
|
||||
PStreamFreeDetach(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output ChannelBindings.\n
|
||||
* @param NTLM context
|
||||
*/
|
||||
|
||||
void ntlm_output_channel_bindings(NTLM_CONTEXT* context)
|
||||
{
|
||||
PStream s;
|
||||
AV_PAIR* ChannelBindings = &context->av_pairs->ChannelBindings;
|
||||
|
||||
ChannelBindings->value = (BYTE*) malloc(48);
|
||||
ChannelBindings->length = 16;
|
||||
|
||||
s = PStreamAllocAttach(ChannelBindings->value, ChannelBindings->length);
|
||||
|
||||
StreamZero(s, 16); /* an all-zero value of the hash is used to indicate absence of channel bindings */
|
||||
|
||||
PStreamFreeDetach(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get current time, in tenths of microseconds since midnight of January 1, 1601.
|
||||
@ -123,13 +192,15 @@ void ntlm_output_channel_bindings(NTLM_CONTEXT* context)
|
||||
|
||||
void ntlm_current_time(BYTE* timestamp)
|
||||
{
|
||||
UINT64 time64;
|
||||
FILETIME filetime;
|
||||
ULARGE_INTEGER time64;
|
||||
|
||||
/* Timestamp (8 bytes), represented as the number of tenths of microseconds since midnight of January 1, 1601 */
|
||||
time64 = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */
|
||||
time64 *= 10000000; /* Convert timestamp to tenths of a microsecond */
|
||||
GetSystemTimeAsFileTime(&filetime);
|
||||
|
||||
CopyMemory(timestamp, &time64, 8); /* Copy into timestamp in little-endian */
|
||||
time64.LowPart = filetime.dwLowDateTime;
|
||||
time64.HighPart = filetime.dwHighDateTime;
|
||||
|
||||
CopyMemory(timestamp, &(time64.QuadPart), 8);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,26 +210,14 @@ void ntlm_current_time(BYTE* timestamp)
|
||||
|
||||
void ntlm_generate_timestamp(NTLM_CONTEXT* context)
|
||||
{
|
||||
ntlm_current_time(context->Timestamp);
|
||||
BYTE ZeroTimestamp[8];
|
||||
|
||||
if (context->ntlm_v2)
|
||||
{
|
||||
if (context->av_pairs->Timestamp.length == 8)
|
||||
{
|
||||
CopyMemory(context->av_pairs->Timestamp.value, context->Timestamp, 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ZeroMemory(ZeroTimestamp, 8);
|
||||
|
||||
if (memcmp(ZeroTimestamp, context->ChallengeTimestamp, 8) != 0)
|
||||
CopyMemory(context->Timestamp, context->ChallengeTimestamp, 8);
|
||||
else
|
||||
{
|
||||
if (context->av_pairs->Timestamp.length != 8)
|
||||
{
|
||||
context->av_pairs->Timestamp.length = 8;
|
||||
context->av_pairs->Timestamp.value = malloc(context->av_pairs->Timestamp.length);
|
||||
}
|
||||
|
||||
CopyMemory(context->av_pairs->Timestamp.value, context->Timestamp, 8);
|
||||
}
|
||||
ntlm_current_time(context->Timestamp);
|
||||
}
|
||||
|
||||
void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
@ -169,13 +228,17 @@ void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash)
|
||||
sam = SamOpen(1);
|
||||
|
||||
entry = SamLookupUserW(sam,
|
||||
(LPWSTR) context->identity.User, context->identity.UserLength,
|
||||
(LPWSTR) context->identity.Domain, context->identity.DomainLength);
|
||||
(LPWSTR) context->identity.User, context->identity.UserLength * 2,
|
||||
(LPWSTR) context->identity.Domain, context->identity.DomainLength * 2);
|
||||
|
||||
if (entry != NULL)
|
||||
{
|
||||
CopyMemory(hash, entry->NtHash, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Could not find user in SAM database\n");
|
||||
}
|
||||
|
||||
SamFreeEntry(sam, entry);
|
||||
|
||||
@ -202,6 +265,13 @@ void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context)
|
||||
char value[16];
|
||||
char ntlm_v2_hash[16];
|
||||
|
||||
if (context->LmCompatibilityLevel < 2)
|
||||
{
|
||||
sspi_SecBufferAlloc(&context->LmChallengeResponse, 24);
|
||||
ZeroMemory(context->LmChallengeResponse.pvBuffer, 24);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the NTLMv2 hash */
|
||||
ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash);
|
||||
|
||||
@ -234,29 +304,29 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
|
||||
SecBuffer ntlm_v2_temp;
|
||||
SecBuffer ntlm_v2_temp_chal;
|
||||
|
||||
sspi_SecBufferAlloc(&ntlm_v2_temp, context->TargetInfo.cbBuffer + 28);
|
||||
sspi_SecBufferAlloc(&ntlm_v2_temp, context->ChallengeTargetInfo.cbBuffer + 28);
|
||||
|
||||
memset(ntlm_v2_temp.pvBuffer, '\0', ntlm_v2_temp.cbBuffer);
|
||||
ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer);
|
||||
blob = (BYTE*) ntlm_v2_temp.pvBuffer;
|
||||
|
||||
/* Compute the NTLMv2 hash */
|
||||
ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("Password (length = %d)\n", context->identity.PasswordLength);
|
||||
winpr_HexDump((BYTE*) context->identity.Password, context->identity.PasswordLength);
|
||||
printf("Password (length = %d)\n", context->identity.PasswordLength * 2);
|
||||
winpr_HexDump((BYTE*) context->identity.Password, context->identity.PasswordLength * 2);
|
||||
printf("\n");
|
||||
|
||||
printf("Username (length = %d)\n", context->identity.UserLength);
|
||||
winpr_HexDump((BYTE*) context->identity.User, context->identity.UserLength);
|
||||
printf("Username (length = %d)\n", context->identity.UserLength * 2);
|
||||
winpr_HexDump((BYTE*) context->identity.User, context->identity.UserLength * 2);
|
||||
printf("\n");
|
||||
|
||||
printf("Domain (length = %d)\n", context->identity.DomainLength);
|
||||
winpr_HexDump((BYTE*) context->identity.Domain, context->identity.DomainLength);
|
||||
printf("Domain (length = %d)\n", context->identity.DomainLength * 2);
|
||||
winpr_HexDump((BYTE*) context->identity.Domain, context->identity.DomainLength * 2);
|
||||
printf("\n");
|
||||
|
||||
printf("Workstation (length = %d)\n", context->WorkstationLength);
|
||||
winpr_HexDump((BYTE*) context->Workstation, context->WorkstationLength);
|
||||
printf("Workstation (length = %d)\n", context->Workstation.Length);
|
||||
winpr_HexDump((BYTE*) context->Workstation.Buffer, context->Workstation.Length);
|
||||
printf("\n");
|
||||
|
||||
printf("NTOWFv2, NTLMv2 Hash\n");
|
||||
@ -269,10 +339,10 @@ void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context)
|
||||
blob[1] = 1; /* HighRespType (1 byte) */
|
||||
/* Reserved1 (2 bytes) */
|
||||
/* Reserved2 (4 bytes) */
|
||||
CopyMemory(&blob[8], context->av_pairs->Timestamp.value, 8); /* Timestamp (8 bytes) */
|
||||
CopyMemory(&blob[8], context->Timestamp, 8); /* Timestamp (8 bytes) */
|
||||
CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */
|
||||
/* Reserved3 (4 bytes) */
|
||||
CopyMemory(&blob[28], context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer);
|
||||
CopyMemory(&blob[28], context->ChallengeTargetInfo.pvBuffer, context->ChallengeTargetInfo.cbBuffer);
|
||||
|
||||
#ifdef WITH_DEBUG_NTLM
|
||||
printf("NTLMv2 Response Temp Blob\n");
|
||||
|
@ -24,6 +24,14 @@
|
||||
|
||||
#include "ntlm_av_pairs.h"
|
||||
|
||||
void ntlm_get_version_info(NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_read_version_info(PStream s, NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_write_version_info(PStream s, NTLM_VERSION_INFO* versionInfo);
|
||||
void ntlm_print_version_info(NTLM_VERSION_INFO* versionInfo);
|
||||
|
||||
void ntlm_read_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response);
|
||||
void ntlm_write_ntlm_v2_response(PStream s, NTLMv2_RESPONSE* response);
|
||||
|
||||
void ntlm_output_restriction_encoding(NTLM_CONTEXT* context);
|
||||
void ntlm_output_target_name(NTLM_CONTEXT* context);
|
||||
void ntlm_output_channel_bindings(NTLM_CONTEXT* context);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,7 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
@ -152,4 +153,17 @@ BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation)
|
||||
return 1;
|
||||
}
|
||||
|
||||
VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
|
||||
{
|
||||
ULARGE_INTEGER time64;
|
||||
|
||||
/* time represented in tenths of microseconds since midnight of January 1, 1601 */
|
||||
|
||||
time64.QuadPart = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */
|
||||
time64.QuadPart *= 10000000; /* Convert timestamp to tenths of a microsecond */
|
||||
|
||||
lpSystemTimeAsFileTime->dwLowDateTime = time64.LowPart;
|
||||
lpSystemTimeAsFileTime->dwHighDateTime = time64.HighPart;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -138,6 +138,10 @@ WINPR_SAM_ENTRY* SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry)
|
||||
memcpy(entry->Domain, p[1], entry->DomainLength);
|
||||
entry->Domain[entry->DomainLength] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->Domain = NULL;
|
||||
}
|
||||
|
||||
if (LmHashLength == 32)
|
||||
{
|
||||
@ -211,9 +215,13 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L
|
||||
WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength)
|
||||
{
|
||||
int length;
|
||||
BOOL found = 0;
|
||||
BOOL Found = 0;
|
||||
BOOL UserMatch;
|
||||
BOOL DomainMatch;
|
||||
LPWSTR EntryUser;
|
||||
UINT32 EntryUserLength;
|
||||
LPWSTR EntryDomain;
|
||||
UINT32 EntryDomainLength;
|
||||
WINPR_SAM_ENTRY* entry;
|
||||
|
||||
entry = (WINPR_SAM_ENTRY*) malloc(sizeof(WINPR_SAM_ENTRY));
|
||||
@ -228,18 +236,56 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength,
|
||||
{
|
||||
if (sam->line[0] != '#')
|
||||
{
|
||||
DomainMatch = 0;
|
||||
UserMatch = 0;
|
||||
|
||||
entry = SamReadEntry(sam, entry);
|
||||
|
||||
EntryUserLength = strlen(entry->User) * 2;
|
||||
EntryUser = (LPWSTR) malloc(EntryUserLength + 2);
|
||||
MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2,
|
||||
(LPWSTR) EntryUser, EntryUserLength / 2);
|
||||
|
||||
if (UserLength == EntryUserLength)
|
||||
if (DomainLength > 0)
|
||||
{
|
||||
if (memcmp(User, EntryUser, UserLength) == 0)
|
||||
if (entry->DomainLength > 0)
|
||||
{
|
||||
found = 1;
|
||||
EntryDomainLength = strlen(entry->Domain) * 2;
|
||||
EntryDomain = (LPWSTR) malloc(EntryDomainLength + 2);
|
||||
MultiByteToWideChar(CP_ACP, 0, entry->Domain, EntryDomainLength / 2,
|
||||
(LPWSTR) EntryDomain, EntryDomainLength / 2);
|
||||
|
||||
if (DomainLength == EntryDomainLength)
|
||||
{
|
||||
if (memcmp(Domain, EntryDomain, DomainLength) == 0)
|
||||
{
|
||||
DomainMatch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DomainMatch = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DomainMatch = 1;
|
||||
}
|
||||
|
||||
if (DomainMatch)
|
||||
{
|
||||
EntryUserLength = strlen(entry->User) * 2;
|
||||
EntryUser = (LPWSTR) malloc(EntryUserLength + 2);
|
||||
MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2,
|
||||
(LPWSTR) EntryUser, EntryUserLength / 2);
|
||||
|
||||
if (UserLength == EntryUserLength)
|
||||
{
|
||||
if (memcmp(User, EntryUser, UserLength) == 0)
|
||||
{
|
||||
UserMatch = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (UserMatch && DomainMatch)
|
||||
{
|
||||
Found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -251,7 +297,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength,
|
||||
|
||||
SamLookupFinish(sam);
|
||||
|
||||
if (!found)
|
||||
if (!Found)
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
|
@ -31,10 +31,10 @@ PStream PStreamAlloc(size_t size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
s->data = (BYTE*) malloc(size);
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = (BYTE*) malloc(size);
|
||||
s->pointer = s->buffer;
|
||||
s->size = size;
|
||||
s->length = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -51,10 +51,10 @@ void StreamAlloc(PStream s, size_t size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
s->data = (BYTE*) malloc(size);
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = (BYTE*) malloc(size);
|
||||
s->pointer = s->buffer;
|
||||
s->size = size;
|
||||
s->length = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -71,37 +71,29 @@ void StreamReAlloc(PStream s, size_t size)
|
||||
{
|
||||
size_t old_size;
|
||||
size_t offset_p;
|
||||
size_t offset_end;
|
||||
|
||||
old_size = s->size;
|
||||
offset_p = s->p - s->data;
|
||||
offset_end = s->end - s->data;
|
||||
offset_p = s->pointer - s->buffer;
|
||||
|
||||
s->data = (BYTE*) realloc(s->data, size);
|
||||
s->buffer = (BYTE*) realloc(s->buffer, size);
|
||||
s->size = size;
|
||||
|
||||
if (old_size <= size)
|
||||
{
|
||||
s->p = s->data + offset_p;
|
||||
s->end = s->data + offset_end;
|
||||
}
|
||||
s->pointer = s->buffer + offset_p;
|
||||
else
|
||||
{
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
}
|
||||
s->pointer = s->buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->size > 0)
|
||||
free(s->data);
|
||||
free(s->buffer);
|
||||
|
||||
ZeroMemory(s, sizeof(Stream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PStream PStreamAllocAttach(BYTE* data, size_t size)
|
||||
PStream PStreamAllocAttach(BYTE* buffer, size_t size)
|
||||
{
|
||||
PStream s;
|
||||
|
||||
@ -109,23 +101,23 @@ PStream PStreamAllocAttach(BYTE* data, size_t size)
|
||||
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = data;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = buffer;
|
||||
s->pointer = s->buffer;
|
||||
s->size = size;
|
||||
s->length = size;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void StreamAllocAttach(PStream s, BYTE* data, size_t size)
|
||||
void StreamAllocAttach(PStream s, BYTE* buffer, size_t size)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = data;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = buffer;
|
||||
s->pointer = s->buffer;
|
||||
s->size = size;
|
||||
s->length = size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,8 +125,8 @@ void PStreamFree(PStream s)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
if (s->data != NULL)
|
||||
free(s->data);
|
||||
if (s->buffer != NULL)
|
||||
free(s->buffer);
|
||||
|
||||
free(s);
|
||||
}
|
||||
@ -144,8 +136,8 @@ void StreamFree(PStream s)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
if (s->data != NULL)
|
||||
free(s->data);
|
||||
if (s->buffer != NULL)
|
||||
free(s->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,10 +145,10 @@ void PStreamFreeDetach(PStream s)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = NULL;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = NULL;
|
||||
s->pointer = s->buffer;
|
||||
s->size = 0;
|
||||
s->length = 0;
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
@ -165,21 +157,21 @@ void StreamFreeDetach(PStream s)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = NULL;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = NULL;
|
||||
s->pointer = s->buffer;
|
||||
s->size = 0;
|
||||
s->length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamAttach(PStream s, BYTE* data, size_t size)
|
||||
void StreamAttach(PStream s, BYTE* buffer, size_t size)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = data;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = buffer;
|
||||
s->pointer = s->buffer;
|
||||
s->size = size;
|
||||
s->length = size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,9 +179,9 @@ void StreamDetach(PStream s)
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
s->data = NULL;
|
||||
s->p = s->data;
|
||||
s->end = s->p;
|
||||
s->buffer = NULL;
|
||||
s->pointer = s->buffer;
|
||||
s->size = 0;
|
||||
s->length = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user