diff --git a/include/winpr/stream.h b/include/winpr/stream.h index f3c5db1c5..4fa89f87d 100644 --- a/include/winpr/stream.h +++ b/include/winpr/stream.h @@ -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 */ diff --git a/include/winpr/sysinfo.h b/include/winpr/sysinfo.h index 85ba5bdc4..efb97e715 100644 --- a/include/winpr/sysinfo.h +++ b/include/winpr/sysinfo.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 */ diff --git a/include/winpr/wtypes.h b/include/winpr/wtypes.h index 94d5ac4a2..f84710fb9 100644 --- a/include/winpr/wtypes.h +++ b/include/winpr/wtypes.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; diff --git a/libfreerdp-crypto/nla.c b/libfreerdp-crypto/nla.c index 22dcef76f..a88eb2582 100644 --- a/libfreerdp-crypto/nla.c +++ b/libfreerdp-crypto/nla.c @@ -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 diff --git a/winpr/sspi/NTLM/ntlm.c b/winpr/sspi/NTLM/ntlm.c index a74cb0e10..0577e5318 100644 --- a/winpr/sspi/NTLM/ntlm.c +++ b/winpr/sspi/NTLM/ntlm.c @@ -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); diff --git a/winpr/sspi/NTLM/ntlm.h b/winpr/sspi/NTLM/ntlm.h index 3288319f2..e4aa4c700 100644 --- a/winpr/sspi/NTLM/ntlm.h +++ b/winpr/sspi/NTLM/ntlm.h @@ -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]; diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/sspi/NTLM/ntlm_av_pairs.c index 29167fca6..2261703ea 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/sspi/NTLM/ntlm_av_pairs.c @@ -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); + } } diff --git a/winpr/sspi/NTLM/ntlm_av_pairs.h b/winpr/sspi/NTLM/ntlm_av_pairs.h index 1fac6bd04..b24472ad3 100644 --- a/winpr/sspi/NTLM/ntlm_av_pairs.h +++ b/winpr/sspi/NTLM/ntlm_av_pairs.h @@ -24,11 +24,18 @@ #include -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 */ diff --git a/winpr/sspi/NTLM/ntlm_compute.c b/winpr/sspi/NTLM/ntlm_compute.c index 998eb8e94..18787aea7 100644 --- a/winpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/sspi/NTLM/ntlm_compute.c @@ -24,6 +24,7 @@ #include #include #include +#include #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"); diff --git a/winpr/sspi/NTLM/ntlm_compute.h b/winpr/sspi/NTLM/ntlm_compute.h index b4bb40e7f..75740a10c 100644 --- a/winpr/sspi/NTLM/ntlm_compute.h +++ b/winpr/sspi/NTLM/ntlm_compute.h @@ -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); diff --git a/winpr/sspi/NTLM/ntlm_message.c b/winpr/sspi/NTLM/ntlm_message.c index ebf9b8a1d..dbdaaed26 100644 --- a/winpr/sspi/NTLM/ntlm_message.c +++ b/winpr/sspi/NTLM/ntlm_message.c @@ -29,51 +29,7 @@ #include "ntlm_message.h" -#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_RESERVEDEQUEST_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) */ - -#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 - -#define MESSAGE_TYPE_NEGOTIATE 1 -#define MESSAGE_TYPE_CHALLENGE 2 -#define MESSAGE_TYPE_AUTHENTICATE 3 - -static const char NTLM_SIGNATURE[] = "NTLMSSP"; +static const char NTLM_SIGNATURE[8] = "NTLMSSP\0"; static const char* const NTLM_NEGOTIATE_STRINGS[] = { @@ -111,27 +67,6 @@ static const char* const NTLM_NEGOTIATE_STRINGS[] = "NTLMSSP_NEGOTIATE_UNICODE" }; -/** - * Output VERSION structure.\n - * VERSION @msdn{cc236654} - * @param s - */ - -void ntlm_output_version(PStream s) -{ - OSVERSIONINFOA osVersionInfo; - - osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - - GetVersionExA(&osVersionInfo); - - StreamWrite_UINT8(s, osVersionInfo.dwMajorVersion); /* ProductMajorVersion (1 byte) */ - StreamWrite_UINT8(s, osVersionInfo.dwMinorVersion); /* ProductMinorVersion (1 byte) */ - StreamWrite_UINT16(s, osVersionInfo.dwBuildNumber); /* ProductBuild (2 bytes) */ - StreamZero(s, 3); /* Reserved (3 bytes) */ - StreamWrite_UINT8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */ -} - void ntlm_print_negotiate_flags(UINT32 flags) { int i; @@ -151,63 +86,132 @@ void ntlm_print_negotiate_flags(UINT32 flags) printf("}\n"); } +void ntlm_read_message_header(PStream s, NTLM_MESSAGE_HEADER* header) +{ + StreamRead(s, header->Signature, sizeof(NTLM_SIGNATURE)); + StreamRead_UINT32(s, header->MessageType); +} + +void ntlm_write_message_header(PStream s, NTLM_MESSAGE_HEADER* header) +{ + StreamWrite(s, header->Signature, sizeof(NTLM_SIGNATURE)); + StreamWrite_UINT32(s, header->MessageType); +} + +void ntlm_populate_message_header(NTLM_MESSAGE_HEADER* header, UINT32 MessageType) +{ + CopyMemory(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); + header->MessageType = MessageType; +} + +BOOL ntlm_validate_message_header(PStream s, NTLM_MESSAGE_HEADER* header, UINT32 MessageType) +{ + if (memcmp(header->Signature, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) != 0) + { + printf("Unexpected NTLM signature: %s, expected:%s\n", header->Signature, NTLM_SIGNATURE); + return FALSE; + } + + if (header->MessageType != MessageType) + { + printf("Unexpected NTLM message type: %d, expected: %d\n", header->MessageType, MessageType); + return FALSE; + } + + return TRUE; +} + +void ntlm_read_message_fields(PStream s, NTLM_MESSAGE_FIELDS* fields) +{ + StreamRead_UINT16(s, fields->Len); /* Len (2 bytes) */ + StreamRead_UINT16(s, fields->MaxLen); /* MaxLen (2 bytes) */ + StreamRead_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */ +} + +void ntlm_write_message_fields(PStream s, NTLM_MESSAGE_FIELDS* fields) +{ + if (fields->MaxLen < 1) + fields->MaxLen = fields->Len; + + StreamWrite_UINT16(s, fields->Len); /* Len (2 bytes) */ + StreamWrite_UINT16(s, fields->MaxLen); /* MaxLen (2 bytes) */ + StreamWrite_UINT32(s, fields->BufferOffset); /* BufferOffset (4 bytes) */ +} + +void ntlm_read_message_fields_buffer(PStream s, NTLM_MESSAGE_FIELDS* fields) +{ + if (fields->Len > 0) + { + fields->Buffer = malloc(fields->Len); + StreamSetPosition(s, fields->BufferOffset); + StreamRead(s, fields->Buffer, fields->Len); + } +} + +void ntlm_write_message_fields_buffer(PStream s, NTLM_MESSAGE_FIELDS* fields) +{ + if (fields->Len > 0) + { + StreamSetPosition(s, fields->BufferOffset); + StreamWrite(s, fields->Buffer, fields->Len); + } +} + +void ntlm_print_message_fields(NTLM_MESSAGE_FIELDS* fields, const char* name) +{ + printf("%s (Len: %d MaxLen: %d BufferOffset: %d)\n", + name, fields->Len, fields->MaxLen, fields->BufferOffset); + + if (fields->Len > 0) + winpr_HexDump(fields->Buffer, fields->Len); + + printf("\n"); +} + SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { PStream s; int length; - BYTE Signature[8]; - UINT32 MessageType; - UINT32 NegotiateFlags; - UINT16 DomainNameLen; - UINT16 DomainNameMaxLen; - UINT32 DomainNameBufferOffset; - UINT16 WorkstationLen; - UINT16 WorkstationMaxLen; - UINT32 WorkstationBufferOffset; + NTLM_NEGOTIATE_MESSAGE message; + ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); - StreamRead(s, Signature, 8); - StreamRead_UINT32(s, MessageType); + ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) &message); - if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0) - { - printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE); - PStreamFreeDetach(s); - return SEC_E_INVALID_TOKEN; - } - - if (MessageType != MESSAGE_TYPE_NEGOTIATE) + if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_NEGOTIATE)) { PStreamFreeDetach(s); return SEC_E_INVALID_TOKEN; } - StreamRead_UINT32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ + StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ - context->NegotiateFlags = NegotiateFlags; + if (!((message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) && + (message.NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE))) + { + PStreamFreeDetach(s); + return SEC_E_INVALID_TOKEN; + } + + context->NegotiateFlags = message.NegotiateFlags; /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ - StreamRead_UINT16(s, DomainNameLen); /* DomainNameLen */ - StreamRead_UINT16(s, DomainNameMaxLen); /* DomainNameMaxLen */ - StreamRead_UINT32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */ + ntlm_read_message_fields(s, &(message.DomainName)); /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ - StreamRead_UINT16(s, WorkstationLen); /* WorkstationLen */ - StreamRead_UINT16(s, WorkstationMaxLen); /* WorkstationMaxLen */ - StreamRead_UINT32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */ + ntlm_read_message_fields(s, &(message.Workstation)); - if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ - StreamSeek(s, 8); /* Version (8 bytes) */ - } + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ - length = StreamSize(s); + length = StreamGetPosition(s); buffer->cbBuffer = length; sspi_SecBufferAlloc(&context->NegotiateMessage, length); @@ -215,9 +219,14 @@ SECURITY_STATUS ntlm_read_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer buf context->NegotiateMessage.BufferType = buffer->BufferType; #ifdef WITH_DEBUG_NTLM - printf("NEGOTIATE_MESSAGE (length = %d)\n", length); - winpr_HexDump(s->data, length); + printf("NEGOTIATE_MESSAGE (length = %d)\n", (int) context->NegotiateMessage.cbBuffer); + winpr_HexDump(context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer); printf("\n"); + + ntlm_print_negotiate_flags(message.NegotiateFlags); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); #endif context->state = NTLM_STATE_CHALLENGE; @@ -231,77 +240,60 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu { PStream s; int length; - UINT32 NegotiateFlags = 0; + NTLM_NEGOTIATE_MESSAGE message; + ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); - StreamWrite(s, NTLM_SIGNATURE, 8); /* Signature (8 bytes) */ - StreamWrite_UINT32(s, MESSAGE_TYPE_NEGOTIATE); /* MessageType */ + ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_NEGOTIATE); - if (context->ntlm_v2) + if (context->NTLMv2) { - NegotiateFlags |= NTLMSSP_NEGOTIATE_56; - NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; - NegotiateFlags |= NTLMSSP_NEGOTIATE_128; - NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; - NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; - NegotiateFlags |= NTLMSSP_REQUEST_TARGET; - NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; - } - else - { - NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; - NegotiateFlags |= NTLMSSP_NEGOTIATE_128; - NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; - NegotiateFlags |= NTLMSSP_REQUEST_TARGET; - NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM; } + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; + message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_get_version_info(&(message.Version)); + if (context->confidentiality) - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; if (context->SendVersionInfo) - NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; - context->NegotiateFlags = NegotiateFlags; + context->NegotiateFlags = message.NegotiateFlags; - StreamWrite_UINT32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ + /* Message Header (12 bytes) */ + ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message); + + StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ - StreamWrite_UINT16(s, 0); /* DomainNameLen */ - StreamWrite_UINT16(s, 0); /* DomainNameMaxLen */ - StreamWrite_UINT32(s, 0); /* DomainNameBufferOffset */ + ntlm_write_message_fields(s, &(message.DomainName)); /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ - StreamWrite_UINT16(s, 0); /* WorkstationLen */ - StreamWrite_UINT16(s, 0); /* WorkstationMaxLen */ - StreamWrite_UINT32(s, 0); /* WorkstationBufferOffset */ + ntlm_write_message_fields(s, &(message.Workstation)); - if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ - ntlm_output_version(s); + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_write_version_info(s, &(message.Version)); -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump((s->p - 8), 8); - printf("\n"); -#endif - } - - length = StreamSize(s); + length = StreamGetPosition(s); buffer->cbBuffer = length; sspi_SecBufferAlloc(&context->NegotiateMessage, length); @@ -310,8 +302,11 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu #ifdef WITH_DEBUG_NTLM printf("NEGOTIATE_MESSAGE (length = %d)\n", length); - winpr_HexDump(s->data, length); + winpr_HexDump(s->buffer, length); printf("\n"); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); #endif context->state = NTLM_STATE_CHALLENGE; @@ -323,104 +318,70 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { - BYTE* p; PStream s; int length; - char Signature[8]; - UINT32 MessageType; - BYTE* StartOffset; - BYTE* PayloadOffset; - UINT16 TargetNameLen; - UINT16 TargetNameMaxLen; - UINT32 TargetNameBufferOffset; - UINT16 TargetInfoLen; - UINT16 TargetInfoMaxLen; - UINT32 TargetInfoBufferOffset; + PBYTE StartOffset; + PBYTE PayloadOffset; + NTLM_AV_PAIR* AvTimestamp; + NTLM_CHALLENGE_MESSAGE message; ntlm_generate_client_challenge(context); + ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); - StreamRead(s, Signature, 8); - StreamRead_UINT32(s, MessageType); + StartOffset = StreamPointer(s); - if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0) - { - printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE); - PStreamFreeDetach(s); - return SEC_E_INVALID_TOKEN; - } + ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) &message); - if (MessageType != MESSAGE_TYPE_CHALLENGE) + if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE)) { PStreamFreeDetach(s); return SEC_E_INVALID_TOKEN; } - StartOffset = StreamGetPointer(s) - 12; - /* TargetNameFields (8 bytes) */ - StreamRead_UINT16(s, TargetNameLen); /* TargetNameLen (2 bytes) */ - StreamRead_UINT16(s, TargetNameMaxLen); /* TargetNameMaxLen (2 bytes) */ - StreamRead_UINT32(s, TargetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */ + ntlm_read_message_fields(s, &(message.TargetName)); - StreamRead_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ + StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ + context->NegotiateFlags = message.NegotiateFlags; -#ifdef WITH_DEBUG_NTLM - ntlm_print_negotiate_flags(context->NegotiateFlags); -#endif + StreamRead(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */ + CopyMemory(context->ServerChallenge, message.ServerChallenge, 8); - StreamRead(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */ - StreamSeek(s, 8); /* Reserved (8 bytes), should be ignored */ + StreamRead(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */ /* TargetInfoFields (8 bytes) */ - StreamRead_UINT16(s, TargetInfoLen); /* TargetInfoLen (2 bytes) */ - StreamRead_UINT16(s, TargetInfoMaxLen); /* TargetInfoMaxLen (2 bytes) */ - StreamRead_UINT32(s, TargetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */ - - /* only present if NTLMSSP_NEGOTIATE_VERSION is set */ + ntlm_read_message_fields(s, &(message.TargetInfo)); if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - StreamSeek(s, 8); /* Version (8 bytes), can be ignored */ - } + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ /* Payload (variable) */ - PayloadOffset = StreamGetPointer(s); + PayloadOffset = StreamPointer(s); - if (TargetNameLen > 0) + if (message.TargetName.Len > 0) + ntlm_read_message_fields_buffer(s, &(message.TargetName)); + + if (message.TargetInfo.Len > 0) { - p = StartOffset + TargetNameBufferOffset; - sspi_SecBufferAlloc(&context->TargetName, TargetNameLen); - CopyMemory(context->TargetName.pvBuffer, p, TargetNameLen); + ntlm_read_message_fields_buffer(s, &(message.TargetInfo)); -#ifdef WITH_DEBUG_NTLM - printf("TargetName (length = %d, offset = %d)\n", TargetNameLen, TargetNameBufferOffset); - winpr_HexDump(context->TargetName.pvBuffer, context->TargetName.cbBuffer); - printf("\n"); -#endif - } + context->ChallengeTargetInfo.pvBuffer = message.TargetInfo.Buffer; + context->ChallengeTargetInfo.cbBuffer = message.TargetInfo.Len; - if (TargetInfoLen > 0) - { - p = StartOffset + TargetInfoBufferOffset; - sspi_SecBufferAlloc(&context->TargetInfo, TargetInfoLen); - CopyMemory(context->TargetInfo.pvBuffer, p, TargetInfoLen); + AvTimestamp = ntlm_av_pair_get((NTLM_AV_PAIR*) message.TargetInfo.Buffer, MsvAvTimestamp); -#ifdef WITH_DEBUG_NTLM - printf("TargetInfo (length = %d, offset = %d)\n", TargetInfoLen, TargetInfoBufferOffset); - winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); - printf("\n"); -#endif - - if (context->ntlm_v2) + if (AvTimestamp != NULL) { - StreamSetPointer(s, p); - ntlm_input_av_pairs(context, s); + if (context->NTLMv2) + context->UseMIC = TRUE; + + CopyMemory(context->ChallengeTimestamp, ntlm_av_pair_get_value_pointer(AvTimestamp), 8); } } - length = (PayloadOffset - StartOffset) + TargetNameLen + TargetInfoLen; + length = (PayloadOffset - StartOffset) + message.TargetName.Len + message.TargetInfo.Len; sspi_SecBufferAlloc(&context->ChallengeMessage, length); CopyMemory(context->ChallengeMessage.pvBuffer, StartOffset, length); @@ -429,19 +390,29 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf printf("CHALLENGE_MESSAGE (length = %d)\n", length); winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); printf("\n"); -#endif + ntlm_print_negotiate_flags(context->NegotiateFlags); + + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.TargetName), "TargetName"); + ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo"); +#endif /* AV_PAIRs */ - if (context->ntlm_v2) - ntlm_populate_av_pairs(context); + + if (context->NTLMv2) + { + ntlm_construct_authenticate_target_info(context); + context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer; + context->ChallengeTargetInfo.cbBuffer = context->AuthenticateTargetInfo.cbBuffer; + } /* Timestamp */ ntlm_generate_timestamp(context); /* LmChallengeResponse */ - - if (context->LmCompatibilityLevel < 2) - ntlm_compute_lm_v2_response(context); + ntlm_compute_lm_v2_response(context); /* NtChallengeResponse */ ntlm_compute_ntlm_v2_response(context); @@ -527,12 +498,13 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu PStream s; int length; UINT32 PayloadOffset; - UINT16 TargetNameLen; - BYTE* TargetNameBuffer; - UINT32 TargetNameBufferOffset; - UINT16 TargetInfoLen; - BYTE* TargetInfoBuffer; - UINT32 TargetInfoBufferOffset; + NTLM_CHALLENGE_MESSAGE message; + + ZeroMemory(&message, sizeof(message)); + s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); + + /* Version */ + ntlm_get_version_info(&(message.Version)); /* Server Challenge */ ntlm_generate_server_challenge(context); @@ -541,99 +513,80 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu ntlm_generate_timestamp(context); /* TargetInfo */ - ntlm_populate_server_av_pairs(context); + ntlm_construct_challenge_target_info(context); - s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); + /* ServerChallenge */ + CopyMemory(message.ServerChallenge, context->ServerChallenge, 8); - StreamWrite(s, NTLM_SIGNATURE, 8); /* Signature (8 bytes) */ - StreamWrite_UINT32(s, MESSAGE_TYPE_CHALLENGE); /* MessageType */ + message.NegotiateFlags = context->NegotiateFlags; - if (context->NegotiateFlags & NTLMSSP_REQUEST_TARGET) + ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_CHALLENGE); + + /* Message Header (12 bytes) */ + ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message); + + if (message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) { - TargetNameLen = (UINT16) context->TargetName.cbBuffer; - TargetNameBuffer = context->TargetName.pvBuffer; - } - else - { - TargetNameLen = 0; - TargetNameBuffer = NULL; + message.TargetName.Len = (UINT16) context->TargetName.cbBuffer; + message.TargetName.Buffer = context->TargetName.pvBuffer; } - context->NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) { - TargetInfoLen = (UINT16) context->TargetInfo.cbBuffer; - TargetInfoBuffer = context->TargetInfo.pvBuffer; - } - else - { - TargetInfoLen = 0; - TargetInfoBuffer = NULL; + message.TargetInfo.Len = (UINT16) context->ChallengeTargetInfo.cbBuffer; + message.TargetInfo.Buffer = context->ChallengeTargetInfo.pvBuffer; } PayloadOffset = 48; - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) PayloadOffset += 8; - TargetNameBufferOffset = PayloadOffset; - TargetInfoBufferOffset = TargetNameBufferOffset + TargetNameLen; + message.TargetName.BufferOffset = PayloadOffset; + message.TargetInfo.BufferOffset = message.TargetName.BufferOffset + message.TargetName.Len; /* TargetNameFields (8 bytes) */ - StreamWrite_UINT16(s, TargetNameLen); /* TargetNameLen (2 bytes) */ - StreamWrite_UINT16(s, TargetNameLen); /* TargetNameMaxLen (2 bytes) */ - StreamWrite_UINT32(s, TargetNameBufferOffset); /* TargetNameBufferOffset (4 bytes) */ + ntlm_write_message_fields(s, &(message.TargetName)); - StreamWrite_UINT32(s, context->NegotiateFlags); /* NegotiateFlags (4 bytes) */ + StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ - StreamWrite(s, context->ServerChallenge, 8); /* ServerChallenge (8 bytes) */ - StreamZero(s, 8); /* Reserved (8 bytes), should be ignored */ + StreamWrite(s, message.ServerChallenge, 8); /* ServerChallenge (8 bytes) */ + StreamWrite(s, message.Reserved, 8); /* Reserved (8 bytes), should be ignored */ /* TargetInfoFields (8 bytes) */ - StreamWrite_UINT16(s, TargetInfoLen); /* TargetInfoLen (2 bytes) */ - StreamWrite_UINT16(s, TargetInfoLen); /* TargetInfoMaxLen (2 bytes) */ - StreamWrite_UINT32(s, TargetInfoBufferOffset); /* TargetInfoBufferOffset (4 bytes) */ + ntlm_write_message_fields(s, &(message.TargetInfo)); - /* only present if NTLMSSP_NEGOTIATE_VERSION is set */ - - if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - ntlm_output_version(s); /* Version (8 bytes), can be ignored */ - } + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_write_version_info(s, &(message.Version)); /* Version (8 bytes) */ /* Payload (variable) */ - if (TargetNameLen > 0) - { - StreamWrite(s, TargetNameBuffer, TargetNameLen); -#ifdef WITH_DEBUG_NTLM - printf("TargetName (length = %d, offset = %d)\n", TargetNameLen, TargetNameBufferOffset); - winpr_HexDump(TargetNameBuffer, TargetNameLen); - printf("\n"); -#endif - } + if (message.NegotiateFlags & NTLMSSP_REQUEST_TARGET) + ntlm_write_message_fields_buffer(s, &(message.TargetName)); - if (TargetInfoLen > 0) - { - StreamWrite(s, TargetInfoBuffer, TargetInfoLen); -#ifdef WITH_DEBUG_NTLM - printf("TargetInfo (length = %d, offset = %d)\n", TargetInfoLen, TargetInfoBufferOffset); - winpr_HexDump(TargetInfoBuffer, TargetInfoLen); - printf("\n"); -#endif - } + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) + ntlm_write_message_fields_buffer(s, &(message.TargetInfo)); - length = StreamSize(s); + length = StreamGetPosition(s); buffer->cbBuffer = length; sspi_SecBufferAlloc(&context->ChallengeMessage, length); - CopyMemory(context->ChallengeMessage.pvBuffer, s->data, length); + CopyMemory(context->ChallengeMessage.pvBuffer, s->buffer, length); #ifdef WITH_DEBUG_NTLM printf("CHALLENGE_MESSAGE (length = %d)\n", length); winpr_HexDump(context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); printf("\n"); + + ntlm_print_negotiate_flags(message.NegotiateFlags); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.TargetName), "TargetName"); + ntlm_print_message_fields(&(message.TargetInfo), "TargetInfo"); #endif context->state = NTLM_STATE_AUTHENTICATE; @@ -647,204 +600,150 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer { PStream s; int length; - BYTE Signature[8]; - UINT32 MessageType; - UINT32 NegotiateFlags; - UINT16 DomainNameLen; - UINT16 DomainNameMaxLen; - BYTE* DomainNameBuffer; - UINT32 DomainNameBufferOffset; - UINT16 UserNameLen; - UINT16 UserNameMaxLen; - BYTE* UserNameBuffer; - UINT32 UserNameBufferOffset; - UINT16 WorkstationLen; - UINT16 WorkstationMaxLen; - BYTE* WorkstationBuffer; - UINT32 WorkstationBufferOffset; - UINT16 LmChallengeResponseLen; - UINT16 LmChallengeResponseMaxLen; - BYTE* LmChallengeResponseBuffer; - UINT32 LmChallengeResponseBufferOffset; - UINT16 NtChallengeResponseLen; - UINT16 NtChallengeResponseMaxLen; - BYTE* NtChallengeResponseBuffer; - UINT32 NtChallengeResponseBufferOffset; - UINT16 EncryptedRandomSessionKeyLen; - UINT16 EncryptedRandomSessionKeyMaxLen; - BYTE* EncryptedRandomSessionKeyBuffer; - UINT32 EncryptedRandomSessionKeyBufferOffset; + UINT32 flags; + UINT32 MicOffset; + NTLM_AV_PAIR* AvFlags; + NTLMv2_RESPONSE response; + UINT32 PayloadBufferOffset; + NTLM_AUTHENTICATE_MESSAGE message; + flags = 0; + MicOffset = 0; + AvFlags = NULL; + + ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); - StreamRead(s, Signature, 8); - StreamRead_UINT32(s, MessageType); + ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*) &message); - if (memcmp(Signature, NTLM_SIGNATURE, 8) != 0) - { - printf("Unexpected NTLM signature: %s, expected:%s\n", Signature, NTLM_SIGNATURE); - PStreamFreeDetach(s); - return SEC_E_INVALID_TOKEN; - } - - if (MessageType != MESSAGE_TYPE_AUTHENTICATE) + if (!ntlm_validate_message_header(s, (NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_AUTHENTICATE)) { PStreamFreeDetach(s); return SEC_E_INVALID_TOKEN; } /* LmChallengeResponseFields (8 bytes) */ - StreamRead_UINT16(s, LmChallengeResponseLen); /* LmChallengeResponseLen */ - StreamRead_UINT16(s, LmChallengeResponseMaxLen); /* LmChallengeResponseMaxLen */ - StreamRead_UINT32(s, LmChallengeResponseBufferOffset); /* LmChallengeResponseBufferOffset */ + ntlm_read_message_fields(s, &(message.LmChallengeResponse)); /* NtChallengeResponseFields (8 bytes) */ - StreamRead_UINT16(s, NtChallengeResponseLen); /* NtChallengeResponseLen */ - StreamRead_UINT16(s, NtChallengeResponseMaxLen); /* NtChallengeResponseMaxLen */ - StreamRead_UINT32(s, NtChallengeResponseBufferOffset); /* NtChallengeResponseBufferOffset */ + ntlm_read_message_fields(s, &(message.NtChallengeResponse)); /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ - StreamRead_UINT16(s, DomainNameLen); /* DomainNameLen */ - StreamRead_UINT16(s, DomainNameMaxLen); /* DomainNameMaxLen */ - StreamRead_UINT32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */ + ntlm_read_message_fields(s, &(message.DomainName)); /* UserNameFields (8 bytes) */ - StreamRead_UINT16(s, UserNameLen); /* UserNameLen */ - StreamRead_UINT16(s, UserNameMaxLen); /* UserNameMaxLen */ - StreamRead_UINT32(s, UserNameBufferOffset); /* UserNameBufferOffset */ + ntlm_read_message_fields(s, &(message.UserName)); /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ - StreamRead_UINT16(s, WorkstationLen); /* WorkstationLen */ - StreamRead_UINT16(s, WorkstationMaxLen); /* WorkstationMaxLen */ - StreamRead_UINT32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */ + ntlm_read_message_fields(s, &(message.Workstation)); /* EncryptedRandomSessionKeyFields (8 bytes) */ - StreamRead_UINT16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyLen */ - StreamRead_UINT16(s, EncryptedRandomSessionKeyMaxLen); /* EncryptedRandomSessionKeyMaxLen */ - StreamRead_UINT32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */ + ntlm_read_message_fields(s, &(message.EncryptedRandomSessionKey)); - StreamRead_UINT32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ + StreamRead_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ - if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_read_version_info(s, &(message.Version)); /* Version (8 bytes) */ -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump(s->p, 8); - printf("\n"); -#endif - - StreamSeek(s, 8); /* Version (8 bytes) */ - } - - length = StreamSize(s); - sspi_SecBufferAlloc(&context->AuthenticateMessage, length); - CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length); - buffer->cbBuffer = length; - -#ifdef WITH_DEBUG_NTLM - printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); - winpr_HexDump(s->data, length); - printf("\n"); -#endif + PayloadBufferOffset = StreamGetPosition(s); /* DomainName */ - if (DomainNameLen > 0) - { - DomainNameBuffer = s->data + DomainNameBufferOffset; -#ifdef WITH_DEBUG_NTLM - printf("DomainName (length = %d, offset = %d)\n", DomainNameLen, DomainNameBufferOffset); - winpr_HexDump(DomainNameBuffer, DomainNameLen); - printf("\n"); -#endif - } + ntlm_read_message_fields_buffer(s, &(message.DomainName)); /* UserName */ - if (UserNameLen > 0) - { - UserNameBuffer = s->data + UserNameBufferOffset; -#ifdef WITH_DEBUG_NTLM - printf("UserName (length = %d, offset = %d)\n", UserNameLen, UserNameBufferOffset); - winpr_HexDump(UserNameBuffer, UserNameLen); - printf("\n"); -#endif - } + ntlm_read_message_fields_buffer(s, &(message.UserName)); /* Workstation */ - if (WorkstationLen > 0) - { - WorkstationBuffer = s->data + WorkstationBufferOffset; -#ifdef WITH_DEBUG_NTLM - printf("Workstation (length = %d, offset = %d)\n", WorkstationLen, WorkstationBufferOffset); - winpr_HexDump(WorkstationBuffer, WorkstationLen); - printf("\n"); -#endif - } + ntlm_read_message_fields_buffer(s, &(message.Workstation)); /* LmChallengeResponse */ - if (LmChallengeResponseLen > 0) - { - LmChallengeResponseBuffer = s->data + LmChallengeResponseBufferOffset; -#ifdef WITH_DEBUG_NTLM - printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); - winpr_HexDump(LmChallengeResponseBuffer, LmChallengeResponseLen); - printf("\n"); -#endif - } + ntlm_read_message_fields_buffer(s, &(message.LmChallengeResponse)); /* NtChallengeResponse */ - if (NtChallengeResponseLen > 0) + ntlm_read_message_fields_buffer(s, &(message.NtChallengeResponse)); + + if (message.NtChallengeResponse.Len > 0) { - BYTE* ClientChallengeBuffer; + PStream s = PStreamAllocAttach(message.NtChallengeResponse.Buffer, message.NtChallengeResponse.Len); + ntlm_read_ntlm_v2_response(s, &response); + PStreamFreeDetach(s); - NtChallengeResponseBuffer = s->data + NtChallengeResponseBufferOffset; + context->NtChallengeResponse.pvBuffer = message.NtChallengeResponse.Buffer; + context->NtChallengeResponse.cbBuffer = message.NtChallengeResponse.Len; - ClientChallengeBuffer = NtChallengeResponseBuffer + 32; - CopyMemory(context->ClientChallenge, ClientChallengeBuffer, 8); + context->ChallengeTargetInfo.pvBuffer = (void*) response.Challenge.AvPairs; + context->ChallengeTargetInfo.cbBuffer = message.NtChallengeResponse.Len - (28 + 16); -#ifdef WITH_DEBUG_NTLM - printf("NtChallengeResponse (length = %d, offset = %d)\n", NtChallengeResponseLen, NtChallengeResponseBufferOffset); - winpr_HexDump(NtChallengeResponseBuffer, NtChallengeResponseLen); - printf("\n"); -#endif + CopyMemory(context->ClientChallenge, response.Challenge.ClientChallenge, 8); + + AvFlags = ntlm_av_pair_get(response.Challenge.AvPairs, MsvAvFlags); + + if (AvFlags != NULL) + flags = *((UINT32*) ntlm_av_pair_get_value_pointer(AvFlags)); } /* EncryptedRandomSessionKey */ - if (EncryptedRandomSessionKeyLen > 0) + ntlm_read_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); + CopyMemory(context->EncryptedRandomSessionKey, message.EncryptedRandomSessionKey.Buffer, 16); + + length = StreamGetPosition(s); + sspi_SecBufferAlloc(&context->AuthenticateMessage, length); + CopyMemory(context->AuthenticateMessage.pvBuffer, s->buffer, length); + buffer->cbBuffer = length; + + StreamSetPosition(s, PayloadBufferOffset); + + if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK) { - EncryptedRandomSessionKeyBuffer = s->data + EncryptedRandomSessionKeyBufferOffset; - CopyMemory(context->EncryptedRandomSessionKey, EncryptedRandomSessionKeyBuffer, 16); + MicOffset = StreamGetPosition(s); + StreamRead(s, message.MessageIntegrityCheck, 16); + PayloadBufferOffset += 16; + } #ifdef WITH_DEBUG_NTLM - printf("EncryptedRandomSessionKey (length = %d, offset = %d)\n", EncryptedRandomSessionKeyLen, EncryptedRandomSessionKeyBufferOffset); - winpr_HexDump(EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen); - printf("\n"); + printf("AUTHENTICATE_MESSAGE (length = %d)\n", (int) context->AuthenticateMessage.cbBuffer); + winpr_HexDump(context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer); + printf("\n"); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.DomainName), "DomainName"); + ntlm_print_message_fields(&(message.UserName), "UserName"); + ntlm_print_message_fields(&(message.Workstation), "Workstation"); + ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); + ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); + ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey"); + + ntlm_print_av_pair_list(response.Challenge.AvPairs); + + if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK) + { + printf("MessageIntegrityCheck:\n"); + winpr_HexDump(message.MessageIntegrityCheck, 16); + } #endif + + if (message.UserName.Len > 0) + { + context->identity.User = (UINT16*) malloc(message.UserName.Len); + CopyMemory(context->identity.User, message.UserName.Buffer, message.UserName.Len); + context->identity.UserLength = message.UserName.Len / 2; } - if (UserNameLen > 0) + if (message.DomainName.Len > 0) { - context->identity.User = (UINT16*) malloc(UserNameLen); - CopyMemory(context->identity.User, UserNameBuffer, UserNameLen); - context->identity.UserLength = UserNameLen; - } - - if (DomainNameLen > 0) - { - context->identity.Domain = (UINT16*) malloc(DomainNameLen); - CopyMemory(context->identity.Domain, DomainNameBuffer, DomainNameLen); - context->identity.DomainLength = DomainNameLen; + context->identity.Domain = (UINT16*) malloc(message.DomainName.Len); + CopyMemory(context->identity.Domain, message.DomainName.Buffer, message.DomainName.Len); + context->identity.DomainLength = message.DomainName.Len / 2; } /* LmChallengeResponse */ - - if (context->LmCompatibilityLevel < 2) - ntlm_compute_lm_v2_response(context); + ntlm_compute_lm_v2_response(context); /* NtChallengeResponse */ ntlm_compute_ntlm_v2_response(context); @@ -858,6 +757,25 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer /* ExportedSessionKey */ ntlm_generate_exported_session_key(context); + if (flags & MSV_AV_FLAGS_MESSAGE_INTEGRITY_CHECK) + { + ZeroMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], 16); + ntlm_compute_message_integrity_check(context); + CopyMemory(&((PBYTE) context->AuthenticateMessage.pvBuffer)[MicOffset], message.MessageIntegrityCheck, 16); + + if (memcmp(context->MessageIntegrityCheck, message.MessageIntegrityCheck, 16) != 0) + { + printf("Message Integrity Check (MIC) verification failed!\n"); + + printf("Expected MIC:\n"); + winpr_HexDump(context->MessageIntegrityCheck, 16); + printf("Actual MIC:\n"); + winpr_HexDump(message.MessageIntegrityCheck, 16); + + return SEC_E_MESSAGE_ALTERED; + } + } + /* Generate signing keys */ ntlm_generate_client_signing_key(context); ntlm_generate_server_signing_key(context); @@ -933,258 +851,174 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer { PStream s; int length; - BYTE* MicOffset = NULL; - UINT32 NegotiateFlags = 0; - - UINT16 DomainNameLen; - UINT16 UserNameLen; - UINT16 WorkstationLen; - UINT16 LmChallengeResponseLen; - UINT16 NtChallengeResponseLen; - UINT16 EncryptedRandomSessionKeyLen; - + UINT32 MicOffset = 0; UINT32 PayloadBufferOffset; - UINT32 DomainNameBufferOffset; - UINT32 UserNameBufferOffset; - UINT32 WorkstationBufferOffset; - UINT32 LmChallengeResponseBufferOffset; - UINT32 NtChallengeResponseBufferOffset; - UINT32 EncryptedRandomSessionKeyBufferOffset; - - BYTE* UserNameBuffer; - BYTE* DomainNameBuffer; - BYTE* WorkstationBuffer; - BYTE* EncryptedRandomSessionKeyBuffer; - - WorkstationLen = context->WorkstationLength; - WorkstationBuffer = (BYTE*) context->Workstation; + NTLM_AUTHENTICATE_MESSAGE message; + ZeroMemory(&message, sizeof(message)); s = PStreamAllocAttach(buffer->pvBuffer, buffer->cbBuffer); - if (context->ntlm_v2 < 1) - WorkstationLen = 0; - - DomainNameLen = (UINT16) context->identity.DomainLength * 2; - DomainNameBuffer = (BYTE*) context->identity.Domain; - - UserNameLen = (UINT16) context->identity.UserLength * 2; - UserNameBuffer = (BYTE*) context->identity.User; - - LmChallengeResponseLen = (UINT16) 24; - NtChallengeResponseLen = (UINT16) context->NtChallengeResponse.cbBuffer; - - EncryptedRandomSessionKeyLen = 16; - EncryptedRandomSessionKeyBuffer = context->EncryptedRandomSessionKey; - - if (context->ntlm_v2) + if (context->NTLMv2) { - /* observed: 35 82 88 e2 (0xE2888235) */ - NegotiateFlags |= NTLMSSP_NEGOTIATE_56; - NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; - NegotiateFlags |= NTLMSSP_NEGOTIATE_128; - NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; - NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; - NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; - NegotiateFlags |= NTLMSSP_REQUEST_TARGET; - NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; - } - else - { - NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; - NegotiateFlags |= NTLMSSP_NEGOTIATE_128; - NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; - NegotiateFlags |= NTLMSSP_REQUEST_TARGET; - NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_56; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; } + if (context->UseMIC) + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_TARGET_INFO; + + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_128; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; + message.NegotiateFlags |= NTLMSSP_REQUEST_TARGET; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_get_version_info(&(message.Version)); + + message.Workstation.Len = context->Workstation.Length; + message.Workstation.Buffer = (BYTE*) context->Workstation.Buffer; + + if (!context->NTLMv2) + message.Workstation.Len = 0; + + if (message.Workstation.Len > 0) + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; + + message.DomainName.Len = (UINT16) context->identity.DomainLength * 2; + message.DomainName.Buffer = (BYTE*) context->identity.Domain; + + if (message.DomainName.Len > 0) + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; + + message.UserName.Len = (UINT16) context->identity.UserLength * 2; + message.UserName.Buffer = (BYTE*) context->identity.User; + + message.LmChallengeResponse.Len = (UINT16) context->LmChallengeResponse.cbBuffer; + message.LmChallengeResponse.Buffer = (BYTE*) context->LmChallengeResponse.pvBuffer; + + message.NtChallengeResponse.Len = (UINT16) context->NtChallengeResponse.cbBuffer; + message.NtChallengeResponse.Buffer = (BYTE*) context->NtChallengeResponse.pvBuffer; + + message.EncryptedRandomSessionKey.Len = 16; + message.EncryptedRandomSessionKey.Buffer = context->EncryptedRandomSessionKey; + if (context->confidentiality) - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + message.NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; - if (context->ntlm_v2) - PayloadBufferOffset = 80; /* starting buffer offset */ - else - PayloadBufferOffset = 64; /* starting buffer offset */ + PayloadBufferOffset = 64; - if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + if (context->UseMIC) + PayloadBufferOffset += 16; /* Message Integrity Check */ + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) PayloadBufferOffset += 8; - DomainNameBufferOffset = PayloadBufferOffset; - UserNameBufferOffset = DomainNameBufferOffset + DomainNameLen; - WorkstationBufferOffset = UserNameBufferOffset + UserNameLen; - LmChallengeResponseBufferOffset = WorkstationBufferOffset + WorkstationLen; - NtChallengeResponseBufferOffset = LmChallengeResponseBufferOffset + LmChallengeResponseLen; - EncryptedRandomSessionKeyBufferOffset = NtChallengeResponseBufferOffset + NtChallengeResponseLen; + message.DomainName.BufferOffset = PayloadBufferOffset; + message.UserName.BufferOffset = message.DomainName.BufferOffset + message.DomainName.Len; + message.Workstation.BufferOffset = message.UserName.BufferOffset + message.UserName.Len; + message.LmChallengeResponse.BufferOffset = message.Workstation.BufferOffset + message.Workstation.Len; + message.NtChallengeResponse.BufferOffset = message.LmChallengeResponse.BufferOffset + message.LmChallengeResponse.Len; + message.EncryptedRandomSessionKey.BufferOffset = message.NtChallengeResponse.BufferOffset + message.NtChallengeResponse.Len; - StreamWrite(s, NTLM_SIGNATURE, 8); /* Signature (8 bytes) */ - StreamWrite_UINT32(s, MESSAGE_TYPE_AUTHENTICATE); /* MessageType */ + ntlm_populate_message_header((NTLM_MESSAGE_HEADER*) &message, MESSAGE_TYPE_AUTHENTICATE); + + /* Message Header (12 bytes) */ + ntlm_write_message_header(s, (NTLM_MESSAGE_HEADER*) &message); /* LmChallengeResponseFields (8 bytes) */ - StreamWrite_UINT16(s, LmChallengeResponseLen); /* LmChallengeResponseLen */ - StreamWrite_UINT16(s, LmChallengeResponseLen); /* LmChallengeResponseMaxLen */ - StreamWrite_UINT32(s, LmChallengeResponseBufferOffset); /* LmChallengeResponseBufferOffset */ + ntlm_write_message_fields(s, &(message.LmChallengeResponse)); /* NtChallengeResponseFields (8 bytes) */ - StreamWrite_UINT16(s, NtChallengeResponseLen); /* NtChallengeResponseLen */ - StreamWrite_UINT16(s, NtChallengeResponseLen); /* NtChallengeResponseMaxLen */ - StreamWrite_UINT32(s, NtChallengeResponseBufferOffset); /* NtChallengeResponseBufferOffset */ + ntlm_write_message_fields(s, &(message.NtChallengeResponse)); /* only set if NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED is set */ /* DomainNameFields (8 bytes) */ - StreamWrite_UINT16(s, DomainNameLen); /* DomainNameLen */ - StreamWrite_UINT16(s, DomainNameLen); /* DomainNameMaxLen */ - StreamWrite_UINT32(s, DomainNameBufferOffset); /* DomainNameBufferOffset */ + ntlm_write_message_fields(s, &(message.DomainName)); /* UserNameFields (8 bytes) */ - StreamWrite_UINT16(s, UserNameLen); /* UserNameLen */ - StreamWrite_UINT16(s, UserNameLen); /* UserNameMaxLen */ - StreamWrite_UINT32(s, UserNameBufferOffset); /* UserNameBufferOffset */ + ntlm_write_message_fields(s, &(message.UserName)); /* only set if NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED is set */ /* WorkstationFields (8 bytes) */ - StreamWrite_UINT16(s, WorkstationLen); /* WorkstationLen */ - StreamWrite_UINT16(s, WorkstationLen); /* WorkstationMaxLen */ - StreamWrite_UINT32(s, WorkstationBufferOffset); /* WorkstationBufferOffset */ + ntlm_write_message_fields(s, &(message.Workstation)); /* EncryptedRandomSessionKeyFields (8 bytes) */ - StreamWrite_UINT16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyLen */ - StreamWrite_UINT16(s, EncryptedRandomSessionKeyLen); /* EncryptedRandomSessionKeyMaxLen */ - StreamWrite_UINT32(s, EncryptedRandomSessionKeyBufferOffset); /* EncryptedRandomSessionKeyBufferOffset */ + ntlm_write_message_fields(s, &(message.EncryptedRandomSessionKey)); - StreamWrite_UINT32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ + StreamWrite_UINT32(s, message.NegotiateFlags); /* NegotiateFlags (4 bytes) */ -#ifdef WITH_DEBUG_NTLM - ntlm_print_negotiate_flags(NegotiateFlags); -#endif + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_write_version_info(s, &(message.Version)); - if (NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) - { - /* Only present if NTLMSSP_NEGOTIATE_VERSION is set */ - ntlm_output_version(s); - -#ifdef WITH_DEBUG_NTLM - printf("Version (length = 8)\n"); - winpr_HexDump((s->p - 8), 8); - printf("\n"); -#endif - } - - if (context->ntlm_v2) + if (context->UseMIC) { /* Message Integrity Check */ - MicOffset = s->p; + MicOffset = StreamGetPosition(s); StreamZero(s, 16); } /* DomainName */ - if (DomainNameLen > 0) - { - StreamWrite(s, DomainNameBuffer, DomainNameLen); -#ifdef WITH_DEBUG_NTLM - printf("DomainName (length = %d, offset = %d)\n", DomainNameLen, DomainNameBufferOffset); - winpr_HexDump(DomainNameBuffer, DomainNameLen); - printf("\n"); -#endif - } + ntlm_write_message_fields_buffer(s, &(message.DomainName)); /* UserName */ - StreamWrite(s, UserNameBuffer, UserNameLen); - -#ifdef WITH_DEBUG_NTLM - printf("UserName (length = %d, offset = %d)\n", UserNameLen, UserNameBufferOffset); - winpr_HexDump(UserNameBuffer, UserNameLen); - printf("\n"); -#endif + ntlm_write_message_fields_buffer(s, &(message.UserName)); /* Workstation */ - if (WorkstationLen > 0) - { - StreamWrite(s, WorkstationBuffer, WorkstationLen); -#ifdef WITH_DEBUG_NTLM - printf("Workstation (length = %d, offset = %d)\n", WorkstationLen, WorkstationBufferOffset); - winpr_HexDump(WorkstationBuffer, WorkstationLen); - printf("\n"); -#endif - } + ntlm_write_message_fields_buffer(s, &(message.Workstation)); /* LmChallengeResponse */ - - if (context->LmCompatibilityLevel < 2) - { - StreamWrite(s, context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); - -#ifdef WITH_DEBUG_NTLM - printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); - winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); - printf("\n"); -#endif - } - else - { - StreamZero(s, LmChallengeResponseLen); - } + ntlm_write_message_fields_buffer(s, &(message.LmChallengeResponse)); /* NtChallengeResponse */ - StreamWrite(s, context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen); - -#ifdef WITH_DEBUG_NTLM - if (context->ntlm_v2) - { - ntlm_print_av_pairs(context); - - printf("targetInfo (length = %d)\n", (int) context->TargetInfo.cbBuffer); - winpr_HexDump(context->TargetInfo.pvBuffer, context->TargetInfo.cbBuffer); - printf("\n"); - } -#endif - -#ifdef WITH_DEBUG_NTLM - printf("NtChallengeResponse (length = %d, offset = %d)\n", NtChallengeResponseLen, NtChallengeResponseBufferOffset); - winpr_HexDump(context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen); - printf("\n"); -#endif + ntlm_write_message_fields_buffer(s, &(message.NtChallengeResponse)); /* EncryptedRandomSessionKey */ - StreamWrite(s, EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen); + ntlm_write_message_fields_buffer(s, &(message.EncryptedRandomSessionKey)); -#ifdef WITH_DEBUG_NTLM - printf("EncryptedRandomSessionKey (length = %d, offset = %d)\n", EncryptedRandomSessionKeyLen, EncryptedRandomSessionKeyBufferOffset); - winpr_HexDump(EncryptedRandomSessionKeyBuffer, EncryptedRandomSessionKeyLen); - printf("\n"); -#endif - - length = StreamSize(s); + length = StreamGetPosition(s); sspi_SecBufferAlloc(&context->AuthenticateMessage, length); - CopyMemory(context->AuthenticateMessage.pvBuffer, s->data, length); + CopyMemory(context->AuthenticateMessage.pvBuffer, s->buffer, length); buffer->cbBuffer = length; - if (context->ntlm_v2) + if (context->UseMIC) { /* Message Integrity Check */ ntlm_compute_message_integrity_check(context); - s->p = MicOffset; + StreamSetPosition(s, MicOffset); StreamWrite(s, context->MessageIntegrityCheck, 16); - s->p = s->data + length; - -#ifdef WITH_DEBUG_NTLM - printf("MessageIntegrityCheck (length = 16)\n"); - winpr_HexDump(MicOffset, 16); - printf("\n"); -#endif + StreamSetPosition(s, length); } #ifdef WITH_DEBUG_NTLM printf("AUTHENTICATE_MESSAGE (length = %d)\n", length); - winpr_HexDump(s->data, length); + winpr_HexDump(s->buffer, length); printf("\n"); + + ntlm_print_negotiate_flags(message.NegotiateFlags); + + if (message.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) + ntlm_print_version_info(&(message.Version)); + + ntlm_print_message_fields(&(message.DomainName), "DomainName"); + ntlm_print_message_fields(&(message.UserName), "UserName"); + ntlm_print_message_fields(&(message.Workstation), "Workstation"); + ntlm_print_message_fields(&(message.LmChallengeResponse), "LmChallengeResponse"); + ntlm_print_message_fields(&(message.NtChallengeResponse), "NtChallengeResponse"); + ntlm_print_message_fields(&(message.EncryptedRandomSessionKey), "EncryptedRandomSessionKey"); + + if (context->UseMIC) + { + printf("MessageIntegrityCheck (length = 16)\n"); + winpr_HexDump(context->MessageIntegrityCheck, 16); + printf("\n"); + } #endif context->state = NTLM_STATE_FINAL; diff --git a/winpr/sysinfo/sysinfo.c b/winpr/sysinfo/sysinfo.c index fb1e5d02a..feadc8986 100644 --- a/winpr/sysinfo/sysinfo.c +++ b/winpr/sysinfo/sysinfo.c @@ -63,6 +63,7 @@ #ifndef _WIN32 +#include #include #include @@ -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 diff --git a/winpr/utils/sam.c b/winpr/utils/sam.c index 58bb3d4bb..14ca4ab01 100644 --- a/winpr/utils/sam.c +++ b/winpr/utils/sam.c @@ -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; diff --git a/winpr/utils/stream.c b/winpr/utils/stream.c index 482e41c24..3def650cf 100644 --- a/winpr/utils/stream.c +++ b/winpr/utils/stream.c @@ -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; } }