You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
7.4 KiB
260 lines
7.4 KiB
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000 - 2001.
|
|
|
|
File: MsgHlpr.cpp
|
|
|
|
Content: Helper functions for messaging.
|
|
|
|
History: 11-15-99 dsie created
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "CAPICOM.h"
|
|
#include "MsgHlpr.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Exported functions.
|
|
//
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : GetMsgParam
|
|
|
|
Synopsis : Allocate memory and retrieve requested message parameter using
|
|
CryptGetMsgParam() API.
|
|
|
|
Parameter: HCRYPTMSG hMsg - Message handler.
|
|
DWORD dwMsgType - Message param type to retrieve.
|
|
DWORD dwIndex - Index (should be 0 most of the time).
|
|
void ** ppvData - Pointer to receive buffer.
|
|
DWORD * pcbData - Size of buffer.
|
|
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT GetMsgParam (HCRYPTMSG hMsg,
|
|
DWORD dwMsgType,
|
|
DWORD dwIndex,
|
|
void ** ppvData,
|
|
DWORD * pcbData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cbData = 0;
|
|
void * pvData = NULL;
|
|
|
|
DebugTrace("Entering GetMsgParam().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(ppvData);
|
|
ATLASSERT(pcbData);
|
|
|
|
//
|
|
// Determine data buffer size.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
dwMsgType,
|
|
dwIndex,
|
|
NULL,
|
|
&cbData))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for buffer.
|
|
//
|
|
if (!(pvData = (void *) ::CoTaskMemAlloc(cbData)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
DebugTrace("Error: out of memory.\n");
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Now get the data.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
dwMsgType,
|
|
dwIndex,
|
|
pvData,
|
|
&cbData))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Return msg param to caller.
|
|
//
|
|
*ppvData = pvData;
|
|
*pcbData = cbData;
|
|
|
|
CommonExit:
|
|
|
|
DebugTrace("Leaving GetMsgParam().\n");
|
|
|
|
return hr;
|
|
|
|
ErrorExit:
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(FAILED(hr));
|
|
|
|
//
|
|
// Free resources.
|
|
//
|
|
if (pvData)
|
|
{
|
|
::CoTaskMemFree(pvData);
|
|
}
|
|
|
|
goto CommonExit;
|
|
}
|
|
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Function : FindSignerCertInMessage
|
|
|
|
Synopsis : Find the signer's cert in the bag of certs of the message for the
|
|
specified signer.
|
|
|
|
Parameter: HCRYPTMSG hMsg - Message handle.
|
|
CERT_NAME_BLOB * pIssuerNameBlob - Pointer to issuer' name
|
|
blob of signer's cert.
|
|
CRYPT_INTEGERT_BLOB * pSerialNumberBlob - Pointer to serial number
|
|
blob of signer's cert.
|
|
PCERT_CONTEXT * ppCertContext - Pointer to PCERT_CONTEXT
|
|
to receive the found
|
|
cert, or NULL to only
|
|
know the result.
|
|
Remark :
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
HRESULT FindSignerCertInMessage (HCRYPTMSG hMsg,
|
|
CERT_NAME_BLOB * pIssuerNameBlob,
|
|
CRYPT_INTEGER_BLOB * pSerialNumberBlob,
|
|
PCERT_CONTEXT * ppCertContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCertCount = 0;
|
|
DWORD cbCertCount = sizeof(dwCertCount);
|
|
|
|
DebugTrace("Entering FindSignerCertInMessage().\n");
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
ATLASSERT(NULL != hMsg);
|
|
ATLASSERT(NULL != pIssuerNameBlob);
|
|
ATLASSERT(NULL != pSerialNumberBlob);
|
|
ATLASSERT(0 < pIssuerNameBlob->cbData);
|
|
ATLASSERT(NULL != pIssuerNameBlob->pbData);
|
|
ATLASSERT(0 < pSerialNumberBlob->cbData);
|
|
ATLASSERT(NULL != pSerialNumberBlob->pbData);
|
|
|
|
//
|
|
// Get count of certs in message.
|
|
//
|
|
if (!::CryptMsgGetParam(hMsg,
|
|
CMSG_CERT_COUNT_PARAM,
|
|
0,
|
|
&dwCertCount,
|
|
&cbCertCount))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// See if the signer's cert is in the bag of certs.
|
|
//
|
|
while (dwCertCount--)
|
|
{
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
CRYPT_DATA_BLOB EncodedCertBlob = {0, NULL};
|
|
|
|
//
|
|
// Get a cert from the bag of certs.
|
|
//
|
|
hr = ::GetMsgParam(hMsg,
|
|
CMSG_CERT_PARAM,
|
|
dwCertCount,
|
|
(void **) &EncodedCertBlob.pbData,
|
|
&EncodedCertBlob.cbData);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugTrace("Error [%#x]: GetMsgParam() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Create a context for the cert.
|
|
//
|
|
pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
(const BYTE *) EncodedCertBlob.pbData,
|
|
EncodedCertBlob.cbData);
|
|
|
|
//
|
|
// Free encoded cert blob memory before checking result.
|
|
//
|
|
::CoTaskMemFree((LPVOID) EncodedCertBlob.pbData);
|
|
|
|
if (NULL == pCertContext)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
|
|
DebugTrace("Error [%#x]: CertCreateCertificateContext() failed.\n", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Compare.
|
|
//
|
|
if (::CertCompareCertificateName(CAPICOM_ASN_ENCODING,
|
|
pIssuerNameBlob,
|
|
&pCertContext->pCertInfo->Issuer) &&
|
|
::CertCompareIntegerBlob(pSerialNumberBlob,
|
|
&pCertContext->pCertInfo->SerialNumber))
|
|
{
|
|
if (NULL != ppCertContext)
|
|
{
|
|
*ppCertContext = (PCERT_CONTEXT) pCertContext;
|
|
}
|
|
else
|
|
{
|
|
::CertFreeCertificateContext(pCertContext);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No, keep looking.
|
|
//
|
|
::CertFreeCertificateContext(pCertContext);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we get here, that means we never found the cert.
|
|
//
|
|
return CAPICOM_E_SIGNER_NOT_FOUND;
|
|
}
|