|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: mscdfapi.cpp
//
// Contents: Microsoft Internet Security Catalog Utilities
//
// Functions: CryptCATCDFOpen
// CryptCATCDFClose
// CryptCATCDFEnumMembers
// CryptCATCDFEnumAttributes
//
// *** local functions ***
//
// CDFGetAttributes
// CDFTextToGUID
// CDFPositionAtGroupTag
// CDFGetNextMember
// CDFGetParam
// CDFGetLine
// CDFSplitAttrLine
// CDFEOLOut
// CDFCheckOID
// CDFCalcIndirectData
//
// History: 01-May-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include <objbase.h>
#include "mscat32.h"
#include "sipguids.h"
#define STRSAFE_NO_DEPRECATE
#include <strsafe.h>
void CDFTextToGUID(LPWSTR pwszText, GUID *pgBin, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError); BOOL CDFPositionAtGroupTag(CRYPTCATCDF *pCDF, LPWSTR pwszTag); BOOL CDFPositionAtLastMember(CRYPTCATCDF *pCDF); BOOL CDFGetNextMember(CRYPTCATCDF *pCDF, LPWSTR pwszMember, int cchMember, LPWSTR pwszLastMember); BOOL CDFGetParam(CRYPTCATCDF *pCDF, LPWSTR pwszGroup, LPWSTR pwszItem, LPWSTR pwszDefault, LPWSTR *ppwszRet, LPWSTR pwszMemberTag); DWORD CDFGetLine(CRYPTCATCDF *pCDF, LPWSTR pwszLineBuf, DWORD dwMaxRead); BOOL CDFSplitAttrLine(LPWSTR pwszLine, DWORD *pdwType, LPWSTR *pwszOID, LPWSTR *pwszValue, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError); void CDFEOLOut(WCHAR *pwsz, DWORD ccLen);
BOOL CDFCalcIndirectData(CRYPTCATCDF *pCDF, WCHAR *pwszFileName, GUID *pgSubjectType, DWORD *pcbIndirectData, BYTE **pIndirectData, DWORD *pdwCertVersion, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError);
BOOL CDFCheckOID(LPWSTR pwszOID, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError);
#define MAX_CDF_LINE_LEN 512
#define CAT_HEADER_TAG L"[CatalogHeader]"
#define CAT_HEADER_NAME_TAG L"Name"
#define CAT_HEADER_RESDIR_TAG L"ResultDir"
#define CAT_HEADER_VERSION_TAG L"PublicVersion"
#define CAT_HEADER_ENCODETYPE_TAG L"EncodingType"
#define CAT_HEADER_ATTR_TAG L"CATATTR"
#define CAT_MEMBER_TAG L"[CatalogFiles]"
#define CAT_MEMBER_ALTSIP_TAG L"ALTSIPID"
#define CAT_MEMBER_ATTR_TAG L"ATTR"
#define CAT_MEMBER_HASH_TAG L"<HASH>"
/////////////////////////////////////////////////////////////////////////////
//
// Exported Functions
//
CRYPTCATCDF * WINAPI CryptCATCDFOpen(LPWSTR pwszFilePath, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { CRYPTCATCDF *pCDF; HANDLE hFile;
if (!(pwszFilePath)) { SetLastError(ERROR_INVALID_PARAMETER);
return(NULL); }
if ((hFile = CreateFileU(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { return(NULL); }
if (!(pCDF = (CRYPTCATCDF *)CatalogNew(sizeof(CRYPTCATCDF)))) { return(NULL); }
WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; LPWSTR pwsz;
memset(pCDF, 0x00, sizeof(CRYPTCATCDF));
pCDF->cbStruct = sizeof(CRYPTCATCDF); pCDF->hFile = hFile;
//
// Name
//
if (pwsz = wcsrchr(pwszFilePath, L'\\')) { if (FAILED(StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, &pwsz[1]))) { CloseHandle(hFile); delete pCDF; return(NULL); } } else { if (FAILED(StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszFilePath))) { CloseHandle(hFile); delete pCDF; return(NULL); } }
LPWSTR pwszStoreName;
pwszStoreName = NULL;
if (!(CDFPositionAtGroupTag(pCDF, CAT_HEADER_TAG))) { CloseHandle(hFile);
delete pCDF;
if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_HEADER, CRYPTCAT_E_CDF_TAGNOTFOUND, CAT_HEADER_TAG); }
return(NULL); }
if (!(CDFGetParam(pCDF, CAT_HEADER_TAG, CAT_HEADER_NAME_TAG, &wszRetValue[0], &pwszStoreName, NULL))) { DELETE_OBJECT(pwszStoreName);
CloseHandle(hFile);
delete pCDF;
if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_HEADER, CRYPTCAT_E_CDF_TAGNOTFOUND, CAT_HEADER_TAG); }
return(NULL); }
//
// ResultDir
//
CDFPositionAtGroupTag(pCDF, CAT_HEADER_TAG); CDFGetParam(pCDF, CAT_HEADER_TAG, CAT_HEADER_RESDIR_TAG, NULL, &pCDF->pwszResultDir, NULL);
//
// actual file
//
DWORD cw; LPWSTR pwszFile = NULL;
cw = wcslen( pwszStoreName ); if ( pCDF->pwszResultDir != NULL ) { cw += wcslen( pCDF->pwszResultDir ); } cw += wcslen( CRYPTCAT_FILEEXT ); cw += 3;
pwszFile = new WCHAR [ cw ]; if ( pwszFile == NULL ) { DELETE_OBJECT(pwszStoreName);
CloseHandle(hFile);
delete pCDF;
return( NULL ); }
pwszFile[ 0 ] = L'\0';
if (pCDF->pwszResultDir) { wcscpy(pwszFile, pCDF->pwszResultDir);
if (pCDF->pwszResultDir[wcslen(pCDF->pwszResultDir) - 1] != L'\\') { wcscat(pwszFile, L"\\"); } }
wcscat(pwszFile, pwszStoreName);
if (!(wcsrchr(pwszFile, '.'))) { wcscat(pwszFile, L"."); wcscat(pwszFile, CRYPTCAT_FILEEXT); }
DWORD dwPublicVersion; DWORD dwEncodingType;
//
// PublicVersion
//
CDFPositionAtGroupTag(pCDF, CAT_HEADER_TAG); wcscpy(&wszRetValue[0], L"0x00000001"); CDFGetParam(pCDF, CAT_HEADER_TAG, CAT_HEADER_VERSION_TAG, &wszRetValue[0], &pwsz, NULL); if (pwsz) { dwPublicVersion = wcstol(pwsz, NULL, 16); delete pwsz; }
//
// EncodingType
//
CDFPositionAtGroupTag(pCDF, CAT_HEADER_TAG); wcscpy(&wszRetValue[0], L"0x00010001"); // PKCS_7_ASN_ENCODING | X509_ASN_ENCODING
CDFGetParam(pCDF, CAT_HEADER_TAG, CAT_HEADER_ENCODETYPE_TAG, &wszRetValue[0], &pwsz, NULL); if (pwsz) { dwEncodingType = wcstol(pwsz, NULL, 16); delete pwsz; }
pCDF->hCATStore = CryptCATOpen(pwszFile, CRYPTCAT_OPEN_CREATENEW, NULL, dwPublicVersion, dwEncodingType);
delete pwszStoreName; delete pwszFile;
if ((pCDF->hCATStore == INVALID_HANDLE_VALUE) || (!(pCDF->hCATStore))) { CryptCATCDFClose(pCDF); pCDF = NULL; }
return(pCDF); }
BOOL WINAPI CryptCATCDFClose(CRYPTCATCDF *pCDF) { BOOL fRet;
if (!(pCDF) || (pCDF->cbStruct != sizeof(CRYPTCATCDF))) { SetLastError(ERROR_INVALID_PARAMETER); return(FALSE); }
fRet = TRUE;
if ((pCDF->hFile) && (pCDF->hFile != INVALID_HANDLE_VALUE)) { fRet &= CloseHandle(pCDF->hFile); }
if ((pCDF->hCATStore) && (pCDF->hCATStore != INVALID_HANDLE_VALUE)) { fRet &= CatalogSaveP7UData((CRYPTCATSTORE *)pCDF->hCATStore);
fRet &= CryptCATClose(pCDF->hCATStore); }
DELETE_OBJECT(pCDF->pwszResultDir);
delete pCDF;
return(fRet); }
CRYPTCATATTRIBUTE * WINAPI CryptCATCDFEnumCatAttributes(CRYPTCATCDF *pCDF, CRYPTCATATTRIBUTE *pPrevAttr, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { if (!(pCDF) || (pCDF->cbStruct != sizeof(CRYPTCATCDF))) { SetLastError(ERROR_INVALID_PARAMETER); return(NULL); }
LPWSTR pwsz; LPWSTR pwszOID; LPWSTR pwszValue; int iAttr; WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; WCHAR wszTemp[64]; DWORD dwType; CRYPTCATATTRIBUTE *pAttr;
iAttr = (pPrevAttr) ? pPrevAttr->dwReserved + 1 : 1;
wcscpy(&wszRetValue[0], CAT_HEADER_ATTR_TAG); wcscat(&wszRetValue[0], _itow(iAttr, &wszTemp[0], 10));
pwsz = NULL; pAttr = NULL;
CDFPositionAtGroupTag(pCDF, CAT_HEADER_TAG); if (CDFGetParam(pCDF, CAT_HEADER_TAG, &wszRetValue[0], NULL, &pwsz, NULL)) { if (pwsz) { if (CDFSplitAttrLine(pwsz, &dwType, &pwszOID, &pwszValue, pfnParseError)) { if (dwType & CRYPTCAT_ATTR_NAMEOBJID) { //
// make sure we have a valid objid in the name.
// we might do something better than this (???)
//
if (!(CDFCheckOID(pwszOID, pfnParseError))) { delete pwsz;
return(NULL); } }
if (dwType & CRYPTCAT_ATTR_UNAUTHENTICATED) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_UNSUPPORTED, pwsz); } } else if (((dwType & CRYPTCAT_ATTR_NAMEOBJID) || (dwType & CRYPTCAT_ATTR_NAMEASCII)) &&
((dwType & CRYPTCAT_ATTR_DATABASE64) || (dwType & CRYPTCAT_ATTR_DATAASCII))) { pAttr = CryptCATPutCatAttrInfo(pCDF->hCATStore, pwszOID, dwType, (wcslen(pwszValue) + 1) * sizeof(WCHAR), (BYTE *)pwszValue); if (pAttr) { pAttr->dwReserved = iAttr; } } else { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TYPECOMBO, pwsz); } } } } }
DELETE_OBJECT(pwsz);
return(pAttr); }
CRYPTCATMEMBER * WINAPI CryptCATCDFEnumMembers(CRYPTCATCDF *pCDF, CRYPTCATMEMBER *pPrevMember, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { LPWSTR pwszLastTag;
pwszLastTag = NULL;
if (pPrevMember) { if (pPrevMember->cbStruct != sizeof(CRYPTCATMEMBER)) { SetLastError(ERROR_INVALID_PARAMETER);
return(NULL); }
if (pPrevMember->pwszReferenceTag) { if (!(pwszLastTag = (LPWSTR)CatalogNew(wcslen(pPrevMember->pwszReferenceTag) * sizeof(WCHAR) + 4))) { return(NULL); }
wcscpy(pwszLastTag, pPrevMember->pwszReferenceTag); } }
if (!(pCDF) || (pCDF->hFile == INVALID_HANDLE_VALUE) || !(pCDF->hFile)) { DELETE_OBJECT(pwszLastTag);
SetLastError(ERROR_INVALID_PARAMETER);
return(NULL); }
WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4];
CDFPositionAtLastMember(pCDF);
if (CDFGetNextMember(pCDF, &wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszLastTag)) { LPWSTR pwsz;
DELETE_OBJECT(pwszLastTag);
//
// file path/name (required!)
//
CDFPositionAtLastMember(pCDF); if (!(CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, &wszRetValue[0]))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_FILE_PATH, &wszRetValue[0]); } } else { CRYPTCATMEMBER *pMember; WCHAR *pwszFileName; WCHAR *pwszReferenceTag; GUID gSubjectType; HANDLE hFile;
//
// file path/name
//
pwszFileName = pwsz; // remember: don't delete pwsz this time!
if ((hFile = CreateFileU(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_FILENOTFOUND, pwszFileName); }
DELETE_OBJECT(pwszFileName);
return(NULL); }
CloseHandle(hFile);
//
// reference tag
//
if (!(pwszReferenceTag = (LPWSTR)CatalogNew((wcslen(&wszRetValue[0]) + 1) * sizeof(WCHAR)))) { DELETE_OBJECT(pwszFileName);
return(NULL); }
wcscpy(pwszReferenceTag, &wszRetValue[0]);
//
// Alt SIP GUID
//
if (FAILED(StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszReferenceTag))) { DELETE_OBJECT(pwszFileName); return(NULL); } if (FAILED(StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, CAT_MEMBER_ALTSIP_TAG))) { DELETE_OBJECT(pwszFileName); return(NULL); }
CDFPositionAtLastMember(pCDF); CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, pwszReferenceTag);
if (pwsz) { CDFTextToGUID(pwsz, &gSubjectType, pfnParseError);
DELETE_OBJECT(pwszFileName);
DELETE_OBJECT(pwsz); } else { if (!(CryptSIPRetrieveSubjectGuidForCatalogFile(pwszFileName, NULL, &gSubjectType))) { return(NULL); } }
//
// Indirect Data
//
BYTE *pbIndirectData; DWORD cbIndirectData; DWORD dwCertVersion;
if (!(CDFCalcIndirectData(pCDF, pwszFileName, &gSubjectType, &cbIndirectData, &pbIndirectData, &dwCertVersion, pfnParseError))) { DELETE_OBJECT(pwszReferenceTag); DELETE_OBJECT(pwszFileName);
return(NULL); }
pMember = CryptCATPutMemberInfo(pCDF->hCATStore, pwszFileName, pwszReferenceTag, &gSubjectType, dwCertVersion, cbIndirectData, pbIndirectData);
if (!(pMember) && (GetLastError() == CRYPT_E_EXISTS)) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_DUPLICATE, pwszReferenceTag); } }
DELETE_OBJECT(pbIndirectData);
//
// Done!
//
DELETE_OBJECT(pwszReferenceTag); DELETE_OBJECT(pwszFileName);
return(pMember); } }
DELETE_OBJECT(pwszLastTag);
return(NULL); }
LPWSTR WINAPI CryptCATCDFEnumMembersByCDFTagEx(CRYPTCATCDF *pCDF, LPWSTR pwszPrevCDFTag, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError, CRYPTCATMEMBER** ppMember, BOOL fContinueOnError, LPVOID pvReserved) { LPWSTR pwszLastTag;
pwszLastTag = pwszPrevCDFTag;
if (!(pCDF) || (pCDF->hFile == INVALID_HANDLE_VALUE) || !(pCDF->hFile)) { DELETE_OBJECT(pwszLastTag);
SetLastError(ERROR_INVALID_PARAMETER);
return(NULL); }
WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4];
CDFPositionAtLastMember(pCDF);
if (CDFGetNextMember(pCDF, &wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszLastTag)) { LPWSTR pwsz;
DELETE_OBJECT(pwszLastTag);
//
// file path/name (required!)
//
CDFPositionAtLastMember(pCDF); if (!(CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, &wszRetValue[0]))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_FILE_PATH, &wszRetValue[0]); }
SetLastError(E_FAIL); return(NULL); } else { CRYPTCATMEMBER *pMember; WCHAR *pwszFileName; WCHAR *pwszReferenceTag; GUID gSubjectType; HANDLE hFile; HRESULT hr;
//
// reference tag
//
if (!(pwszReferenceTag = (LPWSTR)CatalogNew((wcslen(&wszRetValue[0]) + 1) * sizeof(WCHAR)))) { // LastError is set by CatalogNew
return(NULL); }
wcscpy(pwszReferenceTag, &wszRetValue[0]);
//
// From this point on we have the option of continuing on error.
//
//
// file path/name
//
pwszFileName = pwsz; // remember: don't delete pwsz this time!
if ((hFile = CreateFileU(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_FILENOTFOUND, pwszFileName); }
DELETE_OBJECT(pwszFileName);
if ( fContinueOnError == FALSE ) { DELETE_OBJECT(pwszReferenceTag); pwszReferenceTag = NULL; }
// LastError is set by CreateFile
return(pwszReferenceTag); }
CloseHandle(hFile);
//
// Alt SIP GUID
//
if (FAILED(hr = StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszReferenceTag))) { DELETE_OBJECT(pwszReferenceTag); SetLastError(HRESULT_CODE(hr)); return(NULL); } if (FAILED(hr = StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, CAT_MEMBER_ALTSIP_TAG))) { DELETE_OBJECT(pwszReferenceTag); SetLastError(HRESULT_CODE(hr)); return(NULL); }
CDFPositionAtLastMember(pCDF); CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, pwszReferenceTag);
if (pwsz) { CDFTextToGUID(pwsz, &gSubjectType, pfnParseError); // If this call fails, we won't know about it
// but the caller will get a pfnParseError call.
DELETE_OBJECT(pwszFileName);
DELETE_OBJECT(pwsz); } else { if (!(CryptSIPRetrieveSubjectGuidForCatalogFile(pwszFileName, NULL, &gSubjectType))) { if ( fContinueOnError == FALSE ) { DELETE_OBJECT(pwszReferenceTag); pwszReferenceTag = NULL; }
DELETE_OBJECT(pwszFileName);
SetLastError(E_FAIL); return(pwszReferenceTag); } }
//
// Indirect Data
//
BYTE *pbIndirectData; DWORD cbIndirectData; DWORD dwCertVersion; SIP_INDIRECT_DATA* pIndirectData; LPWSTR pwszTagToPut; BOOL fHashTagUsed = FALSE;
if (!(CDFCalcIndirectData(pCDF, pwszFileName, &gSubjectType, &cbIndirectData, &pbIndirectData, &dwCertVersion, pfnParseError))) { DELETE_OBJECT(pwszFileName);
if ( fContinueOnError == FALSE ) { DELETE_OBJECT(pwszReferenceTag); pwszReferenceTag = NULL; }
SetLastError(E_FAIL); return(pwszReferenceTag); }
pIndirectData = (SIP_INDIRECT_DATA *)pbIndirectData; pwszTagToPut = pwszReferenceTag;
if (_wcsnicmp(pwszReferenceTag, CAT_MEMBER_HASH_TAG, wcslen(CAT_MEMBER_HASH_TAG)) == 0) { fHashTagUsed = TRUE;
if (MsCatConstructHashTag( pIndirectData->Digest.cbData, pIndirectData->Digest.pbData, &pwszTagToPut ) == FALSE) { DELETE_OBJECT(pwszFileName);
if ( fContinueOnError == FALSE ) { DELETE_OBJECT(pwszReferenceTag); pwszReferenceTag = NULL; }
SetLastError(E_FAIL); return(pwszReferenceTag); } }
pMember = CryptCATPutMemberInfo(pCDF->hCATStore, pwszFileName, pwszTagToPut, &gSubjectType, dwCertVersion, cbIndirectData, pbIndirectData);
if (!(pMember) && (GetLastError() == CRYPT_E_EXISTS)) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_DUPLICATE, pwszReferenceTag); } }
//
// Some Cleanup to do regardless of error
//
DELETE_OBJECT(pbIndirectData);
if ( fHashTagUsed == TRUE ) { MsCatFreeHashTag(pwszTagToPut); }
DELETE_OBJECT(pwszFileName);
//
// Final error determination
//
if (pMember) { *ppMember = pMember; SetLastError(ERROR_SUCCESS); } else { if ( fContinueOnError == FALSE ) { DELETE_OBJECT(pwszReferenceTag); pwszReferenceTag = NULL; }
SetLastError(E_FAIL); }
//
// Done!
//
return(pwszReferenceTag); } } else { // Successful completion of CDF. This means we hit the last member.
DELETE_OBJECT(pwszLastTag);
SetLastError(ERROR_SUCCESS); return(NULL); }
// Execution never reaches this point.
// The if/else above always returns.
}
LPWSTR WINAPI CryptCATCDFEnumMembersByCDFTag(CRYPTCATCDF *pCDF, LPWSTR pwszPrevCDFTag, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError, CRYPTCATMEMBER** ppMember) { return(CryptCATCDFEnumMembersByCDFTagEx(pCDF, pwszPrevCDFTag, pfnParseError, ppMember, FALSE, NULL)); }
BOOL CDFCalcIndirectData(CRYPTCATCDF *pCDF, WCHAR *pwszFileName, GUID *pgSubjectType, DWORD *pcbIndirectData, BYTE **ppbIndirectData, DWORD *pdwCertVersion, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { SIP_SUBJECTINFO sSubjInfo; SIP_DISPATCH_INFO sSip; CRYPTCATSTORE *pCatStore;
*pcbIndirectData = 0; *ppbIndirectData = NULL;
pCatStore = (CRYPTCATSTORE *)pCDF->hCATStore;
memset(&sSubjInfo, 0x00, sizeof(SIP_SUBJECTINFO)); memset(&sSip, 0x00, sizeof(SIP_DISPATCH_INFO));
sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO);
sSubjInfo.hProv = pCatStore ->hProv; sSubjInfo.DigestAlgorithm.pszObjId = (char *)CertAlgIdToOID(CALG_SHA1); sSubjInfo.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG | MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE; sSubjInfo.dwEncodingType = pCatStore->dwEncodingType;
sSubjInfo.pgSubjectType = pgSubjectType; sSubjInfo.pwsFileName = pwszFileName;
if (!(CryptSIPLoad(pgSubjectType, 0, &sSip))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_INDIRECTDATA, pwszFileName); } return(FALSE); }
sSip.pfCreate(&sSubjInfo, pcbIndirectData, NULL);
if (*pcbIndirectData < 1) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_INDIRECTDATA, pwszFileName); } return(FALSE); }
if (!(*ppbIndirectData = (BYTE *)CatalogNew(*pcbIndirectData))) { *pcbIndirectData = 0;
if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_INDIRECTDATA, pwszFileName); } return(FALSE); }
if (!(sSip.pfCreate(&sSubjInfo, pcbIndirectData, (SIP_INDIRECT_DATA *)*ppbIndirectData))) { DELETE_OBJECT(*ppbIndirectData);
*pcbIndirectData = 0;
if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_MEMBER, CRYPTCAT_E_CDF_MEMBER_INDIRECTDATA, pwszFileName); } return(FALSE); }
*pdwCertVersion = sSubjInfo.dwIntVersion;
return(TRUE); }
CRYPTCATATTRIBUTE * WINAPI CryptCATCDFEnumAttributes(CRYPTCATCDF *pCDF, CRYPTCATMEMBER *pMember, CRYPTCATATTRIBUTE *pPrevAttr, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { if (!(pCDF) || (pCDF->cbStruct != sizeof(CRYPTCATCDF)) || !(pMember) || (pMember->cbStruct != sizeof(CRYPTCATMEMBER))) { SetLastError(ERROR_INVALID_PARAMETER); return(NULL); }
LPWSTR pwsz; LPWSTR pwszOID; LPWSTR pwszValue; int iAttr; WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; WCHAR wszTemp[64]; DWORD dwType; CRYPTCATATTRIBUTE *pAttr;
iAttr = (pPrevAttr) ? pPrevAttr->dwReserved + 1 : 1;
if (FAILED(StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, pMember->pwszReferenceTag))) { return(NULL); } if (FAILED(StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, L"ATTR"))) { return(NULL); } if (FAILED(StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, _itow(iAttr, &wszTemp[0], 10)))) { return(NULL); }
pwsz = NULL; pAttr = NULL;
CDFPositionAtLastMember(pCDF); if (CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, pMember->pwszReferenceTag)) { if (pwsz) { if (CDFSplitAttrLine(pwsz, &dwType, &pwszOID, &pwszValue, pfnParseError)) { if (dwType & CRYPTCAT_ATTR_NAMEOBJID) { //
// make sure we have a valid objid in the name.
// we might do something better than this (???)
//
if (!(CDFCheckOID(pwszOID, pfnParseError))) { delete pwsz;
return(NULL); } }
if (dwType & CRYPTCAT_ATTR_UNAUTHENTICATED) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_UNSUPPORTED, pwsz); } } else if (((dwType & CRYPTCAT_ATTR_NAMEOBJID) || (dwType & CRYPTCAT_ATTR_NAMEASCII)) &&
((dwType & CRYPTCAT_ATTR_DATABASE64) || (dwType & CRYPTCAT_ATTR_DATAASCII))) { pAttr = CryptCATPutAttrInfo(pCDF->hCATStore, pMember, pwszOID, dwType, (wcslen(pwszValue) + 1) * sizeof(WCHAR), (BYTE *)pwszValue); if (pAttr) { pAttr->dwReserved = iAttr; } } else { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TYPECOMBO, pwsz); } } } } }
DELETE_OBJECT(pwsz);
return(pAttr); }
CRYPTCATATTRIBUTE * WINAPI CryptCATCDFEnumAttributesWithCDFTag(CRYPTCATCDF *pCDF, LPWSTR pwszMemberTag, CRYPTCATMEMBER *pMember, CRYPTCATATTRIBUTE *pPrevAttr, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { if (!(pCDF) || (pCDF->cbStruct != sizeof(CRYPTCATCDF)) || !(pwszMemberTag) || !(pMember) || (pMember->cbStruct != sizeof(CRYPTCATMEMBER))) { SetLastError(ERROR_INVALID_PARAMETER); return(NULL); }
LPWSTR pwsz; LPWSTR pwszOID; LPWSTR pwszValue; int iAttr; WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; WCHAR wszTemp[64]; DWORD dwType; CRYPTCATATTRIBUTE *pAttr;
iAttr = (pPrevAttr) ? pPrevAttr->dwReserved + 1 : 1;
if (FAILED(StringCchCopyW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, pwszMemberTag))) { return(NULL); } if (FAILED(StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, L"ATTR"))) { return(NULL); } if (FAILED(StringCchCatW(&wszRetValue[0], MAX_CDF_LINE_LEN + 4, _itow(iAttr, &wszTemp[0], 10)))) { return(NULL); }
pwsz = NULL; pAttr = NULL;
CDFPositionAtLastMember(pCDF); if (CDFGetParam(pCDF, CAT_MEMBER_TAG, &wszRetValue[0], NULL, &pwsz, pwszMemberTag)) { if (pwsz) { if (CDFSplitAttrLine(pwsz, &dwType, &pwszOID, &pwszValue, pfnParseError)) { if (dwType & CRYPTCAT_ATTR_NAMEOBJID) { //
// make sure we have a valid objid in the name.
// we might do something better than this (???)
//
if (!(CDFCheckOID(pwszOID, pfnParseError))) { delete pwsz;
return(NULL); } }
if (dwType & CRYPTCAT_ATTR_UNAUTHENTICATED) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_UNSUPPORTED, pwsz); } } else if (((dwType & CRYPTCAT_ATTR_NAMEOBJID) || (dwType & CRYPTCAT_ATTR_NAMEASCII)) &&
((dwType & CRYPTCAT_ATTR_DATABASE64) || (dwType & CRYPTCAT_ATTR_DATAASCII))) { pAttr = CryptCATPutAttrInfo(pCDF->hCATStore, pMember, pwszOID, dwType, (wcslen(pwszValue) + 1) * sizeof(WCHAR), (BYTE *)pwszValue); if (pAttr) { pAttr->dwReserved = iAttr; } } else { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TYPECOMBO, pwsz); } } } } }
DELETE_OBJECT(pwsz);
return(pAttr); }
/////////////////////////////////////////////////////////////////////////////
//
// Local Functions
//
BOOL CDFCheckOID(LPWSTR pwszOID, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { DWORD cbConv; char *pszOID;
cbConv = WideCharToMultiByte(0, 0, pwszOID, wcslen(pwszOID), NULL, 0, NULL, NULL); if (cbConv < 1) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TYPECOMBO, pwszOID); } return(FALSE); }
if (!(pszOID = (LPSTR)CatalogNew(cbConv))) { return(FALSE); }
WideCharToMultiByte(0, 0, pwszOID, wcslen(pwszOID), pszOID, cbConv, NULL, NULL);
DWORD i; BOOL fRet;
fRet = TRUE; i = 0;
while (i < cbConv) { if (((pszOID[i] < '0') || (pszOID[i] > '9')) && (pszOID[i] != '.')) { fRet = FALSE; break; }
i++; }
delete pszOID;
if (!(fRet)) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TYPECOMBO, pwszOID); } }
return(fRet);
}
BOOL CDFSplitAttrLine(LPWSTR pwszLine, DWORD *pdwType, LPWSTR *ppwszOID, LPWSTR *ppwszValue, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { LPWSTR pwszColon; LPWSTR pwszStart; LPWSTR pwsz;
*pdwType = 0; *ppwszValue = NULL; *ppwszOID = NULL;
if (!(pwsz = (WCHAR *)CatalogNew((wcslen(pwszLine) + 1) * sizeof(WCHAR)))) { return(FALSE); }
wcscpy(pwsz, pwszLine);
pwszStart = pwszLine; //
// first one is type
//
if (!(pwszColon = wcschr(pwszStart, L':'))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TOOFEWVALUES, pwsz); }
delete pwsz;
return(FALSE); }
*pwszColon = NULL; *pdwType = wcstol(pwszStart, NULL, 16);
pwszStart = &pwszColon[1];
//
// next, oid/name
//
if (!(pwszColon = wcschr(pwszStart, L':'))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TOOFEWVALUES, pwsz); }
delete pwsz;
return(FALSE); }
*pwszColon = NULL; *ppwszOID = pwszStart;
pwszStart = &pwszColon[1];
//
// next, value
//
if (!(pwszStart[0])) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_ATTR_TOOFEWVALUES, pwsz); }
delete pwsz;
return(FALSE); }
delete pwsz;
*ppwszValue = pwszStart;
return(TRUE); }
void CDFTextToGUID(LPWSTR pwszText, GUID *pgBin, PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError) { WCHAR wszGuid[256]; GUID gTemp;
memset(pgBin, 0x00, sizeof(GUID));
if ((pwszText[0] != L'[') && (pwszText[0] != L'{')) { if (FAILED(StringCchCopyW(&wszGuid[0], 256, L"{"))) { return; } if (FAILED(StringCchCatW(&wszGuid[0], 256, pwszText))) { return; } if (FAILED(StringCchCatW(&wszGuid[0], 256, L"}"))) { return; } } else { if (FAILED(StringCchCopyW(&wszGuid[0], 256, pwszText))) { return; } }
if (!(wstr2guid(&wszGuid[0], pgBin))) { if (pfnParseError) { pfnParseError(CRYPTCAT_E_AREA_ATTRIBUTE, CRYPTCAT_E_CDF_BAD_GUID_CONV, &wszGuid[0]); } } }
BOOL CDFPositionAtGroupTag(CRYPTCATCDF *pCDF, LPWSTR pwszTag) { if (SetFilePointer(pCDF->hFile, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF) { return(FALSE); }
WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; DWORD ccRet;
while ((ccRet = CDFGetLine(pCDF, &wszRetValue[0], MAX_CDF_LINE_LEN * sizeof(WCHAR))) > 0) { if (wszRetValue[0] == L'#') { continue; }
CDFEOLOut(&wszRetValue[0], ccRet);
if (wszRetValue[0] == L'[') { if (_memicmp(&wszRetValue[0], pwszTag, wcslen(pwszTag) * sizeof(WCHAR)) == 0) { return(TRUE); } } }
return(FALSE); }
BOOL CDFPositionAtLastMember(CRYPTCATCDF *pCDF) { if (pCDF->dwLastMemberOffset == 0) { return(CDFPositionAtGroupTag(pCDF, CAT_MEMBER_TAG)); } else if (SetFilePointer(pCDF->hFile, pCDF->dwLastMemberOffset, NULL, FILE_BEGIN) == 0xFFFFFFFF) { return(FALSE); }
return(TRUE); }
BOOL CDFGetNextMember(CRYPTCATCDF *pCDF, LPWSTR pwszMember, int cchMember, LPWSTR pwszLastMember) { WCHAR wszLine[MAX_CDF_LINE_LEN + 4]; WCHAR wszCheck[MAX_CDF_LINE_LEN + 1]; LPWSTR pwszEqual; DWORD ccRet; DWORD ccLastMember; BOOL fFoundLast;
if (pwszLastMember) { if (FAILED(StringCchCopyW(&wszCheck[0], MAX_CDF_LINE_LEN + 1, pwszLastMember))) { return(FALSE); }
ccLastMember = wcslen(&wszCheck[0]); }
fFoundLast = FALSE;
while ((ccRet = CDFGetLine(pCDF, &wszLine[0], MAX_CDF_LINE_LEN * sizeof(WCHAR))) > 0) { if (wszLine[0] == L'#') { continue; }
CDFEOLOut(&wszLine[0], ccRet);
if (wszLine[0] == L'[') { return(FALSE); }
if (!(pwszEqual = wcschr(&wszLine[0], L'='))) { continue; }
*pwszEqual = NULL;
if (pwszLastMember) { if (fFoundLast) { //
// before we make the determination that we are in fact on a
// different member tag, make sure that we aren't just on the
// same tag's ALTSIP or ATTRx!!!
//
if (FAILED(StringCchCopyW( &wszCheck[ccLastMember], MAX_CDF_LINE_LEN + 1 - ccLastMember, CAT_MEMBER_ALTSIP_TAG))) { return(FALSE); } if (_memicmp(&wszLine[0], &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0) { continue; }
if (FAILED(StringCchCopyW( &wszCheck[ccLastMember], MAX_CDF_LINE_LEN + 1 - ccLastMember, CAT_MEMBER_ATTR_TAG))) { return(FALSE); } if (_memicmp(&wszLine[0], &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0) { continue; }
if (_wcsicmp(&wszLine[0], pwszLastMember) != 0) { if (wcslen(&wszLine[0]) + 1 <= cchMember) { wcscpy(pwszMember, &wszLine[0]); } else { return(FALSE); }
//
// remember the position of the last entry for this member
//
*pwszEqual = L'='; pCDF->dwLastMemberOffset = pCDF->dwCurFilePos - wcslen(&wszLine[0]);
return(TRUE); } } else if (_wcsicmp(&wszLine[0], pwszLastMember) == 0) { fFoundLast = TRUE; }
continue; }
if (wcslen(&wszLine[0]) + 1 <= cchMember) { wcscpy(pwszMember, &wszLine[0]); } else { return(FALSE); }
//
// remember the position of the last entry for this member
//
*pwszEqual = L'='; pCDF->dwLastMemberOffset = pCDF->dwCurFilePos - wcslen(&wszLine[0]);
return(TRUE); }
return(FALSE); }
BOOL CDFGetParam(CRYPTCATCDF *pCDF, LPWSTR pwszGroup, LPWSTR pwszItem, LPWSTR pwszDefault, LPWSTR *ppwszRet, LPWSTR pwszMemberTag) { WCHAR wszRetValue[MAX_CDF_LINE_LEN + 4]; DWORD ccRet; WCHAR *pwsz;
while ((ccRet = CDFGetLine(pCDF, &wszRetValue[0], MAX_CDF_LINE_LEN * sizeof(WCHAR))) > 0) { if (wszRetValue[0] == L'#') { continue; }
CDFEOLOut(&wszRetValue[0], ccRet);
if (wszRetValue[0] == L'[') { break; }
if (pwsz = wcschr(&wszRetValue[0], L'=')) { //
// if we have a member tag and we are past it, get out!
//
if (pwszMemberTag) { if (_memicmp(&wszRetValue[0], pwszMemberTag, wcslen(pwszMemberTag) * sizeof(WCHAR)) != 0) { break; } }
*pwsz = NULL;
if (_memicmp(&wszRetValue[0], pwszItem, wcslen(pwszItem) * sizeof(WCHAR)) == 0) { if (wcslen(&pwsz[1]) < 1) { break; }
if (*ppwszRet = (LPWSTR)CatalogNew((wcslen(&pwsz[1]) + 1) * sizeof(WCHAR))) { wcscpy(*ppwszRet, &pwsz[1]);
return(TRUE); }
return(FALSE); } } }
if (pwszDefault) { if (*ppwszRet = (LPWSTR)CatalogNew((wcslen(pwszDefault) + 1) * sizeof(WCHAR))) { wcscpy(*ppwszRet, pwszDefault);
return(TRUE); } }
*ppwszRet = NULL;
return(FALSE); }
DWORD CDFGetLine(CRYPTCATCDF *pCDF, LPWSTR pwszLineBuf, DWORD cbMaxRead) { DWORD dwHold; DWORD cbRead; DWORD cwbRead; DWORD dw; int iAmt; BYTE *pb;
if ((dwHold = SetFilePointer(pCDF->hFile, 0, NULL, FILE_CURRENT)) == 0xFFFFFFFF) { return(0); }
if (!(pb = (BYTE *)CatalogNew(cbMaxRead + 2))) { return(0); }
cbRead = 0;
if (ReadFile(pCDF->hFile, pb, cbMaxRead, &cbRead, NULL)) { if (cbRead == 0) { pCDF->fEOF = TRUE; delete pb; return(0); }
pb[cbRead] = 0x00; pCDF->fEOF = FALSE;
if (cbRead > 0) { iAmt = 0; for (dw = 0; dw < (cbRead - 1); dw++) { if ((pb[dw] == 0x0d) || (pb[dw] == 0x0a)) { iAmt++; if (pb[dw + 1] == 0x0a) { dw++; iAmt++; }
if (SetFilePointer(pCDF->hFile, dwHold + (dw + 1), NULL, FILE_BEGIN) == 0xFFFFFFFF) { pCDF->dwCurFilePos = 0; } else { pCDF->dwCurFilePos = SetFilePointer(pCDF->hFile, 0, NULL, FILE_CURRENT) - iAmt; }
pb[dw + 1] = 0x00;
cwbRead = MultiByteToWideChar( CP_ACP, 0, (const char *)pb, -1, pwszLineBuf, cbMaxRead / sizeof(WCHAR));
delete pb;
return(cwbRead + 1); } } } } else { delete pb;
return(0); }
if (pb[cbRead - 1] == 0x1a) /* EOF */ { cbRead--; pCDF->dwCurFilePos = 0; pCDF->fEOF = TRUE; } else { pCDF->dwCurFilePos = dwHold; }
pb[cbRead] = 0x00;
cwbRead = MultiByteToWideChar( CP_ACP, 0, (const char *)pb, -1, pwszLineBuf, cbMaxRead / sizeof(WCHAR));
delete pb;
return(cwbRead); }
void CDFEOLOut(WCHAR *pwsz, DWORD ccLen) { DWORD i;
for (i = 0; i < ccLen; i++) { if ((pwsz[i] == (WCHAR)0x0a) || (pwsz[i] == (WCHAR)0x0d)) { pwsz[i] = NULL; return; } } pwsz[ccLen] = NULL; }
|