|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: mscatctl.cpp
//
// Contents: Microsoft Internet Security Catalog Utilities
// implements the Certificate Trust List & persistent storage
//
// Functions: CatalogLoadFileData
// CatalogSaveP7UData
// CatalogSaveP7SData
// IsCatalogFile
//
// *** local functions ***
// CatalogLoadData
// CatalogFillCatStore
// CatalogFillCTL
// CatalogFillCTLAttr
// CatalogFreeCTL
// CatalogFreeCTLAttr
// CatalogFillCatMember
// CatalogFillMemAttr
// CatalogFillCatAttr
// CatalogFillCatLevelAttr
//
// History: 05-May-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "mscat32.h"
//
// for each member, we have at minimum two authenticated attributes.
// 1 = Indirect Data
// 2 = Subject Guid
//
#define CAT_RESERVE_CTL_ATTR 2
// WARNING: this function allocates pbData -- you must delete!
BOOL CatalogLoadData(WCHAR *pwszCatFile, DWORD *cbData, BYTE **pbData);
BOOL CatalogFillCatStore(CRYPTCATSTORE *pCat, PCTL_INFO pCTLInfo); BOOL CatalogFreeCTL(CTL_INFO *pCTL); BOOL CatalogFreeCTLAttr(CRYPT_ATTRIBUTE *pCryptAttr); BOOL CatalogFillCTL(CRYPTCATSTORE *pCat, CTL_INFO *pCTL); BOOL CatalogFillCatAttr(CRYPTCATSTORE *pCat, CERT_EXTENSION *pAttr); BOOL CatalogFillCatLevelAttr(CRYPTCATSTORE *pCatStore, CRYPTCATATTRIBUTE *pAttr, CERT_EXTENSION *pCertAttr); BOOL CatalogFillCTLAttr(CRYPTCATSTORE *pCatStore, CRYPTCATATTRIBUTE *pAttr, PCRYPT_ATTRIBUTE pCryptAttr);
CRYPTCATMEMBER *CatalogFillCatMember(CRYPTCATSTORE *pCat, CTL_ENTRY *pEntry); BOOL CatalogFillMemAttr(CRYPTCATSTORE *pCat, CRYPTCATMEMBER *pMember, CRYPT_ATTRIBUTE *pAttr);
static const char *pszOID = szOID_CATALOG_LIST;
BOOL CatalogLoadFileData(CRYPTCATSTORE *pCat) { BOOL fRet; DWORD cbData; BYTE *pbData;
cbData = 0; pbData = NULL;
if (!(CatalogLoadData(pCat->pwszP7File, &cbData, &pbData))) { return(FALSE); }
if (cbData < 1) { if (pbData) { UnmapViewOfFile(pbData); }
//
// not signed and we are probably creating it!
//
return(TRUE); }
PCCTL_CONTEXT pCTLContext;
pCTLContext = (PCCTL_CONTEXT) CertCreateContext( CERT_STORE_CTL_CONTEXT, pCat->dwEncodingType, pbData, cbData, CERT_CREATE_CONTEXT_NOCOPY_FLAG | CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG, NULL // pCreatePara
);
if (pCTLContext) { //
// got it... fill our arrays!
//
fRet = CatalogFillCatStore(pCat, pCTLContext->pCtlInfo); CertFreeCTLContext(pCTLContext); } else fRet = FALSE;
UnmapViewOfFile(pbData);
return(fRet); }
BOOL CatalogSaveP7SData(CRYPTCATSTORE *pCat, CTL_CONTEXT *pCTLContext) { assert(0); // should never be called!
return(TRUE); }
BOOL CatalogSaveP7UData(CRYPTCATSTORE *pCat) { CMSG_SIGNED_ENCODE_INFO sSignInfo; CTL_INFO sCTLInfo; DWORD cbEncoded; BYTE *pbEncoded; Stack_ *pStack;
//
// sort the data...
//
if (pCat->hReserved) // member stack_
{ pStack = (Stack_ *)pCat->hReserved;
pStack->Sort(WVT_OFFSETOF(CRYPTCATMEMBER, pwszReferenceTag), sizeof(WCHAR *), STACK_SORTTYPE_PWSZ); }
memset(&sSignInfo, 0x00, sizeof(CMSG_SIGNED_ENCODE_INFO)); sSignInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
if (CatalogFillCTL(pCat, &sCTLInfo)) { cbEncoded = 0;
CryptMsgEncodeAndSignCTL( pCat->dwEncodingType, &sCTLInfo, &sSignInfo, 0, NULL, &cbEncoded);
if (cbEncoded > 0) { BOOL fRet;
if (!(pbEncoded = (BYTE *)CatalogNew(cbEncoded))) { CatalogFreeCTL(&sCTLInfo); return(FALSE); }
fRet = CryptMsgEncodeAndSignCTL( pCat->dwEncodingType, &sCTLInfo, &sSignInfo, 0, pbEncoded, &cbEncoded); CatalogFreeCTL(&sCTLInfo);
if (fRet) { HANDLE hFile; DWORD lErr;
lErr = GetLastError();
if ((hFile = CreateFileU(pCat->pwszP7File, GENERIC_WRITE | GENERIC_READ, 0, // no sharing!!
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { DWORD cbWritten;
if (!(WriteFile(hFile, pbEncoded, cbEncoded, &cbWritten, NULL)) || (cbEncoded != cbWritten)) { fRet = FALSE; }
CloseHandle(hFile);
if (fRet) { SetLastError(lErr); } } }
delete pbEncoded;
return(fRet); }
CatalogFreeCTL(&sCTLInfo); }
return(FALSE); }
BOOL CatalogLoadData(WCHAR *pwszCatFile, DWORD *cbData, BYTE **pbData) { HANDLE hFile;
*cbData = 0;
if ((hFile = CreateFileU(pwszCatFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE) { return(FALSE); }
if ((*cbData = GetFileSize(hFile, NULL)) == 0xffffffff) { *cbData = 0; CloseHandle(hFile); return(FALSE); }
if (*cbData < 10) { //
// just created file....
//
*cbData = 0; CloseHandle(hFile); return(TRUE); }
HANDLE hMappedFile;
hMappedFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!(hMappedFile) || (hMappedFile == INVALID_HANDLE_VALUE)) { *cbData = 0; CloseHandle(hFile); return(FALSE); }
*pbData = (BYTE *)MapViewOfFile(hMappedFile, FILE_MAP_READ, 0, 0, 0);
CloseHandle(hMappedFile);
CloseHandle(hFile);
if ((*pbData) == NULL) { return(FALSE); }
return(TRUE); }
BOOL CatalogFillCatStore(CRYPTCATSTORE *pCat, CTL_INFO *pCTL) { int iAttr;
if (pCTL->cCTLEntry > 0) { for (iAttr = 0; iAttr < (int)pCTL->cExtension; iAttr++) { if (!(CatalogFillCatAttr(pCat, &pCTL->rgExtension[iAttr]))) { return(FALSE); } }
CRYPTCATMEMBER *pMember;
for (int iEntry = 0; iEntry < (int)pCTL->cCTLEntry; iEntry++) { pMember = CatalogFillCatMember(pCat, &pCTL->rgCTLEntry[iEntry]);
if (!(pMember)) { return(FALSE); }
if (pCTL->rgCTLEntry[iEntry].cAttribute > 0) { for (iAttr = 0; iAttr < (int)pCTL->rgCTLEntry[iEntry].cAttribute; iAttr++) { if (!(CatalogFillMemAttr(pCat, pMember, &pCTL->rgCTLEntry[iEntry].rgAttribute[iAttr]))) { return(FALSE); } } } }
return(TRUE); }
return(TRUE); }
CRYPTCATMEMBER *CatalogFillCatMember(CRYPTCATSTORE *pCat, CTL_ENTRY *pEntry) { if (!(pEntry)) { return(NULL); }
Stack_ *pStack; CRYPTCATMEMBER *pCatMember;
if (!(pCat->hReserved)) { pStack = new Stack_(&MSCAT_CriticalSection);
if (!(pStack)) { assert(0); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(NULL); }
pCat->hReserved = (HANDLE)pStack; }
pStack = (Stack_ *)pCat->hReserved;
if (!(pCatMember = (CRYPTCATMEMBER *)pStack->Add(sizeof(CRYPTCATMEMBER)))) { return(NULL); }
memset(pCatMember, 0x00, sizeof(CRYPTCATMEMBER));
pCatMember->cbStruct = sizeof(CRYPTCATMEMBER);
// pwszFileName
// pwszReferenceTag
if (!(pCatMember->pwszReferenceTag = (LPWSTR)CatalogNew(pEntry->SubjectIdentifier.cbData))) { return(NULL); }
memcpy(pCatMember->pwszReferenceTag, pEntry->SubjectIdentifier.pbData, pEntry->SubjectIdentifier.cbData);
// pIndirectData (will be filled in while getting attributes!
// gSubjectType (will be filled in while getting attributes!
return(pCatMember); }
BOOL CatalogFillCatAttr(CRYPTCATSTORE *pCat, CERT_EXTENSION *pAttr) { if (!(pAttr)) { return(FALSE); }
Stack_ *pStack; CRYPTCATATTRIBUTE *pCatAttr;
if (!(pCat->hAttrs)) { pStack = new Stack_(&MSCAT_CriticalSection);
if (!(pStack)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); }
pCat->hAttrs = (HANDLE)pStack; }
pStack = (Stack_ *)pCat->hAttrs;
if (!(pCatAttr = (CRYPTCATATTRIBUTE *)pStack->Add(sizeof(CRYPTCATATTRIBUTE)))) { return(FALSE); }
memset(pCatAttr, 0x00, sizeof(CRYPTCATATTRIBUTE));
pCatAttr->cbStruct = sizeof(CRYPTCATATTRIBUTE);
CRYPT_ATTRIBUTE sCryptAttr;
CatalogCertExt2CryptAttr(pAttr, &sCryptAttr);
if (!(CatalogDecodeNameValue(pCat, &sCryptAttr, pCatAttr))) { return(FALSE); }
return(TRUE); }
BOOL CatalogFillMemAttr(CRYPTCATSTORE *pCat, CRYPTCATMEMBER *pMember, CRYPT_ATTRIBUTE *pAttr) { if (!(pAttr)) { return(FALSE); }
if (strcmp(pAttr->pszObjId, SPC_INDIRECT_DATA_OBJID) == 0) { return(CatalogDecodeIndirectData(pCat, pMember, pAttr)); }
if (strcmp(pAttr->pszObjId, CAT_MEMBERINFO_OBJID) == 0) { return(CatalogDecodeMemberInfo(pCat, pMember, pAttr)); }
Stack_ *pStack; CRYPTCATATTRIBUTE *pCatAttr;
if (!(pMember->hReserved)) { pStack = new Stack_(&MSCAT_CriticalSection);
if (!(pStack)) { assert(0); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); }
pMember->hReserved = (HANDLE)pStack; }
pStack = (Stack_ *)pMember->hReserved;
if (!(pCatAttr = (CRYPTCATATTRIBUTE *)pStack->Add(sizeof(CRYPTCATATTRIBUTE)))) { return(FALSE); }
memset(pCatAttr, 0x00, sizeof(CRYPTCATATTRIBUTE));
pCatAttr->cbStruct = sizeof(CRYPTCATATTRIBUTE);
if (!(CatalogDecodeNameValue(pCat, pAttr, pCatAttr))) { return(FALSE); }
return(TRUE); }
BOOL CatalogFillCTL(CRYPTCATSTORE *pCat, CTL_INFO *pCTL) { typedef HRESULT (WINAPI *pfnCoCreateGuid)(GUID FAR *pguid); HINSTANCE hOLE; pfnCoCreateGuid pfnCreateGuid;
memset(pCTL, 0x00, sizeof(CTL_INFO));
// dwVersion
pCTL->dwVersion = CTL_V1;
// SubjectUsage
pCTL->SubjectUsage.cUsageIdentifier = 1; pCTL->SubjectUsage.rgpszUsageIdentifier = (char **)&pszOID;
// ListIdentifier
if (hOLE = LoadLibraryA("OLE32.DLL")) { if (pfnCreateGuid = (pfnCoCreateGuid)GetProcAddress(hOLE, "CoCreateGuid")) { if (pCTL->ListIdentifier.pbData = (BYTE *)CatalogNew(sizeof(GUID))) { pCTL->ListIdentifier.cbData = sizeof(GUID); (*pfnCreateGuid)((GUID *)pCTL->ListIdentifier.pbData); } }
FreeLibrary(hOLE); }
// SequenceNumber
// optional!
// ThisUpdate
GetSystemTimeAsFileTime(&pCTL->ThisUpdate);
// NextUpdate
// optional!
// SubjectAlgorithm
pCTL->SubjectAlgorithm.pszObjId = szOID_CATALOG_LIST_MEMBER;
Stack_ *pStackMember; Stack_ *pStackAttr; CRYPTCATMEMBER *pMember; CRYPTCATATTRIBUTE *pAttr; DWORD dwAttr;
// cCTLEntry & rgCTLEntry
if (pCat->hReserved) { pStackMember = (Stack_ *)pCat->hReserved;
// cCTLEntry
pCTL->cCTLEntry = pStackMember->Count();
if (pCTL->cCTLEntry > 0) { if (!(pCTL->rgCTLEntry = (PCTL_ENTRY)CatalogNew(sizeof(CTL_ENTRY) * pStackMember->Count()))) { return(FALSE); }
memset(pCTL->rgCTLEntry, 0x00, sizeof(CTL_ENTRY) * pStackMember->Count()); }
DWORD dwMember; DWORD dwSize; CTL_ENTRY *pCTLEntry; //
// copy the members to the ctl_entry
//
dwMember = 0;
while (dwMember < pStackMember->Count()) { if (!(pMember = (CRYPTCATMEMBER *)pStackMember->Get(dwMember))) { return(FALSE); }
//
// Subject Identifier
//
dwSize = (wcslen(pMember->pwszReferenceTag) + 1) * sizeof(WCHAR);
pCTLEntry = &pCTL->rgCTLEntry[dwMember];
if (!(pCTLEntry->SubjectIdentifier.pbData = (BYTE *)CatalogNew(dwSize))) { return(FALSE); }
memcpy(pCTLEntry->SubjectIdentifier.pbData, pMember->pwszReferenceTag,dwSize); pCTLEntry->SubjectIdentifier.cbData = dwSize;
//
// rgAttribute
// +1 for Indirect Data
// +1 for Subject Guid
//
if (pMember->hReserved) { pStackAttr = (Stack_ *)pMember->hReserved;
pCTLEntry->cAttribute = pStackAttr->Count() + CAT_RESERVE_CTL_ATTR; } else { pCTLEntry->cAttribute = CAT_RESERVE_CTL_ATTR; }
if (!(pCTLEntry->rgAttribute = (PCRYPT_ATTRIBUTE)CatalogNew(sizeof(CRYPT_ATTRIBUTE) * pCTLEntry->cAttribute))) { return(FALSE); }
memset(pCTLEntry->rgAttribute, 0x00, sizeof(CRYPT_ATTRIBUTE) * pCTLEntry->cAttribute);
//
// put our indirect data in an authenticated attribute
//
if (!(pMember->pIndirectData)) { CatalogReallyDecodeIndirectData(pCat, pMember, &pMember->sEncodedIndirectData); }
CatalogEncodeIndirectData(pCat, pMember, &pCTLEntry->rgAttribute[0]);
//
// put our subject guid in an authenticated attribute
//
if ((pMember->gSubjectType.Data1 == 0) && (pMember->gSubjectType.Data2 == 0) && (pMember->gSubjectType.Data3 == 0)) { CatalogReallyDecodeMemberInfo(pCat, pMember, &pMember->sEncodedMemberInfo); }
CatalogEncodeMemberInfo(pCat, pMember, &pCTLEntry->rgAttribute[1]);
if (pMember->hReserved) { dwAttr = 0;
while (dwAttr < pStackAttr->Count()) { pAttr = (CRYPTCATATTRIBUTE *)pStackAttr->Get(dwAttr);
CatalogFillCTLAttr(pCat, pAttr, &pCTLEntry->rgAttribute[dwAttr + CAT_RESERVE_CTL_ATTR]);
//
// increment our attribute counter!
//
dwAttr++; } }
//
// increment our member counter!
//
dwMember++; } }
//
// cExtension
// rgExtension
//
if (pCat->hAttrs) { pStackAttr = (Stack_ *)pCat->hAttrs;
pCTL->cExtension = pStackAttr->Count();
if (!(pCTL->rgExtension = (CERT_EXTENSION *)CatalogNew(sizeof(CERT_EXTENSION) * pCTL->cExtension))) { return(FALSE); }
memset(pCTL->rgExtension, 0x00, sizeof(CERT_EXTENSION) * pCTL->cExtension);
dwAttr = 0;
while (dwAttr < pStackAttr->Count()) { pAttr = (CRYPTCATATTRIBUTE *)pStackAttr->Get(dwAttr);
if (pAttr) { CatalogFillCatLevelAttr(pCat, pAttr, &pCTL->rgExtension[dwAttr]); }
dwAttr++; } }
return(TRUE); }
BOOL CatalogFillCatLevelAttr(CRYPTCATSTORE *pCatStore, CRYPTCATATTRIBUTE *pAttr, CERT_EXTENSION *pCertAttr) { CRYPT_ATTR_BLOB sAttrBlob; CRYPT_ATTRIBUTE sCryptAttr;
memset(&sAttrBlob, 0x00, sizeof(CRYPT_ATTR_BLOB)); memset(&sCryptAttr, 0x00, sizeof(CRYPT_ATTRIBUTE));
sCryptAttr.cValue = 1; sCryptAttr.rgValue = &sAttrBlob;
if (!(CatalogEncodeNameValue(pCatStore, pAttr, &sCryptAttr))) { return(FALSE); }
CatalogCryptAttr2CertExt(&sCryptAttr, pCertAttr);
return(TRUE); }
BOOL CatalogFillCTLAttr(CRYPTCATSTORE *pCatStore, CRYPTCATATTRIBUTE *pAttr, PCRYPT_ATTRIBUTE pCryptAttr) { if (!(pCryptAttr->rgValue = (PCRYPT_ATTR_BLOB)CatalogNew(sizeof(CRYPT_ATTR_BLOB)))) { return(FALSE); }
pCryptAttr->cValue = 1;
memset(pCryptAttr->rgValue, 0x00, sizeof(CRYPT_ATTR_BLOB));
if (!(CatalogEncodeNameValue(pCatStore, pAttr, pCryptAttr))) { return(FALSE); }
return(TRUE); }
BOOL CatalogFreeCTL(CTL_INFO *pCTL) { DWORD dwEntries; DWORD dwAttributes; CTL_ENTRY *pCTLEntry;
DELETE_OBJECT(pCTL->ListIdentifier.pbData);
dwEntries = pCTL->cCTLEntry;
while (dwEntries > 0) { pCTLEntry = &pCTL->rgCTLEntry[dwEntries - 1];
DELETE_OBJECT(pCTLEntry->SubjectIdentifier.pbData);
dwAttributes = pCTLEntry->cAttribute;
while (dwAttributes > 0) { CatalogFreeCTLAttr(&pCTLEntry->rgAttribute[dwAttributes - 1]);
dwAttributes--; }
DELETE_OBJECT(pCTLEntry->rgAttribute);
dwEntries--; }
DELETE_OBJECT(pCTL->rgCTLEntry);
for (dwEntries = 0; dwEntries < pCTL->cExtension; dwEntries++) { DELETE_OBJECT(pCTL->rgExtension[dwEntries].Value.pbData); }
DELETE_OBJECT(pCTL->rgExtension);
return(TRUE); }
BOOL CatalogFreeCTLAttr(CRYPT_ATTRIBUTE *pCryptAttr) { if (!(pCryptAttr)) { return(FALSE); }
if (pCryptAttr->rgValue) { DELETE_OBJECT(pCryptAttr->rgValue->pbData); DELETE_OBJECT(pCryptAttr->rgValue); }
return(TRUE); }
BOOL WINAPI IsCatalogFile(HANDLE hFile, WCHAR *pwszCatalogFile) { char *pszCatalogListUsageOID = szOID_CATALOG_LIST; BOOL fCloseFile; BOOL fRet; DWORD cbRead; DWORD cbFile; BYTE *pbFile; PCCTL_CONTEXT pCTLContext;
//
// put a try-except around everything in case there is problems with the
// memory mapped file
//
__try {
pCTLContext = NULL; pbFile = NULL; fCloseFile = FALSE; fRet = FALSE;
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) { if (!(pwszCatalogFile)) { goto IsCatInvalidParam; }
if ((hFile = CreateFileU(pwszCatalogFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { goto IsCatFileError; }
fCloseFile = TRUE; }
HANDLE hMappedFile;
hMappedFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!(hMappedFile) || (hMappedFile == INVALID_HANDLE_VALUE)) { goto CreateFileMapFailed; }
pbFile = (BYTE *)MapViewOfFile(hMappedFile, FILE_MAP_READ, 0, 0, 0);
CloseHandle(hMappedFile);
if (!(pbFile)) { goto MapViewFailed; }
if (((cbFile = GetFileSize(hFile, NULL)) == 0xffffffff) || (cbFile < 1)) { goto FileSizeError; }
if (pbFile[0] != (BYTE)0x30) { goto IsCatNotCatalog; }
pCTLContext = (PCCTL_CONTEXT) CertCreateContext( CERT_STORE_CTL_CONTEXT, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, pbFile, cbFile, CERT_CREATE_CONTEXT_NOCOPY_FLAG | CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG | CERT_CREATE_CONTEXT_NO_ENTRY_FLAG, NULL // pCreatePara
);
if (pCTLContext) { if (pCTLContext->pCtlInfo->SubjectUsage.cUsageIdentifier) { if (strcmp(pCTLContext->pCtlInfo->SubjectUsage.rgpszUsageIdentifier[0], pszCatalogListUsageOID) == 0) { fRet = TRUE; goto CommonReturn; } } }
goto IsCatNotCatalog;
} __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); goto ErrorReturn; }
CommonReturn:
if (pCTLContext) { CertFreeCTLContext(pCTLContext); }
if (pbFile) { UnmapViewOfFile(pbFile); }
if (fCloseFile) { CloseHandle(hFile); }
return(fRet);
ErrorReturn: fRet = FALSE; goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, IsCatNotCatalog); TRACE_ERROR_EX(DBG_SS, IsCatFileError); TRACE_ERROR_EX(DBG_SS, CreateFileMapFailed); TRACE_ERROR_EX(DBG_SS, MapViewFailed);
SET_ERROR_VAR_EX(DBG_SS, IsCatInvalidParam, ERROR_INVALID_PARAMETER); SET_ERROR_VAR_EX(DBG_SS, FileSizeError, ERROR_INVALID_PARAMETER); }
|