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.
 
 
 
 
 
 

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;
}