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.
 
 
 
 
 
 

656 lines
17 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: tcatdb.cpp
//
// Contents:
//
//
//
//
// Functions: main
//
// History: 11-Apr-00 reidk created
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include "wintrust.h"
#include "mscat.h"
#include "unicode.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <memory.h>
#include <time.h>
#include "catutil.h"
#define WSZ_CATALOG_NEW_BASE_DIRECTORY L"CatRoot2"
typedef struct _CTL_SLOT
{
PCCTL_CONTEXT pCTLContext;
HANDLE hMappedFile;
BYTE *pbMappedFile;
LPWSTR pwszCatalog;
} CTL_SLOT, *PCTL_SLOT;
GUID g_guidCatRoot;
BOOL g_fUseSingleContext = TRUE;
BOOL g_fDatabaseConsistencyCheck = FALSE;
BOOL g_fUseDefaultGUID = FALSE;
BOOL g_fVerbose = FALSE;
BOOL g_fDatabaseReverseConsistencyCheck = FALSE;
WCHAR g_wszDefaultSystemDir[MAX_PATH + 1];
LPWSTR g_pwszCatalogDir = NULL;
WCHAR g_wszSubSysGUID[1024];
LPWSTR g_pwszCatalogSearchString = NULL;
const char RgchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
void FormatHashString(LPSTR *ppString, DWORD cbBlob, BYTE *pblob)
{
DWORD i, j = 0;
BYTE *pb = NULL;
DWORD numCharsInserted = 0;
LPSTR psz;
*ppString = NULL;
pb = pblob;
// fill the buffer
i=0;
while (j < cbBlob)
{
if ((*ppString) == NULL)
{
psz = NULL;
*ppString = (LPSTR) malloc(3 * sizeof(char));
}
else
{
psz = *ppString;
#pragma prefast(suppress:308, "the pointer was saved above (PREfast bug 506)")
*ppString = (LPSTR) realloc(*ppString, (j+1) * 3 * sizeof(char));
}
if (*ppString == NULL)
{
if (psz != NULL)
{
free(psz);
}
return;
}
(*ppString)[i++] = RgchHex[(*pb & 0xf0) >> 4];
(*ppString)[i++] = RgchHex[*pb & 0x0f];
(*ppString)[i++] = ' ';
pb++;
j++;
}
(*ppString)[i-1] = 0;
}
//---------------------------------------------------------------------------------------
//
// FindAndDecodeHashInCatEntry
//
//---------------------------------------------------------------------------------------
BOOL
FindAndDecodeHashInCatEntry(
PCTL_ENTRY pctlEntry,
SPC_INDIRECT_DATA_CONTENT **ppIndirectData)
{
BOOL fRet = TRUE;
DWORD i;
DWORD cbIndirectData = 0;
*ppIndirectData = NULL;
//
// Search for the hash in the attributes
//
for (i=0; i<pctlEntry->cAttribute; i++)
{
if (strcmp(pctlEntry->rgAttribute[i].pszObjId, SPC_INDIRECT_DATA_OBJID) == 0)
{
break;
}
}
//
// Make sure the hash was found
//
if (i >= pctlEntry->cAttribute)
{
printf("Unexpected error... hash not found in CTL entry\n");
goto ErrorReturn;
}
//
// decode the indirect data
//
if (!CryptDecodeObject(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
SPC_INDIRECT_DATA_CONTENT_STRUCT,
pctlEntry->rgAttribute[i].rgValue[0].pbData,
pctlEntry->rgAttribute[i].rgValue[0].cbData,
0,
NULL,
&cbIndirectData))
{
printf("CryptDecodeObject failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
if (NULL == (*ppIndirectData = (SPC_INDIRECT_DATA_CONTENT *)
malloc(cbIndirectData)))
{
printf("malloc failure\n");
goto ErrorReturn;
}
if (!CryptDecodeObject(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
SPC_INDIRECT_DATA_CONTENT_STRUCT,
pctlEntry->rgAttribute[i].rgValue[0].pbData,
pctlEntry->rgAttribute[i].rgValue[0].cbData,
0,
*ppIndirectData,
&cbIndirectData))
{
printf("CryptDecodeObject failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
CommonReturn:
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
}
BOOL
CheckCatFileEntries(HCATADMIN hCatAdmin, LPWSTR pwszCatalogFile)
{
BOOL fRet = TRUE;
PCCTL_CONTEXT pCTLContext = NULL;
HANDLE hMappedFile = NULL;
BYTE *pbMappedFile = NULL;
DWORD i;
SPC_INDIRECT_DATA_CONTENT *pIndirectData = NULL;
HCATINFO hCatInfo;
BOOL fCatalogFound;
CATALOG_INFO sCatInfo;
LPSTR pszHash = NULL;
HCATADMIN hCatAdminLocal = NULL;
LPWSTR pwszShortCatName = wcsrchr(pwszCatalogFile, L'\\');
pwszShortCatName++;
if (g_fVerbose)
{
printf(" Processing cat file: %S\n", pwszShortCatName);
}
//
// Open, and create a file mapping of the catalog file
//
if (!CatUtil_CreateCTLContextFromFileName(
pwszCatalogFile,
&hMappedFile,
&pbMappedFile,
&pCTLContext,
FALSE))
{
printf(" Error opening catalog file: %S\n", pwszCatalogFile);
goto ErrorReturn;
}
//
// Go through each entry in the catalog
//
for (i=0; i<pCTLContext->pCtlInfo->cCTLEntry; i++)
{
if (!FindAndDecodeHashInCatEntry(
&(pCTLContext->pCtlInfo->rgCTLEntry[i]),
&pIndirectData))
{
goto ErrorReturn;
}
if (!g_fUseSingleContext)
{
if (!(CryptCATAdminAcquireContext(&hCatAdminLocal, &g_guidCatRoot, 0)))
{
printf(" CryptCATAdminAcquireContext failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
}
fCatalogFound = FALSE;
hCatInfo = NULL;
while (hCatInfo = CryptCATAdminEnumCatalogFromHash(
g_fUseSingleContext ? hCatAdmin : hCatAdminLocal,
pIndirectData->Digest.pbData,
pIndirectData->Digest.cbData,
0,
&hCatInfo))
{
memset(&sCatInfo, 0x00, sizeof(CATALOG_INFO));
sCatInfo.cbStruct = sizeof(CATALOG_INFO);
if (!(CryptCATCatalogInfoFromContext(hCatInfo, &sCatInfo, 0)))
{
printf(" CryptCATCatalogInfoFromContext failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
if (_wcsicmp(&(sCatInfo.wszCatalogFile[0]), pwszCatalogFile) == 0)
{
fCatalogFound = TRUE;
break;
}
}
if (!fCatalogFound)
{
FormatHashString(&pszHash, pIndirectData->Digest.cbData, pIndirectData->Digest.pbData);
printf(" FAILURE: Could not enum: %S\n from hash: %s\n", pwszShortCatName, pszHash);
if (g_fVerbose)
{
printf(" GLE: %lx\n", GetLastError());
}
}
if (!g_fUseSingleContext)
{
CryptCATAdminReleaseContext(hCatAdminLocal, NULL);
hCatAdminLocal = NULL;
}
free(pIndirectData);
pIndirectData = NULL;
}
CommonReturn:
if (pIndirectData != NULL)
{
free(pIndirectData);
}
if (pCTLContext != NULL)
{
CertFreeCTLContext(pCTLContext);
}
if (pbMappedFile != NULL)
{
UnmapViewOfFile(pbMappedFile);
}
if (hMappedFile != NULL)
{
CloseHandle(hMappedFile);
}
if (pszHash != NULL)
{
free(pszHash);
}
if (hCatAdminLocal != NULL)
{
CryptCATAdminReleaseContext(hCatAdminLocal, NULL);
}
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
}
BOOL DoDatabaseConsistencyCheck()
{
BOOL fRet = TRUE;
HCATADMIN hCatAdmin = NULL;
LPWSTR pwszCatalogFile = NULL;
HANDLE hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindDataCatalogsInDir;
PCCTL_CONTEXT pCTLContext = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMappedFile = NULL;
DWORD cbFile = 0;
BYTE *pbMappedFile = NULL;
printf("Starting database consistency check\n");
if (g_fUseSingleContext)
{
if (!(CryptCATAdminAcquireContext(&hCatAdmin, &g_guidCatRoot, 0)))
{
printf(" CryptCATAdminAcquireContext failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
}
//
// Find each catalog in the dir
//
//
// Start the catalog enumeration
//
hFindHandleCatalogsInDir = FindFirstFileW(
g_pwszCatalogSearchString,
&FindDataCatalogsInDir);
if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
{
// no files found
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetLastError(0);
}
else
{
goto ErrorReturn;
}
}
else
{
while (1)
{
if ((wcscmp(FindDataCatalogsInDir.cFileName, L".") != 0) &&
(wcscmp(FindDataCatalogsInDir.cFileName, L"..") != 0) &&
(!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
{
//
// Construct fully qualified path name to catalog file
//
if (NULL == (pwszCatalogFile = (LPWSTR)
malloc(sizeof(WCHAR) *
(wcslen(g_pwszCatalogDir) +
wcslen(FindDataCatalogsInDir.cFileName) +
1))))
{
printf(" malloc failure\n");
goto ErrorReturn;
}
wcscpy(pwszCatalogFile, g_pwszCatalogDir);
wcscat(pwszCatalogFile, FindDataCatalogsInDir.cFileName);
//
// Verify that this is a catalog
//
if (IsCatalogFile(NULL, pwszCatalogFile))
{
CheckCatFileEntries(hCatAdmin, pwszCatalogFile);
}
else
{
LPWSTR pwsz = wcsrchr(pwszCatalogFile, L'\\');
pwsz++;
if (_wcsicmp(pwsz, L"CatDB") != 0)
{
wprintf(L" File found that is not a catalog file: %s\n", pwsz);
}
}
free(pwszCatalogFile);
pwszCatalogFile = NULL;
}
//
// Get next catalog file
//
if (!FindNextFileW(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetLastError(0);
break;
}
else
{
goto ErrorReturn;
}
}
}
}
CommonReturn:
printf("Database consistency check complete\n");
if (pwszCatalogFile != NULL)
{
free(pwszCatalogFile);
}
if (hFindHandleCatalogsInDir != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandleCatalogsInDir);
}
if (hCatAdmin != NULL)
{
CryptCATAdminReleaseContext(hCatAdmin, NULL);
}
return (fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
}
static void Usage(void)
{
printf("Usage: tcatdb [options] <GUID>\n");
printf("Options are:\n");
printf(" -h - This message\n");
printf(" -v - Verbose output\n");
printf(" -d - Use default GUID (system GUID)\n");
printf(" -c - Check database consistency\n");
printf(" -s - Use a single HCATADMIN for all calls (default)\n");
printf(" -n - Use a new HCATADMIN for every call\n");
printf("\n");
}
int _cdecl main(int argc, char * argv[])
{
LPSTR pszGUID = NULL;
WCHAR wsz[1024];
int ret = 0;
LPSTR pszCatalogToDelete = NULL;
HCATADMIN hCatAdminLocal = NULL;
while (--argc>0)
{
if (**++argv == '-')
{
switch(argv[0][1])
{
case 'c':
case 'C':
g_fDatabaseConsistencyCheck = TRUE;
break;
case 'd':
case 'D':
g_fUseDefaultGUID = TRUE;
break;
case 's':
case 'S':
g_fUseSingleContext = TRUE;
break;
case 'n':
case 'N':
g_fUseSingleContext = FALSE;
break;
case 'v':
case 'V':
g_fVerbose = TRUE;
break;
case 'h':
case 'H':
default:
Usage();
return -1;
}
} else
pszGUID = argv[0];
}
if (!g_fUseDefaultGUID && (pszGUID == NULL))
{
printf("missing <GUID>\n");
Usage();
return -1;
}
else if (g_fUseDefaultGUID)
{
wstr2guid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &g_guidCatRoot);
}
else
{
MultiByteToWideChar(CP_ACP, 0, pszGUID, -1, wsz, 1024);
if (!(wstr2guid(wsz, &g_guidCatRoot)))
{
return -1;
}
}
//
// setup defaults
//
guid2wstr(&g_guidCatRoot, g_wszSubSysGUID);
g_wszDefaultSystemDir[0] = NULL;
if (0 == GetSystemDirectoryW(&g_wszDefaultSystemDir[0], MAX_PATH))
{
printf("GetSystemDirectory failure\nGLE = %lx\n", GetLastError());
goto ErrorReturn;
}
if (NULL == (g_pwszCatalogDir = (LPWSTR)
malloc(sizeof(WCHAR) *
(wcslen(g_wszDefaultSystemDir) +
wcslen(WSZ_CATALOG_NEW_BASE_DIRECTORY) +
wcslen(g_wszSubSysGUID) +
4))))
{
printf("malloc failure\n");
goto ErrorReturn;
}
wcscpy(g_pwszCatalogDir, g_wszDefaultSystemDir);
if ((g_pwszCatalogDir[0]) &&
(g_pwszCatalogDir[wcslen(&g_wszDefaultSystemDir[0]) - 1] != L'\\'))
{
wcscat(g_pwszCatalogDir, L"\\");
}
wcscat(g_pwszCatalogDir, WSZ_CATALOG_NEW_BASE_DIRECTORY);
wcscat(g_pwszCatalogDir, L"\\");
wcscat(g_pwszCatalogDir, g_wszSubSysGUID);
wcscat(g_pwszCatalogDir, L"\\");
//
// make the search string
//
if (NULL == (g_pwszCatalogSearchString = (LPWSTR)
malloc(sizeof(WCHAR) *
(wcslen(g_wszDefaultSystemDir) +
wcslen(WSZ_CATALOG_NEW_BASE_DIRECTORY) +
wcslen(g_wszSubSysGUID) +
wcslen(L"*") +
4))))
{
printf(" malloc failure\n");
goto ErrorReturn;
}
wcscpy(g_pwszCatalogSearchString, g_wszDefaultSystemDir);
if ((g_pwszCatalogSearchString[0]) &&
(g_pwszCatalogSearchString[wcslen(&g_wszDefaultSystemDir[0]) - 1] != L'\\'))
{
wcscat(g_pwszCatalogSearchString, L"\\");
}
wcscat(g_pwszCatalogSearchString, WSZ_CATALOG_NEW_BASE_DIRECTORY);
wcscat(g_pwszCatalogSearchString, L"\\");
wcscat(g_pwszCatalogSearchString, g_wszSubSysGUID);
wcscat(g_pwszCatalogSearchString, L"\\");
wcscat(g_pwszCatalogSearchString, L"*");
//
// run requested operations
//
if (g_fDatabaseConsistencyCheck)
{
DoDatabaseConsistencyCheck();
}
//
// cleanup
//
CommonReturn:
if (hCatAdminLocal != NULL)
{
CryptCATAdminReleaseContext(hCatAdminLocal, 0);
}
if (g_pwszCatalogDir != NULL)
{
free(g_pwszCatalogDir);
}
if (g_pwszCatalogSearchString != NULL)
{
free(g_pwszCatalogSearchString);
}
printf("Done\n");
return (ret);
ErrorReturn:
ret = -1;
goto CommonReturn;
}