Author: sserapion Date: Mon May 30 21:02:50 2011 New Revision: 52014
URL: http://svn.reactos.org/svn/reactos?rev=52014&view=rev Log: [NTLMSSP] - Implement NtlmHandleNegotiateMessage NtlmHandleChallengeMessage and NtlmHandleAuthenticateMessage - all wine client server tests pass - still missing a lot of stuff (WIP code)
Modified: 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/ntlmssp.h branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.c branches/sspi-bringup/reactos/dll/win32/ntlmssp/protocol.h
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] Mon May 30 21:02:50 2011 @@ -391,13 +391,7 @@ ret = NtlmGenerateNegotiateMessage(newContext, fContextReq, InputToken1, - &OutputToken1); - - if(!NT_SUCCESS(ret)) - { - ERR("NtlmGenerateNegotiateMessage failed with %lx\n", ret); - goto fail; - } + OutputToken1);
/* set result */ phNewContext->dwUpper = NegotiateFlags; @@ -406,7 +400,6 @@ else /* challenge! */ { TRACE("ISC challenged!\n"); - *phNewContext = *phContext; if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) { /* get second input token */ @@ -421,6 +414,7 @@ } }
+ *phNewContext = *phContext; ret = NtlmHandleChallengeMessage(phNewContext->dwLower, fContextReq, InputToken1, @@ -430,13 +424,12 @@ pfContextAttr, ptsExpiry, &NegotiateFlags); - - if(!NT_SUCCESS(ret)) - { - ERR("NtlmHandleChallengeMessage failed with %lx\n", ret); - goto fail; - } - + } + + if(!NT_SUCCESS(ret)) + { + ERR("failed with %lx\n", ret); + goto fail; }
/* build blob with the output message */ @@ -575,7 +568,7 @@ { SECURITY_STATUS ret = SEC_E_OK; PSecBuffer InputToken1, InputToken2; - PSecBuffer OutputToken1; + PSecBuffer OutputToken1, OutputToken2;
TRACE("AcceptSecurityContext %p %p %p %lx %lx %p %p %p %p\n", phCredential, phContext, pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsExpiry); @@ -614,29 +607,56 @@ }
/* first call */ - if(!phContext && !InputToken2) + if(!phContext)// && !InputToken2) { if(!phCredential) { ret = SEC_E_INVALID_HANDLE; goto fail; } - + TRACE("phNewContext->dwLower %lx\n", phNewContext->dwLower); ret = NtlmHandleNegotiateMessage(phCredential->dwLower, - &phNewContext->dwLower, + phNewContext->dwLower, fContextReq, InputToken1, - &OutputToken1, + InputToken2, + OutputToken1, + OutputToken2, pfContextAttr, ptsExpiry); } else { - WARN("Handle Authenticate UNIMPLEMENTED!\n"); - } - //if(!NT_SUCCESS(ret)) - - UNIMPLEMENTED; + *phNewContext = *phContext; + USER_SESSION_KEY sessionKey; + ULONG userflags; + TRACE("phNewContext->dwLower %lx\n", phNewContext->dwLower); + ret = NtlmHandleAuthenticateMessage(phNewContext->dwLower, + fContextReq, + InputToken1, + OutputToken1, + pfContextAttr, + ptsExpiry, + (PUCHAR)&sessionKey, + &userflags); + } + + if(!NT_SUCCESS(ret)) + { + ERR("failed with %lx\n", ret); + goto fail; + } + + /* build blob with the output message */ + SecBufferDesc BufferDesc; + BufferDesc.ulVersion = SECBUFFER_VERSION; + BufferDesc.cBuffers = 1; + BufferDesc.pBuffers = OutputToken1; + + if(fContextReq & ASC_REQ_ALLOCATE_MEMORY) + *pfContextAttr |= ASC_RET_ALLOCATED_MEMORY; + + *pOutput = BufferDesc; return ret; fail: return ret; @@ -703,7 +723,6 @@ ApplyControlToken(IN PCtxtHandle phContext, IN PSecBufferDesc pInput) { - UNIMPLEMENTED; return SEC_E_UNSUPPORTED_FUNCTION; }
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] Mon May 30 21:02:50 2011 @@ -53,7 +53,7 @@
/* sanity */ ASSERT(cred); - TRACE("%p refcount %d\n",cred, cred->RefCount); + TRACE("%p refcount %lx\n",cred, cred->RefCount); ASSERT(cred->RefCount > 0);
/* reference */ @@ -73,7 +73,7 @@
/* sanity */ ASSERT(cred); - TRACE("%p refcount %d\n",cred, cred->RefCount); + TRACE("%p refcount %lx\n",cred, cred->RefCount); ASSERT(cred->RefCount >= 1);
/* decrement reference */ @@ -137,7 +137,7 @@ { SECURITY_STATUS ret;
- TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer); + TRACE("(%p, %lx, %p)\n", phCredential, ulAttribute, pBuffer);
if(ulAttribute == SECPKG_ATTR_NAMES) { @@ -158,7 +158,7 @@ { SECURITY_STATUS ret;
- TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer); + TRACE("(%p, %lx, %p)\n", phCredential, ulAttribute, pBuffer);
if(ulAttribute == SECPKG_ATTR_NAMES) {
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] Mon May 30 21:02:50 2011 @@ -46,9 +46,12 @@
extern UNICODE_STRING NtlmComputerNameString; extern UNICODE_STRING NtlmDomainNameString; +extern UNICODE_STRING NtlmDnsNameString; extern OEM_STRING NtlmOemComputerNameString; extern OEM_STRING NtlmOemDomainNameString; +extern OEM_STRING NtlmOemDnsNameString; extern HANDLE NtlmSystemSecurityToken; +extern UNICODE_STRING NtlmAvTargetInfo; // contains AV pairs with local info
typedef enum _NTLM_MODE { NtlmLsaMode = 1,
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] Mon May 30 21:02:50 2011 @@ -26,7 +26,7 @@ NtlmGenerateNegotiateMessage(IN ULONG_PTR Context, IN ULONG ContextReq, IN PSecBuffer InputToken, - OUT PSecBuffer *OutputToken) + OUT PSecBuffer OutputToken) { PNTLMSSP_CONTEXT context = (PNTLMSSP_CONTEXT)Context; PNTLMSSP_CREDENTIAL cred = context->Credential; @@ -35,13 +35,13 @@ ULONG_PTR offset; NTLM_BLOB blobBuffer[2]; //nego contains 2 blobs
- if(!*OutputToken) + if(!OutputToken) { ERR("No output token!\n"); return SEC_E_BUFFER_TOO_SMALL; }
- if(!((*OutputToken)->pvBuffer)) + if(!(OutputToken->pvBuffer)) { /* according to wine test */ ERR("No output buffer!\n"); @@ -56,23 +56,21 @@ if (!(ContextReq & ISC_REQ_ALLOCATE_MEMORY)) { /* not enough space */ - if(messageSize > (*OutputToken)->cbBuffer) + if(messageSize > OutputToken->cbBuffer) return SEC_E_BUFFER_TOO_SMALL; } else { /* allocate */ - (*OutputToken)->pvBuffer = NtlmAllocate(messageSize); - (*OutputToken)->cbBuffer = messageSize; - - if(!(*OutputToken)->pvBuffer) + OutputToken->pvBuffer = NtlmAllocate(messageSize); + OutputToken->cbBuffer = messageSize; + + if(!OutputToken->pvBuffer) return SEC_E_INSUFFICIENT_MEMORY; }
/* allocate a negotiate message */ - message = (PNEGOTIATE_MESSAGE) NtlmAllocate(messageSize); - - if(!message) + if(!(message = (PNEGOTIATE_MESSAGE) NtlmAllocate(messageSize))) return SEC_E_INSUFFICIENT_MEMORY;
/* build message */ @@ -110,11 +108,12 @@ blobBuffer[1].Offset = offset+1; }
+ /* zero struct */ memset(&message->Version, 0, sizeof(NTLM_WINDOWS_VERSION));
/* send it back */ - memcpy((*OutputToken)->pvBuffer, message, messageSize); - (*OutputToken)->cbBuffer = messageSize; + memcpy(OutputToken->pvBuffer, message, messageSize); + OutputToken->cbBuffer = messageSize; context->State = NegotiateSent;
TRACE("context %p context->NegotiateFlags:\n",context); @@ -128,40 +127,53 @@
SECURITY_STATUS NtlmHandleNegotiateMessage(IN ULONG_PTR hCredential, - IN OUT PULONG_PTR phContext, + IN OUT ULONG_PTR hContext, IN ULONG ContextReq, IN PSecBuffer InputToken, - OUT PSecBuffer *pOutputToken, + IN PSecBuffer InputToken2, + OUT PSecBuffer OutputToken, + OUT PSecBuffer OutputToken2, OUT PULONG pContextAttr, OUT PTimeStamp ptsExpiry) { SECURITY_STATUS ret = SEC_E_OK; PNEGOTIATE_MESSAGE negoMessage = NULL; PNTLMSSP_CREDENTIAL cred = NULL; - PNTLMSSP_CONTEXT newContext = NULL; - - ERR("NtlmHandleNegotiateMessage called!\n"); - - /* InputToken should contain a negotiate message*/ + PNTLMSSP_CONTEXT context = NULL; + UNICODE_STRING targetName; + OEM_STRING OemDomainName, OemWorkstationName; + ULONG targetFlags = 0; + BOOLEAN isUnicode; + + TRACE("NtlmHandleNegotiateMessage hContext %lx\n", hContext); + if(!(context = NtlmAllocateContext())) + { + ret = SEC_E_INSUFFICIENT_MEMORY; + ERR("SEC_E_INSUFFICIENT_MEMORY!\n"); + goto exit; + } + + hContext = (ULONG_PTR)context; + TRACE("NtlmHandleNegotiateMessage hContext %lx\n", hContext); + + /* InputToken should contain a negotiate message */ if(InputToken->cbBuffer > NTLM_MAX_BUF || InputToken->cbBuffer < sizeof(NEGOTIATE_MESSAGE)) { - ERR("Input token too big!!\n"); + ERR("Input wrong size!!\n"); ret = SEC_E_INVALID_TOKEN; goto exit; }
/* allocate a buffer for it */ - negoMessage = NtlmAllocate(InputToken->cbBuffer); - - if(!negoMessage) + if(!(negoMessage = NtlmAllocate(sizeof(NEGOTIATE_MESSAGE)))) { ret = SEC_E_INSUFFICIENT_MEMORY; goto exit; }
/* copy it */ - memcpy(negoMessage, InputToken->pvBuffer, InputToken->cbBuffer); + memcpy(negoMessage, InputToken->pvBuffer, sizeof(NEGOTIATE_MESSAGE));
/* validate it */ if(strncmp(negoMessage->Signature, NTLMSSP_SIGNATURE, 8) && @@ -176,9 +188,11 @@ NtlmPrintNegotiateFlags(negoMessage->NegotiateFlags);
/* get credentials */ - cred = NtlmReferenceCredential(hCredential); - if(!cred) + if(!(cred = NtlmReferenceCredential(hCredential))) + { + ret = SEC_E_INVALID_TOKEN; goto exit; + }
/* must be an incomming request */ if(!(cred->UseFlags & SECPKG_CRED_INBOUND)) @@ -187,72 +201,199 @@ goto exit; }
- /* create new context */ - newContext = NtlmAllocateContext(); - if(!newContext) + /* convert flags */ + if(ContextReq & ASC_REQ_IDENTIFY) + { + *pContextAttr |= ASC_RET_IDENTIFY; + context->ContextFlags |= ASC_RET_IDENTIFY; + } + + if(ContextReq & ASC_REQ_DATAGRAM) + { + *pContextAttr |= ASC_RET_DATAGRAM; + context->ContextFlags |= ASC_RET_DATAGRAM; + } + + if(ContextReq & ASC_REQ_CONNECTION) + { + *pContextAttr |= ASC_RET_CONNECTION; + context->ContextFlags |= ASC_RET_CONNECTION; + } + + if(ContextReq & ASC_REQ_INTEGRITY) + { + *pContextAttr |= ASC_RET_INTEGRITY; + context->ContextFlags |= ASC_RET_INTEGRITY; + } + + if(ContextReq & ASC_REQ_REPLAY_DETECT) + { + *pContextAttr |= ASC_RET_REPLAY_DETECT; + context->ContextFlags |= ASC_RET_REPLAY_DETECT; + } + + if(ContextReq & ASC_REQ_SEQUENCE_DETECT) + { + *pContextAttr |= ASC_RET_SEQUENCE_DETECT; + context->ContextFlags |= ASC_RET_SEQUENCE_DETECT; + } + + if(ContextReq & ASC_REQ_ALLOW_NULL_SESSION) + { + context->ContextFlags |= ASC_REQ_ALLOW_NULL_SESSION; + } + + if(ContextReq & ASC_REQ_ALLOW_NON_USER_LOGONS) + { + *pContextAttr |= ASC_RET_ALLOW_NON_USER_LOGONS; + context->ContextFlags |= ASC_RET_ALLOW_NON_USER_LOGONS; + } + + /* encryption */ + if(ContextReq & ASC_REQ_CONFIDENTIALITY) + { + *pContextAttr |= ASC_RET_CONFIDENTIALITY; + context->ContextFlags |= ASC_RET_CONFIDENTIALITY; + } + + if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY || + negoMessage->NegotiateFlags & NTLMSSP_REQUEST_TARGET) + { + targetFlags |= NTLMSSP_TARGET_TYPE_SERVER | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO; + + if (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE) + { + isUnicode = TRUE; + targetFlags |= NTLMSSP_NEGOTIATE_UNICODE; + RtlInitUnicodeString(&targetName, NtlmComputerNameString.Buffer); + } + else if(negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM) + { + isUnicode = FALSE; + targetFlags |= NTLMSSP_NEGOTIATE_OEM; + RtlInitUnicodeString(&targetName, (PWCHAR)&NtlmOemComputerNameString.Buffer); + } + else + { + ret = SEC_E_INVALID_TOKEN; + ERR("flags invalid!\n"); + goto exit; + } + } + + /* 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; }
- *phContext = (ULONG_PTR)newContext; - - if(ContextReq & ASC_REQ_IDENTIFY) - { + /* 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; - newContext->ContextFlags |= ASC_RET_IDENTIFY; - } - - if(ContextReq & ASC_REQ_DATAGRAM) - { - *pContextAttr |= ASC_RET_DATAGRAM; - newContext->ContextFlags |= ASC_RET_DATAGRAM; - } - - if(ContextReq & ASC_REQ_CONNECTION) - { - *pContextAttr |= ASC_RET_CONNECTION; - newContext->ContextFlags |= ASC_RET_CONNECTION; - } - - if(ContextReq & ASC_REQ_INTEGRITY) - { - *pContextAttr |= ASC_RET_INTEGRITY; - newContext->ContextFlags |= ASC_RET_INTEGRITY; - } - - if(ContextReq & ASC_REQ_REPLAY_DETECT) - { - *pContextAttr |= ASC_RET_REPLAY_DETECT; - newContext->ContextFlags |= ASC_RET_REPLAY_DETECT; - } - - if(ContextReq & ASC_REQ_SEQUENCE_DETECT) - { - *pContextAttr |= ASC_RET_SEQUENCE_DETECT; - newContext->ContextFlags |= ASC_RET_SEQUENCE_DETECT; - } - - if(ContextReq & ASC_REQ_ALLOW_NULL_SESSION) - { - newContext->ContextFlags |= ASC_REQ_ALLOW_NULL_SESSION; - } - - if(ContextReq & ASC_REQ_ALLOW_NON_USER_LOGONS) - { - *pContextAttr |= ASC_RET_ALLOW_NON_USER_LOGONS; - newContext->ContextFlags |= ASC_RET_ALLOW_NON_USER_LOGONS; - } - - /* encryption */ - if(ContextReq & ASC_REQ_CONFIDENTIALITY) - { - *pContextAttr |= ASC_RET_CONFIDENTIALITY; - newContext->ContextFlags |= ASC_RET_CONFIDENTIALITY; - } + context->ContextFlags |= ASC_RET_IDENTIFY; + } + + /* check for local call */ + if((negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) && + (negoMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)) + { + NtlmBlobToUnicodeString(InputToken, negoMessage->OemDomainName, (PUNICODE_STRING)&OemDomainName); + NtlmBlobToUnicodeString(InputToken, negoMessage->OemWorkstationName, (PUNICODE_STRING)&OemWorkstationName); + + if (RtlEqualString(&OemWorkstationName, &NtlmOemComputerNameString, FALSE)&& + RtlEqualString(&OemDomainName, &NtlmOemDomainNameString, FALSE)) + { + TRACE("local negotiate detected!\n"); + chaMessage->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;
exit: - ERR("FIXME: HERE!!!!!!!!!!!!!!!"); + 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); + return ret; }
@@ -261,59 +402,60 @@ IN ULONG ContextReq, IN PSecBuffer InputToken1, IN PSecBuffer InputToken2, - IN OUT PSecBuffer *OutputToken1, - IN OUT PSecBuffer *OutputToken2, + IN OUT PSecBuffer OutputToken1, + IN OUT PSecBuffer OutputToken2, OUT PULONG pContextAttr, OUT PTimeStamp ptsExpiry, OUT PULONG NegotiateFlags) { SECURITY_STATUS ret = SEC_E_OK; - PNTLMSSP_CONTEXT context; - PCHALLENGE_MESSAGE challenge; + PNTLMSSP_CONTEXT context = NULL; + PCHALLENGE_MESSAGE challenge = NULL; + PNTLMSSP_CREDENTIAL cred = NULL; BOOLEAN isUnicode;
+ TRACE("NtlmHandleChallengeMessage hContext %lx\n", hContext); /* get context */ context = NtlmReferenceContext(hContext); if(!context || !context->Credential) { ERR("NtlmHandleChallengeMessage invalid handle!\n"); ret = SEC_E_INVALID_HANDLE; - goto exit; + goto fail; }
/* re-authenticate call */ if(context->State == AuthenticateSent) { UNIMPLEMENTED; + goto fail; } else if(context->State != NegotiateSent) { - ERR("Context not in negotiate sent state!\n"); + ERR("Context not in correct state!\n"); ret = SEC_E_OUT_OF_SEQUENCE; - goto exit; + goto fail; }
/* InputToken1 should contain a challenge message */ - TRACE("input token size %lx\n", InputToken1->cbBuffer); if(InputToken1->cbBuffer > NTLM_MAX_BUF || InputToken1->cbBuffer < sizeof(CHALLENGE_MESSAGE)) { ERR("Input token invalid!\n"); ret = SEC_E_INVALID_TOKEN; - goto exit; + goto fail; }
/* allocate a buffer for it */ - challenge = NtlmAllocate(InputToken1->cbBuffer); - if(!challenge) + if(!(challenge = NtlmAllocate(sizeof(CHALLENGE_MESSAGE)))) { ERR("failed to allocate challenge buffer!\n"); ret = SEC_E_INSUFFICIENT_MEMORY; - goto exit; + goto fail; }
/* copy it */ - memcpy(challenge, InputToken1->pvBuffer, InputToken1->cbBuffer); + memcpy(challenge, InputToken1->pvBuffer, sizeof(CHALLENGE_MESSAGE));
/* validate it */ if(strncmp(challenge->Signature, NTLMSSP_SIGNATURE, 8) && @@ -321,14 +463,14 @@ { ERR("Input message not valid!\n"); ret = SEC_E_INVALID_TOKEN; - goto exit; + goto fail; }
TRACE("Got valid challege message! with flags:\n"); NtlmPrintNegotiateFlags(challenge->NegotiateFlags);
/* print challenge message and payloads */ - NtlmPrintHexDump((PBYTE)challenge, InputToken1->cbBuffer); + NtlmPrintHexDump((PBYTE)InputToken1->pvBuffer, InputToken1->cbBuffer);
if(challenge->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) { @@ -364,14 +506,14 @@ /* these flags must be bad! */ ERR("challenge flags did not specify unicode or oem!\n"); ret = SEC_E_INVALID_TOKEN; - goto exit; + goto fail; }
/* support ntlm2 */ if(challenge->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { challenge->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY; - context->NegotiateFlags &= ~(NTLMSSP_NEGOTIATE_LM_KEY); + context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } else { @@ -383,7 +525,7 @@ { ERR("netware authentication not supported!!!\n"); ret = SEC_E_UNSUPPORTED_FUNCTION; - goto exit; + goto fail; } }
@@ -430,7 +572,7 @@ if(!NT_SUCCESS(ret)) { ERR("could not get target info!\n"); - goto exit; + goto fail; } } else @@ -444,20 +586,23 @@ if(!NT_SUCCESS(ret)) { ERR("could not get target info!\n"); - goto exit; + goto fail; } if(isUnicode) FIXME("convert to unicode!\n"); } - TRACE("ServerName %s\n", debugstr_w(ServerName.Buffer)); - - PNTLMSSP_CREDENTIAL cred = NtlmReferenceCredential((ULONG_PTR)context->Credential); + + MSV1_0_NTLM3_RESPONSE NtResponse; LM2_RESPONSE Lm2Response; USER_SESSION_KEY UserSessionKey; LM_SESSION_KEY LmSessionKey;
- NtlmUnProtectMemory(cred->Password.Buffer, cred->Password.Length * sizeof(WCHAR)); + 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)); @@ -472,9 +617,255 @@ &UserSessionKey, &LmSessionKey);
-exit: + 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 + InitString(NtResponseString, NtResponse); + //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))) + { + ret = SEC_E_INSUFFICIENT_MEMORY; + goto fail; + } + + strcpy(authmessage->Signature, NTLMSSP_SIGNATURE); + authmessage->MsgType = NtlmAuthenticate; + + offset = (ULONG_PTR)(authmessage+1); + + NtlmUnicodeStringToBlob((PVOID)authmessage, + &cred->DomainName, + &authmessage->DomainName, + &offset); + + NtlmUnicodeStringToBlob((PVOID)authmessage, + &cred->UserName, + &authmessage->UserName, + &offset); + + NtlmUnicodeStringToBlob((PVOID)authmessage, + &ServerName, + &authmessage->WorkstationName, + &offset); + + //if(targetinfo) + //NtlmUnicodeStringToBlob((PVOID)authmessage, + // &LmResponseString, + // &authmessage->LmChallengeResponse, + // &offset); + + NtlmUnicodeStringToBlob((PVOID)authmessage, + &NtResponseString, + &authmessage->NtChallengeResponse, + &offset); + + NtlmUnicodeStringToBlob((PVOID)authmessage, + &UserSessionKeyString, + &authmessage->EncryptedRandomSessionKey, + &offset); + + /* if should not allocate */ + if (!(ContextReq & ISC_REQ_ALLOCATE_MEMORY)) + { + /* not enough space */ + if(messageSize > OutputToken1->cbBuffer) + { + ret = SEC_E_BUFFER_TOO_SMALL; + goto fail; + } + } + else + { + /* allocate */ + if(!(OutputToken1->pvBuffer = NtlmAllocate(messageSize))) + { + ret = SEC_E_INSUFFICIENT_MEMORY; + goto fail; + } + } + + OutputToken1->cbBuffer = messageSize; /* says wine test */ + memcpy(OutputToken1->pvBuffer, authmessage, messageSize); + context->State = AuthenticateSent; + ret = SEC_E_OK; + +fail: + if(authmessage) NtlmFree(authmessage); + if(context) NtlmDereferenceContext((ULONG_PTR)context); + if(cred) NtlmDereferenceCredential((ULONG_PTR)cred); ERR("handle challenge end\n"); - return ret; }
+SECURITY_STATUS +NtlmHandleAuthenticateMessage(IN ULONG_PTR hContext, + IN ULONG ContextReq, + IN PSecBuffer InputToken, + OUT PSecBuffer OutputToken, + OUT PULONG pContextAttr, + OUT PTimeStamp ptsExpiry, + OUT PUCHAR pSessionKey, + OUT PULONG pfUserFlags) +{ + SECURITY_STATUS ret = SEC_E_OK; + PNTLMSSP_CONTEXT context = NULL; + PAUTHENTICATE_MESSAGE authMessage = NULL; + BOOLEAN isUnicode; + + TRACE("NtlmHandleAuthenticateMessage hContext %x!\n", hContext); + /* get context */ + if(!(context = NtlmReferenceContext(hContext))) + { + ret = SEC_E_INVALID_HANDLE; + goto fail; + } + + TRACE("context->State %d\n", context->State); + if(context->State != ChallengeSent || context->State != Authenticated) + { + ERR("Context not in correct state!\n"); + ret = SEC_E_OUT_OF_SEQUENCE; + goto fail; + } + + /* re-authorize */ + if(context->State == Authenticated) + UNIMPLEMENTED; + + /* InputToken1 should contain a authenticate message */ + TRACE("input token size %lx\n", InputToken->cbBuffer); + if(InputToken->cbBuffer > NTLM_MAX_BUF || + InputToken->cbBuffer < sizeof(AUTHENTICATE_MESSAGE)) + { + ERR("Input token invalid!\n"); + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + /* allocate a buffer for it */ + if(!(authMessage = NtlmAllocate(sizeof(AUTHENTICATE_MESSAGE)))) + { + ERR("failed to allocate authMessage buffer!\n"); + ret = SEC_E_INSUFFICIENT_MEMORY; + goto fail; + } + + /* copy it */ + memcpy(authMessage, InputToken->pvBuffer, sizeof(AUTHENTICATE_MESSAGE)); + + /* validate it */ + if(strncmp(authMessage->Signature, NTLMSSP_SIGNATURE, 8) && + authMessage->MsgType == NtlmAuthenticate) + { + ERR("Input message not valid!\n"); + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + /* datagram */ + if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) + { + /* context and message dont agree on connection type! */ + if(!(authMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM)) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + /* use message flags */ + context->NegotiateFlags = authMessage->NegotiateFlags; + + /* need a key */ + if(context->NegotiateFlags & (NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL)) + context->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH; + + /* remove lm key */ + if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) + context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + } + + /* supports unicode */ + if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE) + { + context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_OEM; + isUnicode = TRUE; + } + else if(context->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM) + { + context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_UNICODE; + isUnicode = FALSE; + } + else + { + /* these flags must be bad! */ + ERR("authenticate flags did not specify unicode or oem!\n"); + 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))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, + authMessage->NtChallengeResponse, &NtChallengeResponse))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, + authMessage->UserName, &UserName))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, + authMessage->WorkstationName, &Workstation))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, + authMessage->DomainName, &DomainName))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + //if(NTLMSSP_NEGOTIATE_KEY_EXCHANGE) + if(!NT_SUCCESS(NtlmBlobToUnicodeString(InputToken, + authMessage->EncryptedRandomSessionKey, &SessionKey))) + { + ret = SEC_E_INVALID_TOKEN; + goto fail; + } + + ret = SEC_I_COMPLETE_NEEDED; + +fail: + NtlmDereferenceContext((ULONG_PTR)context); + return ret; +}
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] Mon May 30 21:02:50 2011 @@ -164,6 +164,14 @@ /* payload */ }AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+typedef struct _MESSAGE_SIGNATURE +{ + ULONG Version; + ULONG RandomPad; + ULONG Checksum; + ULONG Nonce; +}MESSAGE_SIGNATURE, *PMESSAGE_SIGNATURE; + /* basic functions */
VOID @@ -173,14 +181,14 @@
VOID NTOWFv2( - PWCHAR password, - PWCHAR user, - PWCHAR domain, + const PWCHAR password, + const PWCHAR user, + const PWCHAR domain, PUCHAR result);
VOID LMOWFv1( - PCCHAR password, + const PCCHAR password, PUCHAR result);
VOID @@ -275,15 +283,17 @@ IN ULONG_PTR hContext, IN ULONG ContextReq, IN PSecBuffer InputToken, - OUT PSecBuffer *OutputToken); + OUT PSecBuffer OutputToken);
SECURITY_STATUS NtlmHandleNegotiateMessage( IN ULONG_PTR hCredential, - IN OUT PULONG_PTR phContext, + IN OUT ULONG_PTR hContext, IN ULONG fContextReq, - IN PSecBuffer InputToken, - OUT PSecBuffer *OutputToken, + IN PSecBuffer InputToken1, + IN PSecBuffer InputToken2, + OUT PSecBuffer OutputToken1, + OUT PSecBuffer OutputToken2, OUT PULONG pContextAttr, OUT PTimeStamp ptsExpiry);
@@ -293,8 +303,8 @@ IN ULONG ContextReq, IN PSecBuffer InputToken1, IN PSecBuffer InputToken2, - IN OUT PSecBuffer *OutputToken1, - IN OUT PSecBuffer *OutputToken2, + IN OUT PSecBuffer OutputToken1, + IN OUT PSecBuffer OutputToken2, OUT PULONG ContextAttr, OUT PTimeStamp ptsExpiry, OUT PULONG NegotiateFlags); @@ -303,15 +313,11 @@ NtlmHandleAuthenticateMessage( IN ULONG_PTR hContext, IN ULONG fContextReq, - IN PSecBuffer *pInputTokens, + IN PSecBuffer InputToken, OUT PSecBuffer OutputToken, OUT PULONG pContextAttr, OUT PTimeStamp ptsExpiry, OUT PUCHAR pSessionKey, - OUT PULONG pfNegotiateFlags, - OUT PHANDLE TokenHandle, - OUT PNTSTATUS pSubStatus, - OUT PTimeStamp ptsPasswordExpiry, OUT PULONG pfUserFlags);
/* helper functions */