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.
331 lines
9.3 KiB
331 lines
9.3 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1996
|
|
//
|
|
// File: updroots.cpp
|
|
//
|
|
// Contents: Updates LocalMachine roots. Pre-whistler, HKLM "Root" store.
|
|
// Otherwise, HKLM "AuthRoot" store.
|
|
//
|
|
// See Usage() for list of options.
|
|
//
|
|
//
|
|
// Functions: main
|
|
//
|
|
// History: 30-Aug-00 philh created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include <windows.h>
|
|
#include "wincrypt.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
|
|
#define SHA1_HASH_LEN 20
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// crypt32.dll Whistler version numbers
|
|
//
|
|
// Doesn't need to be the official Whistler release #. Any build # after
|
|
// the "AuthRoot" store was added.
|
|
//--------------------------------------------------------------------------
|
|
#define WHISTLER_CRYPT32_DLL_VER_MS (( 5 << 16) | 131 )
|
|
#define WHISTLER_CRYPT32_DLL_VER_LS (( 2257 << 16) | 1 )
|
|
|
|
|
|
BOOL fLocalMachine = FALSE;
|
|
|
|
void PrintLastError(LPCSTR pszMsg)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
char buf[512];
|
|
|
|
sprintf(buf, "%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
|
|
MessageBoxA(
|
|
NULL, // hWnd
|
|
buf,
|
|
"UpdRoots",
|
|
MB_OK | MB_ICONERROR | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
void PrintMsg(LPCSTR pszMsg)
|
|
{
|
|
MessageBoxA(
|
|
NULL, // hWnd
|
|
pszMsg,
|
|
"UpdRoots",
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
static void Usage(void)
|
|
{
|
|
MessageBoxA(
|
|
NULL, // hWnd
|
|
"Usage: UpdRoots [options] <SrcStoreFilename>\n"
|
|
"Options are:\n"
|
|
"-h -\tThis message\n"
|
|
"-d -\tDelete (default is to add)\n"
|
|
"-l -\tLocal Machine (default is Third Party)\n"
|
|
"\n",
|
|
"UpdRoots",
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
|
|
PCCERT_CONTEXT FindCertificateInOtherStore(
|
|
IN HCERTSTORE hOtherStore,
|
|
IN PCCERT_CONTEXT pCert
|
|
)
|
|
{
|
|
BYTE rgbHash[SHA1_HASH_LEN];
|
|
CRYPT_DATA_BLOB HashBlob;
|
|
|
|
HashBlob.pbData = rgbHash;
|
|
HashBlob.cbData = SHA1_HASH_LEN;
|
|
if (!CertGetCertificateContextProperty(
|
|
pCert,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
rgbHash,
|
|
&HashBlob.cbData
|
|
) || SHA1_HASH_LEN != HashBlob.cbData)
|
|
return NULL;
|
|
|
|
return CertFindCertificateInStore(
|
|
hOtherStore,
|
|
0, // dwCertEncodingType
|
|
0, // dwFindFlags
|
|
CERT_FIND_SHA1_HASH,
|
|
(const void *) &HashBlob,
|
|
NULL //pPrevCertContext
|
|
);
|
|
}
|
|
|
|
BOOL DeleteCertificateFromOtherStore(
|
|
IN HCERTSTORE hOtherStore,
|
|
IN PCCERT_CONTEXT pCert
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
PCCERT_CONTEXT pOtherCert;
|
|
|
|
if (pOtherCert = FindCertificateInOtherStore(hOtherStore, pCert))
|
|
fResult = CertDeleteCertificateFromStore(pOtherCert);
|
|
else
|
|
fResult = TRUE;
|
|
return fResult;
|
|
}
|
|
|
|
typedef BOOL (WINAPI *PFN_CRYPT_GET_FILE_VERSION)(
|
|
IN LPCWSTR pwszFilename,
|
|
OUT DWORD *pdwFileVersionMS, /* e.g. 0x00030075 = "3.75" */
|
|
OUT DWORD *pdwFileVersionLS /* e.g. 0x00000031 = "0.31" */
|
|
);
|
|
|
|
#define NO_LOGICAL_STORE_VERSION 0
|
|
#define LOGICAL_STORE_VERSION 1
|
|
#define AUTH_STORE_VERSION 2
|
|
|
|
// Note, I_CryptGetFileVersion and logical stores, not supported in all
|
|
// versions of crypt32.dll
|
|
//
|
|
// Returns one of the above defined version constants
|
|
DWORD GetCrypt32Version()
|
|
{
|
|
DWORD dwVersion;
|
|
DWORD dwFileVersionMS;
|
|
DWORD dwFileVersionLS;
|
|
HMODULE hModule;
|
|
PFN_CRYPT_GET_FILE_VERSION pfnCryptGetFileVersion;
|
|
|
|
hModule = GetModuleHandleA("crypt32.dll");
|
|
if (NULL == hModule)
|
|
return NO_LOGICAL_STORE_VERSION;
|
|
|
|
if (NULL == GetProcAddress(hModule, "CertEnumPhysicalStore"))
|
|
return NO_LOGICAL_STORE_VERSION;
|
|
|
|
if (fLocalMachine)
|
|
return LOGICAL_STORE_VERSION;
|
|
|
|
pfnCryptGetFileVersion = (PFN_CRYPT_GET_FILE_VERSION) GetProcAddress(
|
|
hModule, "I_CryptGetFileVersion");
|
|
if (NULL == pfnCryptGetFileVersion)
|
|
return LOGICAL_STORE_VERSION;
|
|
|
|
dwVersion = LOGICAL_STORE_VERSION;
|
|
if (pfnCryptGetFileVersion(
|
|
L"crypt32.dll",
|
|
&dwFileVersionMS,
|
|
&dwFileVersionLS)) {
|
|
if (WHISTLER_CRYPT32_DLL_VER_MS < dwFileVersionMS)
|
|
dwVersion = AUTH_STORE_VERSION;
|
|
else if (WHISTLER_CRYPT32_DLL_VER_MS == dwFileVersionMS &&
|
|
WHISTLER_CRYPT32_DLL_VER_LS <= dwFileVersionLS)
|
|
dwVersion = AUTH_STORE_VERSION;
|
|
}
|
|
|
|
return dwVersion;
|
|
}
|
|
|
|
int _cdecl main(int argc, char * argv[])
|
|
{
|
|
BOOL fResult;
|
|
int ReturnStatus = 0;
|
|
LPSTR pszSrcStoreFilename = NULL; // not allocated
|
|
HANDLE hSrcStore = NULL;
|
|
HANDLE hRootStore = NULL;
|
|
|
|
BOOL fDelete = FALSE;
|
|
DWORD dwVersion;
|
|
PCCERT_CONTEXT pSrcCert;
|
|
|
|
while (--argc>0)
|
|
{
|
|
if (**++argv == '-')
|
|
{
|
|
switch(argv[0][1])
|
|
{
|
|
case 'd':
|
|
fDelete = TRUE;
|
|
break;
|
|
case 'l':
|
|
fLocalMachine = TRUE;
|
|
break;
|
|
case 'h':
|
|
default:
|
|
goto BadUsage;
|
|
|
|
}
|
|
} else {
|
|
if (pszSrcStoreFilename == NULL)
|
|
pszSrcStoreFilename = argv[0];
|
|
else {
|
|
PrintMsg("too many store filenames\n");
|
|
goto BadUsage;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL == pszSrcStoreFilename) {
|
|
PrintMsg("missing store filename\n");
|
|
goto BadUsage;
|
|
}
|
|
|
|
// Attempt to open the source store
|
|
hSrcStore = CertOpenStore(
|
|
CERT_STORE_PROV_FILENAME_A,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, // hCryptProv
|
|
CERT_STORE_READONLY_FLAG,
|
|
(const void *) pszSrcStoreFilename
|
|
);
|
|
if (NULL == hSrcStore) {
|
|
PrintLastError("Open SrcStore");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Attempt to open the destination root store. For Whistler and beyond its
|
|
// the HKLM "AuthRoot" store. Pre-Whistler its the HKLM "Root" store.
|
|
// Also, earlier versions of crypt32 didn't support logical stores.
|
|
// For -l option, force it to be the HKLM "Root" store.
|
|
|
|
dwVersion = GetCrypt32Version();
|
|
|
|
if (NO_LOGICAL_STORE_VERSION == dwVersion) {
|
|
// Need to open the registry to bypass the add root message boxes
|
|
HKEY hKey = NULL;
|
|
LONG lErr;
|
|
|
|
if (ERROR_SUCCESS != (lErr = RegOpenKeyExA(
|
|
HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\SystemCertificates\\Root",
|
|
0, // dwReserved
|
|
KEY_ALL_ACCESS,
|
|
&hKey))) {
|
|
SetLastError(lErr);
|
|
PrintLastError("RegOpenKeyExA(root)\n");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
hRootStore = CertOpenStore(
|
|
CERT_STORE_PROV_REG,
|
|
0, // dwEncodingType
|
|
0, // hCryptProv
|
|
0, // dwFlags
|
|
(const void *) hKey
|
|
);
|
|
|
|
RegCloseKey(hKey);
|
|
} else {
|
|
LPCSTR pszRootStoreName;
|
|
|
|
if (AUTH_STORE_VERSION == dwVersion)
|
|
pszRootStoreName = "AuthRoot";
|
|
else
|
|
pszRootStoreName = "Root";
|
|
|
|
hRootStore = CertOpenStore(
|
|
CERT_STORE_PROV_SYSTEM_REGISTRY_A,
|
|
0, // dwEncodingType
|
|
0, // hCryptProv
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
(const void *) pszRootStoreName
|
|
);
|
|
}
|
|
|
|
if (NULL == hRootStore) {
|
|
PrintLastError("Open RootStore");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Iterate through all the certificates in the source store. Add or delete
|
|
// from the root store.
|
|
fResult = TRUE;
|
|
pSrcCert = NULL;
|
|
while (pSrcCert = CertEnumCertificatesInStore(hSrcStore, pSrcCert)) {
|
|
if (fDelete) {
|
|
if (!DeleteCertificateFromOtherStore(hRootStore, pSrcCert)) {
|
|
fResult = FALSE;
|
|
PrintLastError("DeleteCert");
|
|
}
|
|
} else {
|
|
// Note, earlier versions of crypt32.dll didn't support
|
|
// CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
|
|
if (!CertAddCertificateContextToStore(
|
|
hRootStore,
|
|
pSrcCert,
|
|
CERT_STORE_ADD_REPLACE_EXISTING,
|
|
NULL)) {
|
|
fResult = FALSE;
|
|
PrintLastError("AddCert");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fResult)
|
|
goto ErrorReturn;
|
|
|
|
ReturnStatus = 0;
|
|
CommonReturn:
|
|
if (hSrcStore)
|
|
CertCloseStore(hSrcStore, 0);
|
|
if (hRootStore)
|
|
CertCloseStore(hRootStore, 0);
|
|
return ReturnStatus;
|
|
|
|
BadUsage:
|
|
Usage();
|
|
ErrorReturn:
|
|
ReturnStatus = -1;
|
|
goto CommonReturn;
|
|
}
|