secur32: Use a helper function for creating the signature as this simplifies implementing NTLM2 signing a lot.

This commit is contained in:
Kai Blin 2006-11-08 12:10:37 +01:00 committed by Alexandre Julliard
parent 6720a129f3
commit a51e02c5d6
2 changed files with 99 additions and 114 deletions

View File

@ -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); TRACE("%p\n", pMessage);
if (!phContext)
return SEC_E_INVALID_HANDLE;
if(fQOP) for( i = 0; i < pMessage->cBuffers; ++i )
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;
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
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);
@ -1298,6 +1283,41 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
return SEC_E_UNSUPPORTED_FUNCTION; return SEC_E_UNSUPPORTED_FUNCTION;
} }
/***********************************************************************
* 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
*/ */
@ -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,
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,18 +1352,6 @@ 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)
{
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_buff = HeapAlloc(GetProcessHeap(), 0, pMessage->cBuffers * sizeof(SecBuffer));
local_desc.ulVersion = SECBUFFER_VERSION; local_desc.ulVersion = SECBUFFER_VERSION;
@ -1371,7 +1374,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
} }
} }
ntlm_MakeSignature(phContext, fQOP, &local_desc, MessageSeqNo); 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, if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8)) ((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
@ -1380,34 +1384,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
ret = SEC_E_OK; ret = SEC_E_OK;
HeapFree(GetProcessHeap(), 0, local_buff); HeapFree(GetProcessHeap(), 0, local_buff);
pfQOP = &fQOP;
return ret; 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,
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");
return SEC_E_MESSAGE_ALTERED;
}
else
{
pfQOP = &fQOP;
return SEC_E_OK;
}
}
return SEC_E_UNSUPPORTED_FUNCTION;
} }
/*********************************************************************** /***********************************************************************

View File

@ -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.