Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

801 lines
20 KiB

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
File: Attribute.cpp
Content: Implementation of CAttribute.
History: 11-15-99 dsie created
------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "CAPICOM.h"
#include "Attribute.h"
#include "Common.h"
#include "Convert.h"
////////////////////////////////////////////////////////////////////////////////
//
// Exported functions.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CreateAttributebject
Synopsis : Create an IAttribute object and initialize the object with data
from the specified attribute.
Parameter: CRYPT_ATTRIBUTE * pAttribute - Pointer to CRYPT_ATTRIBUTE.
IAttribute ** ppIAttribute - Pointer to pointer IAttribute object.
Remark :
------------------------------------------------------------------------------*/
HRESULT CreateAttributeObject (CRYPT_ATTRIBUTE * pAttribute,
IAttribute ** ppIAttribute)
{
HRESULT hr = S_OK;
CAPICOM_ATTRIBUTE AttrName;
CComVariant varValue;
CComObject<CAttribute> * pCAttribute = NULL;
DebugTrace("Entering CreateAttributeObject().\n");
//
// Sanity check.
//
ATLASSERT(pAttribute);
ATLASSERT(ppIAttribute);
try
{
//
// Create the object. Note that the ref count will still be 0
// after the object is created.
//
if (FAILED(hr = CComObject<CAttribute>::CreateInstance(&pCAttribute)))
{
DebugTrace("Error [%#x]: CComObject<CAttribute>::CreateInstance() failed.\n", hr);
goto ErrorExit;
}
//
// Determine OID value.
//
if (0 == ::strcmp(pAttribute->pszObjId, szOID_RSA_signingTime))
{
DATE SigningTime;
SYSTEMTIME st;
CRYPT_DATA_BLOB FileTimeBlob = {0, NULL};
if (FAILED(hr = ::DecodeObject(szOID_RSA_signingTime,
pAttribute->rgValue->pbData,
pAttribute->rgValue->cbData,
&FileTimeBlob)))
{
DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
goto ErrorExit;
}
if (!::FileTimeToSystemTime((FILETIME *) FileTimeBlob.pbData, &st) ||
!::SystemTimeToVariantTime(&st, &SigningTime))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
::CoTaskMemFree(FileTimeBlob.pbData);
DebugTrace("Error [%#x]: unable to convert FILETIME to DATE.\n", hr);
goto ErrorExit;
}
::CoTaskMemFree(FileTimeBlob.pbData);
AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
varValue = SigningTime;
varValue.ChangeType(VT_DATE, NULL);
}
else if (0 == ::strcmp(pAttribute->pszObjId, szOID_CAPICOM_DOCUMENT_NAME))
{
CComBSTR bstrName;
CRYPT_DATA_BLOB NameBlob = {0, NULL};
if (FAILED(hr = ::DecodeObject(X509_OCTET_STRING,
pAttribute->rgValue->pbData,
pAttribute->rgValue->cbData,
&NameBlob)))
{
DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
goto ErrorExit;
}
if (FAILED(hr = ::BlobToBstr((DATA_BLOB *) NameBlob.pbData, &bstrName)))
{
::CoTaskMemFree(NameBlob.pbData);
DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr);
goto ErrorExit;
}
::CoTaskMemFree(NameBlob.pbData);
AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME;
varValue = bstrName;
}
else if (0 == ::strcmp(pAttribute->pszObjId, szOID_CAPICOM_DOCUMENT_DESCRIPTION))
{
CComBSTR bstrDesc;
CRYPT_DATA_BLOB DescBlob = {0, NULL};
if (FAILED(hr = ::DecodeObject(X509_OCTET_STRING,
pAttribute->rgValue->pbData,
pAttribute->rgValue->cbData,
&DescBlob)))
{
DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
goto ErrorExit;
}
if (FAILED(hr = ::BlobToBstr((DATA_BLOB *) DescBlob.pbData, &bstrDesc)))
{
::CoTaskMemFree(DescBlob.pbData);
DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr);
goto ErrorExit;
}
::CoTaskMemFree(DescBlob.pbData);
AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION;
varValue = bstrDesc;
}
else
{
hr = CAPICOM_E_ATTRIBUTE_INVALID_NAME;
DebugTrace("Error [%#x]: Unknown attribute OID (%#s).\n", hr, pAttribute->pszObjId);
goto ErrorExit;
}
//
// Initialize object.
//
if (FAILED(hr = pCAttribute->Init(AttrName, pAttribute->pszObjId, varValue)))
{
DebugTrace("Error [%#x]: pCAttribute->Init() failed.\n", hr);
goto ErrorExit;
}
//
// Return interface pointer to caller.
//
if (FAILED(hr = pCAttribute->QueryInterface(ppIAttribute)))
{
DebugTrace("Error [%#x]: pCAttribute->QueryInterface() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
CommonExit:
DebugTrace("Leaving CreateAttributeObject().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
if (pCAttribute)
{
delete pCAttribute;
}
goto CommonExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : AttributePairIsValid
Synopsis : Check to see if an attribute name and value pair is valid.
Parameter: CAPICOM_ATTRIBUTE AttrName - Attribute name.
VARIANT varValue - Attribute value.
Remark :
------------------------------------------------------------------------------*/
HRESULT AttributePairIsValid (CAPICOM_ATTRIBUTE AttrName,
VARIANT varValue)
{
HRESULT hr = S_OK;
DebugTrace("Entering AttributePairIsValid()");
//
// Check attribute name and value pair validity.
//
switch (AttrName)
{
case CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME:
{
if (VT_DATE != varValue.vt)
{
hr = CAPICOM_E_ATTRIBUTE_INVALID_VALUE;
DebugTrace("Error [%#x]: attribute name and value type does not match.\n", hr);
}
break;
}
case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME:
case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION:
{
if (VT_BSTR != varValue.vt)
{
hr = CAPICOM_E_ATTRIBUTE_INVALID_VALUE;
DebugTrace("Error [%#x]: attribute data type does not match attribute name type, expecting a BSTR variant.\n", hr);
}
break;
}
default:
{
hr = CAPICOM_E_ATTRIBUTE_INVALID_NAME;
DebugTrace("Error [%#x]: unknown attribute name (%#x).\n", hr, AttrName);
break;
}
}
DebugTrace("Leaving AttributePairIsValid().\n");
return hr;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : AttributeIsValid
Synopsis : Check to see if an attribute is valid.
Parameter: IAttribute * pVal - Attribute to be checked.
Remark :
------------------------------------------------------------------------------*/
HRESULT AttributeIsValid (IAttribute * pAttribute)
{
HRESULT hr = S_OK;
CAPICOM_ATTRIBUTE AttrName;
CComVariant varValue;
DebugTrace("Entering AttributeIsValid()");
//
// Sanity check.
//
ATLASSERT(pAttribute);
//
// Get attribute name.
//
if (FAILED(hr = pAttribute->get_Name(&AttrName)))
{
DebugTrace("Error [%#x]: pVal->get_Name() failed.\n", hr);
goto ErrorExit;
}
//
// Get attribute value.
//
if (FAILED(hr = pAttribute->get_Value(&varValue)))
{
DebugTrace("Error [%#x]: pVal->get_Value() failed.\n", hr);
goto ErrorExit;
}
//
// Check attribute name and value pair validity.
//
if (FAILED(hr = AttributePairIsValid(AttrName, varValue)))
{
DebugTrace("Error [%#x]: AttributePairIsValid() failed.\n", hr);
goto ErrorExit;
}
CommonExit:
DebugTrace("Leaving AttributeIsValid().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
goto CommonExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : AttributeIsSupported
Synopsis : Check to see if an attribute is supported.
Parameter: LPSTR pszObjId - Pointer to attribute OID.
Remark :
------------------------------------------------------------------------------*/
BOOL AttributeIsSupported (LPSTR pszObjId)
{
//
// Sanity check.
//
ATLASSERT(pszObjId);
return (0 == ::strcmp(pszObjId, szOID_RSA_signingTime) ||
0 == ::strcmp(pszObjId, szOID_CAPICOM_DOCUMENT_NAME) ||
0 == ::strcmp(pszObjId, szOID_CAPICOM_DOCUMENT_DESCRIPTION));
}
///////////////////////////////////////////////////////////////////////////////
//
// CAttribute
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CAttribute::get_Name
Synopsis : Return the name of the attribute.
Parameter: CAPICOM_ATTRIBUTE * pVal - Pointer to CAPICOM_ATTRIBUTE to receive
result.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CAttribute::get_Name (CAPICOM_ATTRIBUTE * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CAttribute::get_Name().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure it is initialized.
//
if (!m_bInitialized)
{
hr = CAPICOM_E_ATTRIBUTE_NAME_NOT_INITIALIZED;
DebugTrace("Error [%#x]: attribute name has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return result.
//
*pVal = m_AttrName;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CAttribute::get_Name().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CAttribute::put_Name
Synopsis : Set attribute enum name.
Parameter: CAPICOM_ATTRIBUTE newVal - attribute enum name.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CAttribute::put_Name (CAPICOM_ATTRIBUTE newVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CAttribute::put_Name().\n");
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Reset value based on EKU name.
//
switch (newVal)
{
case CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME:
{
if (!(m_bstrOID = szOID_RSA_signingTime))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: m_bstrOID = szOID_RSA_signingTime failed.\n", hr);
goto ErrorExit;
}
break;
}
case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME:
{
if (!(m_bstrOID = szOID_CAPICOM_DOCUMENT_NAME))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: m_bstrOID = szOID_CAPICOM_DOCUMENT_NAME failed.\n", hr);
goto ErrorExit;
}
break;
}
case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION:
{
if (!(m_bstrOID = szOID_CAPICOM_DOCUMENT_DESCRIPTION))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: m_bstrOID = szOID_CAPICOM_DOCUMENT_DESCRIPTION failed.\n", hr);
goto ErrorExit;
}
break;
}
default:
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Unknown attribute name (%#x).\n", hr, newVal);
goto ErrorExit;
}
}
//
// Store name.
//
m_AttrName = newVal;
m_varValue.Clear();
m_bInitialized = TRUE;
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CAttribute::put_Name().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CAttribute::get_Value
Synopsis : Return the actual value of the attribute.
Parameter: VARIANT * pVal - Pointer to VARIANT to receive value.
Remark : Note: value type varies depending on the attribute type. For
example, szOID_RSA_SigningTime would have a DATE value.
------------------------------------------------------------------------------*/
STDMETHODIMP CAttribute::get_Value (VARIANT * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CAttribute::get_Value().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure it was set.
//
if (VT_EMPTY == m_varValue.vt)
{
hr = CAPICOM_E_ATTRIBUTE_VALUE_NOT_INITIALIZED;
DebugTrace("Error [%#x]: attribute value has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Return result.
//
if (FAILED(hr = ::VariantCopy(pVal, &m_varValue)))
{
DebugTrace("Error [%#x]: VariantCopy() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CAttribute::get_Value().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
return S_OK;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CAttribute::put_Value
Synopsis : Set attribute value.
Parameter: VARIANT newVal - attribute value.
Remark : Note: value type varies depending on the attribute type. For
example, szOID_RSA_SigningTime would have a DATE value.
------------------------------------------------------------------------------*/
STDMETHODIMP CAttribute::put_Value (VARIANT newVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CAttribute::put_Value().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Make sure it is initialized.
//
if (!m_bInitialized)
{
hr = CAPICOM_E_ATTRIBUTE_NAME_NOT_INITIALIZED;
DebugTrace("Error [%#x]: attribute name has not been initialized.\n", hr);
goto ErrorExit;
}
//
// Make sure data type matches attribute type.
//
if (FAILED(hr = AttributePairIsValid(m_AttrName, newVal)))
{
DebugTrace("Error [%#x]: AttributePairIsValid() failed.\n", hr);
goto ErrorExit;
}
//
// Store value.
//
m_varValue = newVal;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CAttribute::put_Value().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// Private methods.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CAttribute::Init
Synopsis : Initialize the object.
Parameter: DWORD AttrName - Enum name of Attribute.
LPSTR lpszOID - Attribute OID string.
VARIANT varValue - Value of attribute (data type depends on
the type of attribute).
Remark : This method is not part of the COM interface (it is a normal C++
member function). We need it to initialize the object created
internally by us with CERT_CONTEXT.
Since it is only a normal C++ member function, this function can
only be called from a C++ class pointer, not an interface pointer.
------------------------------------------------------------------------------*/
STDMETHODIMP CAttribute::Init (CAPICOM_ATTRIBUTE AttrName,
LPSTR lpszOID,
VARIANT varValue)
{
HRESULT hr = S_OK;
DebugTrace("Entering CAttribute::Init().\n");
//
// Sanity check.
//
ATLASSERT(lpszOID);
//
// Init private members.
//
if (!(m_bstrOID = lpszOID))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: m_bstrOID = lpszOID failed.\n", hr);
goto ErrorExit;
}
m_bInitialized = TRUE;
m_AttrName = AttrName;
m_varValue = varValue;
CommonExit:
DebugTrace("Leaving CAttribute::Init().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
m_bstrOID.Empty();
goto CommonExit;
}