secur32: Implementing InitializeSecurityContext(A|W) for the
NTLM security provider
Kai Blin
blin at gmx.net
Wed Dec 7 03:00:39 CST 2005
* Kai Blin <blin at gmx.net> [07/12/05, 09:55:29]:
> Changelog
> Kai Blin <blin at gmx.net>
> Implementing InitializeSecurityContext(A|W) for the NTLM security
> provider.
>
> dlls/secur32/ntlm.c | 309
> +++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 files changed, 299 insertions(+), 10 deletions(-)
>
This time, including the attachment. Sorry about that.
--
Kai Blin, (blin at gmx dot net)
You know, Callahan's is a peaceable bar, but if you ask that dog what his
favorite formatter is, and he says "roff! roff!", well, I'll just have to...
-------------- next part --------------
2a67e40b6a6e104c4fc3351f36e2af0050700600
diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c
index c6bdcc7..94715b5 100644
--- a/dlls/secur32/ntlm.c
+++ b/dlls/secur32/ntlm.c
@@ -389,10 +389,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_Ac
}
/***********************************************************************
- * InitializeSecurityContextA
+ * InitializeSecurityContextW
*/
-static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(
- PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
+static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
+ PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
@@ -400,10 +400,283 @@ static SECURITY_STATUS SEC_ENTRY ntlm_In
SECURITY_STATUS ret;
TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext,
- debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
+ debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
if(phCredential){
- ret = SEC_E_UNSUPPORTED_FUNCTION;
+ /* As the server side of sspi never calls this, make sure that
+ * the handler is a client handler.
+ */
+ PNegoHelper helper = (PNegoHelper)phCredential->dwLower;
+ ULONG ctxt_attr = 0;
+ if(helper->mode == NTLM_CLIENT)
+ {
+ /****************************************
+ * When communicating with the client, there can be the
+ * following reply packets:
+ * YR <base64 blob> should be sent to the server
+ * PW should be sent back to helper with
+ * base64 encoded password
+ * AF <base64 blob> client is done, blob should be
+ * sent to server with KK prefixed
+ * BH <char reason> something broke
+ */
+ BOOL first = FALSE;
+ /* The squid cache size is 2010 chars, and that's what ntlm_auth uses */
+ char* buffer = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(char) * NTLM_MAX_BUF);
+ PBYTE bin = HeapAlloc(GetProcessHeap(), 0, sizeof(BYTE) *
+ NTLM_MAX_BUF);
+ int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
+
+ if((phContext == NULL) && (pInput == NULL))
+ first = TRUE;
+ if (pszTargetName)
+ {
+ TRACE("According to a MS whitepaper pszTargetName is ignored.\n");
+ }
+ /* Handle all the flags */
+ if(fContextReq & ISC_REQ_ALLOCATE_MEMORY)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_ALLOCATE_MEMORY stub\n");
+ }
+ if(fContextReq & ISC_REQ_CONFIDENTIALITY)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_CONFIDENTIALITY stub\n");
+ }
+ if(fContextReq & ISC_REQ_CONNECTION)
+ {
+ /* This is default, so we'll enable it */
+ ctxt_attr |= ISC_RET_CONNECTION;
+ }
+ if(fContextReq & ISC_REQ_EXTENDED_ERROR)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_EXTENDED_ERROR stub\n");
+ }
+ if(fContextReq & ISC_REQ_INTEGRITY)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_INTEGRITY stub\n");
+ }
+ if(fContextReq & ISC_REQ_MUTUAL_AUTH)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_MUTUAL_AUTH stub\n");
+ }
+ if(fContextReq & ISC_REQ_REPLAY_DETECT)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_REPLAY_DETECT stub\n");
+ }
+ if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_SEQUENCE_DETECT stub\n");
+ }
+ if(fContextReq & ISC_REQ_STREAM)
+ {
+ FIXME("InitializeSecurityContext(): ISC_REQ_STREAM stub\n");
+ }
+ /* Done with the flags */
+ if(TargetDataRep == SECURITY_NETWORK_DREP){
+ FIXME("Don't know how to do SECURITY_NETWORK_DREP\n");
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ if(first)
+ {
+ TRACE("First time in ISC()\n");
+ /* Request a challenge request from ntlm_auth */
+ if(helper->password == NULL)
+ {
+ FIXME("Using empty password for now.\n");
+ lstrcpynA(buffer, "PW AA==", max_len-1);
+ }
+ else
+ {
+ lstrcpynA(buffer, "PW ", max_len-1);
+ if((ret = encodeBase64((unsigned char*)helper->password,
+ helper->pwlen-2, buffer+3,
+ max_len-3, &buffer_len)) != SEC_E_OK)
+ {
+ TRACE("Deleting password!\n");
+ memset(helper->password, 0, helper->pwlen-2);
+ HeapFree(GetProcessHeap(), 0, helper->password);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ }
+
+ TRACE("Sending to helper: %s\n", debugstr_a(buffer));
+ if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
+ SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+ TRACE("Helper returned %s\n", debugstr_a(buffer));
+ lstrcpynA(buffer, "YR", max_len-1);
+
+ if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
+ SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ TRACE("%s\n", buffer);
+
+ if(strncmp(buffer, "YR ", 3) != 0)
+ {
+
+ /* Something borked */
+ TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INTERNAL_ERROR;
+ }
+ if((ret = decodeBase64(buffer+3, buffer_len-3, bin,
+ max_len-1, &bin_len)) != SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ /* put the decoded client blob into the out buffer */
+ if(pOutput == NULL){
+ TRACE("pOutput is NULL\n");
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INSUFFICIENT_MEMORY;
+ }
+
+ if(pOutput->cBuffers < 1)
+ {
+ TRACE("pOutput->cBuffers is %ld\n", pOutput->cBuffers);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INSUFFICIENT_MEMORY;
+ }
+ pOutput->pBuffers[0].cbBuffer = bin_len;
+ pOutput->pBuffers[0].BufferType = SECBUFFER_DATA;
+ memcpy(pOutput->pBuffers[0].pvBuffer, bin, bin_len);
+
+ ret = SEC_I_CONTINUE_NEEDED;
+ }
+ else
+ {
+ /* handle second call here */
+ /* encode server data to base64 */
+ if(pInput == NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INCOMPLETE_MESSAGE;
+ }
+
+ if(pInput->cBuffers < 1)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INCOMPLETE_MESSAGE;
+ }
+
+ if(pInput->pBuffers[0].cbBuffer > max_len)
+ {
+ TRACE("pInput->pBuffers[0].cbBuffer is: %ld\n",
+ pInput->pBuffers[0].cbBuffer);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INVALID_TOKEN;
+ }
+ else
+ bin_len = pInput->pBuffers[0].cbBuffer;
+
+ memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
+
+ lstrcpynA(buffer, "TT ", max_len-1);
+
+ if((ret = encodeBase64(bin, bin_len, buffer+3,
+ max_len-3, &buffer_len)) != SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ TRACE("Server sent: %s\n", debugstr_a(buffer));
+
+ /* send TT base64 blob to ntlm_auth */
+ if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
+ SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ TRACE("Helper replied: %s\n", debugstr_a(buffer));
+
+ if( (strncmp(buffer, "KK ", 3) != 0) &&
+ (strncmp(buffer, "AF ", 3) !=0))
+ {
+ TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INVALID_TOKEN;
+ }
+
+ /* decode the blob and send it to server */
+ if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
+ &bin_len)) != SEC_E_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return ret;
+ }
+
+ if(pOutput == NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INSUFFICIENT_MEMORY;
+ }
+
+ if(pOutput->cBuffers < 1)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ return SEC_E_INSUFFICIENT_MEMORY;
+ }
+
+ pOutput->pBuffers[0].cbBuffer = bin_len;
+ pOutput->pBuffers[0].BufferType = SECBUFFER_DATA;
+ memcpy(pOutput->pBuffers[0].pvBuffer, bin, bin_len);
+
+ ret = SEC_E_OK;
+ phNewContext->dwUpper = ctxt_attr;
+ phNewContext->dwLower = ret;
+
+ }
+ HeapFree(GetProcessHeap(), 0, buffer);
+ HeapFree(GetProcessHeap(), 0, bin);
+ if(ret != SEC_I_CONTINUE_NEEDED)
+ {
+ TRACE("Deleting password!\n");
+ if(helper->password)
+ memset(helper->password, 0, helper->pwlen-2);
+ HeapFree(GetProcessHeap(), 0, helper->password);
+ }
+
+ }
+ else
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ TRACE("Helper mode = %d\n", helper->mode);
+ }
}
else
{
@@ -413,10 +686,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_In
}
/***********************************************************************
- * InitializeSecurityContextW
+ * InitializeSecurityContextA
*/
-static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
- PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
+static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(
+ PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
@@ -424,11 +697,27 @@ static SECURITY_STATUS SEC_ENTRY ntlm_In
SECURITY_STATUS ret;
TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext,
- debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
+ debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
if (phCredential)
{
- ret = SEC_E_UNSUPPORTED_FUNCTION;
+ SEC_WCHAR *target = NULL;
+ if(pszTargetName != NULL)
+ {
+ int target_size = MultiByteToWideChar(CP_ACP, 0, pszTargetName,
+ strlen(pszTargetName)+1, NULL, 0);
+ target = HeapAlloc(GetProcessHeap(), 0, target_size *
+ sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, pszTargetName, strlen(pszTargetName)+1,
+ target, target_size);
+ }
+
+ ret = ntlm_InitializeSecurityContextW(phCredential, phContext, target,
+ fContextReq, Reserved1, TargetDataRep, pInput, Reserved2,
+ phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
+ HeapFree(GetProcessHeap(), 0, target);
}
else
{
---
0.99.9i
More information about the wine-patches
mailing list