559 lines
12 KiB
C++
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);
|
|
}
|