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.
555 lines
14 KiB
555 lines
14 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1996
|
|
//
|
|
// File: updcrl.cpp
|
|
//
|
|
// Contents: Updates CRL in the "CA" store.
|
|
//
|
|
// See Usage() for list of options.
|
|
//
|
|
//
|
|
// Functions: main
|
|
//
|
|
// History: 30-Aug-00 philh created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include <windows.h>
|
|
#include "wincrypt.h"
|
|
#include "wintrust.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
|
|
|
|
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,
|
|
"UpdCrl",
|
|
MB_OK | MB_ICONERROR | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
void PrintMsg(LPCSTR pszMsg)
|
|
{
|
|
MessageBoxA(
|
|
NULL, // hWnd
|
|
pszMsg,
|
|
"UpdCrl",
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
static void Usage(void)
|
|
{
|
|
MessageBoxA(
|
|
NULL, // hWnd
|
|
"Usage: UpdCrl [options] <SrcCrlFilename>\n"
|
|
"Options are:\n"
|
|
"-h -\tThis message\n"
|
|
"-r -\tRegister NoCDPCRLRevocationChecking\n"
|
|
"-e -\tEnable revocation checking\n"
|
|
"-d -\tDisable revocation checking\n"
|
|
"-u -\tUser\n"
|
|
"\n",
|
|
"UpdCrl",
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsLogicalStoreSupported()
|
|
{
|
|
HMODULE hModule;
|
|
|
|
hModule = GetModuleHandleA("crypt32.dll");
|
|
if (NULL == hModule)
|
|
return FALSE;
|
|
|
|
if (NULL == GetProcAddress(hModule, "CertEnumPhysicalStore"))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
UpdateRevocation(
|
|
IN BOOL fEnable
|
|
)
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD dwState;
|
|
DWORD cbData;
|
|
DWORD dwType;
|
|
DWORD dwDisposition;
|
|
|
|
// Open the registry and get to the "State" REG_DWORD value
|
|
if (ERROR_SUCCESS != RegCreateKeyExA(
|
|
HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\WinTrust\\Trust Providers\\Software Publishing",
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition
|
|
))
|
|
return;
|
|
|
|
dwState = 0;
|
|
cbData = sizeof(dwState);
|
|
if (ERROR_SUCCESS != RegQueryValueExA(
|
|
hKey,
|
|
"State",
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *) &dwState,
|
|
&cbData
|
|
) || sizeof(dwState) != cbData || REG_DWORD != dwType)
|
|
dwState = WTPF_IGNOREREVOCATIONONTS;
|
|
|
|
if (fEnable) {
|
|
dwState &= ~WTPF_IGNOREREVOKATION;
|
|
dwState |=
|
|
WTPF_OFFLINEOK_IND |
|
|
WTPF_OFFLINEOK_COM |
|
|
WTPF_OFFLINEOKNBU_IND |
|
|
WTPF_OFFLINEOKNBU_COM
|
|
;
|
|
} else
|
|
dwState |= WTPF_IGNOREREVOKATION;
|
|
|
|
|
|
RegSetValueExA(
|
|
hKey,
|
|
"State",
|
|
0, // dwReserved
|
|
REG_DWORD,
|
|
(BYTE *) &dwState,
|
|
sizeof(dwState)
|
|
);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
|
|
PCCRL_CONTEXT
|
|
OpenCrlFile(
|
|
IN LPSTR pszCrlFilename
|
|
)
|
|
{
|
|
PCCRL_CONTEXT pCrl = NULL;
|
|
HANDLE hFile = NULL;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
DWORD cbRead;
|
|
DWORD dwErr = 0;
|
|
|
|
if (INVALID_HANDLE_VALUE == (hFile = CreateFile(
|
|
pszCrlFilename,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL)))
|
|
return NULL;
|
|
|
|
cbEncoded = GetFileSize(hFile, NULL);
|
|
if (0 == cbEncoded)
|
|
goto EmptyFileError;
|
|
|
|
if (NULL == (pbEncoded = (BYTE *) LocalAlloc(LPTR, cbEncoded)))
|
|
goto OutOfMemory;
|
|
|
|
if (!ReadFile(hFile, pbEncoded, cbEncoded, &cbRead, NULL) ||
|
|
(cbRead != cbEncoded))
|
|
goto ReadFileError;
|
|
|
|
pCrl = CertCreateCRLContext(
|
|
X509_ASN_ENCODING,
|
|
pbEncoded,
|
|
cbEncoded
|
|
);
|
|
|
|
CommonReturn:
|
|
dwErr = GetLastError();
|
|
if (hFile)
|
|
CloseHandle(hFile);
|
|
if (pbEncoded)
|
|
LocalFree(pbEncoded);
|
|
|
|
SetLastError(dwErr);
|
|
return pCrl;
|
|
|
|
ErrorReturn:
|
|
goto CommonReturn;
|
|
|
|
EmptyFileError:
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
goto ErrorReturn;
|
|
|
|
OutOfMemory:
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto ErrorReturn;
|
|
|
|
ReadFileError:
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
#if 0
|
|
// In W2K, the NOCDP CRL needs to be time valid.
|
|
BOOL
|
|
IsNoCDPCRLSupported()
|
|
{
|
|
HMODULE hModule;
|
|
|
|
hModule = GetModuleHandleA("crypt32.dll");
|
|
if (NULL == hModule)
|
|
return FALSE;
|
|
|
|
// "CryptVerifyCertificateSignatureEx" added in W2K, WinME and CMS
|
|
if (NULL == GetProcAddress(hModule, "CertIsValidCRLForCertificate"))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
FIsWinNT5()
|
|
{
|
|
BOOL fIsWinNT5 = FALSE;
|
|
OSVERSIONINFO osVer;
|
|
|
|
memset(&osVer, 0, sizeof(OSVERSIONINFO));
|
|
osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
if (GetVersionEx(&osVer)) {
|
|
BOOL fIsWinNT;
|
|
|
|
fIsWinNT = (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
if (!fIsWinNT) {
|
|
return FALSE;
|
|
}
|
|
|
|
fIsWinNT5 = ( osVer.dwMajorVersion >= 5 );
|
|
}
|
|
|
|
return fIsWinNT5;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Get file version of the specified file
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
I_GetFileVersion(
|
|
IN LPCSTR pszFilename,
|
|
OUT DWORD *pdwFileVersionMS, /* e.g. 0x00030075 = "3.75" */
|
|
OUT DWORD *pdwFileVersionLS /* e.g. 0x00000031 = "0.31" */
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD dwHandle = 0;
|
|
DWORD cbInfo;
|
|
void *pvInfo = NULL;
|
|
VS_FIXEDFILEINFO *pFixedFileInfo = NULL; // not allocated
|
|
UINT ccFixedFileInfo = 0;
|
|
|
|
if (0 == (cbInfo = GetFileVersionInfoSizeA((LPSTR) pszFilename, &dwHandle)))
|
|
goto GetFileVersionInfoSizeError;
|
|
|
|
if (NULL == (pvInfo = LocalAlloc(LPTR, cbInfo)))
|
|
goto OutOfMemory;
|
|
|
|
if (!GetFileVersionInfoA(
|
|
(LPSTR) pszFilename,
|
|
0, // dwHandle, ignored
|
|
cbInfo,
|
|
pvInfo
|
|
))
|
|
goto GetFileVersionInfoError;
|
|
|
|
if (!VerQueryValueA(
|
|
pvInfo,
|
|
"\\", // VS_FIXEDFILEINFO
|
|
(void **) &pFixedFileInfo,
|
|
&ccFixedFileInfo
|
|
))
|
|
goto VerQueryValueError;
|
|
|
|
*pdwFileVersionMS = pFixedFileInfo->dwFileVersionMS;
|
|
*pdwFileVersionLS = pFixedFileInfo->dwFileVersionLS;
|
|
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
if (pvInfo)
|
|
LocalFree(pvInfo);
|
|
return fResult;
|
|
|
|
OutOfMemory:
|
|
GetFileVersionInfoSizeError:
|
|
GetFileVersionInfoError:
|
|
VerQueryValueError:
|
|
*pdwFileVersionMS = 0;
|
|
*pdwFileVersionLS = 0;
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
void
|
|
RegisterNoCDPCRLRevocationChecking()
|
|
{
|
|
CHAR szSystemDir[MAX_PATH + 32];
|
|
UINT cch;
|
|
|
|
// Just in case, unregister vsrevoke.dll
|
|
CryptUnregisterDefaultOIDFunction(
|
|
X509_ASN_ENCODING,
|
|
CRYPT_OID_VERIFY_REVOCATION_FUNC,
|
|
L"vsrevoke.dll"
|
|
);
|
|
|
|
// For W2K and beyond, won't be installing mscrlrev.dll
|
|
if (FIsWinNT5()) {
|
|
// For upgrades, unregister legacy versions
|
|
|
|
CryptUnregisterDefaultOIDFunction(
|
|
X509_ASN_ENCODING,
|
|
CRYPT_OID_VERIFY_REVOCATION_FUNC,
|
|
L"mscrlrev.dll"
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
// Need to copy mscrlrev.dll to system32
|
|
cch = GetSystemDirectory(szSystemDir, MAX_PATH - 1);
|
|
if (0 == cch || MAX_PATH <= cch) {
|
|
PrintLastError("GetSystemDirectory");
|
|
return;
|
|
}
|
|
|
|
strcpy(&szSystemDir[cch], "\\mscrlrev.dll");
|
|
|
|
// On the first copy, only succeed if the file doesn't already exist
|
|
if (!CopyFileA("mscrlrev.dll", szSystemDir, TRUE)) {
|
|
DWORD dwOldFileVersionMS = 0;
|
|
DWORD dwOldFileVersionLS = 0;
|
|
DWORD dwNewFileVersionMS = 0;
|
|
DWORD dwNewFileVersionLS = 0;
|
|
|
|
// Determine if we have a newer mscrlrev.dll to be installed
|
|
I_GetFileVersion(szSystemDir,
|
|
&dwOldFileVersionMS, &dwOldFileVersionLS);
|
|
I_GetFileVersion("mscrlrev.dll",
|
|
&dwNewFileVersionMS, &dwNewFileVersionLS);
|
|
|
|
if (dwNewFileVersionMS > dwOldFileVersionMS
|
|
||
|
|
(dwNewFileVersionMS == dwOldFileVersionMS &&
|
|
dwNewFileVersionLS > dwOldFileVersionLS)) {
|
|
// We have a newer version
|
|
|
|
SetFileAttributesA(szSystemDir, FILE_ATTRIBUTE_NORMAL);
|
|
// Copy over the existing file
|
|
if (!CopyFileA("mscrlrev.dll", szSystemDir, FALSE)) {
|
|
DWORD dwLastErr;
|
|
|
|
dwLastErr = GetLastError();
|
|
if (ERROR_ACCESS_DENIED != dwLastErr)
|
|
PrintLastError("CopyFile(mscrlrev.dll)");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Need to register mscrlrev.dll
|
|
if (!CryptRegisterDefaultOIDFunction(
|
|
X509_ASN_ENCODING,
|
|
CRYPT_OID_VERIFY_REVOCATION_FUNC,
|
|
CRYPT_REGISTER_FIRST_INDEX,
|
|
L"mscrlrev.dll"
|
|
)) {
|
|
if (ERROR_FILE_EXISTS != GetLastError())
|
|
PrintLastError("Register mscrlrev.dll");
|
|
}
|
|
}
|
|
|
|
#define MAX_CRL_FILE_CNT 32
|
|
|
|
int _cdecl main(int argc, char * argv[])
|
|
{
|
|
BOOL fResult;
|
|
int ReturnStatus = 0;
|
|
LPSTR rgpszCrlFilename[MAX_CRL_FILE_CNT]; // not allocated
|
|
DWORD cCrlFilename = 0;
|
|
HCERTSTORE hCAStore = NULL;
|
|
BOOL fUser = FALSE;
|
|
BOOL fLogicalStoreSupported = FALSE;
|
|
DWORD i;
|
|
|
|
while (--argc>0)
|
|
{
|
|
if (**++argv == '-')
|
|
{
|
|
switch(argv[0][1])
|
|
{
|
|
case 'e':
|
|
UpdateRevocation(TRUE);
|
|
break;
|
|
case 'd':
|
|
UpdateRevocation(FALSE);
|
|
break;
|
|
case 'r':
|
|
RegisterNoCDPCRLRevocationChecking();
|
|
break;
|
|
case 'u':
|
|
fUser = TRUE;
|
|
break;
|
|
case 'h':
|
|
default:
|
|
goto BadUsage;
|
|
|
|
}
|
|
} else {
|
|
if (MAX_CRL_FILE_CNT > cCrlFilename)
|
|
rgpszCrlFilename[cCrlFilename++] = argv[0];
|
|
else {
|
|
PrintMsg("Too many Crl filenames\n");
|
|
goto BadUsage;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 == cCrlFilename)
|
|
goto SuccessReturn;
|
|
|
|
fLogicalStoreSupported = IsLogicalStoreSupported();
|
|
if (fUser && fLogicalStoreSupported)
|
|
// Already installed in HKLM
|
|
goto SuccessReturn;
|
|
|
|
// Attempt to open the destination CA store.
|
|
// For earlier versions not supporting logical stores, its the
|
|
// HKCU "CA" store. Otherwise, its the HKLM "CA" store.
|
|
hCAStore = CertOpenStore(
|
|
CERT_STORE_PROV_SYSTEM_A,
|
|
0, // dwEncodingType
|
|
0, // hCryptProv
|
|
fLogicalStoreSupported ?
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER,
|
|
(const void *) "CA"
|
|
);
|
|
if (NULL == hCAStore) {
|
|
PrintLastError("Open CAStore");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
for (i = 0; i < cCrlFilename; i++) {
|
|
PCCRL_CONTEXT pCrl;
|
|
|
|
// Attempt to open the Crl file
|
|
pCrl = OpenCrlFile(rgpszCrlFilename[i]);
|
|
if (NULL == pCrl) {
|
|
PrintLastError("Open CrlFile");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fResult = CertAddCRLContextToStore(
|
|
hCAStore,
|
|
pCrl,
|
|
CERT_STORE_ADD_NEWER,
|
|
NULL
|
|
);
|
|
if (!fResult && CRYPT_E_EXISTS != GetLastError()) {
|
|
// Note, earlier versions of crypt32.dll didn't support
|
|
// CERT_STORE_ADD_NEWER
|
|
|
|
// Will need to see if the CRL already exists in the store
|
|
// and do our comparison.
|
|
|
|
PCCRL_CONTEXT pExistingCrl = NULL;
|
|
DWORD dwGetFlags = 0;
|
|
|
|
while (pExistingCrl = CertGetCRLFromStore(
|
|
hCAStore,
|
|
NULL, // pIssuerContext
|
|
pExistingCrl,
|
|
&dwGetFlags
|
|
)) {
|
|
dwGetFlags = 0;
|
|
|
|
// See if it has the same issuer name
|
|
if (pExistingCrl->dwCertEncodingType !=
|
|
pCrl->dwCertEncodingType
|
|
||
|
|
!CertCompareCertificateName(
|
|
pCrl->dwCertEncodingType,
|
|
&pCrl->pCrlInfo->Issuer,
|
|
&pExistingCrl->pCrlInfo->Issuer
|
|
))
|
|
continue;
|
|
|
|
// See if the existing is newer
|
|
// CompareFileTime returns 0 if the same and
|
|
// +1 if first time > second time
|
|
if (0 <= CompareFileTime(
|
|
&pExistingCrl->pCrlInfo->ThisUpdate,
|
|
&pCrl->pCrlInfo->ThisUpdate
|
|
))
|
|
break;
|
|
}
|
|
|
|
if (pExistingCrl)
|
|
CertFreeCRLContext(pExistingCrl);
|
|
else {
|
|
fResult = CertAddCRLContextToStore(
|
|
hCAStore,
|
|
pCrl,
|
|
CERT_STORE_ADD_REPLACE_EXISTING,
|
|
NULL
|
|
);
|
|
|
|
if (!fResult)
|
|
PrintLastError("AddCRL");
|
|
}
|
|
}
|
|
|
|
CertFreeCRLContext(pCrl);
|
|
|
|
if (!fResult)
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
SuccessReturn:
|
|
ReturnStatus = 0;
|
|
CommonReturn:
|
|
if (hCAStore)
|
|
CertCloseStore(hCAStore, 0);
|
|
return ReturnStatus;
|
|
|
|
BadUsage:
|
|
Usage();
|
|
ErrorReturn:
|
|
ReturnStatus = -1;
|
|
goto CommonReturn;
|
|
}
|