mirror of
https://github.com/reactos/wine.git
synced 2025-02-28 00:39:06 +00:00
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.
This commit is contained in:
parent
e1bfe4c18a
commit
cd8332ae1c
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user