//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: crldist.cpp // // Contents: Cert Server Extension Encoding/Decoding implementation // //--------------------------------------------------------------------------- #include "pch.cpp" #pragma hdrstop #include #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); }