Author: sserapion Date: Thu Jan 5 19:53:57 2017 New Revision: 73504
URL: http://svn.reactos.org/svn/reactos?rev=73504&view=rev Log: [NTLM] Commit ancient code that was dormant in my working copy: Mostly some style fixes, allocation checks, debug messages. Implement QueryCredentialsAttributes SECPKG_ATTR_NAMES case Enable/disable the use of crypto api RNG with USE_CRYPTOAPI, probably could use crypto api for RC4 and other such things as well. Implement message support with EncryptMessage, DecryptMessage
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/CMakeLists.txt branches/sspi-bringup/reactos/dll/win32/ntlmssp/avl.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/calculations.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/ciphers.h branches/sspi-bringup/reactos/dll/win32/ntlmssp/context.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/credentials.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/crypt.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/debug.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/dllmain.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/messages.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.h branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.h branches/sspi-bringup/reactos/dll/win32/ntlmssp/sign.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/util.c
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/CMakeLists.txt [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/CMakeLists.txt [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -1,7 +1,7 @@ -spec2def(ntlmssp.dll ntlmssp.spec) +spec2def(ntlmssp.dll ntlmssp.spec ADD_IMPORTLIB)
list(APPEND SOURCE - avl.c + avl.c calculations.c ciphers.c context.c @@ -9,17 +9,17 @@ crypt.c debug.c dllmain.c - messages.c + messages.c ntlmssp.c protocol.c stubs.c sign.c util.c - ${CMAKE_CURRENT_BINARY_DIR}/ntlmssp_stubs.c - ${CMAKE_CURRENT_BINARY_DIR}/ntlmssp.def) + ${CMAKE_CURRENT_BINARY_DIR}/ntlmssp_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/ntlmssp.def)
add_library(ntlmssp SHARED ${SOURCE}) - +allow_warnings(ntlmssp) set_module_type(ntlmssp win32dll UNICODE)
target_link_libraries(ntlmssp wine) @@ -27,4 +27,4 @@ add_importlibs(ntlmssp advapi32 crypt32 netapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET ntlmssp DESTINATION reactos/system32 FOR all) -add_importlib_target(ntlmssp.spec) +#add_importlib_target(ntlmssp.spec)
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/avl.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/avl.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/avl.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -19,6 +19,9 @@
#include "ntlmssp.h" #include "protocol.h" + +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
PMSV1_0_AV_PAIR NtlmAvlInit(IN void * pAvList) @@ -47,7 +50,8 @@ return NULL; pAvPair = (PMSV1_0_AV_PAIR)((PUCHAR)pAvPair + pAvPair->AvLen + sizeof(MSV1_0_AV_PAIR)); - }while(1); + }while(pAvPair); + return NULL; }
ULONG
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/calculations.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/calculations.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/calculations.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
VOID -NTOWFv1(const PWCHAR password, +NTOWFv1(LPCWSTR password, PUCHAR result) { ULONG i, len = wcslen(password); @@ -40,15 +40,18 @@ MD4((PUCHAR)pass, 14, result); }
-VOID -NTOWFv2(const PWCHAR password, const PWCHAR user, const PWCHAR domain, PUCHAR result) +BOOLEAN +NTOWFv2(LPCWSTR password, + LPCWSTR user, + LPCWSTR domain, + PUCHAR result) { UCHAR response_key_nt_v1 [16]; ULONG len_user = user ? wcslen(user) : 0; ULONG len_domain = domain ? wcslen(domain) : 0; - WCHAR user_upper[len_user + 1]; ULONG len_user_u = len_user * sizeof(WCHAR); ULONG len_domain_u = len_domain * sizeof(WCHAR); + WCHAR user_upper[len_user + 1]; WCHAR buff[len_user + len_domain]; ULONG i;
@@ -62,10 +65,12 @@
NTOWFv1(password, response_key_nt_v1); HMAC_MD5(response_key_nt_v1, 16, (PUCHAR)buff, len_user_u + len_domain_u, result); -} - -VOID -LMOWFv1(PCCHAR password, PUCHAR result) + + return TRUE; +} + +VOID +LMOWFv1(const PCCHAR password, PUCHAR result) { #if 0 SystemFunction006(password, result); @@ -95,14 +100,18 @@ #endif }
-VOID -LMOWFv2(PWCHAR password, PWCHAR user, PWCHAR domain, PUCHAR result) -{ - NTOWFv2(password, user, domain, result); -} - -VOID -NONCE(PUCHAR buffer, ULONG num) +BOOLEAN +LMOWFv2(LPCWSTR password, + LPCWSTR user, + LPCWSTR domain, + PUCHAR result) +{ + return NTOWFv2(password, user, domain, result); +} + +VOID +NONCE(PUCHAR buffer, + ULONG num) { NtlmGenerateRandomBits(buffer, num); } @@ -118,21 +127,23 @@ memcpy(key_exchange_key, session_base_key, 16); }
-VOID +BOOLEAN SIGNKEY(const PUCHAR RandomSessionKey, BOOLEAN IsClient, PUCHAR Result) { PCHAR magic = IsClient ? "session key to client-to-server signing key magic constant" : "session key to server-to-client signing key magic constant"; - ULONG len = strlen(magic); - UCHAR md5_input [16 + len]; + UCHAR md5_input[16 + len]; + memcpy(md5_input, RandomSessionKey, 16); memcpy(md5_input + 16, magic, len); MD5(md5_input, len + 16, Result); -} - -VOID + + return TRUE; +} + +BOOLEAN SEALKEY(ULONG flags, const PUCHAR RandomSessionKey, BOOLEAN client, PUCHAR result) { if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) @@ -142,8 +153,15 @@ : "session key to server-to-client sealing key magic constant";
ULONG len = strlen(magic) + 1; - UCHAR md5_input [16 + len]; + UCHAR* md5_input; ULONG key_len; + + md5_input = (UCHAR*)NtlmAllocate(16+len); + if(!md5_input) + { + ERR("Out of memory\n"); + return FALSE; + }
if (flags & NTLMSSP_NEGOTIATE_128) { TRACE("NTLM SEALKEY(): 128-bit key (Extended session security)\n"); @@ -179,9 +197,11 @@ TRACE("NTLM SEALKEY(): 128-bit key\n"); memcpy(result, RandomSessionKey, 16); } -} - -VOID + + return TRUE; +} + +BOOLEAN MAC(ULONG flags, PCCHAR buf, ULONG buf_len, @@ -195,7 +215,8 @@ { ULONG *res_ptr;
- if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { + if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) + { UCHAR seal_key_ [16]; UCHAR hmac[16]; UCHAR tmp[4 + buf_len]; @@ -204,7 +225,8 @@ RC4Init(Handle, SealingKey')
*/ - if (flags & NTLMSSP_NEGOTIATE_DATAGRAM) { + if (flags & NTLMSSP_NEGOTIATE_DATAGRAM) + { UCHAR tmp2 [16+4]; memcpy(tmp2, seal_key, seal_key_len); *((ULONG *)(tmp2+16)) = sequence; @@ -225,7 +247,8 @@
HMAC_MD5(sign_key, sign_key_len, tmp, 4 + buf_len, hmac);
- if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH) + { TRACE("NTLM MAC(): Key Exchange\n"); RC4K(seal_key_, seal_key_len, hmac, 8, result+4); } else { @@ -248,6 +271,8 @@ // Replace the first four bytes of the ciphertext with the random_pad res_ptr[1] = random_pad; // 4 bytes } + + return TRUE; }
VOID @@ -324,6 +349,9 @@ pNtResponse->Flags = 0; pNtResponse->MsgWord = 0;
+ TRACE("%wZ %wZ %wZ %wZ %p %p %p %p %p\n", + pUserName, pPassword, pDomainName, pServerName, ChallengeToClient, + pNtResponse, pLm2Response, pUserSessionKey, pLmSessionKey);
NtQuerySystemTime((PLARGE_INTEGER)&pNtResponse->TimeStamp); NtlmGenerateRandomBits(pNtResponse->ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH); @@ -361,7 +389,6 @@ { HMAC_MD5_CTX ctx;
- HMACMD5Init(&ctx, (PUCHAR)NtpUserSessionKey, sizeof(*NtpUserSessionKey)); HMACMD5Update(&ctx, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH); HMACMD5Update(&ctx, ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH);
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/ciphers.h URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/ciphers.h [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/ciphers.h [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -54,7 +54,7 @@ }MD5_CTX;
/* advapi32 */ -void WINAPI MD5Init( MD5_CTX *ctx); +void WINAPI MD5Init(MD5_CTX *ctx); void WINAPI MD5Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len); void WINAPI MD5Final(MD5_CTX *ctx);
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/context.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/context.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/context.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -280,8 +280,7 @@ goto fail; } } - - }//end is datagram + }
/* generate session key */ if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) @@ -329,9 +328,10 @@ OUT OPTIONAL PTimeStamp ptsExpiry) { SECURITY_STATUS ret = SEC_E_OK; - PSecBuffer InputToken1, InputToken2; - PSecBuffer OutputToken1, OutputToken2; - ULONG_PTR newContext; + PSecBuffer InputToken1, InputToken2 = NULL; + PSecBuffer OutputToken1, OutputToken2 = NULL; + SecBufferDesc BufferDesc; + ULONG_PTR newContext = 0; ULONG NegotiateFlags; UCHAR sessionKey;
@@ -390,14 +390,13 @@
ret = NtlmGenerateNegotiateMessage(newContext, fContextReq, - InputToken1, OutputToken1);
/* set result */ phNewContext->dwUpper = NegotiateFlags; phNewContext->dwLower = newContext; } - else /* challenge! */ + else if(phContext) /* challenge! */ { TRACE("ISC challenged!\n"); if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) @@ -413,7 +412,6 @@ return SEC_E_INVALID_TOKEN; } } - *phNewContext = *phContext; ret = NtlmHandleChallengeMessage(phNewContext->dwLower, fContextReq, @@ -425,6 +423,11 @@ ptsExpiry, &NegotiateFlags); } + else + { + ERR("bad call to InitializeSecurityContext\n"); + goto fail; + }
if(!NT_SUCCESS(ret)) { @@ -433,7 +436,6 @@ }
/* build blob with the output message */ - SecBufferDesc BufferDesc; BufferDesc.ulVersion = SECBUFFER_VERSION; BufferDesc.cBuffers = 1; BufferDesc.pBuffers = OutputToken1; @@ -441,7 +443,8 @@ if(fContextReq & ISC_REQ_ALLOCATE_MEMORY) *pfContextAttr |= ISC_RET_ALLOCATED_MEMORY;
- *pOutput = BufferDesc; + if(pOutput) + *pOutput = BufferDesc;
return ret;
@@ -455,7 +458,7 @@ if(OutputToken1 && OutputToken1->pvBuffer) NtlmFree(OutputToken1->pvBuffer); if(OutputToken2 && OutputToken2->pvBuffer) - NtlmFree(OutputToken1->pvBuffer); + NtlmFree(OutputToken2->pvBuffer); }
return ret; @@ -567,8 +570,11 @@ OUT PTimeStamp ptsExpiry) { SECURITY_STATUS ret = SEC_E_OK; - PSecBuffer InputToken1, InputToken2; - PSecBuffer OutputToken1, OutputToken2; + PSecBuffer InputToken1, InputToken2 = NULL; + PSecBuffer OutputToken1, OutputToken2 = NULL; + SecBufferDesc BufferDesc; + USER_SESSION_KEY sessionKey; + ULONG userflags;
TRACE("AcceptSecurityContext %p %p %p %lx %lx %p %p %p %p\n", phCredential, phContext, pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsExpiry); @@ -591,7 +597,7 @@ FALSE); if(!ret) { - ERR("Failed to get input token!\n"); + ERR("Failed to get input token 2!\n"); //return SEC_E_INVALID_TOKEN; }
@@ -628,8 +634,6 @@ else { *phNewContext = *phContext; - USER_SESSION_KEY sessionKey; - ULONG userflags; TRACE("phNewContext->dwLower %lx\n", phNewContext->dwLower); ret = NtlmHandleAuthenticateMessage(phNewContext->dwLower, fContextReq, @@ -648,7 +652,6 @@ }
/* build blob with the output message */ - SecBufferDesc BufferDesc; BufferDesc.ulVersion = SECBUFFER_VERSION; BufferDesc.cBuffers = 1; BufferDesc.pBuffers = OutputToken1;
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/credentials.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/credentials.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/credentials.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -135,18 +135,29 @@ ULONG ulAttribute, PVOID pBuffer) { + PNTLMSSP_CREDENTIAL credentials = NULL; + PSecPkgContext_NamesW credname; SECURITY_STATUS ret;
TRACE("(%p, %lx, %p)\n", phCredential, ulAttribute, pBuffer);
- if(ulAttribute == SECPKG_ATTR_NAMES) - { - FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + credentials = NtlmReferenceCredential(phCredential->dwLower); + + switch(ulAttribute) + { + case SECPKG_ATTR_NAMES: + credname = (PSecPkgContext_NamesW) pBuffer; + credname->sUserName = _wcsdup(credentials->UserName.Buffer); + ret = SEC_E_OK; + break; + default: + FIXME("QueryCredentialsAttributesW(%p, %lx, %p) Unimplemented\n", + phCredential, ulAttribute, pBuffer); ret = SEC_E_UNSUPPORTED_FUNCTION; - } - else - ret = SEC_E_UNSUPPORTED_FUNCTION; - + break; + } + + NtlmDereferenceCredential(phCredential->dwLower); return ret; }
@@ -156,18 +167,23 @@ IN ULONG ulAttribute, OUT PVOID pBuffer) { + //PNTLMSSP_CREDENTIAL credentials = NULL; SECURITY_STATUS ret;
TRACE("(%p, %lx, %p)\n", phCredential, ulAttribute, pBuffer);
- if(ulAttribute == SECPKG_ATTR_NAMES) - { - FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + //credentials = NtlmReferenceCredential(phCredential->dwLower); + + switch(ulAttribute) + { + default: + FIXME("QueryCredentialsAttributesA(%p, %lx, %p) Unimplemented\n", + phCredential, ulAttribute, pBuffer); ret = SEC_E_UNSUPPORTED_FUNCTION; - } - else - ret = SEC_E_UNSUPPORTED_FUNCTION; - + break; + } + + //NtlmDereferenceCredential(phCredential->dwLower); return ret; }
@@ -203,8 +219,7 @@ RtlInitUnicodeString(&domain, NULL); RtlInitUnicodeString(&password, NULL);
- //if(fCredentialUse == SECPKG_CRED_OUTBOUND) - if(pAuthData) + if(fCredentialUse == SECPKG_CRED_OUTBOUND && pAuthData) { PSEC_WINNT_AUTH_IDENTITY_W auth_data = pAuthData;
@@ -265,7 +280,6 @@ /* FIXME: LOOKUP STORED CREDENTIALS!!! */
/* we need to build a credential */ - /* refactor: move into seperate function */ if(!foundCred) { cred = (PNTLMSSP_CREDENTIAL)NtlmAllocate(sizeof(NTLMSSP_CREDENTIAL)); @@ -305,8 +319,8 @@ phCredential->dwUpper = credFlags; phCredential->dwLower = (ULONG_PTR)cred;
- //*ptsExpiry->HighPart = 0x7FFFFF36; - //*ptsExpiry->LowPart = 0xD5969FFF; + ptsExpiry->HighPart = 0x7FFFFF36; + ptsExpiry->LowPart = 0xD5969FFF;
/* free strings as we used recycled credentials */ @@ -438,7 +452,7 @@ if(!phCredential) return SEC_E_INVALID_HANDLE;
- NtlmDereferenceCredential((ULONG_PTR)phCredential->dwLower); + NtlmDereferenceCredential(phCredential->dwLower); phCredential = NULL;
return SEC_E_OK;
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/crypt.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/crypt.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/crypt.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -22,14 +22,17 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
+#ifdef USE_CRYPTOAPI HCRYPTPROV Prov; +#endif PVOID LockedMemoryPtr = NULL; ULONG LockedMemorySize = 0; + BOOL NtlmInitializeRNG(VOID) { - BOOL ret; - + BOOL ret = TRUE; +#ifdef USE_CRYPTOAPI /* prevent double initialization */ if(Prov) return TRUE; @@ -42,27 +45,33 @@
if(!ret) ERR("CryptAcquireContext failed with %x.\n",GetLastError()); +#endif return ret; }
VOID NtlmTerminateRNG(VOID) { +#ifdef USE_CRYPTOAPI if(Prov) { CryptReleaseContext(Prov,0); Prov = 0; } +#endif }
NTSTATUS NtlmGenerateRandomBits(VOID *Bits, ULONG Size) { +#ifdef USE_CRYPTOAPI if(CryptGenRandom(Prov, Size, (BYTE*)Bits)) return STATUS_SUCCESS; - - //return STATUS_UNSUCCESSFUL; - return STATUS_SUCCESS; +#else + if(RtlGenRandom(Bits, Size)) + return STATUS_SUCCESS; +#endif + return STATUS_UNSUCCESSFUL; }
BOOL
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/debug.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/debug.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/debug.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -118,7 +118,7 @@ rgbLine[cbLine++] = 0; TRACE("%s\n", rgbLine); } -} // end PrintHexDump +}
void NtlmPrintAvPairs(const PVOID Buffer)
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/dllmain.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/dllmain.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/dllmain.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -26,21 +26,15 @@
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved); + TRACE("DllMain(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
switch (fdwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); NtlmInitializeGlobals(); - - /* rsaehn has still not registered its crypto providers */ - if(!SetupIsActive()) - { - //REACTOS BUG: even after 2nd stage crypto providers are not available! - NtlmInitializeRNG(); - NtlmInitializeProtectedMemory(); - } + NtlmInitializeRNG(); + NtlmInitializeProtectedMemory(); NtlmCredentialInitialize(); NtlmContextInitialize(); break;
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/messages.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/messages.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/messages.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -17,6 +17,7 @@ * */ #include "ntlmssp.h" +#include "ciphers.h"
#include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ntlm); @@ -27,34 +28,74 @@ SECURITY_STATUS SEC_ENTRY EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { - SECURITY_STATUS ret = SEC_E_UNSUPPORTED_FUNCTION; - //int token_idx, data_idx; + SECURITY_STATUS ret = SEC_E_OK; + PSecBuffer data_buffer = NULL; + PSecBuffer signature_buffer = NULL; + UCHAR digest[16], checksum[8], *signature; + UINT index, length, version = 1; + PNTLMSSP_CONTEXT context; + HMAC_MD5_CTX hmac; + void* data;
- TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo); + ERR("EncryptMessage(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo); + + if(fQOP) + FIXME("Ignoring fQOP\n");
if(!phContext) return SEC_E_INVALID_HANDLE;
- if(fQOP) - FIXME("Ignoring fQOP\n"); - - if(MessageSeqNo) - FIXME("Ignoring MessageSeqNo\n"); - if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) return SEC_E_INVALID_TOKEN;
- //if((token_idx = GetTokenBufferIndex(pMessage)) == -1) - // return SEC_E_INVALID_TOKEN; + /* get context, need to free it later! */ + context = NtlmReferenceContext(phContext->dwLower);
- //if((data_idx = GetDataBufferIndex(pMessage)) ==-1 ) - // return SEC_E_INVALID_TOKEN; + TRACE("pMessage->cBuffers %d\n", pMessage->cBuffers); + /* extract data and signature buffers */ + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + TRACE("pMessage->pBuffers[index].BufferType %d\n", pMessage->pBuffers[index].BufferType); + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer = &pMessage->pBuffers[index]; + else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN) + signature_buffer = &pMessage->pBuffers[index]; + }
- //if(pMessage->pBuffers[token_idx].cbBuffer < 16) - // return SEC_E_BUFFER_TOO_SMALL; + if (!data_buffer || !signature_buffer) + { + ERR("No data or tokens provided!\n"); + ret = SEC_E_INVALID_TOKEN; + goto exit; + }
- FIXME("EncryptMessage Unimplemented\n"); + /* Copy original data buffer */ + length = data_buffer->cbBuffer; + data = NtlmAllocate(length); + memcpy(data, data_buffer->pvBuffer, length);
+ /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ + HMACMD5Init(&hmac, context->ClientSigningKey, sizeof(context->ServerSigningKey)); + HMACMD5Update(&hmac, (void*) &(MessageSeqNo), sizeof(MessageSeqNo)); + HMACMD5Update(&hmac, data, length); + HMACMD5Final(&hmac, digest); + + /* Encrypt message using with RC4, result overwrites original buffer */ + rc4_crypt(context->SendSealKey, data_buffer->pvBuffer, data, length); + NtlmFree(data); + + /* RC4-encrypt first 8 bytes of digest */ + rc4_crypt(context->SendSealKey, checksum, digest, 8); + signature = (UCHAR*) signature_buffer->pvBuffer; + + /* Concatenate version, ciphertext and sequence number to build signature */ + memcpy(signature, (void*) &version, sizeof(version)); + memcpy(&signature[4], (void*) checksum, sizeof(checksum)); + memcpy(&signature[12], (void*) &(MessageSeqNo), sizeof(MessageSeqNo)); + context->SentSequenceNum++; + +exit: + NtlmDereferenceContext(phContext->dwLower); return ret;
} @@ -65,30 +106,84 @@ SECURITY_STATUS SEC_ENTRY DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) { - //int token_idx, data_idx; - SECURITY_STATUS ret = SEC_E_UNSUPPORTED_FUNCTION; + SECURITY_STATUS ret = SEC_E_OK; + PNTLMSSP_CONTEXT context; + ULONG index, length; + HMAC_MD5_CTX hmac; + UINT version = 1; + UCHAR digest[16], expected_signature[16], checksum[8]; + PSecBuffer data_buffer = NULL, signature = NULL; + PVOID data;
TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
+ /* sanity checks */ if(!phContext) return SEC_E_INVALID_HANDLE; - - if(MessageSeqNo) - FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) return SEC_E_INVALID_TOKEN;
- //if((token_idx = GetTokenBufferIndex(pMessage)) == -1) - // return SEC_E_INVALID_TOKEN; + /* get context */ + context = NtlmReferenceContext(phContext->dwLower);
- //if((data_idx = GetDataBufferIndex(pMessage)) ==-1) - // return SEC_E_INVALID_TOKEN; + /* extract data and signature buffers */ + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer = &pMessage->pBuffers[index]; + else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN) + signature = &pMessage->pBuffers[index]; + }
- //if(pMessage->pBuffers[token_idx].cbBuffer < 16) - // return SEC_E_BUFFER_TOO_SMALL; + /* verify we got needed buffers */ + if (!data_buffer || !signature) + { + ERR("No data or tokens provided!\n"); + ret = SEC_E_INVALID_TOKEN; + goto exit; + }
- FIXME("DecryptMessage Unimplemented\n"); + + if(signature->cbBuffer < 16) + { + ERR("Signature buffer too small!\n"); + ret = SEC_E_BUFFER_TOO_SMALL; + goto exit; + } + + /* Copy original data buffer */ + length = data_buffer->cbBuffer; + data = NtlmAllocate(length); + memcpy(data, data_buffer->pvBuffer, length);
+ /* Decrypt message using with RC4 */ + rc4_crypt(context->RecvSealKey, data_buffer->pvBuffer, data, length); + + /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ + HMACMD5Init(&hmac, context->ServerSigningKey, sizeof(context->ServerSigningKey)); + HMACMD5Update(&hmac, (UCHAR*) &(MessageSeqNo), sizeof(MessageSeqNo)); + HMACMD5Update(&hmac, data_buffer->pvBuffer, data_buffer->cbBuffer); + HMACMD5Final(&hmac, digest); + NtlmFree(data); + + /* RC4-encrypt first 8 bytes of digest */ + rc4_crypt(context->RecvSealKey, digest, checksum, 8); + + /* Concatenate version, ciphertext and sequence number to build signature */ + memcpy(expected_signature, (void*) &version, 4); + memcpy(&expected_signature[4], (void*) checksum, 4); + memcpy(&expected_signature[12], (void*) &(MessageSeqNo), 4); + context->RecvSequenceNum++; + + if (memcmp(signature->pvBuffer, expected_signature, sizeof(expected_signature)) != 0) + { + /* signature verification failed! */ + ERR("signature verification failed, something nasty is going on!\n"); + ret = SEC_E_MESSAGE_ALTERED; + } + +exit: + NtlmDereferenceContext(phContext->dwLower); return ret; }
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -25,11 +25,11 @@ /* globals */ CRITICAL_SECTION GlobalCritSect; /* use to read/write global state */
-NTLM_MODE NtlmMode = NtlmUserMode; /* FIXME */ +NTLM_MODE NtlmMode = NtlmUserMode; /* FIXME: No LSA mode support */ UNICODE_STRING NtlmComputerNameString; UNICODE_STRING NtlmDomainNameString; UNICODE_STRING NtlmDnsNameString; -UNICODE_STRING NtlmAvTargetInfo; // contains AV pairs with local info +UNICODE_STRING NtlmAvTargetInfo; OEM_STRING NtlmOemComputerNameString; OEM_STRING NtlmOemDomainNameString; OEM_STRING NtlmOemDnsNameString; @@ -41,7 +41,7 @@ NtlmInitializeGlobals(VOID) { NTSTATUS status = STATUS_SUCCESS; - //LPWKSTA_USER_INFO_1 pBuf = NULL; + LPWKSTA_USER_INFO_1 pBuf = NULL; WCHAR compName[CNLEN + 1], domName[DNLEN+1], dnsName[256]; ULONG compNamelen = sizeof(compName), dnsNamelen = sizeof(dnsName); PMSV1_0_AV_PAIR pAvPairs; @@ -58,24 +58,24 @@ if (!GetComputerNameExW(ComputerNameDnsFullyQualified, dnsName, &dnsNamelen)) { dnsName[0] = L'\0'; + ERR("could not get dns name!\n"); + } + TRACE("%s\n",debugstr_w(dnsName)); + + /* FIXME: this still does not match what msv1_0 returns */ + if (!(NERR_Success == NetWkstaUserGetInfo(0, 1, (LPBYTE*)&pBuf))) + { + wcscpy(domName, L"WORKGROUP"); ERR("could not get domain name!\n"); } - TRACE("%s\n",debugstr_w(dnsName)); - - /* FIXME: this still does not match what msv1_0 returns */ - // if (!(NERR_Success == NetWkstaUserGetInfo(0, 1, (LPBYTE*)&pBuf))) - //{ - wcscpy(domName, L"WORKGROUP\0"); - FIXME("how to get domain name!?\n"); - //} - //else - //{ - // wcscpy(domName, pBuf->wkui1_logon_domain); - //} - - //if (pBuf != NULL) - // NetApiBufferFree(pBuf); - TRACE("%s\n",debugstr_w(domName)); + else + { + wcscpy(domName, pBuf->wkui1_logon_domain); + } + + if (pBuf != NULL) + NetApiBufferFree(pBuf); + ERR("%s\n",debugstr_w(domName));
RtlCreateUnicodeString(&NtlmComputerNameString, compName); RtlCreateUnicodeString(&NtlmDnsNameString, dnsName); @@ -101,9 +101,8 @@ { ERR("could not get process token!!\n"); } - + //FIX ME: This is broken /* init global target AV pairs */ - RtlInitUnicodeString(&NtlmAvTargetInfo, NULL); AvPairsLen = NtlmDomainNameString.Length + //fix me: domain controller name NtlmComputerNameString.Length + //computer name @@ -126,6 +125,8 @@ NtlmAvlAdd(pAvPairs, MsvAvDnsComputerName, &NtlmDnsNameString, AvPairsLen); NtlmAvTargetInfo.Length = (USHORT)NtlmAvlLen(pAvPairs, AvPairsLen);
+ ERR("NtlmAvTargetInfo %S\n", NtlmAvTargetInfo.Buffer); + NtlmPrintAvPairs(pAvPairs); return status; }
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.h URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.h [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/ntlmssp.h [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -110,19 +110,30 @@ typedef struct _NTLMSSP_CONTEXT { LIST_ENTRY Entry; - LARGE_INTEGER StartTime;//context creation time + LARGE_INTEGER StartTime; BOOL isServer; BOOL isLocal; - ULONG Timeout;//how long context is valid pre-authentication + ULONG Timeout; ULONG RefCount; ULONG NegotiateFlags; ULONG ContextFlags; NTLMSSP_CONTEXT_STATE State; PNTLMSSP_CREDENTIAL Credential; - UCHAR Challenge[MSV1_0_CHALLENGE_LENGTH]; //ChallengeSent - UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; //LSA + UCHAR Challenge[MSV1_0_CHALLENGE_LENGTH]; + UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; HANDLE ClientToken; ULONG ProcId; + + /* message support */ + int SentSequenceNum; + int RecvSequenceNum; + struct _rc4_key* SendSealKey; + struct _rc4_key* RecvSealKey; + UCHAR ClientSigningKey[16]; + UCHAR ClientSealingKey[16]; + UCHAR ServerSigningKey[16]; + UCHAR ServerSealingKey[16]; + UCHAR MessageIntegrityCheck[16]; } NTLMSSP_CONTEXT, *PNTLMSSP_CONTEXT;
/* private functions */
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -25,7 +25,6 @@ SECURITY_STATUS NtlmGenerateNegotiateMessage(IN ULONG_PTR Context, IN ULONG ContextReq, - IN PSecBuffer InputToken, OUT PSecBuffer OutputToken) { PNTLMSSP_CONTEXT context = (PNTLMSSP_CONTEXT)Context; @@ -69,18 +68,18 @@ return SEC_E_INSUFFICIENT_MEMORY; }
- /* allocate a negotiate message */ - if(!(message = (PNEGOTIATE_MESSAGE) NtlmAllocate(messageSize))) - return SEC_E_INSUFFICIENT_MEMORY; + /* use allocated memory */ + message = (PNEGOTIATE_MESSAGE) OutputToken->pvBuffer; + offset = (ULONG_PTR)(message+1);
/* build message */ - strcpy(message->Signature, NTLMSSP_SIGNATURE); + strncpy(message->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE)); message->MsgType = NtlmNegotiate; message->NegotiateFlags = context->NegotiateFlags;
TRACE("nego message %p size %lu\n", message, messageSize); - - offset = (ULONG_PTR)(message+1); + TRACE("context %p context->NegotiateFlags:\n",context); + NtlmPrintNegotiateFlags(message->NegotiateFlags);
/* local connection */ if((!cred->DomainName.Buffer && !cred->UserName.Buffer && @@ -108,20 +107,69 @@ blobBuffer[1].Offset = offset+1; }
- /* zero struct */ + /* zero version struct */ memset(&message->Version, 0, sizeof(NTLM_WINDOWS_VERSION));
- /* send it back */ - memcpy(OutputToken->pvBuffer, message, messageSize); + /* set state */ + context->State = NegotiateSent; + return SEC_I_CONTINUE_NEEDED; +} + +SECURITY_STATUS +NtlmGenerateChallengeMessage(IN PNTLMSSP_CONTEXT Context, + IN PNTLMSSP_CREDENTIAL Credentials, + IN UNICODE_STRING TargetName, + IN ULONG MessageFlags, + OUT PSecBuffer OutputToken) +{ + PCHALLENGE_MESSAGE chaMessage = NULL; + ULONG messageSize, offset; + + /* compute message size */ + messageSize = sizeof(CHALLENGE_MESSAGE) + NtlmAvTargetInfo.Length; + if(TargetName.Length > 0) + messageSize += TargetName.Length; + + ERR("generating chaMessage of size %lu\n", messageSize); + + /* + * according to tests ntlm does not listen to ASC_REQ_ALLOCATE_MEMORY + * or lack thereof, furthermore the buffer size is always NTLM_MAX_BUF + */ + OutputToken->pvBuffer = NtlmAllocate(NTLM_MAX_BUF); OutputToken->cbBuffer = messageSize; - context->State = NegotiateSent; - - TRACE("context %p context->NegotiateFlags:\n",context); - NtlmPrintNegotiateFlags(message->NegotiateFlags); - - /* free resources */ - NtlmFree(message); - + + /* check allocation */ + if(!OutputToken->pvBuffer) + return SEC_E_INSUFFICIENT_MEMORY; + + /* use allocated memory */ + chaMessage = (PCHALLENGE_MESSAGE)OutputToken->pvBuffer; + + /* build message */ + strncpy(chaMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE)); + chaMessage->MsgType = NtlmChallenge; + chaMessage->NegotiateFlags = Context->NegotiateFlags; + chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; + + /* generate server challenge */ + NtlmGenerateRandomBits(chaMessage->ServerChallenge, MSV1_0_CHALLENGE_LENGTH); + memcpy(Context->Challenge, chaMessage->ServerChallenge, MSV1_0_CHALLENGE_LENGTH); + + /* point to the end of chaMessage */ + offset = (ULONG_PTR)(chaMessage+messageSize); + + /* set target information */ + ERR("set target information chaMessage %p to %S, len %d, offset %d\n", chaMessage, TargetName.Buffer, TargetName.Length, &offset); + NtlmUnicodeStringToBlob((PVOID)chaMessage, &TargetName, &chaMessage->TargetName, &offset); + + //ERR("set target information %p to avl %S, %d, %d\n", chaMessage, NtlmAvTargetInfo.Buffer, NtlmAvTargetInfo.Length, offset); + //NtlmPrintAvPairs(&NtlmAvTargetInfo); + //NtlmUnicodeStringToBlob((PVOID)chaMessage, &NtlmAvTargetInfo, &chaMessage->TargetInfo, &offset); + chaMessage->NegotiateFlags |= MessageFlags; + + /* set state */ + Context->State = ChallengeSent; return SEC_I_CONTINUE_NEEDED; }
@@ -142,8 +190,7 @@ PNTLMSSP_CONTEXT context = NULL; UNICODE_STRING targetName; OEM_STRING OemDomainName, OemWorkstationName; - ULONG targetFlags = 0; - BOOLEAN isUnicode; + ULONG negotiateFlags = 0;
TRACE("NtlmHandleNegotiateMessage hContext %lx\n", hContext); if(!(context = NtlmAllocateContext())) @@ -154,7 +201,6 @@ }
hContext = (ULONG_PTR)context; - TRACE("NtlmHandleNegotiateMessage hContext %lx\n", hContext);
/* InputToken should contain a negotiate message */ if(InputToken->cbBuffer > NTLM_MAX_BUF || @@ -259,18 +305,16 @@ if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY || negoMessage->NegotiateFlags & NTLMSSP_REQUEST_TARGET) { - targetFlags |= NTLMSSP_TARGET_TYPE_SERVER | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO; + negotiateFlags |= NTLMSSP_TARGET_TYPE_SERVER | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO;
if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE) { - isUnicode = TRUE; - targetFlags |= NTLMSSP_NEGOTIATE_UNICODE; + negotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; RtlInitUnicodeString(&targetName, NtlmComputerNameString.Buffer); } else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM) { - isUnicode = FALSE; - targetFlags |= NTLMSSP_NEGOTIATE_OEM; + negotiateFlags |= NTLMSSP_NEGOTIATE_OEM; RtlInitUnicodeString(&targetName, (PWCHAR)&NtlmOemComputerNameString.Buffer); } else @@ -281,87 +325,6 @@ } }
- /* create a challenge message */ - PCHALLENGE_MESSAGE chaMessage = NULL; - ULONG messageSize = sizeof(CHALLENGE_MESSAGE)+ targetName.Length + 1 + NtlmAvTargetInfo.Length; - ULONG offset; - - /* ntlm does not listen to ASC_REQ_ALLOCATE_MEMORY or lack thereof */ - /* further more the buffer size is always NTLM_MAX_BUF */ - /* allocate output buffer */ - OutputToken->pvBuffer = NtlmAllocate(NTLM_MAX_BUF); - OutputToken->cbBuffer = messageSize; - - if(!OutputToken->pvBuffer) - { - ret = SEC_E_INSUFFICIENT_MEMORY; - goto exit; - } - - /* allocate message */ - if (!(chaMessage = (PCHALLENGE_MESSAGE)NtlmAllocate(messageSize))) - { - ret = SEC_E_INSUFFICIENT_MEMORY; - goto exit; - } - - TRACE("message %p size %lu\n", chaMessage, messageSize); - - /* build message */ - strcpy(chaMessage->Signature, NTLMSSP_SIGNATURE); - chaMessage->MsgType = NtlmChallenge; - chaMessage->NegotiateFlags = context->NegotiateFlags; - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - - /* generate challenge */ - NtlmGenerateRandomBits(chaMessage->ServerChallenge, MSV1_0_CHALLENGE_LENGTH); - memcpy(context->Challenge, chaMessage->ServerChallenge, MSV1_0_CHALLENGE_LENGTH); - - offset = (ULONG_PTR)(chaMessage+1); - - if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) - { - negoMessage->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY; - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY; - } - else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY) - { - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; - } - - if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - - if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) - { - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; - *pContextAttr |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT); - context->ContextFlags |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT); - } - - if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL) - { - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; - *pContextAttr |= ASC_RET_CONFIDENTIALITY; - context->ContextFlags |= ASC_RET_CONFIDENTIALITY; - } - - if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; - - /* client requested encryption */ - if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_128) - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_128; - else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_56) - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_56; - - if(negoMessage->NegotiateFlags & NTLMSSP_REQUEST_INIT_RESP) - { - chaMessage->NegotiateFlags |= NTLMSSP_REQUEST_INIT_RESP; - *pContextAttr |= ASC_RET_IDENTIFY; - context->ContextFlags |= ASC_RET_IDENTIFY; - } - /* check for local call */ if((negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) && (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)) @@ -369,30 +332,70 @@ NtlmBlobToUnicodeString(InputToken, negoMessage->OemDomainName, (PUNICODE_STRING)&OemDomainName); NtlmBlobToUnicodeString(InputToken, negoMessage->OemWorkstationName, (PUNICODE_STRING)&OemWorkstationName);
- if (RtlEqualString(&OemWorkstationName, &NtlmOemComputerNameString, FALSE)&& + if (RtlEqualString(&OemWorkstationName, &NtlmOemComputerNameString, FALSE) && RtlEqualString(&OemDomainName, &NtlmOemDomainNameString, FALSE)) { TRACE("local negotiate detected!\n"); - chaMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_LOCAL_CALL; + negotiateFlags |= NTLMSSP_NEGOTIATE_LOCAL_CALL; } }
- NtlmUnicodeStringToBlob((PVOID)chaMessage, &targetName, &chaMessage->TargetName, &offset); - NtlmUnicodeStringToBlob((PVOID)chaMessage, &NtlmAvTargetInfo, &chaMessage->TargetInfo, &offset); - chaMessage->NegotiateFlags |= targetFlags; - - memcpy(OutputToken->pvBuffer, chaMessage, messageSize); - OutputToken->cbBuffer = messageSize; - context->State = ChallengeSent; - ret = SEC_I_CONTINUE_NEEDED; + /* compute negotiate message flags */ + if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) + { + negoMessage->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + negotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY; + } + else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY) + { + negotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; + } + + if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) + negotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + + if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) + { + *pContextAttr |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT); + context->ContextFlags |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT); + negotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; + } + + if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL) + { + *pContextAttr |= ASC_RET_CONFIDENTIALITY; + context->ContextFlags |= ASC_RET_CONFIDENTIALITY; + negotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + } + + if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) + negotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; + + /* client requested encryption */ + if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_128) + negotiateFlags |= NTLMSSP_NEGOTIATE_128; + else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_56) + negotiateFlags |= NTLMSSP_NEGOTIATE_56; + + if(negoMessage->NegotiateFlags & NTLMSSP_REQUEST_INIT_RESP) + { + *pContextAttr |= ASC_RET_IDENTIFY; + context->ContextFlags |= ASC_RET_IDENTIFY; + negotiateFlags |= NTLMSSP_REQUEST_INIT_RESP; + } + + ret = NtlmGenerateChallengeMessage(context, + cred, + targetName, + negotiateFlags, + OutputToken);
exit: - //if(chaMessage) NtlmFree(chaMessage); - //if(negoMessage) NtlmFree(negoMessage); - //if(cred) NtlmDereferenceCredential((ULONG_PTR)cred); - //if(targetName.Buffer) NtlmFree(targetName.Buffer); - //if(OemDomainName.Buffer) NtlmFree(OemDomainName.Buffer); - //if(OemWorkstationName.Buffer) NtlmFree(OemWorkstationName.Buffer); + if(negoMessage) NtlmFree(negoMessage); + if(cred) NtlmDereferenceCredential((ULONG_PTR)cred); + if(targetName.Buffer) NtlmFree(targetName.Buffer); + if(OemDomainName.Buffer) NtlmFree(OemDomainName.Buffer); + if(OemWorkstationName.Buffer) NtlmFree(OemWorkstationName.Buffer);
return ret; } @@ -413,6 +416,19 @@ PCHALLENGE_MESSAGE challenge = NULL; PNTLMSSP_CREDENTIAL cred = NULL; BOOLEAN isUnicode; + UNICODE_STRING ServerName; + MSV1_0_NTLM3_RESPONSE NtResponse; + LM2_RESPONSE Lm2Response; + USER_SESSION_KEY UserSessionKey; + LM_SESSION_KEY LmSessionKey; + + PAUTHENTICATE_MESSAGE authmessage = NULL; + ULONG_PTR offset; + UNICODE_STRING NtResponseString; + UNICODE_STRING LmResponseString; + UNICODE_STRING UserSessionKeyString; + UNICODE_STRING LmSessionKeyString; + ULONG messageSize;
TRACE("NtlmHandleChallengeMessage hContext %lx\n", hContext); /* get context */ @@ -561,27 +577,32 @@ ERR("NTLMSSP_NEGOTIATE_LOCAL_CALL set!\n");
/* extract target info */ - UNICODE_STRING ServerName; - if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) { - /* wtf? shouldnt this contain AV pairs? */ - ret = NtlmBlobToUnicodeString(InputToken1, - challenge->TargetInfo, - &ServerName); - if(!NT_SUCCESS(ret)) - { - ERR("could not get target info!\n"); - goto fail; - } - } - else + ERR("NTLMSSP_NEGOTIATE_TARGET_INFO\n"); + //PMSV1_0_AV_PAIR pAvPair; + //pAvPair = (PMSV1_0_AV_PAIR)challenge->TargetInfo; + + //PVOID ptr = ((PUCHAR)InputToken1->pvBuffer + challenge->TargetInfo.Offset); + //NtlmPrintAvPairs(ptr); + //NtlmPrintHexDump(InputToken1->pvBuffer, InputToken1->cbBuffer); + + //NtlmAvlGet(pAvPair, MsvAvNbDomainName, GetRespRequest->ServerName.Length) + + //if(!NT_SUCCESS(ret)) + //{ + // ERR("could not get target info!\n"); + // goto fail; + //} + } + //else { /* spec: "A server that is a member of a domain returns the domain of which it * is a member, and a server that is not a member of a domain returns * the server name." how to tell?? */ ret = NtlmBlobToUnicodeString(InputToken1, - challenge->TargetName, + challenge->TargetInfo, + //challenge->TargetName, &ServerName); if(!NT_SUCCESS(ret)) { @@ -592,20 +613,15 @@ FIXME("convert to unicode!\n"); }
- - MSV1_0_NTLM3_RESPONSE NtResponse; - LM2_RESPONSE Lm2Response; - USER_SESSION_KEY UserSessionKey; - LM_SESSION_KEY LmSessionKey; - if(!(cred = NtlmReferenceCredential((ULONG_PTR)context->Credential))) goto fail;
/* unscramble password */ NtlmUnProtectMemory(cred->Password.Buffer, cred->Password.Length);
- TRACE("cred: %s %s %s\n", debugstr_w(cred->UserName.Buffer), - debugstr_w(cred->Password.Buffer), debugstr_w(cred->DomainName.Buffer)); + TRACE("cred: %s %s %s %s\n", debugstr_w(cred->UserName.Buffer), + debugstr_w(cred->Password.Buffer), debugstr_w(cred->DomainName.Buffer), + debugstr_w(ServerName.Buffer));
NtlmChallengeResponse(&cred->UserName, &cred->Password, @@ -617,32 +633,23 @@ &UserSessionKey, &LmSessionKey);
- PAUTHENTICATE_MESSAGE authmessage = NULL; - ULONG_PTR offset; - - UNICODE_STRING NtResponseString; - //UNICODE_STRING LmResponseString; - UNICODE_STRING UserSessionKeyString; - UNICODE_STRING LmSessionKeyString; - -#define InitString(str, input) str.MaximumLength = str.Length = sizeof(input)*sizeof(WCHAR); str.Buffer = (WCHAR*)&input +#define InitString(str, input) str.MaximumLength = str.Length = sizeof(input); str.Buffer = (WCHAR*)&input InitString(NtResponseString, NtResponse); - //InitString(LmResponseString, Lm2Response); + InitString(LmResponseString, Lm2Response); InitString(UserSessionKeyString, UserSessionKey); InitString(LmSessionKeyString, LmSessionKey);
- ULONG messageSize = sizeof(AUTHENTICATE_MESSAGE) + - ServerName.Length + cred->UserName.Length + cred->DomainName.Length + - NtResponseString.Length + UserSessionKeyString.Length + LmSessionKeyString.Length; - //LmResponseString.Length; - - if(!(authmessage = NtlmAllocate(messageSize))) + messageSize = sizeof(AUTHENTICATE_MESSAGE) + ServerName.Length + + cred->UserName.Length + cred->DomainName.Length + NtResponseString.Length + + UserSessionKeyString.Length + LmSessionKeyString.Length + LmResponseString.Length; + + if(!(authmessage = (PAUTHENTICATE_MESSAGE)NtlmAllocate(messageSize))) { ret = SEC_E_INSUFFICIENT_MEMORY; goto fail; }
- strcpy(authmessage->Signature, NTLMSSP_SIGNATURE); + strncpy(authmessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE)); authmessage->MsgType = NtlmAuthenticate;
offset = (ULONG_PTR)(authmessage+1); @@ -662,11 +669,13 @@ &authmessage->WorkstationName, &offset);
- //if(targetinfo) - //NtlmUnicodeStringToBlob((PVOID)authmessage, - // &LmResponseString, - // &authmessage->LmChallengeResponse, - // &offset); + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_TARGET_INFO) + { + NtlmUnicodeStringToBlob((PVOID)authmessage, + &LmResponseString, + &authmessage->LmChallengeResponse, + &offset); + }
NtlmUnicodeStringToBlob((PVOID)authmessage, &NtResponseString, @@ -724,7 +733,9 @@ SECURITY_STATUS ret = SEC_E_OK; PNTLMSSP_CONTEXT context = NULL; PAUTHENTICATE_MESSAGE authMessage = NULL; - BOOLEAN isUnicode; + UNICODE_STRING LmChallengeResponse, NtChallengeResponse, SessionKey; + UNICODE_STRING UserName, Workstation, DomainName; + //BOOLEAN isUnicode;
TRACE("NtlmHandleAuthenticateMessage hContext %x!\n", hContext); /* get context */ @@ -735,7 +746,7 @@ }
TRACE("context->State %d\n", context->State); - if(context->State != ChallengeSent || context->State != Authenticated) + if(context->State != ChallengeSent && context->State != Authenticated) { ERR("Context not in correct state!\n"); ret = SEC_E_OUT_OF_SEQUENCE; @@ -802,12 +813,12 @@ if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE) { context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_OEM; - isUnicode = TRUE; + //isUnicode = TRUE; } else if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM) { context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_UNICODE; - isUnicode = FALSE; + //isUnicode = FALSE; } else { @@ -816,9 +827,6 @@ ret = SEC_E_INVALID_TOKEN; goto fail; } - - UNICODE_STRING LmChallengeResponse, NtChallengeResponse, SessionKey; - UNICODE_STRING UserName, Workstation, DomainName;
if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, authMessage->LmChallengeResponse, &LmChallengeResponse)))
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.h URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.h [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.h [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -1,24 +1,24 @@ /* - * Copyright 2011 Samuel Serapión - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - */ +* Copyright 2011 Samuel Serapión +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +* +*/
/* see "NT LAN Manager (NTLM) Authentication Protocol Specification" - * [MS-NLMP] v20110504 for more details */ +* [MS-NLMP] v20110504 for more details */
/* signature */ #define NTLMSSP_SIGNATURE "NTLMSSP\0" @@ -65,6 +65,8 @@ #define NTLMSSP_REVISION_W2K3 0x0F
/* basic types */ +typedef char const* PCCHAR; + typedef struct _CYPHER_BLOCK { CHAR data[8]; @@ -111,10 +113,10 @@ }NTLM_WINDOWS_VERSION, *PNTLM_WINDOWS_VERSION;
/* - * Offset contains the offset from the beginning of the message to the - * actual value in the payload area. In the event of no data being sent - * Length and MaxLength should generaly be set to zero and ignored. - */ +* Offset contains the offset from the beginning of the message to the +* actual value in the payload area. In the event of no data being sent +* Length and MaxLength should generaly be set to zero and ignored. +*/ //NTLM_UNICODE_STRING_OVER_THE_WIRE typedef struct _NTLM_BLOB { @@ -161,7 +163,7 @@ ULONG NegotiateFlags; NTLM_WINDOWS_VERSION Version; BYTE MIC[16]; //doc says its ommited in nt,2k,xp,2k3 - /* payload */ + /* payload */ }AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
typedef struct _MESSAGE_SIGNATURE @@ -172,18 +174,19 @@ ULONG Nonce; }MESSAGE_SIGNATURE, *PMESSAGE_SIGNATURE;
+C_ASSERT(sizeof(MESSAGE_SIGNATURE) == 16); /* basic functions */
VOID NTOWFv1( - const PWCHAR password, - PUCHAR result); - -VOID + LPCWSTR password, + PUCHAR result); + +BOOLEAN NTOWFv2( - const PWCHAR password, - const PWCHAR user, - const PWCHAR domain, + LPCWSTR password, + LPCWSTR user, + LPCWSTR domain, PUCHAR result);
VOID @@ -191,11 +194,11 @@ const PCCHAR password, PUCHAR result);
-VOID +BOOLEAN LMOWFv2( - const PWCHAR password, - const PWCHAR user, - const PWCHAR domain, + LPCWSTR password, + LPCWSTR user, + LPCWSTR domain, PUCHAR result);
VOID @@ -211,20 +214,20 @@ const PUCHAR server_challenge, PUCHAR key_exchange_key);
-VOID +BOOLEAN SIGNKEY( const PUCHAR RandomSessionKey, BOOLEAN IsClient, PUCHAR Result);
-VOID +BOOLEAN SEALKEY( ULONG flags, const PUCHAR RandomSessionKey, BOOLEAN client, PUCHAR result);
-VOID +BOOLEAN MAC(ULONG flags, PCCHAR buf, ULONG buf_len, @@ -282,7 +285,6 @@ NtlmGenerateNegotiateMessage( IN ULONG_PTR hContext, IN ULONG ContextReq, - IN PSecBuffer InputToken, OUT PSecBuffer OutputToken);
SECURITY_STATUS @@ -298,6 +300,14 @@ OUT PTimeStamp ptsExpiry);
SECURITY_STATUS +NtlmGenerateChallengeMessage( + IN PNTLMSSP_CONTEXT Context, + IN PNTLMSSP_CREDENTIAL Credentials, + IN UNICODE_STRING TargetName, + IN ULONG MessageFlags, + OUT PSecBuffer OutputToken); + +SECURITY_STATUS NtlmHandleChallengeMessage( IN ULONG_PTR hContext, IN ULONG ContextReq,
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/sign.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/sign.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/sign.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -27,7 +27,6 @@ SECURITY_STATUS SEC_ENTRY MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { - //int token_idx; SECURITY_STATUS ret = SEC_E_UNSUPPORTED_FUNCTION;
TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, fQOP); @@ -36,15 +35,6 @@
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) return SEC_E_INVALID_TOKEN; - - //if((token_idx = GetTokenBufferIndex(pMessage)) == -1) - // return SEC_E_INVALID_TOKEN; - - //if(pMessage->pBuffers[token_idx].cbBuffer < 16) - // return SEC_E_BUFFER_TOO_SMALL; - - if(MessageSeqNo) - FIXME("Ignoring MessageSeqNo\n");
FIXME("MakeSignature unimplemented\n"); return ret; @@ -57,7 +47,6 @@ PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) { SECURITY_STATUS ret = SEC_E_UNSUPPORTED_FUNCTION; - //int token_idx;
TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP); if(!phContext) @@ -66,15 +55,6 @@ if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) return SEC_E_INVALID_TOKEN;
- //if((token_idx = GetTokenBufferIndex(pMessage)) == -1) - // return SEC_E_INVALID_TOKEN; - - //if(pMessage->pBuffers[token_idx].cbBuffer < 16) - // return SEC_E_BUFFER_TOO_SMALL; - - if(MessageSeqNo) - FIXME("Ignoring MessageSeqNo\n"); - FIXME("VerifySignature unimplemented\n"); return ret; }
Modified: branches/sspi-bringup/reactos/dll/win32/ntlmssp/util.c URL: http://svn.reactos.org/svn/reactos/branches/sspi-bringup/reactos/dll/win32/n... ============================================================================== --- branches/sspi-bringup/reactos/dll/win32/ntlmssp/util.c [iso-8859-1] (original) +++ branches/sspi-bringup/reactos/dll/win32/ntlmssp/util.c [iso-8859-1] Thu Jan 5 19:53:57 2017 @@ -194,8 +194,9 @@ }
/* convert blob into a string */ - OutputStr->MaximumLength = OutputStr->Length = Blob.Length; + OutputStr->MaximumLength = Blob.Length; OutputStr->Buffer = (PWSTR)((PCHAR)InputBuffer->pvBuffer) + offset; + OutputStr->Length = wcslen(OutputStr->Buffer) * sizeof(WCHAR);
return SEC_E_OK; }