|
|
//+--------------------------------------------------------------------------
//
// 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 "altname.h"
#include "celib.h"
#ifndef EAN_NAMEOBJECTID
#define EAN_NAMEOBJECTID ( 0x80000000 )
#endif EAN_NAMEOBJECTID
//+--------------------------------------------------------------------------
// CCertEncodeAltName::CCertEncodeAltName -- constructor
//
// initialize class
//+--------------------------------------------------------------------------
CCertEncodeAltName::CCertEncodeAltName() { m_aValue = NULL; m_DecodeInfo = NULL; m_fConstructing = FALSE; }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::~CCertEncodeAltName -- destructor
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
CCertEncodeAltName::~CCertEncodeAltName() { _Cleanup(); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::_NameType -- determine name type tag
//
//+--------------------------------------------------------------------------
CCertEncodeAltName::enumNameType CCertEncodeAltName::_NameType( IN DWORD NameChoice) { enumNameType Type = enumUnknown;
switch (NameChoice) { case CERT_ALT_NAME_RFC822_NAME: case CERT_ALT_NAME_DNS_NAME: case CERT_ALT_NAME_URL: Type = enumUnicode; break;
case CERT_ALT_NAME_REGISTERED_ID: Type = enumAnsi; break;
case CERT_ALT_NAME_DIRECTORY_NAME: case CERT_ALT_NAME_IP_ADDRESS: Type = enumBlob; break;
case CERT_ALT_NAME_OTHER_NAME: Type = enumOther; break;
//case CERT_ALT_NAME_X400_ADDRESS:
//case CERT_ALT_NAME_EDI_PARTY_NAME:
} return(Type); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::_Cleanup -- release all resources
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
VOID CCertEncodeAltName::_Cleanup() { if (NULL != m_aValue) { if (!m_fConstructing) { if (NULL != m_DecodeInfo) { LocalFree(m_DecodeInfo); m_DecodeInfo = NULL; } } else { CERT_ALT_NAME_ENTRY *pName; CERT_ALT_NAME_ENTRY *pNameEnd;
for (pName = m_aValue, pNameEnd = &m_aValue[m_cValue]; pName < pNameEnd; pName++) { BYTE **ppb;
ppb = NULL;
switch (_NameType(pName->dwAltNameChoice)) { case enumUnicode: case enumAnsi: ppb = (BYTE **) &pName->pwszURL; break;
case enumBlob: ppb = (BYTE **) &pName->DirectoryName.pbData; break;
case enumOther: { CERT_OTHER_NAME *pOther = pName->pOtherName; if (NULL != pOther) { if (NULL != pOther->pszObjId) { LocalFree(pOther->pszObjId); } if (NULL != pOther->Value.pbData) { LocalFree(pOther->Value.pbData); } } ppb = (BYTE **) &pName->pOtherName; break; } } if (NULL != ppb && NULL != *ppb) { LocalFree(*ppb); } } LocalFree(m_aValue); } m_aValue = NULL; } assert(NULL == m_DecodeInfo); m_fConstructing = FALSE; }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::_MapName -- map a distribution point
//
//+--------------------------------------------------------------------------
HRESULT CCertEncodeAltName::_MapName( IN BOOL fEncode, IN LONG NameIndex, // NameIndex | EAN_*
OUT CERT_ALT_NAME_ENTRY **ppName) { HRESULT hr = S_OK; CERT_ALT_NAME_ENTRY *pName;
if (fEncode) { pName = m_fConstructing? m_aValue : NULL; } else { pName = m_aValue; }
if (NULL == pName) { hr = E_INVALIDARG; ceERRORPRINTLINE("bad parameter", hr); goto error; }
NameIndex &= ~EAN_NAMEOBJECTID; if (m_cValue <= NameIndex) { ceERRORPRINTLINE("bad NameIndex parameter", hr); hr = E_INVALIDARG; goto error; } *ppName = &pName[NameIndex];
error: return(hr); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::Decode -- Decode AltName
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::Decode( /* [in] */ BSTR const strBinary) { HRESULT hr = S_OK;
_Cleanup();
if (NULL == strBinary) { hr = E_POINTER; ceERRORPRINTLINE("NULL parm", hr); goto error; }
// Decode CERT_ALT_NAME_INFO:
if (!ceDecodeObject( X509_ASN_ENCODING, X509_ALTERNATE_NAME, (BYTE *) strBinary, SysStringByteLen(strBinary), FALSE, (VOID **) &m_DecodeInfo, &m_DecodeLength)) { hr = ceHLastError(); ceERRORPRINTLINE("ceDecodeObject", hr); goto error; }
m_aValue = m_DecodeInfo->rgAltEntry; m_cValue = m_DecodeInfo->cAltEntry;
error: if (S_OK != hr) { _Cleanup(); } return(_SetErrorInfo(hr, L"CCertEncodeAltName::Decode")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::GetNameCount -- Get the Distribution Name Count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::GetNameCount( /* [out, retval] */ LONG __RPC_FAR *pNameCount) { HRESULT hr = E_INVALIDARG;
if (NULL == pNameCount) { hr = E_POINTER; ceERRORPRINTLINE("NULL parm", hr); goto error; } if (NULL == m_aValue) { ceERRORPRINTLINE("bad parameter", hr); goto error; } *pNameCount = m_cValue; hr = S_OK;
error: return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetNameCount")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::GetNameChoice -- Get a Name Choice
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::GetNameChoice( /* [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, NameIndex, &pName); if (S_OK != hr) { ceERRORPRINTLINE("_MapName", hr); goto error; } if (enumUnknown == _NameType(pName->dwAltNameChoice)) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); ceERRORPRINTLINE("uninitialized", hr); goto error; } *pNameChoice = pName->dwAltNameChoice;
error: return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetNameChoice")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::GetName -- Get a Name
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::GetName( /* [in] */ LONG NameIndex, // NameIndex | EAN_*
/* [out, retval] */ BSTR __RPC_FAR *pstrName) { HRESULT hr; CERT_ALT_NAME_ENTRY *pName;
if (NULL == pstrName) { hr = E_POINTER; ceERRORPRINTLINE("NULL parm", hr); goto error; } ceFreeBstr(pstrName); hr = _MapName(FALSE, NameIndex, &pName); if (S_OK != hr) { ceERRORPRINTLINE("_MapName", hr); goto error; }
hr = E_OUTOFMEMORY; switch (_NameType(pName->dwAltNameChoice)) { case enumUnicode: if (!ceConvertWszToBstr(pstrName, pName->pwszURL, -1)) { ceERRORPRINTLINE("no memory", hr); goto error; } break;
case enumAnsi: if (!ceConvertSzToBstr(pstrName, pName->pszRegisteredID, -1)) { ceERRORPRINTLINE("no memory", hr); goto error; } break;
case enumBlob: if (!ceConvertWszToBstr( pstrName, (WCHAR const *) pName->DirectoryName.pbData, pName->DirectoryName.cbData)) { ceERRORPRINTLINE("no memory", hr); goto error; } break;
case enumOther: if (EAN_NAMEOBJECTID & NameIndex) { if (!ceConvertSzToBstr( pstrName, pName->pOtherName->pszObjId, -1)) { ceERRORPRINTLINE("no memory", hr); goto error; } } else { if (!ceConvertWszToBstr( pstrName, (WCHAR const *) pName->pOtherName->Value.pbData, pName->pOtherName->Value.cbData)) { ceERRORPRINTLINE("no memory", hr); goto error; } } break;
default: assert(enumUnknown == _NameType(pName->dwAltNameChoice)); hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); ceERRORPRINTLINE("uninitialized", hr); goto error; } hr = S_OK;
error: return(_SetErrorInfo(hr, L"CCertEncodeAltName::GetName")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::Reset -- clear out data
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::Reset( /* [in] */ LONG NameCount) { HRESULT hr = S_OK;
_Cleanup(); m_fConstructing = TRUE; if (CENCODEMAX < NameCount || 0 > NameCount) { hr = E_INVALIDARG; ceERRORPRINTLINE("bad count parameter", hr); goto error; }
m_aValue = (CERT_ALT_NAME_ENTRY *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, NameCount * sizeof(m_aValue[0])); if (NULL == m_aValue) { hr = E_OUTOFMEMORY; ceERRORPRINTLINE("LocalAlloc", hr); goto error; } m_cValue = NameCount;
error: if (S_OK != hr) { _Cleanup(); } return(_SetErrorInfo(hr, L"CCertEncodeAltName::Reset")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::SetNameEntry -- Set a Name Netry
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::SetNameEntry( /* [in] */ LONG NameIndex, // NameIndex | EAN_*
/* [in] */ LONG NameChoice, /* [in] */ BSTR const strName) { HRESULT hr; CERT_ALT_NAME_ENTRY *pName; DATA_BLOB *pBlob = NULL; CCertEncodeAltName::enumNameType enumT;
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, NameIndex, &pName); if (S_OK != hr) { ceERRORPRINTLINE("_MapName", hr); goto error; }
enumT = enumUnknown; if (CERT_ALT_NAME_OTHER_NAME == pName->dwAltNameChoice && 0 == (EAN_NAMEOBJECTID & NameIndex)) { enumT = enumOther; } if (_NameType(pName->dwAltNameChoice) != enumT) { hr = E_INVALIDARG; ceERRORPRINTLINE("bad parameter", hr); goto error; } if (CERT_ALT_NAME_OTHER_NAME != pName->dwAltNameChoice || 0 == (EAN_NAMEOBJECTID & NameIndex)) { hr = ceVerifyAltNameString(NameChoice, strName); if (S_OK != hr) { ceERRORPRINTLINE("ceVerifyAltNameString", hr); goto error; } }
switch (_NameType(NameChoice)) { case enumUnicode: pName->pwszURL = ceDuplicateString(strName); if (NULL == pName->pwszURL) { hr = E_OUTOFMEMORY; ceERRORPRINTLINE("ceDuplicateString", hr); goto error; } break;
case enumAnsi: if (CERT_ALT_NAME_REGISTERED_ID == NameChoice) { hr = ceVerifyObjId(strName); if (S_OK != hr) { ceERRORPRINTLINE("ceVerifyObjId", hr); goto error; } } if (!ceConvertWszToSz(&pName->pszRegisteredID, strName, -1)) { hr = E_OUTOFMEMORY; ceERRORPRINTLINE("ceConvertWszToSz", hr); goto error; } break;
case enumBlob: pBlob = &pName->DirectoryName; break;
case enumOther: if (NULL == pName->pOtherName) { pName->pOtherName = (CERT_OTHER_NAME *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(*pName->pOtherName)); if (NULL == pName->pOtherName) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } } else if (CERT_ALT_NAME_OTHER_NAME != pName->dwAltNameChoice) { hr = E_INVALIDARG; _JumpError(hr, error, "NameChoice conflict"); } if (EAN_NAMEOBJECTID & NameIndex) { if (NULL != pName->pOtherName->pszObjId) { hr = E_INVALIDARG; _JumpError(hr, error, "pszObjId already set"); } hr = ceVerifyObjId(strName); if (S_OK != hr) { ceERRORPRINTLINE("ceVerifyObjId", hr); goto error; } if (!ceConvertWszToSz(&pName->pOtherName->pszObjId, strName, -1)) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "ceConvertWszToSz"); } } else { pBlob = &pName->pOtherName->Value; } break;
default: hr = E_INVALIDARG; ceERRORPRINTLINE("bad NameChoice parameter", hr); goto error; break; }
if (NULL != pBlob) { if (NULL != pBlob->pbData) { hr = E_INVALIDARG; _JumpError(hr, error, "pbData already set"); } pBlob->cbData = SysStringByteLen(strName); pBlob->pbData = (BYTE *) LocalAlloc(LMEM_FIXED, pBlob->cbData); if (NULL == pBlob->pbData) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } CopyMemory(pBlob->pbData, strName, pBlob->cbData); } pName->dwAltNameChoice = NameChoice;
error: return(_SetErrorInfo(hr, L"CCertEncodeAltName::SetNameEntry")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::_VerifyName -- Verify name
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
BOOL CCertEncodeAltName::_VerifyName( IN LONG NameIndex) { HRESULT hr; BOOL fOk = FALSE; CERT_ALT_NAME_ENTRY *pName;
assert(m_fConstructing);
hr = _MapName(TRUE, NameIndex, &pName); if (S_OK != hr) { ceERRORPRINTLINE("_MapName", hr); goto error; } assert(NULL != pName); switch (_NameType(pName->dwAltNameChoice)) { case enumOther: if (NULL != pName->pOtherName && NULL != pName->pOtherName->pszObjId && NULL != pName->pOtherName->Value.pbData) { break; } // FALLTHROUGH
case enumUnknown: hr = E_INVALIDARG; ceERRORPRINTLINE("uninitialized name", hr); goto error; } fOk = TRUE;
error: return(fOk); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::Encode -- Encode AltName
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP CCertEncodeAltName::Encode( /* [out, retval] */ BSTR __RPC_FAR *pstrBinary) { HRESULT hr = S_OK; CERT_ALT_NAME_INFO AltName; BYTE *pbEncoded = NULL; DWORD cbEncoded; LONG i;
if (NULL == pstrBinary) { hr = E_POINTER; ceERRORPRINTLINE("NULL parm", hr); goto error; }
AltName.cAltEntry = m_cValue; AltName.rgAltEntry = m_aValue;
ceFreeBstr(pstrBinary); if (!m_fConstructing || NULL == m_aValue) { hr = E_INVALIDARG; ceERRORPRINTLINE("bad parameter", hr); goto error; }
for (i = 0; i < m_cValue; i++) { // Verify all entries are initialized:
if (!_VerifyName(i)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); ceERRORPRINTLINE("uninitialized name", hr); goto error; } }
// Encode CERT_ALT_NAME_INFO:
if (!ceEncodeObject( X509_ASN_ENCODING, X509_ALTERNATE_NAME, &AltName, 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"CCertEncodeAltName::Encode")); }
//+--------------------------------------------------------------------------
// CCertEncodeAltName::_SetErrorInfo -- set error object information
//
// Returns passed HRESULT
//+--------------------------------------------------------------------------
HRESULT CCertEncodeAltName::_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_CERTENCODEALTNAME, &IID_ICertEncodeAltName); assert(hr == hrError); } return(hrError); }
|