windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/mscat32/mscdfapi.cpp
2020-09-26 16:20:57 +08:00

1545 lines
42 KiB
C++

//+-------------------------------------------------------------------------
//
// 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"
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, 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'\\'))
{
wcscpy(&wszRetValue[0], &pwsz[1]);
}
else
{
wcscpy(&wszRetValue[0], pwszFilePath);
}
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 += 2;
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;
BOOL fFoundLastTag;
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], 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 pwszFileName;
return(NULL);
}
wcscpy(pwszReferenceTag, &wszRetValue[0]);
//
// Alt SIP GUID
//
wcscpy(&wszRetValue[0], pwszReferenceTag);
wcscat(&wszRetValue[0], CAT_MEMBER_ALTSIP_TAG);
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;
BOOL fFoundLastTag;
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], 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;
//
// reference tag
//
if (!(pwszReferenceTag = (LPWSTR)CatalogNew((wcslen(&wszRetValue[0]) + 1) * sizeof(WCHAR))))
{
return(NULL);
}
wcscpy(pwszReferenceTag, &wszRetValue[0]);
//
// 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;
}
return(pwszReferenceTag);
}
CloseHandle(hFile);
//
// Alt SIP GUID
//
wcscpy(&wszRetValue[0], pwszReferenceTag);
wcscat(&wszRetValue[0], CAT_MEMBER_ALTSIP_TAG);
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;
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;
}
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;
}
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);
}
}
DELETE_OBJECT(pbIndirectData);
//
// Done!
//
if ( fHashTagUsed == TRUE )
{
MsCatFreeHashTag(pwszTagToPut);
}
DELETE_OBJECT(pwszFileName);
*ppMember = pMember;
return(pwszReferenceTag);
}
}
DELETE_OBJECT(pwszLastTag);
return(NULL);
}
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;
wcscpy(&wszRetValue[0], pMember->pwszReferenceTag);
wcscat(&wszRetValue[0], L"ATTR");
wcscat(&wszRetValue[0], _itow(iAttr, &wszTemp[0], 10));
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;
wcscpy(&wszRetValue[0], pwszMemberTag);
wcscat(&wszRetValue[0], L"ATTR");
wcscat(&wszRetValue[0], _itow(iAttr, &wszTemp[0], 10));
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'{'))
{
wcscpy(&wszGuid[0], L"{");
wcscat(&wszGuid[0], pwszText);
wcscat(&wszGuid[0], L"}");
}
else
{
wcscpy(&wszGuid[0], pwszText);
}
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, 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)
{
wcscpy(&wszCheck[0], pwszLastMember);
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!!!
//
wcscpy(&wszCheck[ccLastMember], CAT_MEMBER_ALTSIP_TAG);
if (_memicmp(&wszLine[0], &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0)
{
continue;
}
wcscpy(&wszCheck[ccLastMember], CAT_MEMBER_ATTR_TAG);
if (_memicmp(&wszLine[0], &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0)
{
continue;
}
if (_wcsicmp(&wszLine[0], pwszLastMember) != 0)
{
wcscpy(pwszMember, &wszLine[0]);
//
// 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;
}
wcscpy(pwszMember, &wszLine[0]);
//
// 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;
}