windows-nt/Source/XPSP1/NT/ds/security/services/ca/certenc/crldist.cpp

812 lines
18 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: crldist.cpp
//
// Contents: Cert Server Extension Encoding/Decoding implementation
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <assert.h>
#include "resource.h"
#include "crldist.h"
#include "celib.h"
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::~CCertEncodeCRLDistInfo -- destructor
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
CCertEncodeCRLDistInfo::~CCertEncodeCRLDistInfo()
{
_Cleanup();
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::_Cleanup -- release all resources
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
VOID
CCertEncodeCRLDistInfo::_Cleanup()
{
if (NULL != m_aValue)
{
if (!m_fConstructing)
{
if (NULL != m_DecodeInfo)
{
LocalFree(m_DecodeInfo);
m_DecodeInfo = NULL;
}
}
else
{
CRL_DIST_POINT *pDistPoint;
CRL_DIST_POINT *pDistPointEnd;
for (pDistPoint = m_aValue, pDistPointEnd = &m_aValue[m_cValue];
pDistPoint < pDistPointEnd;
pDistPoint++)
{
CERT_ALT_NAME_ENTRY *pName;
CERT_ALT_NAME_ENTRY *pNameEnd;
pName = pDistPoint->DistPointName.FullName.rgAltEntry;
if (NULL != pName)
{
for (pNameEnd = &pName[pDistPoint->DistPointName.FullName.cAltEntry];
pName < pNameEnd;
pName++)
{
if (NULL != pName->pwszURL) // test arbitrary union arm
{
LocalFree(pName->pwszURL);
}
}
LocalFree(pDistPoint->DistPointName.FullName.rgAltEntry);
}
}
LocalFree(m_aValue);
}
m_aValue = NULL;
}
assert(NULL == m_DecodeInfo);
m_fConstructing = FALSE;
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::_MapDistPoint -- map a distribution point
//
//+--------------------------------------------------------------------------
HRESULT
CCertEncodeCRLDistInfo::_MapDistPoint(
IN BOOL fEncode,
IN LONG DistPointIndex,
OUT LONG **ppNameCount,
OUT CERT_ALT_NAME_ENTRY ***ppaName)
{
HRESULT hr = S_OK;
CRL_DIST_POINT *pDistPoint;
if (fEncode)
{
pDistPoint = m_fConstructing? m_aValue : NULL;
}
else
{
pDistPoint = m_aValue;
}
if (NULL == pDistPoint)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
if (m_cValue <= DistPointIndex)
{
ceERRORPRINTLINE("bad DistPointIndex parameter", hr);
hr = E_INVALIDARG;
goto error;
}
*ppNameCount =
(LONG *) &pDistPoint[DistPointIndex].DistPointName.FullName.cAltEntry;
*ppaName = &pDistPoint[DistPointIndex].DistPointName.FullName.rgAltEntry;
error:
return(hr);
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::_MapName -- map a name
//
//+--------------------------------------------------------------------------
HRESULT
CCertEncodeCRLDistInfo::_MapName(
IN BOOL fEncode,
IN LONG DistPointIndex,
IN LONG NameIndex,
OUT CERT_ALT_NAME_ENTRY **ppName)
{
HRESULT hr;
LONG *pNameCount;
CERT_ALT_NAME_ENTRY **paName;
if (NULL == ppName)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
hr = _MapDistPoint(fEncode, DistPointIndex, &pNameCount, &paName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapDistPoint", hr);
goto error;
}
if (*pNameCount <= NameIndex)
{
ceERRORPRINTLINE("bad NameIndex parameter", hr);
hr = E_INVALIDARG;
goto error;
}
*ppName = &(*paName)[NameIndex];
error:
return(hr);
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::Decode -- Decode CRLDistInfo
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::Decode(
/* [in] */ BSTR const strBinary)
{
HRESULT hr = S_OK;
DWORD cbCRLDist;
_Cleanup();
if (NULL == strBinary)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
// Decode CRL_DIST_POINTS_INFO:
if (!ceDecodeObject(
X509_ASN_ENCODING,
X509_CRL_DIST_POINTS,
(BYTE *) strBinary,
SysStringByteLen(strBinary),
FALSE,
(VOID **) &m_DecodeInfo,
&cbCRLDist))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceDecodeObject", hr);
goto error;
}
m_aValue = m_DecodeInfo->rgDistPoint;
m_cValue = m_DecodeInfo->cDistPoint;
error:
if (S_OK != hr)
{
_Cleanup();
}
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::Decode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::GetDistPointCount -- Get the Distribution Name Count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::GetDistPointCount(
/* [out, retval] */ LONG __RPC_FAR *pDistPointCount)
{
HRESULT hr = E_INVALIDARG;
if (NULL == m_aValue)
{
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
if (NULL == pDistPointCount)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
*pDistPointCount = m_cValue;
hr = S_OK;
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::GetDistPointCount"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::GetNameCount -- Get a Name Count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::GetNameCount(
/* [in] */ LONG DistPointIndex,
/* [out, retval] */ LONG __RPC_FAR *pNameCount)
{
HRESULT hr;
LONG *pCount;
CERT_ALT_NAME_ENTRY **paName;
if (NULL == pNameCount)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
hr = _MapDistPoint(FALSE, DistPointIndex, &pCount, &paName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapDistPoint", hr);
goto error;
}
if (NULL == *paName)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
ceERRORPRINTLINE("uninitialized", hr);
goto error;
}
*pNameCount = *pCount;
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::GetNameCount"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::GetNameChoice -- Get a Name Choice
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::GetNameChoice(
/* [in] */ LONG DistPointIndex,
/* [in] */ LONG NameIndex,
/* [out, retval] */ LONG __RPC_FAR *pNameChoice)
{
HRESULT hr;
CERT_ALT_NAME_ENTRY *pName;
if (NULL == pNameChoice)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
hr = _MapName(FALSE, DistPointIndex, NameIndex, &pName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapName", hr);
goto error;
}
*pNameChoice = pName->dwAltNameChoice;
if (0 == pName->dwAltNameChoice)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
ceERRORPRINTLINE("uninitialized", hr);
goto error;
}
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::GetNameChoice"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::GetName -- Get a Name
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::GetName(
/* [in] */ LONG DistPointIndex,
/* [in] */ LONG NameIndex,
/* [out, retval] */ BSTR __RPC_FAR *pstrName)
{
HRESULT hr;
CERT_ALT_NAME_ENTRY *pName;
WCHAR const *pwsz = NULL;
char const *psz = NULL;
if (NULL == pstrName)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
ceFreeBstr(pstrName);
hr = _MapName(FALSE, DistPointIndex, NameIndex, &pName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapName", hr);
goto error;
}
switch (pName->dwAltNameChoice)
{
case CERT_ALT_NAME_RFC822_NAME:
pwsz = pName->pwszRfc822Name;
break;
case CERT_ALT_NAME_DNS_NAME:
pwsz = pName->pwszDNSName;
break;
case CERT_ALT_NAME_URL:
pwsz = pName->pwszURL;
break;
case CERT_ALT_NAME_REGISTERED_ID:
psz = pName->pszRegisteredID;
break;
//case CERT_ALT_NAME_DIRECTORY_NAME:
//case CERT_ALT_NAME_OTHER_NAME:
//case CERT_ALT_NAME_X400_ADDRESS:
//case CERT_ALT_NAME_EDI_PARTY_NAME:
//case CERT_ALT_NAME_IP_ADDRESS:
default:
assert(0 == pName->dwAltNameChoice);
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
ceERRORPRINTLINE("uninitialized", hr);
goto error;
}
// we'd better assure 1 and only 1 of these is non null
if ((NULL != pwsz) ^ (NULL == psz))
{
hr = E_UNEXPECTED;
_JumpError(hr, error, "((NULL != pwsz) ^ (NULL == psz))");
}
hr = E_OUTOFMEMORY;
if (NULL != pwsz)
{
if (!ceConvertWszToBstr(pstrName, pwsz, -1))
{
ceERRORPRINTLINE("no memory", hr);
goto error;
}
}
else
{
assert(NULL != psz);
if (!ceConvertSzToBstr(pstrName, psz, -1))
{
ceERRORPRINTLINE("no memory", hr);
goto error;
}
}
hr = S_OK;
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::GetName"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::Reset -- clear out data
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::Reset(
/* [in] */ LONG DistPointCount)
{
HRESULT hr = S_OK;
CERT_NAME_VALUE *aNameValue = NULL;
_Cleanup();
m_fConstructing = TRUE;
if (CENCODEMAX < DistPointCount || 0 > DistPointCount)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad count parameter", hr);
goto error;
}
m_aValue = (CRL_DIST_POINT *) LocalAlloc(
LMEM_FIXED | LMEM_ZEROINIT,
DistPointCount * sizeof(m_aValue[0]));
if (NULL == m_aValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
m_cValue = DistPointCount;
error:
if (S_OK != hr)
{
_Cleanup();
}
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::Reset"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::SetNameCount -- Set the Name Count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::SetNameCount(
/* [in] */ LONG DistPointIndex,
/* [in] */ LONG NameCount)
{
HRESULT hr;
LONG *pNameCount;
CERT_ALT_NAME_ENTRY **paName;
hr = E_INVALIDARG;
if (!m_fConstructing)
{
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
if (CENCODEMAX < NameCount || 0 > NameCount)
{
ceERRORPRINTLINE("bad count parameter", hr);
goto error;
}
hr = _MapDistPoint(FALSE, DistPointIndex, &pNameCount, &paName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapDistPoint", hr);
goto error;
}
if (0 != *pNameCount || NULL != *paName)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
*paName = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
LMEM_FIXED | LMEM_ZEROINIT,
NameCount * sizeof(CERT_ALT_NAME_ENTRY));
if (NULL == *paName)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
*pNameCount = NameCount;
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::SetNameCount"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::SetNameEntry -- Set a Name Netry
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::SetNameEntry(
/* [in] */ LONG DistPointIndex,
/* [in] */ LONG NameIndex,
/* [in] */ LONG NameChoice,
/* [in] */ BSTR const strName)
{
HRESULT hr;
CERT_ALT_NAME_ENTRY *pName;
WCHAR **ppwsz = NULL;
char **ppsz = NULL;
if (NULL == strName)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (!m_fConstructing)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
hr = _MapName(TRUE, DistPointIndex, NameIndex, &pName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapName", hr);
goto error;
}
if (NULL != pName->pwszURL)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
switch (NameChoice)
{
case CERT_ALT_NAME_RFC822_NAME:
ppwsz = &pName->pwszRfc822Name;
break;
case CERT_ALT_NAME_DNS_NAME:
ppwsz = &pName->pwszDNSName;
break;
case CERT_ALT_NAME_URL:
ppwsz = &pName->pwszURL;
break;
case CERT_ALT_NAME_REGISTERED_ID:
hr = ceVerifyObjId(strName);
if (S_OK != hr)
{
ceERRORPRINTLINE("ceVerifyObjId", hr);
goto error;
}
ppsz = &pName->pszRegisteredID;
break;
//case CERT_ALT_NAME_DIRECTORY_NAME:
//case CERT_ALT_NAME_OTHER_NAME:
//case CERT_ALT_NAME_X400_ADDRESS:
//case CERT_ALT_NAME_EDI_PARTY_NAME:
//case CERT_ALT_NAME_IP_ADDRESS:
}
if (NULL != ppwsz)
{
if (NULL != *ppwsz)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("string already set", hr);
goto error;
}
hr = ceVerifyAltNameString(NameChoice, strName);
if (S_OK != hr)
{
ceERRORPRINTLINE("ceVerifyAltNameString", hr);
goto error;
}
*ppwsz = ceDuplicateString(strName);
if (NULL == *ppwsz)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceDuplicateString", hr);
goto error;
}
}
else if (NULL != ppsz)
{
if (NULL != *ppsz)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("string already set", hr);
goto error;
}
if (!ceConvertWszToSz(ppsz, strName, -1))
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceConvertWszToSz", hr);
goto error;
}
}
else
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad NameChoice parameter", hr);
goto error;
}
pName->dwAltNameChoice = NameChoice;
error:
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::SetNameEntry"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::_VerifyNames -- Verify names
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
BOOL
CCertEncodeCRLDistInfo::_VerifyNames(
IN LONG DistPointIndex)
{
HRESULT hr;
BOOL fOk = FALSE;
LONG Count;
LONG *pNameCount;
LONG i;
CERT_ALT_NAME_ENTRY **paName;
assert(m_fConstructing);
hr = _MapDistPoint(TRUE, DistPointIndex, &pNameCount, &paName);
if (S_OK != hr)
{
ceERRORPRINTLINE("_MapDistPoint", hr);
goto error;
}
Count = *pNameCount;
if (0 != Count)
{
CERT_ALT_NAME_ENTRY *pName;
pName = *paName;
assert(NULL != pName);
for (i = 0; i < Count; pName++, i++)
{
if (NULL == pName->pwszURL) // test arbitrary union arm
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
ceERRORPRINTLINE("uninitialized name", hr);
goto error;
}
}
}
fOk = TRUE;
error:
return(fOk);
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::Encode -- Encode CRLDistInfo
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeCRLDistInfo::Encode(
/* [out, retval] */ BSTR __RPC_FAR *pstrBinary)
{
HRESULT hr = S_OK;
CRL_DIST_POINTS_INFO CRLDistInfo;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
LONG i;
CRLDistInfo.cDistPoint = m_cValue;
CRLDistInfo.rgDistPoint = m_aValue;
if (NULL == pstrBinary)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
ceFreeBstr(pstrBinary);
if (!m_fConstructing || NULL == m_aValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
for (i = 0; i < m_cValue; i++)
{
m_aValue[i].DistPointName.dwDistPointNameChoice =
CRL_DIST_POINT_FULL_NAME;
// Verify all entries are initialized:
if (!_VerifyNames(i))
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
ceERRORPRINTLINE("uninitialized name", hr);
goto error;
}
}
// Encode CRL_DIST_POINTS_INFO:
if (!ceEncodeObject(
X509_ASN_ENCODING,
X509_CRL_DIST_POINTS,
&CRLDistInfo,
0,
FALSE,
&pbEncoded,
&cbEncoded))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceEncodeObject", hr);
goto error;
}
if (!ceConvertWszToBstr(pstrBinary, (WCHAR const *) pbEncoded, cbEncoded))
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceConvertWszToBstr", hr);
goto error;
}
error:
if (NULL != pbEncoded)
{
LocalFree(pbEncoded);
}
return(_SetErrorInfo(hr, L"CCertEncodeCRLDistInfo::Encode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeCRLDistInfo::_SetErrorInfo -- set error object information
//
// Returns passed HRESULT
//+--------------------------------------------------------------------------
HRESULT
CCertEncodeCRLDistInfo::_SetErrorInfo(
IN HRESULT hrError,
IN WCHAR const *pwszDescription)
{
assert(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
if (FAILED(hrError))
{
HRESULT hr;
hr = ceDispatchSetErrorInfo(
hrError,
pwszDescription,
wszCLASS_CERTENCODECRLDISTINFO,
&IID_ICertEncodeCRLDistInfo);
assert(hr == hrError);
}
return(hrError);
}