//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998-2002. // // File: AutoCert.cpp // // Contents: implementation of the CAutoCertRequest class. // //---------------------------------------------------------------------------- #include "stdafx.h" #include #include "AutoCert.h" #include "storegpe.h" USE_HANDLE_MACROS("CERTMGR(AutoCert.cpp)") //////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CAutoCertRequest::CAutoCertRequest (const PCCTL_CONTEXT pCTLContext, CCertStore& rCertStore) : CCTL (pCTLContext, rCertStore, CERTMGR_AUTO_CERT_REQUEST), m_pCertTypeExtension (0), m_pEnhKeyUsageExtension (0), m_bCANamesEnumerated (false), m_hCertType (0) { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); } CAutoCertRequest::~CAutoCertRequest() { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); if ( m_hCertType ) { VERIFY (SUCCEEDED (::CACloseCertType (m_hCertType))); } } HRESULT CAutoCertRequest::GetCertTypeName(CString & certTypeName) { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); HRESULT hResult = S_OK; if ( CERTMGR_LOG_STORE_GPE != GetCertStore().m_objecttype && CERTMGR_LOG_STORE_RSOP != GetCertStore().m_objecttype ) { hResult = E_FAIL; return hResult; } CCertStore* pStore = reinterpret_cast (&GetCertStore()); if(pStore == NULL) { hResult = E_FAIL; return hResult; } if ( m_szCertTypeName.IsEmpty () ) { bool bFound = false; hResult = E_FAIL; PCERT_EXTENSION pCertTypeExtension = GetCertTypeExtension (); if ( pCertTypeExtension ) { DWORD cbValue = 0; if ( ::CryptDecodeObject( CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, pCertTypeExtension->Value.pbData, pCertTypeExtension->Value.cbData, 0, 0, &cbValue) ) { CERT_NAME_VALUE* pCNValue = (CERT_NAME_VALUE*) ::LocalAlloc(LPTR, cbValue); if ( pCNValue ) { if ( ::CryptDecodeObject( CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, pCertTypeExtension->Value.pbData, pCertTypeExtension->Value.cbData, 0, pCNValue, &cbValue) ) { LPWSTR pszCertTypeName = (LPWSTR) pCNValue->Value.pbData; CString CAName; HCERTTYPE hCertType = 0; hResult = ::CAFindCertTypeByName ( pszCertTypeName, NULL, (pStore->IsMachineStore()?CT_ENUM_MACHINE_TYPES:CT_ENUM_USER_TYPES), &hCertType); if ( SUCCEEDED (hResult) ) { WCHAR** pawszPropertyValue = 0; hResult = ::CAGetCertTypeProperty (hCertType, CERTTYPE_PROP_FRIENDLY_NAME, &pawszPropertyValue); ASSERT (SUCCEEDED (hResult)); if ( SUCCEEDED (hResult) ) { if ( pawszPropertyValue[0] ) { m_szCertTypeName = pawszPropertyValue[0]; bFound = true; m_hCertType = hCertType; } else { VERIFY (SUCCEEDED (::CAFreeCertTypeProperty (hCertType, pawszPropertyValue))); } } if ( !bFound ) { hResult = ::CACloseCertType (hCertType); ASSERT (SUCCEEDED (hResult)); } } } else { DWORD dwErr = GetLastError (); DisplaySystemError (NULL, dwErr); hResult = HRESULT_FROM_WIN32 (dwErr); } ::LocalFree (pCNValue); } else { hResult = E_OUTOFMEMORY; } } else { DWORD dwErr = GetLastError (); DisplaySystemError (NULL, dwErr); hResult = HRESULT_FROM_WIN32 (dwErr); } } // If all calls succeded but it still wasn't found, then fail anyway. if ( SUCCEEDED (hResult) && !bFound ) hResult = E_FAIL; } if ( SUCCEEDED (hResult) ) certTypeName = m_szCertTypeName; return hResult; } PCERT_EXTENSION CAutoCertRequest::GetCertTypeExtension() { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); if ( !m_pCertTypeExtension ) { m_pCertTypeExtension = ::CertFindExtension ( szOID_ENROLL_CERTTYPE_EXTENSION, GetCTLContext ()->pCtlInfo->cExtension, GetCTLContext ()->pCtlInfo->rgExtension); ASSERT (m_pCertTypeExtension); if ( !m_pCertTypeExtension ) { DisplaySystemError (NULL, GetLastError ()); } } return m_pCertTypeExtension; } PCERT_EXTENSION CAutoCertRequest::GetEnhancedKeyUsageExtension() { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); if ( !m_pEnhKeyUsageExtension ) { m_pEnhKeyUsageExtension = ::CertFindExtension ( szOID_ENHANCED_KEY_USAGE, GetCTLContext ()->pCtlInfo->cExtension, GetCTLContext ()->pCtlInfo->rgExtension); ASSERT (m_pEnhKeyUsageExtension); if ( !m_pEnhKeyUsageExtension ) { DWORD dwErr = GetLastError (); if ( dwErr ) DisplaySystemError (NULL, dwErr); } } return m_pEnhKeyUsageExtension; } HRESULT CAutoCertRequest::GetUsages(CString & usages) { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); HRESULT hResult = S_OK; if ( m_szUsages.IsEmpty () ) { hResult = E_FAIL; PCERT_EXTENSION pEnhKeyUsageExtension = GetEnhancedKeyUsageExtension (); ASSERT (pEnhKeyUsageExtension); if ( pEnhKeyUsageExtension ) { DWORD cbEnhKeyUsage = 0; if ( ::CryptDecodeObject(CRYPT_ASN_ENCODING, szOID_ENHANCED_KEY_USAGE, pEnhKeyUsageExtension->Value.pbData, pEnhKeyUsageExtension->Value.cbData, 0, NULL, &cbEnhKeyUsage) ) { PCERT_ENHKEY_USAGE pEnhKeyUsage = (PCERT_ENHKEY_USAGE) ::LocalAlloc (LPTR, cbEnhKeyUsage); if ( pEnhKeyUsage ) { if ( ::CryptDecodeObject (CRYPT_ASN_ENCODING, szOID_ENHANCED_KEY_USAGE, pEnhKeyUsageExtension->Value.pbData, pEnhKeyUsageExtension->Value.cbData, 0, pEnhKeyUsage, &cbEnhKeyUsage) ) { CString usageName; for (DWORD dwIndex = 0; dwIndex < pEnhKeyUsage->cUsageIdentifier; dwIndex++) { if ( MyGetOIDInfo (usageName, pEnhKeyUsage->rgpszUsageIdentifier[dwIndex]) ) { // add delimeter if not first iteration if ( dwIndex ) m_szUsages += _T(", "); m_szUsages += usageName; } } hResult = S_OK; } else DisplaySystemError (NULL, GetLastError()); ::LocalFree (pEnhKeyUsage); } else { hResult = E_OUTOFMEMORY; } } else DisplaySystemError (NULL, GetLastError()); } } if ( SUCCEEDED (hResult) ) usages = m_szUsages; return hResult; } // To get CAs, enumerate CAs on DS, get certs, get hash, compare with stored hash // in CTL, if match found, call GetCAInfoFromDS HRESULT CAutoCertRequest::BuildCANameList() { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); HRESULT hResult = S_OK; if ( !m_bCANamesEnumerated ) { m_bCANamesEnumerated = true; // To get CAs, enumerate CAs on DS, get certs, get hash, compare with stored hash // in CTL, if match found, call GetCAInfoFromDS CWaitCursor waitCursor; HCAINFO hCAInfo = 0; DWORD dwCACnt = 0; HCAINFO* pCAList = 0; UINT nIndex = 0; PCCERT_CONTEXT* ppCertContext = NULL; DWORD cbHash = 20; hResult = ::CAEnumFirstCA (NULL, 0, &hCAInfo); if ( SUCCEEDED (hResult) ) dwCACnt = ::CACountCAs (hCAInfo); if ( dwCACnt > 0 ) { pCAList = new HCAINFO[dwCACnt]; ppCertContext = new PCCERT_CONTEXT[dwCACnt]; if ( pCAList && ppCertContext ) { nIndex = 0; while (SUCCEEDED (hResult) && hCAInfo && nIndex < dwCACnt) { pCAList[nIndex] = hCAInfo; hResult = ::CAGetCACertificate (hCAInfo, &ppCertContext[nIndex]); ASSERT (SUCCEEDED (hResult)); nIndex++; hResult = ::CAEnumNextCA (hCAInfo, &hCAInfo); } PCCTL_CONTEXT pCTLContext = GetCTLContext (); if ( pCTLContext ) { PCTL_INFO pCTLInfo = pCTLContext->pCtlInfo; DWORD cCTLEntry = pCTLInfo->cCTLEntry; PCTL_ENTRY rgCTLEntry = pCTLInfo->rgCTLEntry; const size_t HASH_SIZE = 20; BYTE pbHash[HASH_SIZE]; for (UINT nCAHash = 0; nCAHash < cCTLEntry; nCAHash++) { for (UINT nCertContextIndex = 0; nCertContextIndex < dwCACnt; nCertContextIndex++) { cbHash = HASH_SIZE; if (::CertGetCertificateContextProperty (ppCertContext[nCertContextIndex], CERT_SHA1_HASH_PROP_ID, pbHash, &cbHash) ) { // Compare pbHash with pCAHash; // security review 2/26/2002 BryanWal ok ASSERT (pbHash); if ( !pbHash ) break; if ( !memcmp (pbHash, rgCTLEntry[nCAHash].SubjectIdentifier.pbData, rgCTLEntry[nCAHash].SubjectIdentifier.cbData) ) { LPWSTR *awszCAName = NULL; LPWSTR *awszCADisplayName = NULL; // // Add this CA to the list of // CA's. // // get the name of the CA hResult = ::CAGetCAProperty (pCAList[nCertContextIndex], CA_PROP_NAME, &awszCAName); if (SUCCEEDED (hResult) && awszCAName && awszCAName[0] ) { // get the display name of the CA hResult = ::CAGetCAProperty (pCAList[nCertContextIndex], CA_PROP_DISPLAY_NAME, &awszCADisplayName); if ( SUCCEEDED(hResult) && awszCADisplayName && awszCADisplayName[0] ) { m_CANameList.AddHead (awszCAName[0]); m_CADisplayNameList.AddHead (awszCADisplayName[0]); } } if ( awszCAName ) { CAFreeCAProperty(pCAList[nCertContextIndex], awszCAName); } if ( awszCADisplayName ) { CAFreeCAProperty(pCAList[nCertContextIndex], awszCADisplayName); } break; } } else { DWORD dwErr = GetLastError (); hResult = HRESULT_FROM_WIN32 (dwErr); DisplaySystemError (NULL, dwErr); break; } } } } for (UINT nCAListIndex = 0; nCAListIndex < dwCACnt; nCAListIndex++) { hResult = ::CACloseCA (pCAList[nCAListIndex]); ASSERT (SUCCEEDED (hResult)); ::CertFreeCertificateContext (ppCertContext[nCAListIndex]); } } else { hResult = E_OUTOFMEMORY; } if ( pCAList ) delete [] pCAList; if ( ppCertContext ) delete [] ppCertContext; } } return hResult; } CStringList& CAutoCertRequest::GetCANameList(bool fDisplayName) { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); BuildCANameList (); return fDisplayName?m_CADisplayNameList:m_CANameList; } HCERTTYPE CAutoCertRequest::GetCertType() { ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype); if ( !m_hCertType ) { CString name; GetCertTypeName (name); // generates m_hCertType } return m_hCertType; }