Module: wine Branch: refs/heads/master Commit: 43b21b6e8649f26b348b58fd64262f242e308da4 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=43b21b6e8649f26b348b58fd...
Author: Kai Blin kai.blin@gmail.com Date: Mon Dec 19 21:20:03 2005 +0100
secur32: Adding AcceptSecurityContext to the NTLM security provider.
---
dlls/secur32/ntlm.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 226 insertions(+), 1 deletions(-)
diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c index 3de699f..feaef9b 100644 --- a/dlls/secur32/ntlm.c +++ b/dlls/secur32/ntlm.c @@ -741,7 +741,232 @@ static SECURITY_STATUS SEC_ENTRY ntlm_Ac ptsExpiry); if (phCredential) { - ret = SEC_E_UNSUPPORTED_FUNCTION; + PNegoHelper helper = (PNegoHelper)phCredential->dwLower; + /* Max size of input data is 2010 byte, as that's the maximum size + * ntlm_auth will handle*/ + 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; + ULONG ctxt_attr = 0; + + if(helper->mode != NTLM_SERVER) + { + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + return SEC_E_INVALID_HANDLE; + } + + /* Handle all the flags */ + if(fContextReq & ISC_REQ_ALLOCATE_MEMORY) + { + FIXME("AcceptSecurityContext(): ISC_REQ_ALLOCATE_MEMORY stub\n"); + } + if(fContextReq & ISC_REQ_CONFIDENTIALITY) + { + FIXME("AcceptSecurityContext(): 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("AcceptSecurityContext(): ISC_REQ_EXTENDED_ERROR stub\n"); + } + if(fContextReq & ISC_REQ_INTEGRITY) + { + FIXME("AcceptSecurityContext(): ISC_REQ_INTEGRITY stub\n"); + } + if(fContextReq & ISC_REQ_MUTUAL_AUTH) + { + FIXME("AcceptSecurityContext(): ISC_REQ_MUTUAL_AUTH stub\n"); + } + if(fContextReq & ISC_REQ_REPLAY_DETECT) + { + FIXME("AcceptSecurityContext(): ISC_REQ_REPLAY_DETECT stub\n"); + } + if(fContextReq & ISC_REQ_SEQUENCE_DETECT) + { + FIXME("AcceptSecurityContext(): ISC_REQ_SEQUENCE_DETECT stub\n"); + } + if(fContextReq & ISC_REQ_STREAM) + { + FIXME("AcceptSecurityContext(): 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(phContext == NULL) + { + /* This is the first call to AcceptSecurityHandle */ + 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) + { + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + return SEC_E_INVALID_TOKEN; + } + else + bin_len = pInput->pBuffers[0].cbBuffer; + + /* This is the YR request from the client, encode to base64 */ + + memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len); + + lstrcpynA(buffer, "YR ", 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("Client sent: %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("Reply from ntlm_auth: %s\n", debugstr_a(buffer)); + /* The expected answer is TT <base64 blob> */ + + if(strncmp(buffer, "TT ", 3) != 0) + { + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + return SEC_E_INVALID_TOKEN; + } + + 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; + } + + /* send this to the client */ + 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_I_CONTINUE_NEEDED; + + } + else + { + /* we expect a KK request from client */ + 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) + { + 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, "KK ", 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("Client sent: %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("Reply from ntlm_auth: %s\n", debugstr_a(buffer)); + + if(strncmp(buffer, "AF ", 3) != 0) + { + if(strncmp(buffer, "NA ", 3) == 0) + { + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + return SEC_E_LOGON_DENIED; + } + else + { + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + return SEC_E_INVALID_TOKEN; + } + } + + ret = SEC_E_OK; + } + + phNewContext->dwUpper = ctxt_attr; + phNewContext->dwLower = ret; + HeapFree(GetProcessHeap(), 0, buffer); + HeapFree(GetProcessHeap(), 0, bin); + } else {