windows-nt/Source/XPSP1/NT/ds/security/services/ca/certenc/astring.cpp
2020-09-26 16:20:57 +08:00

559 lines
12 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: astring.cpp
//
// Contents: Cert Server Extension Encoding/Decoding implementation
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <assert.h>
#include "resource.h"
#include "astring.h"
#include "celib.h"
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::~CCertEncodeStringArray -- destructor
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
CCertEncodeStringArray::~CCertEncodeStringArray()
{
_Cleanup();
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::_Cleanup -- release all resources
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
VOID
CCertEncodeStringArray::_Cleanup()
{
LONG i;
if (NULL != m_aValue)
{
for (i = 0; i < m_cValue; i++)
{
CERT_NAME_VALUE *pNameValue;
pNameValue = m_aValue[i];
assert(NULL != pNameValue);
if (m_fConstructing)
{
if (NULL != pNameValue->Value.pbData)
{
LocalFree(pNameValue->Value.pbData);
}
}
else
{
LocalFree(pNameValue);
}
}
if (m_fConstructing && NULL != m_aValue[0])
{
LocalFree(m_aValue[0]);
}
LocalFree(m_aValue);
m_aValue = NULL;
}
m_cValue = 0;
m_cValuesSet = 0;
m_fConstructing = FALSE;
m_StringType = CERT_RDN_IA5_STRING;
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::Decode -- Decode StringArray
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::Decode(
/* [in] */ BSTR const strBinary)
{
HRESULT hr = S_OK;
CRYPT_SEQUENCE_OF_ANY *pSequence = NULL;
DWORD cbSequence;
LONG i;
_Cleanup();
if (NULL == strBinary)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
// Decode to an array of ASN blobs:
if (!ceDecodeObject(
X509_ASN_ENCODING,
X509_SEQUENCE_OF_ANY,
(BYTE *) strBinary,
SysStringByteLen(strBinary),
FALSE,
(VOID **) &pSequence,
&cbSequence))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceDecodeObject", hr);
goto error;
}
m_aValue = (CERT_NAME_VALUE **) LocalAlloc(
LMEM_FIXED,
pSequence->cValue * sizeof(m_aValue[0]));
if (NULL == m_aValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
for (i = 0; i < (LONG) pSequence->cValue; i++)
{
DWORD cb;
// Decode each ASN blob to a name value (string blob + encoding type):
if (!ceDecodeObject(
X509_ASN_ENCODING,
X509_UNICODE_ANY_STRING,
pSequence->rgValue[i].pbData,
pSequence->rgValue[i].cbData,
FALSE,
(VOID **) &m_aValue[i],
&cb))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceDecodeObject", hr);
goto error;
}
if (0 == i)
{
m_StringType = m_aValue[i]->dwValueType;
}
else
{
if (m_StringType != (LONG) m_aValue[i]->dwValueType)
{
ceERRORPRINTLINE("dwValueType mismatch", hr);
}
}
m_cValue++;
}
assert((LONG) pSequence->cValue == m_cValue);
error:
if (NULL != pSequence)
{
LocalFree(pSequence);
}
if (S_OK != hr)
{
_Cleanup();
}
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::Decode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::GetStringType -- Get string type
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::GetStringType(
/* [out, retval] */ LONG __RPC_FAR *pStringType)
{
HRESULT hr = S_OK;
if (NULL == pStringType)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (NULL == m_aValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
*pStringType = m_StringType;
error:
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::GetStringType"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::GetCount -- Get Array count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::GetCount(
/* [out, retval] */ LONG __RPC_FAR *pCount)
{
HRESULT hr = S_OK;
if (NULL == pCount)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (NULL == m_aValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
*pCount = m_cValue;
error:
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::GetCount"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::GetValue -- Fetch the indexed string
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::GetValue(
/* [in] */ LONG Index,
/* [out, retval] */ BSTR __RPC_FAR *pstr)
{
HRESULT hr = S_OK;
if (NULL == pstr)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
ceFreeBstr(pstr);
if (NULL == m_aValue || Index >= m_cValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
if (NULL == m_aValue[Index]->Value.pbData)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
ceERRORPRINTLINE("uninitialized", hr);
goto error;
}
if (!ceConvertWszToBstr(
pstr,
(WCHAR const *) m_aValue[Index]->Value.pbData,
-1))
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceConvertWszToBstr", hr);
goto error;
}
error:
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::GetValue"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::Reset -- clear out data
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::Reset(
/* [in] */ LONG Count,
/* [in] */ LONG StringType)
{
HRESULT hr = S_OK;
CERT_NAME_VALUE *aNameValue = NULL;
LONG i;
_Cleanup();
m_fConstructing = TRUE;
if (CENCODEMAX < Count || 0 > Count)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad count parameter", hr);
goto error;
}
switch (StringType)
{
case CERT_RDN_ANY_TYPE:
//case CERT_RDN_ENCODED_BLOB:
//case CERT_RDN_OCTET_STRING:
case CERT_RDN_NUMERIC_STRING:
case CERT_RDN_PRINTABLE_STRING:
//case CERT_RDN_TELETEX_STRING: same as CERT_RDN_T61_STRING:
case CERT_RDN_T61_STRING:
case CERT_RDN_VIDEOTEX_STRING:
case CERT_RDN_IA5_STRING:
case CERT_RDN_GRAPHIC_STRING:
//case CERT_RDN_VISIBLE_STRING: same as CERT_RDN_ISO646_STRING:
case CERT_RDN_ISO646_STRING:
case CERT_RDN_GENERAL_STRING:
//case CERT_RDN_UNIVERSAL_STRING: same as CERT_RDN_INT4_STRING:
case CERT_RDN_INT4_STRING:
//case CERT_RDN_BMP_STRING: same as case CERT_RDN_UNICODE_STRING:
case CERT_RDN_UNICODE_STRING:
break;
default:
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
m_StringType = StringType;
aNameValue = (CERT_NAME_VALUE *) LocalAlloc(
LMEM_FIXED | LMEM_ZEROINIT,
Count * sizeof(*m_aValue[0]));
if (NULL == aNameValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
m_aValue = (CERT_NAME_VALUE **) LocalAlloc(
LMEM_FIXED,
Count * sizeof(m_aValue[0]));
if (NULL == m_aValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
m_cValue = Count;
for (i = 0; i < Count; i++)
{
m_aValue[i] = &aNameValue[i];
}
aNameValue = NULL;
error:
if (NULL != aNameValue)
{
LocalFree(aNameValue);
}
if (S_OK != hr)
{
_Cleanup();
}
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::Reset"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::SetValue -- Set an array string
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::SetValue(
/* [in] */ LONG Index,
/* [in] */ BSTR const str)
{
HRESULT hr = S_OK;
WCHAR *pwsz;
if (NULL == str)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (!m_fConstructing ||
NULL == m_aValue ||
Index >= m_cValue ||
m_cValuesSet >= m_cValue ||
NULL != m_aValue[Index]->Value.pbData)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
pwsz = ceDuplicateString(str);
if (NULL == pwsz)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceDuplicateString", hr);
goto error;
}
m_aValue[Index]->dwValueType = m_StringType;
m_aValue[Index]->Value.pbData = (BYTE *) pwsz;
m_aValue[Index]->Value.cbData = 0;
m_cValuesSet++;
error:
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::SetValue"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::Encode -- Encode StringArray
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeStringArray::Encode(
/* [out, retval] */ BSTR __RPC_FAR *pstrBinary)
{
HRESULT hr = S_OK;
LONG i;
CRYPT_SEQUENCE_OF_ANY Sequence;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
Sequence.cValue = 0;
Sequence.rgValue = NULL;
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;
}
if (m_cValuesSet != m_cValue)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
ceERRORPRINTLINE("uninitialized values", hr);
goto error;
}
Sequence.rgValue = (CRYPT_DER_BLOB *) LocalAlloc(
LMEM_FIXED,
m_cValue * sizeof(Sequence.rgValue[0]));
if (NULL == Sequence.rgValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
for (i = 0; i < m_cValue; i++)
{
// Encode each name blob into an ASN blob:
if (!ceEncodeObject(
X509_ASN_ENCODING,
X509_UNICODE_ANY_STRING,
m_aValue[i],
0,
FALSE,
&Sequence.rgValue[i].pbData,
&Sequence.rgValue[i].cbData))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceEncodeObject", hr);
goto error;
}
Sequence.cValue++;
}
assert((LONG) Sequence.cValue == m_cValue);
// Encode the array of ASN blob:
if (!ceEncodeObject(
X509_ASN_ENCODING,
X509_SEQUENCE_OF_ANY,
&Sequence,
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);
}
if (NULL != Sequence.rgValue)
{
assert((LONG) Sequence.cValue <= m_cValue);
for (i = 0; i < (LONG) Sequence.cValue; i++)
{
assert(NULL != Sequence.rgValue[i].pbData);
LocalFree(Sequence.rgValue[i].pbData);
}
LocalFree(Sequence.rgValue);
}
return(_SetErrorInfo(hr, L"CCertEncodeStringArray::Encode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeStringArray::_SetErrorInfo -- set error object information
//
// Returns passed HRESULT
//+--------------------------------------------------------------------------
HRESULT
CCertEncodeStringArray::_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_CERTENCODESTRINGARRAY,
&IID_ICertEncodeStringArray);
assert(hr == hrError);
}
return(hrError);
}