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

secur32: Fix handling of buffers that don't have the SECBUFFER_TOKEN as the first buffer.

Thanks to Robert Shearman for catching this one and providing some of the test code.
parent e1bfe4c1
......@@ -1207,6 +1207,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
{
PNegoHelper helper;
ULONG sign_version = 1;
UINT i;
int token_idx = -1;
TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
if (!phContext)
......@@ -1218,12 +1220,22 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
if(MessageSeqNo)
FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2 ||
pMessage->pBuffers[0].BufferType != SECBUFFER_TOKEN ||
!pMessage->pBuffers[0].pvBuffer)
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[0].cbBuffer < 16)
for(i=0; i < pMessage->cBuffers; ++i)
{
if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
{
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 SEC_E_BUFFER_TOO_SMALL;
helper = (PNegoHelper)phContext->dwLower;
......@@ -1235,9 +1247,17 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
}
if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
{
PBYTE sig = pMessage->pBuffers[0].pvBuffer;
ULONG crc = ComputeCrc32(pMessage->pBuffers[1].pvBuffer,
pMessage->pBuffers[1].cbBuffer);
PBYTE sig = pMessage->pBuffers[token_idx].pvBuffer;
ULONG crc = 0U;
for(i=0; i < pMessage->cBuffers; ++i)
{
if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
{
crc = ComputeCrc32(pMessage->pBuffers[i].pvBuffer,
pMessage->pBuffers[i].cbBuffer, crc);
}
}
sig[ 0] = (sign_version >> 0) & 0xff;
sig[ 1] = (sign_version >> 8) & 0xff;
......@@ -1269,9 +1289,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
{
TRACE("Generating dummy signature\n");
/* A dummy signature is 0x01 followed by 15 bytes of 0x00 */
memset(pMessage->pBuffers[0].pvBuffer, 0, 16);
memset(pMessage->pBuffers[0].pvBuffer, 0x01, 1);
pMessage->pBuffers[0].cbBuffer = 16;
memset(pMessage->pBuffers[token_idx].pvBuffer, 0, 16);
memset(pMessage->pBuffers[token_idx].pvBuffer, 0x01, 1);
pMessage->pBuffers[token_idx].cbBuffer = 16;
return SEC_E_OK;
}
......@@ -1286,17 +1306,28 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
{
PNegoHelper helper;
ULONG fQOP = 0;
UINT i;
int token_idx = -1;
TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
if(!phContext)
return SEC_E_INVALID_HANDLE;
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2 ||
pMessage->pBuffers[0].BufferType != SECBUFFER_TOKEN ||
!pMessage->pBuffers[0].pvBuffer)
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)
{
token_idx = i;
break;
}
}
if(token_idx == -1)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[0].cbBuffer < 16)
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
if(MessageSeqNo)
......@@ -1329,7 +1360,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
ntlm_MakeSignature(phContext, fQOP, &local_desc, MessageSeqNo);
if(memcmp(((PBYTE)local_buff[0].pvBuffer) + 8, ((PBYTE)pMessage->pBuffers[0].pvBuffer) + 8, 8))
if(memcmp(((PBYTE)local_buff[0].pvBuffer) + 8,
((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
return SEC_E_MESSAGE_ALTERED;
return SEC_E_OK;
......@@ -1346,7 +1378,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
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[0].pvBuffer, dummy_sig, sizeof(dummy_sig)) != 0)
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;
......@@ -1389,6 +1421,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext,
ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
PNegoHelper helper;
UINT i;
int token_idx = -1;
TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
if(!phContext)
......@@ -1400,12 +1435,22 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext,
if(MessageSeqNo)
FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2 ||
pMessage->pBuffers[0].BufferType != SECBUFFER_TOKEN ||
!pMessage->pBuffers[0].pvBuffer)
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[0].cbBuffer < 16)
for(i=0; i < pMessage->cBuffers; ++i)
{
if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
{
token_idx = i;
break;
}
}
if(token_idx == -1)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
helper = (PNegoHelper) phContext->dwLower;
......@@ -1417,11 +1462,19 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext,
}
else
{
PBYTE sig = pMessage->pBuffers[0].pvBuffer;
ULONG crc = ComputeCrc32(pMessage->pBuffers[1].pvBuffer,
pMessage->pBuffers[1].cbBuffer);
PBYTE sig = pMessage->pBuffers[token_idx].pvBuffer;
ULONG crc = 0U;
ULONG sign_version = 1l;
for(i=0; i < pMessage->cBuffers; ++i)
{
if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
{
crc = ComputeCrc32(pMessage->pBuffers[i].pvBuffer,
pMessage->pBuffers[i].cbBuffer, crc);
}
}
sig[ 0] = (sign_version >> 0) & 0xff;
sig[ 1] = (sign_version >> 8) & 0xff;
sig[ 2] = (sign_version >> 16) & 0xff;
......@@ -1459,6 +1512,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext,
SECURITY_STATUS ret;
ULONG ntlmssp_flags_save;
PNegoHelper helper;
UINT i;
int token_idx = -1;
TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
if(!phContext)
......@@ -1467,12 +1522,21 @@ static SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext,
if(MessageSeqNo)
FIXME("Ignoring MessageSeqNo\n");
if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2 ||
pMessage->pBuffers[0].BufferType != SECBUFFER_TOKEN ||
!pMessage->pBuffers[0].pvBuffer)
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)
{
token_idx = i;
break;
}
}
if(token_idx == -1)
return SEC_E_INVALID_TOKEN;
if(pMessage->pBuffers[0].cbBuffer < 16)
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
helper = (PNegoHelper) phContext->dwLower;
......
......@@ -134,7 +134,7 @@ SECURITY_STATUS decodeBase64(char *in_buf, int in_len, BYTE *out_buf,
int max_len, int *out_len);
/* Functions from util.c */
ULONG ComputeCrc32(const BYTE *pData, INT iLen);
ULONG ComputeCrc32(const BYTE *pData, INT iLen, ULONG initial_crc);
SECURITY_STATUS SECUR32_CreateNTLMv1SessionKey(PBYTE password, int len, PBYTE session_key);
arc4_info *SECUR32_arc4Alloc(void);
void SECUR32_arc4Init(arc4_info *a4i, const BYTE *key, unsigned int keyLen);
......
......@@ -111,6 +111,8 @@ static BYTE message_binary[] =
static char message[] = "Hello, world!";
static char message_header[] = "Header Test";
static BYTE crypt_trailer_client[] =
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xc7,
0xaa, 0x26, 0x16, 0x39, 0x07, 0x4e};
......@@ -119,6 +121,14 @@ static BYTE crypt_message_client[] =
{0x86, 0x9c, 0x5a, 0x10, 0x78, 0xb3, 0x30, 0x98, 0x46, 0x15,
0xa0, 0x31, 0xd9};
static BYTE crypt_trailer_client2[] =
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xa7,
0xf7, 0x0f, 0x5b, 0x25, 0xbe, 0xa4};
static BYTE crypt_message_client2[] =
{0x20, 0x6c, 0x01, 0xab, 0xb0, 0x4c, 0x93, 0xe4, 0x1e, 0xfc,
0xe1, 0xfa, 0xfe};
static BYTE crypt_trailer_server[] =
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x46,
0x2e, 0x77, 0xeb, 0xf0, 0xf6, 0x9e};
......@@ -674,7 +684,7 @@ static void testSignSeal()
SEC_WINNT_AUTH_IDENTITY id;
static char sec_pkg_name[] = "NTLM";
SecBufferDesc crypt;
SecBuffer data[2], fake_data[2];
SecBuffer data[2], fake_data[2], complex_data[4];
ULONG qop = 0;
SecPkgContext_Sizes ctxt_sizes;
......@@ -807,6 +817,45 @@ static void testSignSeal()
crypt.pBuffers[1].cbBuffer),
"Failed to decrypt message correctly.\n");
trace("Testing with more than one buffer.\n");
crypt.cBuffers = sizeof(complex_data)/sizeof(complex_data[0]);
crypt.pBuffers = complex_data;
complex_data[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM;
complex_data[0].cbBuffer = sizeof(message_header);
complex_data[0].pvBuffer = message_header;
complex_data[1].BufferType = SECBUFFER_DATA;
complex_data[1].cbBuffer = lstrlen(message);
complex_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
memcpy(complex_data[1].pvBuffer, message, complex_data[1].cbBuffer);
complex_data[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM;
complex_data[2].cbBuffer = sizeof(message_header);
complex_data[2].pvBuffer = message_header;
complex_data[3].BufferType = SECBUFFER_TOKEN;
complex_data[3].cbBuffer = ctxt_sizes.cbSecurityTrailer;
complex_data[3].pvBuffer = HeapAlloc(GetProcessHeap(), 0, complex_data[3].cbBuffer);
/* We should get a dummy signature again. */
sec_status = pMakeSignature(client.ctxt, 0, &crypt, 0);
ok(sec_status == SEC_E_OK, "MakeSignature returned %s, not SEC_E_OK.\n",
getSecError(sec_status));
ok(!memcmp(crypt.pBuffers[3].pvBuffer, message_signature,
crypt.pBuffers[3].cbBuffer), "Signature is not as expected.\n");
sec_status = pEncryptMessage(client.ctxt, 0, &crypt, 0);
ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
getSecError(sec_status));
ok(!memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2,
crypt.pBuffers[3].cbBuffer), "Crypt trailer not as expected.\n");
ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client2,
crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
end:
cleanupBuffers(&client);
cleanupBuffers(&server);
......
......@@ -93,9 +93,9 @@ VOID WINAPI MD4Init( MD4_CTX *ctx );
VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len );
VOID WINAPI MD4Final( MD4_CTX *ctx );
ULONG ComputeCrc32(const BYTE *pData, INT iLen)
ULONG ComputeCrc32(const BYTE *pData, INT iLen, ULONG initial_crc)
{
ULONG crc = ~0U;
ULONG crc = ~initial_crc;
while (iLen > 0)
{
......
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