//+-------------------------------------------------------------------------- // // 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 "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); }