Commit a51e02c5 authored by Kai Blin's avatar Kai Blin Committed by Alexandre Julliard

secur32: Use a helper function for creating the signature as this simplifies…

secur32: Use a helper function for creating the signature as this simplifies implementing NTLM2 signing a lot.
parent 6720a129
...@@ -1199,50 +1199,41 @@ static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContex ...@@ -1199,50 +1199,41 @@ static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContex
return ret; return ret;
} }
/*********************************************************************** /*************************************************************************
* MakeSignature * ntlm_GetTokenBufferIndex
* Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
* Returns index if found or -1 if not found.
*/ */
static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
PSecBufferDesc pMessage, ULONG MessageSeqNo)
{ {
PNegoHelper helper;
ULONG sign_version = 1;
UINT i; UINT i;
int token_idx = -1;
TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if(fQOP)
FIXME("Ignoring fQOP 0x%08x\n", fQOP);
if(MessageSeqNo)
FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) TRACE("%p\n", pMessage);
return SEC_E_INVALID_TOKEN;
for(i=0; i < pMessage->cBuffers; ++i) for( i = 0; i < pMessage->cBuffers; ++i )
{ {
if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN) if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
{ return i;
token_idx = i;
break;
}
} }
/* If we didn't find a SECBUFFER_TOKEN type buffer */
if(token_idx == -1)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[token_idx].cbBuffer < 16) return -1;
return SEC_E_BUFFER_TOO_SMALL; }
helper = (PNegoHelper)phContext->dwLower; /***********************************************************************
TRACE("Negotiated flags are: 0x%08lx\n", helper->neg_flags); * ntlm_CreateSignature
if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) * As both MakeSignature and VerifySignature need this, but different keys
* are needed for NTLMv2, the logic goes into a helper function.
*/
static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc pMessage,
int token_idx, SignDirection direction)
{
ULONG sign_version = 1;
UINT i;
TRACE("%p, %p, %d\n", helper, pMessage, direction);
if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 &&
helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
{ {
FIXME("Can't handle NTLMv2 signing yet. Aborting.\n");
return SEC_E_UNSUPPORTED_FUNCTION; return SEC_E_UNSUPPORTED_FUNCTION;
} }
if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN) if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
...@@ -1279,15 +1270,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG ...@@ -1279,15 +1270,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
return SEC_E_OK; return SEC_E_OK;
} }
if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
{
FIXME("Can't handle encrypted session key yet. Aborting.\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0) if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
{ {
TRACE("Generating dummy signature\n"); TRACE("Creating a dummy signature.\n");
/* A dummy signature is 0x01 followed by 15 bytes of 0x00 */ /* A dummy signature is 0x01 followed by 15 bytes of 0x00 */
memset(pMessage->pBuffers[token_idx].pvBuffer, 0, 16); memset(pMessage->pBuffers[token_idx].pvBuffer, 0, 16);
memset(pMessage->pBuffers[token_idx].pvBuffer, 0x01, 1); memset(pMessage->pBuffers[token_idx].pvBuffer, 0x01, 1);
...@@ -1299,6 +1284,41 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG ...@@ -1299,6 +1284,41 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
} }
/*********************************************************************** /***********************************************************************
* MakeSignature
*/
static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
PNegoHelper helper;
int token_idx;
TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if(fQOP)
FIXME("Ignoring fQOP 0x%08x\n", fQOP);
if(MessageSeqNo)
FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
return SEC_E_INVALID_TOKEN;
/* If we didn't find a SECBUFFER_TOKEN type buffer */
if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
helper = (PNegoHelper)phContext->dwLower;
TRACE("Negotiated flags are: 0x%08lx\n", helper->neg_flags);
return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND);
}
/***********************************************************************
* VerifySignature * VerifySignature
*/ */
static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
...@@ -1307,8 +1327,11 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, ...@@ -1307,8 +1327,11 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
PNegoHelper helper; PNegoHelper helper;
ULONG fQOP = 0; ULONG fQOP = 0;
UINT i; UINT i;
int token_idx = -1; int token_idx;
SECURITY_STATUS ret; SECURITY_STATUS ret;
SecBufferDesc local_desc;
PSecBuffer local_buff;
BYTE local_sig[16];
TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP); TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
if(!phContext) if(!phContext)
...@@ -1317,15 +1340,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, ...@@ -1317,15 +1340,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2) if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
return SEC_E_INVALID_TOKEN; return SEC_E_INVALID_TOKEN;
for(i=0; i < pMessage->cBuffers; ++i) if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
{
if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
{
token_idx = i;
break;
}
}
if(token_idx == -1)
return SEC_E_INVALID_TOKEN; return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[token_idx].cbBuffer < 16) if(pMessage->pBuffers[token_idx].cbBuffer < 16)
...@@ -1337,77 +1352,42 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, ...@@ -1337,77 +1352,42 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
helper = (PNegoHelper)phContext->dwLower; helper = (PNegoHelper)phContext->dwLower;
TRACE("Negotiated flags: 0x%08lx\n", helper->neg_flags); TRACE("Negotiated flags: 0x%08lx\n", helper->neg_flags);
if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) local_buff = HeapAlloc(GetProcessHeap(), 0, pMessage->cBuffers * sizeof(SecBuffer));
{
FIXME("Can't handle NTLMv2 signing yet. Aborting.\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
{
SecBufferDesc local_desc;
PSecBuffer local_buff;
BYTE local_sig[16];
local_buff = HeapAlloc(GetProcessHeap(), 0, pMessage->cBuffers * sizeof(SecBuffer));
local_desc.ulVersion = SECBUFFER_VERSION; local_desc.ulVersion = SECBUFFER_VERSION;
local_desc.cBuffers = pMessage->cBuffers; local_desc.cBuffers = pMessage->cBuffers;
local_desc.pBuffers = local_buff; local_desc.pBuffers = local_buff;
for(i=0; i < pMessage->cBuffers; ++i) for(i=0; i < pMessage->cBuffers; ++i)
{
if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
{
local_buff[i].BufferType = SECBUFFER_TOKEN;
local_buff[i].cbBuffer = 16;
local_buff[i].pvBuffer = local_sig;
}
else
{
local_buff[i].BufferType = pMessage->pBuffers[i].BufferType;
local_buff[i].cbBuffer = pMessage->pBuffers[i].cbBuffer;
local_buff[i].pvBuffer = pMessage->pBuffers[i].pvBuffer;
}
}
ntlm_MakeSignature(phContext, fQOP, &local_desc, MessageSeqNo);
if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
ret = SEC_E_MESSAGE_ALTERED;
else
ret = SEC_E_OK;
HeapFree(GetProcessHeap(), 0, local_buff);
return ret;
}
if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
{
FIXME("Can't handle encrypted session keys yet. Aborting.\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
{ {
const BYTE dummy_sig[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
TRACE("Assuming dummy signature.\n");
if(memcmp(pMessage->pBuffers[token_idx].pvBuffer, dummy_sig, sizeof(dummy_sig)) != 0)
{ {
TRACE("Failed to verify the packet signature. Not a dummy signature?\n"); local_buff[i].BufferType = SECBUFFER_TOKEN;
return SEC_E_MESSAGE_ALTERED; local_buff[i].cbBuffer = 16;
local_buff[i].pvBuffer = local_sig;
} }
else else
{ {
pfQOP = &fQOP; local_buff[i].BufferType = pMessage->pBuffers[i].BufferType;
return SEC_E_OK; local_buff[i].cbBuffer = pMessage->pBuffers[i].cbBuffer;
local_buff[i].pvBuffer = pMessage->pBuffers[i].pvBuffer;
} }
} }
return SEC_E_UNSUPPORTED_FUNCTION; if((ret = ntlm_CreateSignature(helper, &local_desc, token_idx, NTLM_RECV)) != SEC_E_OK)
return ret;
if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
ret = SEC_E_MESSAGE_ALTERED;
else
ret = SEC_E_OK;
HeapFree(GetProcessHeap(), 0, local_buff);
pfQOP = &fQOP;
return ret;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -80,6 +80,11 @@ typedef struct _NegoHelper { ...@@ -80,6 +80,11 @@ typedef struct _NegoHelper {
} crypt; } crypt;
} NegoHelper, *PNegoHelper; } NegoHelper, *PNegoHelper;
typedef enum _sign_direction {
NTLM_SEND,
NTLM_RECV
} SignDirection;
/* Allocates space for and initializes a new provider. If fnTableA or fnTableW /* Allocates space for and initializes a new provider. If fnTableA or fnTableW
* is non-NULL, assumes the provider is built-in (and is thus already loaded.) * is non-NULL, assumes the provider is built-in (and is thus already loaded.)
* Otherwise moduleName must not be NULL. * Otherwise moduleName must not be NULL.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment