//+------------------------------------------------------------------------- // // 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 #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"" ///////////////////////////////////////////////////////////////////////////// // // 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; }