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.
 
 
 
 
 
 

446 lines
13 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: caddroot.cpp
//
//--------------------------------------------------------------------------
// caddroot.cpp : Implementation of Ccaddroot
#include "stdafx.h"
#include "cobjsaf.h"
#include "Xaddroot.h"
#include "caddroot.h"
#include "rootlist.h"
#include "assert.h"
#include "wincrypt.h"
#include "unicode.h"
#include "ui.h"
BOOL FAnyCertUpdates(HCERTSTORE hStore, HCERTSTORE hStoreCertsToCheck) {
BOOL fSomeNotInStore = FALSE;
PCCERT_CONTEXT pCertContext = NULL;
PCCERT_CONTEXT pCertTemp = NULL;
BYTE arHashBytes[20];
CRYPT_HASH_BLOB blobHash = {sizeof(arHashBytes), arHashBytes};
while(NULL != (pCertContext = CertEnumCertificatesInStore(hStoreCertsToCheck, pCertContext))) {
if( CryptHashCertificate(
NULL,
0,
X509_ASN_ENCODING,
pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded,
blobHash.pbData,
&blobHash.cbData) ) {
pCertTemp = CertFindCertificateInStore(
hStore,
X509_ASN_ENCODING,
0,
CERT_FIND_HASH,
&blobHash,
NULL);
fSomeNotInStore = (fSomeNotInStore || (pCertTemp == NULL));
if(pCertTemp != NULL)
CertFreeCertificateContext(pCertTemp);
}
}
return(fSomeNotInStore);
}
BOOL MyCryptInstallSignedListOfTrustedRoots(
DWORD dwMsgAndCertEncodeingType,
LPCWSTR wszCTL,
DWORD dwFlags,
void * pvReserved
) {
BOOL fIsProtected = TRUE;
BOOL fRet = TRUE;
DWORD cb = 0;
BYTE * pb = NULL;
BOOL fRemoveRoots = FALSE;
HCERTSTORE hStore = NULL;
HCERTSTORE hStoreRoot = NULL;
PCCERT_CONTEXT pCertContext = NULL;
PCCERT_CONTEXT pCertContextInStore = NULL;
PCCERT_CONTEXT pCertContextSigner = NULL;
HINSTANCE hCryptUI = NULL;
INT_PTR iDlgRet = 0;
HKEY hKeyStores = NULL;
DWORD err;
DWORD dwVer = 0;
CRYPT_DATA_BLOB dataBlob = {0, NULL};
MDI mdi;
WCHAR wrgInstallCA[MAX_MSG_LEN];
WCHAR wrgJustSayYes[MAX_MSG_LEN];
BYTE arHashBytes[20];
CRYPT_HASH_BLOB blobHash = {sizeof(arHashBytes), arHashBytes};
BOOL fAnyCertUpdates;
if(NULL == (pb = HTTPGet(wszCTL, &cb)))
goto ErrorReturn;
// get the certs to add or delete
if(!I_CertVerifySignedListOfTrustedRoots(
pb,
cb,
&fRemoveRoots,
&hStore,
&pCertContextSigner
))
goto ErrorReturn;
if(fRemoveRoots) {
SetLastError(E_NOTIMPL);
goto ErrorReturn;
}
dwVer = GetVersion();
// see if this is NT5 or higher
if((dwVer < 0x80000000) && ((dwVer & 0xFF) >= 5)) {
if(NULL == (hStoreRoot = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG,
L"Root"
)) )
goto ErrorReturn;
// else it is before NT5 or Win9x and does not have a protected store.
} else {
if(ERROR_SUCCESS != (err = RegOpenKeyA(
HKEY_CURRENT_USER,
"Software\\Microsoft\\SystemCertificates\\Root",
&hKeyStores
))) {
SetLastError(err);
hKeyStores = NULL;
goto ErrorReturn;
}
// open the root store
// must be current user
if( NULL == (hStoreRoot = CertOpenStore(
CERT_STORE_PROV_REG,
X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
(void *) hKeyStores
)) )
goto ErrorReturn;
fIsProtected = FALSE;
}
// prepare the data for the dialog
memset(&mdi, 0, sizeof(mdi));
if( NULL != (hCryptUI = LoadLibraryA("cryptui.dll")) )
mdi.pfnCryptUIDlgViewCertificateW = (PFNCryptUIDlgViewCertificateW)
GetProcAddress(hCryptUI, "CryptUIDlgViewCertificateW");
mdi.hStore = hStore;
mdi.pCertSigner = pCertContextSigner;
mdi.hInstance = _Module.GetResourceInstance();
fAnyCertUpdates = FAnyCertUpdates(hStoreRoot, hStore);
if (fAnyCertUpdates) {
// put the dialog up
iDlgRet = DialogBoxParam(
_Module.GetResourceInstance(),
(LPSTR) MAKEINTRESOURCE(IDD_MAINDLG),
NULL,
MainDialogProc,
(LPARAM) &mdi);
}
else
{
iDlgRet = IDYES;
}
if(hCryptUI != NULL)
FreeLibrary(hCryptUI);
hCryptUI = NULL;
// only take it if the user said OK
if(iDlgRet != IDYES)
goto ErrorReturn;
// throw UI if we are on a protected system
if(fIsProtected && fAnyCertUpdates) {
// put up the Just Say Yes to install the CA dialog
LoadStringU(_Module.GetResourceInstance(), IDS_INSTALLCA, wrgInstallCA, sizeof(wrgInstallCA)/sizeof(WCHAR));
LoadStringU(_Module.GetResourceInstance(), IDS_JUST_SAY_YES, wrgJustSayYes, sizeof(wrgJustSayYes)/sizeof(WCHAR));
MessageBoxU(NULL, wrgJustSayYes, wrgInstallCA, MB_OK);
}
while(NULL != (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext))) {
// add the cert to the store
assert(pCertContextInStore == NULL);
CertAddCertificateContextToStore(
hStoreRoot,
pCertContext,
CERT_STORE_ADD_USE_EXISTING,
&pCertContextInStore
);
// move the EKU property in case the cert already existed
if(pCertContextInStore != NULL) {
assert(dataBlob.cbData == 0);
// Attempt to delete the old EKU, if we succeed we will put
// the new EKU on it, otherwise if we fail we know we don't
// have access to HKLM and we should just add the cert to the HKCU
if(!CertSetCertificateContextProperty(
pCertContextInStore,
CERT_ENHKEY_USAGE_PROP_ID,
0,
NULL
)) {
// just add the cert, should go to HKCU, if it fails, what am I going
// to do about it, just continue
CertAddCertificateContextToStore(
hStoreRoot,
pCertContext,
CERT_STORE_ADD_ALWAYS,
NULL
);
// at this point I know I have access to the cert and I know the
// EKU have been removed, only add the EKU if the new one has some EKU's
} else if( CertGetCertificateContextProperty(
pCertContext,
CERT_ENHKEY_USAGE_PROP_ID,
NULL,
&dataBlob.cbData
)
&&
(NULL != (dataBlob.pbData = (PBYTE) malloc(dataBlob.cbData)))
&&
CertGetCertificateContextProperty(
pCertContext,
CERT_ENHKEY_USAGE_PROP_ID,
dataBlob.pbData,
&dataBlob.cbData
)
) {
// set EKU on the cert, what am I going to do if it fails, just continue
CertSetCertificateContextProperty(
pCertContextInStore,
CERT_ENHKEY_USAGE_PROP_ID,
0,
&dataBlob
);
}
// free context and memory
CertFreeCertificateContext(pCertContextInStore);
pCertContextInStore = NULL;
if(dataBlob.pbData != NULL)
free(dataBlob.pbData);
memset(&dataBlob, 0, sizeof(CRYPT_DATA_BLOB));
}
}
CommonReturn:
if(pCertContextSigner != NULL)
CertFreeCertificateContext(pCertContextSigner);
if(pCertContext != NULL)
CertFreeCertificateContext(pCertContext);
if(pCertContextInStore != NULL)
CertFreeCertificateContext(pCertContextInStore);
if(hStore != NULL)
CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG); // clean up from dialog box dups
if(hStoreRoot != NULL)
CertCloseStore(hStoreRoot, 0);
if(hKeyStores != NULL)
RegCloseKey(hKeyStores);
if(pb != NULL)
free(pb);
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
}
HRESULT STDMETHODCALLTYPE Ccaddroot::AddRoots(BSTR wszCTL) {
HRESULT hr;
DWORD fRet = TRUE;
fRet = MyCryptInstallSignedListOfTrustedRoots(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
wszCTL,
0,
NULL);
if(fRet)
hr = S_OK;
else
hr = MY_HRESULT_FROM_WIN32(GetLastError());
return hr;
}
BOOL MyCryptInstallIntermediateCAs(
DWORD dwMsgAndCertEncodeingType,
LPCWSTR wszX509,
DWORD dwFlags,
void * pvReserved
) {
DWORD cb = 0;
DWORD cCerts = 0;
BYTE * pb = NULL;
PCCERT_CONTEXT pCertContext = NULL;
PCCERT_CONTEXT pCertContextT = NULL;
HCERTSTORE hStore = NULL;
BOOL fOK = FALSE;
pb = HTTPGet(wszX509, &cb);
if(pb != NULL) {
pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING,
pb,
cb
);
if(pCertContext != NULL) {
hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"CA"
);
if(hStore != NULL) {
// count the number of certs in the store
cCerts = 0;
while(NULL != (pCertContextT = CertEnumCertificatesInStore(hStore, pCertContextT)))
cCerts++;
if(FIsTooManyCertsOK(cCerts, _Module.GetResourceInstance())) {
CertAddCertificateContextToStore(
hStore,
pCertContext,
CERT_STORE_ADD_USE_EXISTING,
NULL
);
CertCloseStore(hStore, 0);
fOK = TRUE;
}
}
CertFreeCertificateContext(pCertContext);
}
free(pb);
}
return(fOK);
}
HRESULT STDMETHODCALLTYPE Ccaddroot::AddCA(BSTR wszX509) {
HRESULT hr;
DWORD fRet = TRUE;
fRet = MyCryptInstallIntermediateCAs(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
wszX509,
0,
NULL);
if(fRet)
hr = S_OK;
else
hr = MY_HRESULT_FROM_WIN32(GetLastError());
return hr;
}
HRESULT __stdcall Ccaddroot::GetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
/* [out] */ DWORD __RPC_FAR *pdwEnabledOptions) {
RPC_STATUS rpcStatus;
if(0 != UuidCompare((GUID *) &riid, (GUID *) &IID_IDispatch, &rpcStatus) )
return(E_NOINTERFACE);
*pdwEnabledOptions = dwEnabledSafteyOptions;
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
return(S_OK);
}
HRESULT __stdcall Ccaddroot::SetInterfaceSafetyOptions(
/* [in] */ REFIID riid,
/* [in] */ DWORD dwOptionSetMask,
/* [in] */ DWORD dwEnabledOptions) {
RPC_STATUS rpcStatus;
DWORD dwSupport = 0;
if(0 != UuidCompare((GUID *) &riid, (GUID *) &IID_IDispatch, &rpcStatus) )
return(E_NOINTERFACE);
dwSupport = dwOptionSetMask & ~(INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA);
if(dwSupport != 0)
return(E_FAIL);
dwEnabledSafteyOptions &= ~dwOptionSetMask;
dwEnabledSafteyOptions |= dwEnabledOptions;
return(S_OK);
}