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.
1009 lines
29 KiB
1009 lines
29 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows NT Security
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: updcat.cpp
|
|
//
|
|
// Contents: Update Catalog Entry
|
|
//
|
|
// History: 02-Sep-98 kirtd Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#include "wincrypt.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
#include <mscat.h>
|
|
#include <mssip.h>
|
|
#include <sipguids.h>
|
|
#include <wintrust.h>
|
|
// Prototypes
|
|
|
|
// BOOL AddFileToCatalog (IN HANDLE hCatalog, IN LPWSTR pwszFileName);
|
|
BOOL RemoveHashFromCatalog(IN LPWSTR pwszCatalogFile, IN LPSTR pszHash);
|
|
BOOL AddFileOrAuthAttrToCatalog(IN HANDLE hCatalog, IN LPWSTR pwszFileName,
|
|
IN DWORD dwAttrFlags, IN LPWSTR pwszAttrName,
|
|
IN LPWSTR pwszAttrValue);
|
|
BOOL CheckFileSize(IN LPWSTR pFileName, IN ULONG size);
|
|
extern "C" BOOL MsCatConstructHashTag (IN DWORD cbDigest, IN LPBYTE pbDigest, OUT LPWSTR* ppwszHashTag);
|
|
extern "C" VOID MsCatFreeHashTag (IN LPWSTR pwszHashTag);
|
|
|
|
#define AddFileToCatalog(cat, file) AddFileOrAuthAttrToCatalog(cat, file, 0, NULL, NULL)
|
|
|
|
|
|
#define PWSZ_SPATTR L"SpAttr"
|
|
#define PSZ_SPATTR_OPTION "-SpAttr:"
|
|
ULONG sizeLimit = 0;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Usage
|
|
//
|
|
// Synopsis: prints the usage statement
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
static void Usage(void)
|
|
{
|
|
printf("Usage: updcat <Catalog File> [-s <Size>] [-a <FileName>]\n");
|
|
printf("Usage: updcat <Catalog File> [-d <Hash>]\n");
|
|
printf("Usage: updcat <Catalog File> [-s <Size>] [-r <Hash> <FileName>]\n");
|
|
printf("Usage: updcat <Catalog File> [-attr <FileName> <Name> <Value>]\n");
|
|
printf(" -a, add the file by hash to the catalog\n");
|
|
printf(" -d, delete the hash from the catalog\n");
|
|
printf(" -r, replace the hash in the catalog with the hash of the file\n");
|
|
printf(" -s, fail if the file is smaller than this size (in bytes)\n");
|
|
printf(" -attr, add an ASCII attribute to a file's catalog entry\n");
|
|
printf(" -SpAttr:, replace the current (or add new) SpAttr in the catalog\n");
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: main
|
|
//
|
|
// Synopsis: main program entry point
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int _cdecl main(int argc, char * argv[])
|
|
{
|
|
BOOL fResult = TRUE;
|
|
LPSTR pszCatalogFile = NULL;
|
|
LPWSTR pwszCatalogFile = NULL;
|
|
LPSTR pszFileName = NULL;
|
|
LPSTR pszHash = NULL;
|
|
LPWSTR pwszFileName = NULL;
|
|
LPSTR pszAttrName = NULL;
|
|
LPWSTR pwszAttrName = NULL;
|
|
LPSTR pszAttrValue = NULL;
|
|
LPWSTR pwszAttrValue = NULL;
|
|
BOOL fAddEntry = FALSE;
|
|
DWORD cch = 0;
|
|
HANDLE hCatalog = NULL;
|
|
BOOL fOptionChosen = FALSE;
|
|
LPWSTR pwszSpAttr = NULL;
|
|
CRYPTCATATTRIBUTE *pCatAttr = NULL;
|
|
|
|
if ( argc < 2 )
|
|
{
|
|
Usage();
|
|
return( 1 );
|
|
}
|
|
|
|
argv++;
|
|
argc--;
|
|
|
|
printf( "command line: %s\n", GetCommandLineA() );
|
|
|
|
pszCatalogFile = argv[0];
|
|
cch = strlen( pszCatalogFile );
|
|
|
|
while ( --argc > 0 )
|
|
{
|
|
if ( **++argv == '-' )
|
|
{
|
|
switch( argv[0][1] )
|
|
{
|
|
case 'a':
|
|
case 'A':
|
|
|
|
if ( argc < 2 )
|
|
{
|
|
Usage();
|
|
return( 1 );
|
|
}
|
|
|
|
pszFileName = argv[1];
|
|
fAddEntry = TRUE;
|
|
|
|
if (_strcmpi(&argv[0][1], "attr") == 0)
|
|
{
|
|
if ( argc < 4 )
|
|
{
|
|
Usage();
|
|
return( 1 );
|
|
}
|
|
|
|
pszAttrName = argv[2];
|
|
pszAttrValue = argv[3];
|
|
}
|
|
break;
|
|
|
|
case 'd':
|
|
case 'D':
|
|
|
|
if ( argc < 2 )
|
|
{
|
|
Usage();
|
|
return( 1 );
|
|
}
|
|
|
|
pszHash = argv[1];
|
|
break;
|
|
|
|
case 'r':
|
|
case 'R':
|
|
|
|
if ( argc < 3 )
|
|
{
|
|
Usage();
|
|
return( 1 );
|
|
}
|
|
|
|
pszHash = argv[1];
|
|
fAddEntry = TRUE;
|
|
pszFileName = argv[2];
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
if (memcmp(&(argv[0][0]), (void *) PSZ_SPATTR_OPTION, strlen(PSZ_SPATTR_OPTION)) == 0)
|
|
{
|
|
DWORD dwNumChars;
|
|
|
|
dwNumChars = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
&(argv[0][strlen(PSZ_SPATTR_OPTION)]),
|
|
-1,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (dwNumChars == 0)
|
|
{
|
|
printf( "Error calling MultiByteToWideChar on %s\n", &(argv[0][strlen(PSZ_SPATTR_OPTION)]));
|
|
return -1;
|
|
}
|
|
|
|
pwszSpAttr = new WCHAR [ dwNumChars ];
|
|
|
|
if (pwszSpAttr == NULL)
|
|
{
|
|
printf("Out of memory error\n");
|
|
return -1;
|
|
}
|
|
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
&(argv[0][strlen(PSZ_SPATTR_OPTION)]),
|
|
-1,
|
|
pwszSpAttr,
|
|
dwNumChars
|
|
) == 0 )
|
|
{
|
|
|
|
delete pwszSpAttr;
|
|
printf( "Error calling MultiByteToWideChar on %s\n", &(argv[0][strlen(PSZ_SPATTR_OPTION)]));
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Usage();
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
case 's':
|
|
if ((argc < 2) || (argv[0][2] != '\0'))
|
|
{
|
|
Usage();
|
|
return -1;
|
|
}
|
|
sizeLimit = strtol(*(argv+1), NULL, 10);
|
|
if (errno || (sizeLimit == 0))
|
|
{
|
|
printf ("Invalid size specified with -s option: %s\n",*(argv+1));
|
|
Usage();
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
Usage();
|
|
return -1;
|
|
}
|
|
|
|
fOptionChosen = TRUE;
|
|
argc -= 1;
|
|
argv++;
|
|
}
|
|
}
|
|
pwszCatalogFile = new WCHAR [ cch + 1 ];
|
|
if ( pwszCatalogFile != NULL )
|
|
{
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszCatalogFile,
|
|
-1,
|
|
pwszCatalogFile,
|
|
cch + 1
|
|
) == 0 )
|
|
{
|
|
delete pwszCatalogFile;
|
|
return( 1 );
|
|
}
|
|
}
|
|
|
|
if (!fOptionChosen)
|
|
{
|
|
Usage();
|
|
delete pwszCatalogFile;
|
|
return -1;
|
|
}
|
|
|
|
if (pszFileName != NULL)
|
|
{
|
|
cch = strlen( pszFileName );
|
|
|
|
pwszFileName = new WCHAR [ cch + 1 ];
|
|
if ( pwszFileName != NULL )
|
|
{
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszFileName,
|
|
-1,
|
|
pwszFileName,
|
|
cch + 1
|
|
) == 0 )
|
|
{
|
|
delete pwszCatalogFile;
|
|
delete pwszFileName;
|
|
return( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pszAttrName != NULL)
|
|
{
|
|
cch = strlen( pszAttrName );
|
|
|
|
pwszAttrName = new WCHAR [ cch + 1 ];
|
|
if ( pwszAttrName != NULL )
|
|
{
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszAttrName,
|
|
-1,
|
|
pwszAttrName,
|
|
cch + 1
|
|
) == 0 )
|
|
{
|
|
printf("Error converting AttrName to wchar\n");
|
|
delete pwszCatalogFile;
|
|
delete pwszFileName;
|
|
delete pwszAttrName;
|
|
return( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pszAttrValue != NULL)
|
|
{
|
|
cch = strlen( pszAttrValue );
|
|
|
|
pwszAttrValue = new WCHAR [ cch + 1 ];
|
|
if ( pwszAttrValue != NULL )
|
|
{
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszAttrValue,
|
|
-1,
|
|
pwszAttrValue,
|
|
cch + 1
|
|
) == 0 )
|
|
{
|
|
printf("Error converting AttrValue to wchar\n");
|
|
delete pwszCatalogFile;
|
|
delete pwszFileName;
|
|
delete pwszAttrName;
|
|
delete pwszAttrValue;
|
|
return( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pszHash != NULL )
|
|
{
|
|
fResult = RemoveHashFromCatalog(pwszCatalogFile, pszHash);
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
printf("Error removing <%s> from catalog <%s>\n", pszHash, pszCatalogFile);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// If there haven't been any errors, and we are adding a hash
|
|
//
|
|
if (( fResult == TRUE ) && ( fAddEntry == TRUE ))
|
|
{
|
|
hCatalog = CryptCATOpen(
|
|
pwszCatalogFile,
|
|
CRYPTCAT_OPEN_ALWAYS,
|
|
NULL,
|
|
0x00000001,
|
|
0x00010001
|
|
);
|
|
|
|
if ( hCatalog == NULL )
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// If we're adding an attribute
|
|
if (pwszAttrName && pwszAttrValue)
|
|
{
|
|
fResult = AddFileOrAuthAttrToCatalog( hCatalog, pwszFileName,
|
|
0x10010001, pwszAttrName,
|
|
pwszAttrValue );
|
|
CryptCATClose( hCatalog );
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
printf("Error adding Attribute <%s> to catalog <%s>\n",
|
|
pszAttrName, pszCatalogFile);
|
|
}
|
|
}
|
|
else
|
|
// If we're only adding the file by hash
|
|
{
|
|
fResult = AddFileToCatalog( hCatalog, pwszFileName );
|
|
CryptCATClose( hCatalog );
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
printf("Error adding <%s> to catalog <%s>\n",
|
|
pszFileName, pszCatalogFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( pwszSpAttr != NULL )
|
|
{
|
|
hCatalog = CryptCATOpen(
|
|
pwszCatalogFile,
|
|
CRYPTCAT_OPEN_ALWAYS,
|
|
NULL,
|
|
0x00000001,
|
|
0x00010001
|
|
);
|
|
|
|
if ( hCatalog == NULL )
|
|
{
|
|
fResult = FALSE;
|
|
goto Return;
|
|
}
|
|
|
|
//
|
|
// Check to see if it already has an SpAttr
|
|
//
|
|
pCatAttr = CryptCATGetCatAttrInfo(hCatalog, PWSZ_SPATTR);
|
|
|
|
if ( pCatAttr == NULL )
|
|
{
|
|
if (NULL == CryptCATPutCatAttrInfo(
|
|
hCatalog,
|
|
PWSZ_SPATTR,
|
|
0x10010001,
|
|
(wcslen(pwszSpAttr) + 1) * sizeof(WCHAR),
|
|
(BYTE *) pwszSpAttr))
|
|
{
|
|
printf("Error adding SpAttr to catalog <%s>\n", pszCatalogFile);
|
|
fResult = FALSE;
|
|
goto Return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL == CryptCATPutCatAttrInfo(
|
|
hCatalog,
|
|
PWSZ_SPATTR,
|
|
0x10040001,
|
|
(wcslen(pwszSpAttr) + 1) * sizeof(WCHAR),
|
|
(BYTE *) pwszSpAttr))
|
|
{
|
|
if (GetLastError() == ERROR_INVALID_PARAMETER)
|
|
{
|
|
printf("The SpAttr modification failed, it is likely due to an old wintrust.dll\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Error changing SpAttr in catalog <%s>\n", pszCatalogFile);
|
|
}
|
|
fResult = FALSE;
|
|
goto Return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
CryptCATPersistStore(hCatalog);
|
|
CryptCATClose( hCatalog );
|
|
}
|
|
|
|
Return:
|
|
return( !fResult );
|
|
}
|
|
|
|
|
|
typedef BOOL (WINAPI *PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE) (
|
|
IN LPCWSTR FileName,
|
|
IN HANDLE hFileIn,
|
|
OUT GUID *pgSubject
|
|
);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddFileOrAuthAttrToCatalog
|
|
//
|
|
// Synopsis: add a file as an entry to the catalog. The tag will be the
|
|
// hash
|
|
// additionally, you can add an authenticated attribute.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL AddFileOrAuthAttrToCatalog (IN HANDLE hCatalog,
|
|
IN LPWSTR pwszFileName,
|
|
IN DWORD dwAttrFlags,
|
|
IN LPWSTR pwszAttrName,
|
|
IN LPWSTR pwszAttrValue)
|
|
{
|
|
BOOL fResult;
|
|
GUID FlatSubject = CRYPT_SUBJTYPE_FLAT_IMAGE;
|
|
GUID SubjectType;
|
|
SIP_SUBJECTINFO SubjectInfo;
|
|
SIP_DISPATCH_INFO DispatchInfo;
|
|
DWORD cbIndirectData;
|
|
SIP_INDIRECT_DATA* pIndirectData = NULL;
|
|
CRYPTCATSTORE* pCatStore = CryptCATStoreFromHandle( hCatalog );
|
|
CRYPTCATMEMBER* pMember;
|
|
CRYPTCATATTRIBUTE* pAttr;
|
|
LPWSTR pwszHashTag = NULL;
|
|
HMODULE hMod = NULL;
|
|
PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE pSIPFunc = NULL;
|
|
|
|
memset( &SubjectInfo, 0, sizeof( SubjectInfo ) );
|
|
memset( &DispatchInfo, 0, sizeof( DispatchInfo ) );
|
|
|
|
|
|
if (sizeLimit)
|
|
{
|
|
// Check that we do not add the hash for a file whose
|
|
// size if less than the specified lower limit
|
|
if ( !CheckFileSize(pwszFileName, sizeLimit) )
|
|
{
|
|
printf ("Error: %S is smaller than the specified minimum size (%d)\n",
|
|
pwszFileName, sizeLimit);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// NOTE!!!!!
|
|
//
|
|
// Try to use the function that only retrieves SIPs for hashing files
|
|
// that are to be included in catalog files. This function is new and
|
|
// only exists post win2k, so if it isn't there, then fall back to the
|
|
// win2k function... which should be OK since Win2k didn't SHIP
|
|
// with any SIPs that caused problems (although SIPs could be installed on
|
|
// a win2k system after the fact that do cause problems)
|
|
//
|
|
|
|
if (NULL != (hMod = LoadLibrary("crypt32.dll")))
|
|
{
|
|
pSIPFunc = (PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE)
|
|
GetProcAddress(hMod, "CryptSIPRetrieveSubjectGuidForCatalogFile");
|
|
|
|
if (pSIPFunc != NULL)
|
|
{
|
|
if ( pSIPFunc(pwszFileName, NULL, &SubjectType) == FALSE )
|
|
{
|
|
memcpy( &SubjectType, &FlatSubject, sizeof( GUID ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pSIPFunc == NULL)
|
|
{
|
|
//
|
|
// Fall back to old SIP resolver
|
|
//
|
|
if ( CryptSIPRetrieveSubjectGuid(
|
|
pwszFileName,
|
|
NULL,
|
|
&SubjectType
|
|
) == FALSE )
|
|
{
|
|
memcpy( &SubjectType, &FlatSubject, sizeof( GUID ) );
|
|
}
|
|
}
|
|
|
|
if (hMod != NULL)
|
|
{
|
|
FreeLibrary(hMod);
|
|
}
|
|
|
|
if ( CryptSIPLoad( &SubjectType, 0, &DispatchInfo ) == FALSE )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Some of this subject info stuff should be configurable but
|
|
// since the CDF API does not allow it, we won't worry about it
|
|
// yet.
|
|
SubjectInfo.cbSize = sizeof( SubjectInfo );
|
|
SubjectInfo.hProv = pCatStore->hProv;
|
|
SubjectInfo.DigestAlgorithm.pszObjId = (char *)CertAlgIdToOID( CALG_SHA1 );
|
|
|
|
SubjectInfo.dwFlags = SPC_INC_PE_RESOURCES_FLAG |
|
|
SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
|
|
MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE;
|
|
|
|
SubjectInfo.dwEncodingType = pCatStore->dwEncodingType;
|
|
SubjectInfo.pgSubjectType = &SubjectType;
|
|
SubjectInfo.pwsFileName = pwszFileName;
|
|
|
|
fResult = DispatchInfo.pfCreate( &SubjectInfo, &cbIndirectData, NULL );
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
pIndirectData = (SIP_INDIRECT_DATA *)new BYTE [ cbIndirectData ];
|
|
if ( pIndirectData != NULL )
|
|
{
|
|
fResult = DispatchInfo.pfCreate(
|
|
&SubjectInfo,
|
|
&cbIndirectData,
|
|
pIndirectData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SetLastError( E_OUTOFMEMORY );
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( fResult == TRUE )
|
|
{
|
|
fResult = MsCatConstructHashTag(
|
|
pIndirectData->Digest.cbData,
|
|
pIndirectData->Digest.pbData,
|
|
&pwszHashTag
|
|
);
|
|
}
|
|
|
|
if ( fResult == FALSE )
|
|
{
|
|
goto Return;
|
|
}
|
|
|
|
if (pwszAttrName && pwszAttrValue)
|
|
{
|
|
// We're adding an Attribute
|
|
|
|
if (dwAttrFlags != 0x10010001)
|
|
{
|
|
printf("Error: Unsupported flag specified\n");
|
|
fResult = FALSE;
|
|
goto Return;
|
|
}
|
|
|
|
// Find the member in the catalog.
|
|
pMember = CryptCATGetMemberInfo(hCatalog, pwszHashTag);
|
|
if (pMember == NULL)
|
|
{
|
|
// Catalog member was not found. Adding it...
|
|
pMember = CryptCATPutMemberInfo(
|
|
hCatalog,
|
|
pwszFileName,
|
|
pwszHashTag,
|
|
&SubjectType,
|
|
SubjectInfo.dwIntVersion,
|
|
cbIndirectData,
|
|
(LPBYTE)pIndirectData
|
|
);
|
|
}
|
|
if (pMember == NULL)
|
|
{
|
|
printf("Error: Could not find file hash, and could not add it.\n");
|
|
fResult = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (pAttr = CryptCATGetAttrInfo(hCatalog, pMember, pwszAttrName))
|
|
{
|
|
if (wcscmp(pwszAttrValue, LPCWSTR(pAttr->pbValue)) == 0)
|
|
{
|
|
printf("Attribute already exists with the same value\n");
|
|
fResult = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pAttr->cbValue = (wcslen(pwszAttrValue) + 1) * sizeof(WCHAR);
|
|
delete(pAttr->pbValue);
|
|
pAttr->pbValue = (BYTE *)pwszAttrValue;
|
|
pAttr->pbValue = new BYTE[pAttr->cbValue];
|
|
if (pAttr->pbValue)
|
|
{
|
|
memcpy(pAttr->pbValue, pwszAttrValue, pAttr->cbValue);
|
|
fResult = CryptCATPersistStore(hCatalog);
|
|
}
|
|
else
|
|
{
|
|
pAttr->cbValue = 0;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pAttr = CryptCATPutAttrInfo(hCatalog,
|
|
pMember,
|
|
pwszAttrName,
|
|
dwAttrFlags,
|
|
(wcslen(pwszAttrValue) + 1) * sizeof(WCHAR),
|
|
(BYTE *)pwszAttrValue);
|
|
if (pAttr != NULL)
|
|
{
|
|
fResult = CryptCATPersistStore(hCatalog);
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We're just adding a catalog member
|
|
|
|
// Does this member already exist?
|
|
pMember = CryptCATGetMemberInfo(hCatalog, pwszHashTag);
|
|
if (pMember == NULL)
|
|
{
|
|
// it does not exist in the catalog yet. Add it.
|
|
pMember = CryptCATPutMemberInfo(
|
|
hCatalog,
|
|
pwszFileName,
|
|
pwszHashTag,
|
|
&SubjectType,
|
|
SubjectInfo.dwIntVersion,
|
|
cbIndirectData,
|
|
(LPBYTE)pIndirectData
|
|
);
|
|
|
|
if ( pMember != NULL )
|
|
{
|
|
fResult = CryptCATPersistStore( hCatalog );
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// It already exists in the catalog.
|
|
printf("This file's hash is already present in the catalog.\n");
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
Return:
|
|
if ( pwszHashTag != NULL )
|
|
{
|
|
MsCatFreeHashTag( pwszHashTag );
|
|
}
|
|
|
|
delete (LPBYTE)pIndirectData;
|
|
|
|
return( fResult );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RemoveHashFromCatalog
|
|
//
|
|
// Synopsis: removes a hash entry from the catalog.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
RemoveHashFromCatalog(IN LPWSTR pwszCatalogFile, IN LPSTR pszHash)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
LPSTR pChar = NULL;
|
|
int i, j;
|
|
DWORD dwContentType;
|
|
PCTL_CONTEXT pCTLContext = NULL;
|
|
CTL_CONTEXT CTLContext;
|
|
CTL_INFO CTLInfo;
|
|
DWORD cbEncodedCTL = 0;
|
|
BYTE *pbEncodedCTL = NULL;
|
|
DWORD cbWritten = 0;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD cch = 0;
|
|
LPWSTR pwszHash = NULL;
|
|
BOOL fHashFound = FALSE;
|
|
|
|
CMSG_SIGNED_ENCODE_INFO signedInfo;
|
|
memset(&signedInfo, 0, sizeof(signedInfo));
|
|
signedInfo.cbSize = sizeof(signedInfo);
|
|
|
|
|
|
CTLInfo.rgCTLEntry = NULL;
|
|
|
|
cch = strlen( pszHash );
|
|
|
|
pwszHash = new WCHAR [ cch + 1 ];
|
|
if ( pwszHash == NULL )
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
if ( MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszHash,
|
|
-1,
|
|
pwszHash,
|
|
cch + 1
|
|
) == 0 )
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Get rid of all the ' ' chars
|
|
//
|
|
i = 0;
|
|
j = 0;
|
|
for (i=0; i<(int)wcslen(pwszHash); i++)
|
|
{
|
|
if (pwszHash[i] != ' ')
|
|
{
|
|
pwszHash[j++] = pwszHash[i];
|
|
}
|
|
}
|
|
pwszHash[j] = '\0';
|
|
|
|
//
|
|
// Open the cat file as a CTL
|
|
//
|
|
if (!CryptQueryObject(
|
|
CERT_QUERY_OBJECT_FILE,
|
|
pwszCatalogFile,
|
|
CERT_QUERY_CONTENT_FLAG_CTL,
|
|
CERT_QUERY_FORMAT_FLAG_BINARY,
|
|
0, //flags
|
|
NULL,
|
|
&dwContentType,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
(const void **) &pCTLContext))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (dwContentType != CERT_QUERY_CONTENT_CTL)
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Create another CTL context just like pCTLContext
|
|
//
|
|
CTLInfo = *(pCTLContext->pCtlInfo);
|
|
CTLInfo.rgCTLEntry = (PCTL_ENTRY) new CTL_ENTRY[pCTLContext->pCtlInfo->cCTLEntry];
|
|
|
|
if (CTLInfo.rgCTLEntry == NULL)
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// Loop through all the ctl entries and remove the entry
|
|
// that corresponds to the hash given
|
|
//
|
|
CTLInfo.cCTLEntry = 0;
|
|
for (i=0; i<(int)pCTLContext->pCtlInfo->cCTLEntry; i++)
|
|
{
|
|
if (wcscmp(
|
|
(LPWSTR) pCTLContext->pCtlInfo->rgCTLEntry[i].SubjectIdentifier.pbData,
|
|
pwszHash) != 0)
|
|
{
|
|
CTLInfo.rgCTLEntry[CTLInfo.cCTLEntry++] = pCTLContext->pCtlInfo->rgCTLEntry[i];
|
|
}
|
|
else
|
|
{
|
|
fHashFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fHashFound)
|
|
{
|
|
printf("<%S> not found in <%S>\n", pwszHash, pwszCatalogFile);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// now save the CTL which is exactly the same as the previous one,
|
|
// except it doesn't doesn't have the hash being removed, back to
|
|
// the original filename
|
|
//
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
&CTLInfo,
|
|
&signedInfo,
|
|
0,
|
|
NULL,
|
|
&cbEncodedCTL))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (NULL == (pbEncodedCTL = new BYTE[cbEncodedCTL]))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
&CTLInfo,
|
|
&signedInfo,
|
|
0,
|
|
pbEncodedCTL,
|
|
&cbEncodedCTL))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
|
|
if (INVALID_HANDLE_VALUE == (hFile = CreateFileW(
|
|
pwszCatalogFile,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL)))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!WriteFile(
|
|
hFile,
|
|
pbEncodedCTL,
|
|
cbEncodedCTL,
|
|
&cbWritten,
|
|
NULL))
|
|
{
|
|
printf("WriteFile of <%S> failed with %x\n", pwszCatalogFile, GetLastError());
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (cbWritten != cbEncodedCTL)
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
hFile = INVALID_HANDLE_VALUE;
|
|
|
|
CommonReturn:
|
|
if (pwszHash != NULL)
|
|
{
|
|
delete (pwszHash);
|
|
}
|
|
|
|
if (pCTLContext != NULL)
|
|
{
|
|
CertFreeCTLContext(pCTLContext);
|
|
}
|
|
|
|
if (CTLInfo.rgCTLEntry != NULL)
|
|
{
|
|
delete (CTLInfo.rgCTLEntry);
|
|
}
|
|
|
|
if (pbEncodedCTL != NULL)
|
|
{
|
|
delete (pbEncodedCTL);
|
|
}
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (!CloseHandle(hFile))
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CheckFileSize
|
|
//
|
|
// Synopsis: Checks that a file meets the minumum size requirement.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CheckFileSize (LPWSTR fileName, ULONG sizeLimit)
|
|
{
|
|
HANDLE hFile;
|
|
LARGE_INTEGER sizeFile = {0};
|
|
|
|
// Attempt to open the specified file
|
|
hFile = CreateFileW( fileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL );
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
printf("Error opening %S (%lu)\n", fileName, GetLastError() );
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the file size
|
|
if (!GetFileSizeEx(hFile, &sizeFile))
|
|
{
|
|
printf("Error determining size of %S (%lu)\n", fileName, GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if ((!sizeFile.HighPart) && (sizeFile.LowPart < sizeLimit))
|
|
{
|
|
// File is too small
|
|
return FALSE;
|
|
}
|
|
|
|
// Success. File is not too small.
|
|
return TRUE;
|
|
}
|
|
|
|
|