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.
504 lines
12 KiB
504 lines
12 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|