|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1997
//
// File: tfindctl.cpp
//
// Contents: Find CTL in Cert Store API Tests
//
// See Usage() for list of test options.
//
//
// Functions: main
//
// History: 06-May-96 philh created
//--------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include "certtest.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <time.h>
static void Usage(void) { printf("Usage: tfindctl [options] <StoreName>\n"); printf("Options are:\n"); printf(" -h - This message\n"); printf(" -D<digest> - Find CTL matching Digest (Hash)\n"); printf(" -S<filename> - Subject certificate file\n"); printf(" -I<filename> - CTL issuer certificate file\n"); printf(" -U<ObjectID> - Usage Identifiers\n"); printf(" -L<text> - List Identifier\n"); printf(" -A - Test via AnySubjectType\n"); printf(" -e<number> - Cert encoding type\n"); printf(" -s - Open the \"StoreName\" System store\n"); printf(" -p<filename> - Put encoded CTL to file\n"); printf(" -d - Delete CTL\n"); printf(" -b - Brief\n"); printf(" -v - Verbose\n"); printf(" -c - Verify checks enabled\n"); printf(" -q - Quiet. Don't display CTLs\n"); printf(" -fTimeValid - Only Time Valid CTLs\n"); printf(" -fTimeInvalid - Only Time Invalid CTLs\n"); printf(" -fSameUsage - Only CTLs with same -U<ObjectID>'s\n"); printf("\n"); printf("Default: find all CTLs in the store\n"); }
static PCCERT_CONTEXT GetCertFromFile( LPSTR pszCertFilename ) { BYTE *pbEncodedCert = NULL; DWORD cbEncodedCert; PCCERT_CONTEXT pCert = NULL;
if (!ReadDERFromFile(pszCertFilename, &pbEncodedCert, &cbEncodedCert)) { PrintLastError("GetCertFromFile::ReadDERFromFile"); goto ErrorReturn; } if (NULL == (pCert = CertCreateCertificateContext( dwCertEncodingType, pbEncodedCert, cbEncodedCert ))) { PrintLastError("GetCertFromFile::CertCreateCertificateContext"); goto ErrorReturn; }
ErrorReturn: if (pbEncodedCert) TestFree(pbEncodedCert); return pCert; }
// Attempt to read as a file containing an encoded CTL.
static HCERTSTORE OpenCtlStoreFile( LPSTR pszStoreFilename) { HCERTSTORE hStore; BYTE *pbEncoded; DWORD cbEncoded;
if (!ReadDERFromFile(pszStoreFilename, &pbEncoded, &cbEncoded)) return NULL; if (NULL == (hStore = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
))) goto CommonReturn;
if (!CertAddEncodedCTLToStore( hStore, dwMsgAndCertEncodingType, pbEncoded, cbEncoded, CERT_STORE_ADD_ALWAYS, NULL // ppCtlContext
)) { CertCloseStore(hStore, 0); hStore = NULL; }
CommonReturn: TestFree(pbEncoded); return hStore; }
int _cdecl main(int argc, char * argv[]) { int ReturnStatus;
DWORD dwFindType = CTL_FIND_ANY; DWORD dwFindFlags = 0; void *pvFindPara = NULL;
DWORD cbHash = 0; BYTE rgbHash[MAX_HASH_LEN]; CRYPT_HASH_BLOB HashBlob;
LPSTR pszSubjectFilename = NULL; // not allocated
PCCERT_CONTEXT pSubjectCert = NULL;
LPSTR pszIssuerFilename = NULL; // not allocated
PCCERT_CONTEXT pIssuerCert = NULL;
#define MAX_USAGE_ID 20
LPSTR rgpszUsageId[MAX_USAGE_ID];
CTL_FIND_USAGE_PARA FindUsagePara; CTL_FIND_SUBJECT_PARA FindSubjectPara;
CTL_ANY_SUBJECT_INFO AnySubjectInfo;
BOOL fFindUsagePara = FALSE; BOOL fFindSubjectPara = FALSE; BOOL fAnySubjectType = FALSE;
BOOL fSystemStore = FALSE; BOOL fDelete = FALSE; BOOL fTimeValid = FALSE; BOOL fTimeInvalid = FALSE; LPSTR pszStoreFilename = NULL; // not allocated
LPSTR pszPutFilename = NULL; // not allocated
DWORD dwDisplayFlags = 0; BOOL fQuiet = FALSE; HCERTSTORE hStore = NULL;
memset(&FindUsagePara, 0, sizeof(FindUsagePara)); FindUsagePara.cbSize = sizeof(FindUsagePara); memset(&FindSubjectPara, 0, sizeof(FindSubjectPara)); FindSubjectPara.cbSize = sizeof(FindSubjectPara);
while (--argc>0) { if (**++argv == '-') { switch(argv[0][1]) { case 'D': { char *pszHash = argv[0]+2; int cchHash = strlen(pszHash); char rgch[3]; if (!(cchHash == 32 || cchHash == 40)) { printf("Need 32 digits (MD5) or 40 digits (SHA) "); printf("for hash , not %d digits\n", cchHash); goto BadUsage; } if (32 == cchHash) dwFindType = CTL_FIND_MD5_HASH; else dwFindType = CTL_FIND_SHA1_HASH; cbHash = 0; while (cchHash > 0) { rgch[0] = *pszHash++; rgch[1] = *pszHash++; rgch[2] = '\0'; rgbHash[cbHash++] = (BYTE) strtoul(rgch, NULL, 16); cchHash -= 2; } } break; case 'U': if (FindUsagePara.SubjectUsage.cUsageIdentifier >= MAX_USAGE_ID) { printf("Maximum number of Usage Identifiers: %d\n", MAX_USAGE_ID); goto BadUsage; } FindUsagePara.SubjectUsage.rgpszUsageIdentifier = rgpszUsageId; rgpszUsageId[FindUsagePara.SubjectUsage.cUsageIdentifier++] = argv[0] + 2; fFindUsagePara = TRUE; break; case 'L': if (0 == strlen(argv[0] + 2)) FindUsagePara.ListIdentifier.cbData = CTL_FIND_NO_LIST_ID_CBDATA; else { FindUsagePara.ListIdentifier.cbData = strlen(argv[0] + 2); FindUsagePara.ListIdentifier.pbData = (BYTE *) argv[0] + 2; } fFindUsagePara = TRUE; break; case 'I': if (0 == strlen(argv[0] + 2)) FindUsagePara.pSigner = CTL_FIND_NO_SIGNER_PTR; else pszIssuerFilename = argv[0]+2; fFindUsagePara = TRUE; break; case 'S': pszSubjectFilename = argv[0]+2; if (*pszSubjectFilename == '\0') { printf("Need to specify SubjectFilename\n"); goto BadUsage; } fFindSubjectPara = TRUE; break; case 'p': pszPutFilename = argv[0]+2; if (*pszPutFilename == '\0') { printf("Need to specify filename\n"); goto BadUsage; } break; case 'A': fAnySubjectType = TRUE; break; case 'd': fDelete = TRUE; break; case 'f': if (argv[0][2]) { if (0 == _stricmp(argv[0]+2, "TimeValid")) fTimeValid = TRUE; else if (0 == _stricmp(argv[0]+2, "TimeInvalid")) fTimeInvalid = TRUE; else if (0 == _stricmp(argv[0]+2, "SameUsage")) dwFindFlags |= CTL_FIND_SAME_USAGE_FLAG; else { printf("Need to specify -fTimeValid | -fTimeInvalid | -fSameUsage\n"); goto BadUsage; } } else { printf("Need to specify -fTimeValid | -fTimeInvalid | -fSameUsage\n"); goto BadUsage; } break; case 'b': dwDisplayFlags |= DISPLAY_BRIEF_FLAG; break; case 'v': dwDisplayFlags |= DISPLAY_VERBOSE_FLAG; break; case 'c': dwDisplayFlags |= DISPLAY_CHECK_FLAG; break; case 'q': fQuiet = TRUE; break; case 's': fSystemStore = TRUE; break; case 'e': dwCertEncodingType = (DWORD) strtoul(argv[0]+2, NULL, 0); break; case 'h': default: goto BadUsage; } } else { if (pszStoreFilename == NULL) pszStoreFilename = argv[0]; else { printf("Too many arguments\n"); goto BadUsage; } } } printf("command line: %s\n", GetCommandLine());
if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) dwDisplayFlags &= ~DISPLAY_BRIEF_FLAG;
if (pszStoreFilename == NULL) { printf("missing store filename\n"); goto BadUsage; }
if (pszIssuerFilename) { if (NULL == (pIssuerCert = GetCertFromFile(pszIssuerFilename))) { printf("Unable to read/decode IssuerFilename\n"); goto ErrorReturn; } FindUsagePara.pSigner = pIssuerCert->pCertInfo; }
if (pszSubjectFilename) { if (NULL == (pSubjectCert = GetCertFromFile(pszSubjectFilename))) { printf("Unable to read/decode SubjectFilename\n"); goto ErrorReturn; }
if (fAnySubjectType) { memset(&AnySubjectInfo, 0, sizeof(AnySubjectInfo)); AnySubjectInfo.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
AnySubjectInfo.SubjectIdentifier.cbData = MAX_HASH_LEN; if (!CertGetCertificateContextProperty( pSubjectCert, CERT_SHA1_HASH_PROP_ID, rgbHash, &AnySubjectInfo.SubjectIdentifier.cbData) || 0 == AnySubjectInfo.SubjectIdentifier.cbData) { printf("failed => unable to get SHA1 hash for Subject Cert\n"); goto ErrorReturn;; } AnySubjectInfo.SubjectIdentifier.pbData = rgbHash;
FindSubjectPara.dwSubjectType = CTL_ANY_SUBJECT_TYPE; FindSubjectPara.pvSubject = &AnySubjectInfo; } else { FindSubjectPara.dwSubjectType = CTL_CERT_SUBJECT_TYPE; FindSubjectPara.pvSubject = (void *) pSubjectCert; } }
if (fFindSubjectPara) { if (fFindUsagePara) FindSubjectPara.pUsagePara = &FindUsagePara; dwFindType = CTL_FIND_SUBJECT; } else if (fFindUsagePara) dwFindType = CTL_FIND_USAGE;
switch (dwFindType) { case CTL_FIND_ANY: printf("Finding all CTLs\n"); break; case CTL_FIND_MD5_HASH: case CTL_FIND_SHA1_HASH: { if (CTL_FIND_MD5_HASH == dwFindType) printf("Finding MD5 hash:: "); else printf("Finding SHA1 hash:: ");
DWORD cb = cbHash; BYTE *pb = rgbHash; for (; cb > 0; cb--, pb++) printf("%02X", *pb); printf("\n"); } HashBlob.pbData = rgbHash; HashBlob.cbData = cbHash; pvFindPara = &HashBlob; break; case CTL_FIND_USAGE: printf("Finding by Usage\n"); pvFindPara = &FindUsagePara; break; case CTL_FIND_SUBJECT: if (FindSubjectPara.pUsagePara) printf("Finding by Usage and Subject\n"); else printf("Finding by Subject\n"); pvFindPara = &FindSubjectPara; break; default: printf("Bad dwFindType: %x\n", dwFindType); goto BadUsage; }
if (fFindUsagePara) { DWORD cUsageId = FindUsagePara.SubjectUsage.cUsageIdentifier; if (0 == cUsageId) printf("No Usage Identifiers\n"); else { LPSTR *ppszId = FindUsagePara.SubjectUsage.rgpszUsageIdentifier; DWORD i;
printf("Usage Identifiers::\n"); for (i = 0; i < cUsageId; i++, ppszId++) printf(" [%d] %s\n", i, *ppszId); }
if (CTL_FIND_NO_LIST_ID_CBDATA == FindUsagePara.ListIdentifier.cbData) printf("Enabled:: CTL_FIND_NO_LIST_ID_CBDATA\n"); else if (0 == FindUsagePara.ListIdentifier.cbData) printf("Matching any ListIdentifier\n"); else printf("Matching ListIdentifier: %s\n", FindUsagePara.ListIdentifier.pbData);
if (CTL_FIND_NO_SIGNER_PTR == FindUsagePara.pSigner) printf("Enabled:: CTL_FIND_NO_SIGNER_PTR\n"); else if (NULL == FindUsagePara.pSigner) printf("Matching any Signer\n"); else printf("Matching signer with certificate from %s\n", pszIssuerFilename); }
if (fFindSubjectPara) { printf("Matching subject with certificate from %s", pszSubjectFilename); if (FindSubjectPara.dwSubjectType == CTL_ANY_SUBJECT_TYPE) printf("Using CTL_ANY_SUBJECT_TYPE\n"); else printf("\n"); }
if (!fSystemStore) // Attempt to open as encoded CTL file
hStore = OpenCtlStoreFile(pszStoreFilename); else hStore = NULL;
if (NULL == hStore) { // Attempt to open the store
hStore = OpenStore(fSystemStore, pszStoreFilename); if (hStore == NULL) goto ErrorReturn; }
{ PCCTL_CONTEXT pCtl = NULL; DWORD i = 0; while (pCtl = CertFindCTLInStore( hStore, dwMsgAndCertEncodingType, dwFindFlags, dwFindType, pvFindPara, pCtl )) { if (fTimeValid && !IsTimeValidCtl(pCtl)) continue; if (fTimeInvalid && IsTimeValidCtl(pCtl)) continue;
if (!fQuiet) { printf("===== %d =====\n", i); DisplayCtl(pCtl, dwDisplayFlags, hStore); if (fFindSubjectPara) { PCTL_ENTRY pEntry; pEntry = CertFindSubjectInCTL( dwMsgAndCertEncodingType, FindSubjectPara.dwSubjectType, FindSubjectPara.pvSubject, pCtl, 0 // dwFlags
); printf("\n"); if (pEntry) printf("Subject Index:: %d\n", pEntry - pCtl->pCtlInfo->rgCTLEntry); else PrintLastError("CertFindSubjectInCTL"); } } i++;
if (pszPutFilename) { printf("Putting\n"); if (!WriteDERToFile( pszPutFilename, pCtl->pbCtlEncoded, pCtl->cbCtlEncoded )) PrintLastError("Put Ctl::WriteDERToFile"); }
if (fDelete) { PCCTL_CONTEXT pDeleteCtl; printf("Deleting\n"); pDeleteCtl = CertDuplicateCTLContext(pCtl); if (!CertDeleteCTLFromStore(pDeleteCtl)) PrintLastError("CertDeleteCTLFromStore"); } }
if (i == 0) { if (GetLastError() == CRYPT_E_NOT_FOUND) printf("CertFindCTLsInStore warning => CTL not found\n"); else PrintLastError("CertFindCTLsInStore"); } else if (fDelete && !fSystemStore) SaveStore(hStore, pszStoreFilename); }
if (!CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG)) PrintLastError("CertCloseStore");
ReturnStatus = 0; goto CommonReturn;
BadUsage: Usage(); ErrorReturn: ReturnStatus = -1; CommonReturn: if (pSubjectCert) CertFreeCertificateContext(pSubjectCert); if (pIssuerCert) CertFreeCertificateContext(pIssuerCert);
if (!ReturnStatus) printf("Passed\n"); else printf("Failed\n"); return ReturnStatus; }
|