Merge pull request #650 from FreeRDP/winpr

WinPR Server-Side NLA
This commit is contained in:
Marc-André Moreau 2012-07-04 18:27:54 -07:00
commit 5da865a120
14 changed files with 1338 additions and 1329 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}
}