|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows NT
//
// Copyright (C) Microsoft Corporation, 1995 - 1998
//
// File: cepca.cpp
//
// Contents: Cisco enrollment protocal implementation.
// This file has CA specific code.
//
//
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include <dbgdef.h>
//--------------------------------------------------------------------------
//
// InitCAInformation
//
//--------------------------------------------------------------------------
BOOL InitCAInformation(CEP_CA_INFO *pCAInfo) { BOOL fResult = FALSE; long nCount=0; long nIndex=0; WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwSize=MAX_COMPUTERNAME_LENGTH + 1; HRESULT hr = E_FAIL; DWORD cbData=0; DWORD dwData=0; DWORD dwType=0; long dwErr=0;
ICertConfig *pICertConfig=NULL; BSTR bstrFieldName=NULL; BSTR bstrFieldValue=NULL; HKEY hKeyCAType=NULL; HKEY hKeyCEP=NULL;
memset(pCAInfo, 0, sizeof(CEP_CA_INFO));
//we should only worry about the NetBois name. Do not care about the DNS
//GetComputerNameW in Win2K only returns NetBois name
if(!GetComputerNameW(wszComputerName, &dwSize)) goto TraceErr;
if(S_OK != (hr=CoCreateInstance(CLSID_CCertConfig, NULL, CLSCTX_INPROC_SERVER, IID_ICertConfig, (void **)&pICertConfig))) goto CertSrvErr;
if(S_OK != (hr=pICertConfig->Reset(nIndex, &nCount))) goto CertSrvErr;
if(0==nCount) goto NoSrvErr;
if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_SERVER))) goto MemoryErr;
while(nIndex != -1) { //find the configuration that matches the current machine's name
if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &bstrFieldValue))) goto CertSrvErr;
if(0==_wcsnicmp(bstrFieldValue, wszComputerName, wcslen(wszComputerName))) { if(NULL == ((pCAInfo->bstrCAMachine)=SysAllocString(bstrFieldValue))) goto MemoryErr;
//CA name
SysFreeString(bstrFieldName); bstrFieldName=NULL;
if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_AUTHORITY))) goto MemoryErr;
if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrCAName)))) goto CertSrvErr;
if(NULL == pCAInfo->bstrCAName) goto FailErr;
//CA config
SysFreeString(bstrFieldName); bstrFieldName=NULL;
if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_CONFIG))) goto MemoryErr;
if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrCAConfig)))) goto CertSrvErr;
if(NULL == pCAInfo->bstrCAConfig) goto FailErr;
//DSName
SysFreeString(bstrFieldName); bstrFieldName=NULL;
if(NULL == (bstrFieldName=SysAllocString(wszCONFIG_SANITIZEDSHORTNAME))) goto MemoryErr;
if(S_OK != (hr=pICertConfig->GetField(bstrFieldName, &(pCAInfo->bstrDSName)))) goto CertSrvErr;
if(NULL == pCAInfo->bstrDSName) goto FailErr;
//ICertRequest
if(S_OK != (hr=CoCreateInstance(CLSID_CCertRequest, NULL, CLSCTX_INPROC_SERVER, IID_ICertRequest, (void **)&(pCAInfo->pICertRequest)))) goto CertSrvErr;
//success
break; }
SysFreeString(bstrFieldValue); bstrFieldValue=NULL;
hr = pICertConfig->Next(&nIndex);
if( (S_OK != hr) && (-1 != nIndex)) goto CertSrvErr; }
if(-1 == nIndex) goto NoSrvErr;
//get the CA's type from the registry
cbData=sizeof(dwData); //we have to have the knowledge of the ca type
if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_CATYPE_LOCATION, 0, KEY_READ, &hKeyCAType))) goto RegErr;
if(ERROR_SUCCESS != (dwErr = RegQueryValueExU( hKeyCAType, MSCEP_KEY_CATYPE, NULL, &dwType, (BYTE *)&dwData, &cbData))) goto RegErr;
if ((dwType != REG_DWORD) && (dwType != REG_BINARY)) goto RegErr;
if(0 == dwData) pCAInfo->fEnterpriseCA=FALSE; else pCAInfo->fEnterpriseCA=TRUE;
if(pCAInfo->fEnterpriseCA) { //get the template name for key usage requests
if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_LOCATION, 0, KEY_READ, &hKeyCEP))) goto RegErr;
//signature template
cbData=0; if(ERROR_SUCCESS == (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_SIG_TEMPLATE, NULL, &dwType, NULL, &cbData))) { if((REG_SZ == dwType) && (1 < cbData)) { pCAInfo->pwszTemplateSig=(LPWSTR)malloc(cbData); if(NULL == pCAInfo->pwszTemplateSig) goto MemoryErr;
if(ERROR_SUCCESS != (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_SIG_TEMPLATE, NULL, &dwType, (BYTE *)(pCAInfo->pwszTemplateSig), &cbData))) goto RegErr;
} }
//encryption template
cbData=0; if(ERROR_SUCCESS == (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_ENCYPT_TEMPLATE, NULL, &dwType, NULL, &cbData))) { if((REG_SZ == dwType) && (1 < cbData)) { pCAInfo->pwszTemplateEnt=(LPWSTR)malloc(cbData); if(NULL == pCAInfo->pwszTemplateEnt) goto MemoryErr;
if(ERROR_SUCCESS != (dwErr = RegQueryValueExW(hKeyCEP, MSCEP_KEY_ENCYPT_TEMPLATE, NULL, &dwType, (BYTE *)(pCAInfo->pwszTemplateEnt), &cbData))) goto RegErr;
}
}
//make sure both templates are present in the DS
//make sure the CA does issue the template
if(pCAInfo->pwszTemplateSig) { if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, pCAInfo->pwszTemplateSig))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, pCAInfo->pwszTemplateSig, pCAInfo->bstrDSName); goto CertSrvErr; } }
if(pCAInfo->pwszTemplateEnt) { if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, pCAInfo->pwszTemplateEnt))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, pCAInfo->pwszTemplateEnt, pCAInfo->bstrDSName); goto CertSrvErr; } }
if(S_OK != (hr=CheckACLOnCertTemplate(FALSE, pCAInfo->bstrDSName, wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE))) { LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_NO_ENROLL, 3, g_pwszComputerName, wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE, pCAInfo->bstrDSName); goto CertSrvErr; } }
//get the hProv to generate the random password
if(!CryptAcquireContextU(&(pCAInfo->hProv), NULL, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) goto TraceErr;
fResult = TRUE;
CommonReturn:
if(hKeyCEP) RegCloseKey(hKeyCEP);
if(hKeyCAType) RegCloseKey(hKeyCAType);
if(bstrFieldName) SysFreeString(bstrFieldName);
if(bstrFieldValue) SysFreeString(bstrFieldValue);
if(pICertConfig) pICertConfig->Release();
return fResult;
ErrorReturn:
FreeCAInformation(pCAInfo);
fResult=FALSE; goto CommonReturn;
SET_ERROR_VAR(CertSrvErr, hr); SET_ERROR(NoSrvErr, E_FAIL); TRACE_ERROR(TraceErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); SET_ERROR(FailErr, E_FAIL); SET_ERROR_VAR(RegErr, dwErr); }
//--------------------------------------------------------------------------
//
// GetCACertFromInfo
//
//--------------------------------------------------------------------------
BOOL GetCACertFromInfo(CEP_CA_INFO *pCAInfo, HCERTSTORE *pHCACertStore) { BOOL fResult = FALSE; HRESULT hr = S_OK; CERT_BLOB CertBlob; DWORD dwFlags=0; PCCERT_CONTEXT pPreCert=NULL; DWORD cbData=0; BSTR bstrCACert=NULL; PCCERT_CONTEXT pCurCert=NULL; BYTE *pbData=NULL;
if(NULL == (pCAInfo->pICertRequest)) goto InvalidArgErr;
//NT5 SPECIFIC: fExchangeCertificate can only be FALSE
if(S_OK != (hr=(pCAInfo->pICertRequest)->GetCACertificate( FALSE, pCAInfo->bstrCAConfig, CR_OUT_BINARY | CR_OUT_CHAIN, &bstrCACert))) goto CAErr;
if(NULL == bstrCACert) goto UnexpectedErr;
CertBlob.cbData = (DWORD)SysStringByteLen(bstrCACert); CertBlob.pbData = (BYTE *)bstrCACert;
if(NULL == (*pHCACertStore = CertOpenStore( CERT_STORE_PROV_PKCS7, ENCODE_TYPE, NULL, 0, &CertBlob))) goto TraceErr;
//we now need to get the CA's certificate's MD5 hash
while(pCurCert=CertEnumCertificatesInStore(*pHCACertStore, pPreCert)) { dwFlags = CERT_STORE_SIGNATURE_FLAG; if(CertVerifySubjectCertificateContext(pCurCert, pCurCert, &dwFlags) && (0==dwFlags))
break;
pPreCert=pCurCert; }
if(NULL==pCurCert) goto InvalidArgErr;
//get the MD5 hash
if(!CertGetCertificateContextProperty(pCurCert, CERT_MD5_HASH_PROP_ID, NULL, &cbData)) goto TraceErr;
pbData=(BYTE *)malloc(cbData);
if(NULL==pbData) goto MemoryErr;
if(!CertGetCertificateContextProperty(pCurCert, CERT_MD5_HASH_PROP_ID, pbData, &cbData)) goto TraceErr;
if(!ConvertByteToWstr(pbData, cbData, &(pCAInfo->pwszCAHash), TRUE)) goto TraceErr;
fResult = TRUE;
CommonReturn:
if(pbData) free(pbData);
if(pCurCert) CertFreeCertificateContext(pCurCert);
if(bstrCACert) SysFreeString(bstrCACert);
return fResult;
ErrorReturn:
fResult=FALSE; goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR_VAR(CAErr, hr); TRACE_ERROR(TraceErr); SET_ERROR(UnexpectedErr, E_UNEXPECTED); SET_ERROR(MemoryErr, E_OUTOFMEMORY); }
//--------------------------------------------------------------------------
//
// FreeCAInformation
//
//--------------------------------------------------------------------------
BOOL FreeCAInformation(CEP_CA_INFO *pCAInfo) { if(pCAInfo) { if(pCAInfo->bstrCAMachine) SysFreeString(pCAInfo->bstrCAMachine);
if(pCAInfo->bstrCAName) SysFreeString(pCAInfo->bstrCAName);
if(pCAInfo->bstrCAConfig) SysFreeString(pCAInfo->bstrCAConfig);
if(pCAInfo->bstrDSName) SysFreeString(pCAInfo->bstrDSName);
if(pCAInfo->pwszCAHash) free(pCAInfo->pwszCAHash);
if(pCAInfo->hProv) CryptReleaseContext(pCAInfo->hProv, 0);
if(pCAInfo->pICertRequest) (pCAInfo->pICertRequest)->Release();
if(pCAInfo->pwszTemplateSig) free(pCAInfo->pwszTemplateSig);
if(pCAInfo->pwszTemplateEnt) free(pCAInfo->pwszTemplateEnt);
//reset the data
memset(pCAInfo, 0, sizeof(CEP_CA_INFO)); }
return TRUE; }
//--------------------------------------------------------------------------
//
// OperationGetCACert
//
//--------------------------------------------------------------------------
BOOL OperationGetCACert(HCERTSTORE hCACertStore, LPSTR szMsg, BYTE **ppbData, DWORD *pcbData) { BOOL fResult = FALSE; CERT_BLOB CertBlob;
CertBlob.cbData=0; CertBlob.pbData=NULL;
if(!CertSaveStore(hCACertStore, ENCODE_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &CertBlob, 0)) goto CertErr;
CertBlob.pbData = (BYTE *)malloc(CertBlob.cbData);
if(NULL == CertBlob.pbData) goto MemoryErr;
if(!CertSaveStore(hCACertStore, ENCODE_TYPE, CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_MEMORY, &CertBlob, 0)) goto CertErr;
//copy the memory
*ppbData=CertBlob.pbData; *pcbData=CertBlob.cbData; CertBlob.pbData=NULL;
fResult = TRUE;
CommonReturn:
if(CertBlob.pbData) free(CertBlob.pbData);
return fResult;
ErrorReturn:
fResult=FALSE; goto CommonReturn;
TRACE_ERROR(CertErr); SET_ERROR(MemoryErr, E_OUTOFMEMORY); }
|