Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1970 lines
57 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: certexts.cpp
  8. //
  9. // Contents: NTSD/WINDBG certificate extensions dll
  10. //
  11. // See DECLARE_API( help ) for a list of extensions
  12. //
  13. //
  14. // Functions: help
  15. // store
  16. // context
  17. // ele
  18. // cert
  19. // crl
  20. // ctl
  21. // chain
  22. //
  23. // History: 06-Jun-98 philh created
  24. //--------------------------------------------------------------------------
  25. #include "global.hxx"
  26. #define MAX_HASH_LEN 20
  27. #define SHA1_HASH_LEN 20
  28. #define MAX_PROP_CNT 100
  29. #define MAX_CONTEXT_CNT 1000
  30. #define MAX_STORE_SIBLING_CNT 100
  31. #define MAX_STORE_NEST_CNT 100
  32. #define MAX_SIMPLE_CHAIN_CNT 50
  33. #define MAX_CHAIN_ELEMENT_CNT 50
  34. WINDBG_EXTENSION_APIS ExtensionApis;
  35. HANDLE ExtensionCurrentProcess;
  36. // Display flags
  37. #define DISPLAY_SHORT_FLAG 0x00000001
  38. #define DISPLAY_VERBOSE_FLAG 0x00000002
  39. #define DISPLAY_UI_FLAG 0x00000004
  40. #define DISPLAY_EXT_FLAG 0x00000008
  41. #define DISPLAY_PROP_FLAG 0x00000010
  42. // ATTENTION: the following were lifted from newstor.cpp. Should be moved
  43. // to a shared .h file
  44. //+-------------------------------------------------------------------------
  45. // Store data structure definitions
  46. //--------------------------------------------------------------------------
  47. // Assumes
  48. // 0 - Certificates
  49. // 1 - CRLs
  50. // 2 - CTLs
  51. #define CONTEXT_COUNT 3
  52. typedef struct _CONTEXT_ELEMENT CONTEXT_ELEMENT, *PCONTEXT_ELEMENT;
  53. typedef struct _PROP_ELEMENT PROP_ELEMENT, *PPROP_ELEMENT;
  54. typedef struct _CERT_STORE CERT_STORE, *PCERT_STORE;
  55. typedef struct _CERT_STORE_LINK CERT_STORE_LINK, *PCERT_STORE_LINK;
  56. typedef struct _COLLECTION_STACK_ENTRY COLLECTION_STACK_ENTRY,
  57. *PCOLLECTION_STACK_ENTRY;
  58. // Used to maintain collection state across context find next calls.
  59. //
  60. // Ref count on pStoreLink. No ref count on pCollection.
  61. // pStoreLink may be NULL.
  62. struct _COLLECTION_STACK_ENTRY {
  63. PCERT_STORE pCollection;
  64. PCERT_STORE_LINK pStoreLink;
  65. PCOLLECTION_STACK_ENTRY pPrev;
  66. };
  67. typedef struct _CONTEXT_CACHE_INFO {
  68. PPROP_ELEMENT pPropHead;
  69. } CONTEXT_CACHE_INFO;
  70. typedef struct _CONTEXT_EXTERNAL_INFO {
  71. // For ELEMENT_FIND_NEXT_FLAG
  72. void *pvProvInfo;
  73. } CONTEXT_EXTERNAL_INFO;
  74. typedef struct _CONTEXT_COLLECTION_INFO {
  75. // For Find
  76. PCOLLECTION_STACK_ENTRY pCollectionStack;
  77. } CONTEXT_COLLECTION_INFO;
  78. #define ELEMENT_DELETED_FLAG 0x00010000
  79. // Only set for external elements
  80. #define ELEMENT_FIND_NEXT_FLAG 0x00020000
  81. // Set during CertCloseStore if ELEMENT_FIND_NEXT_FLAG was set.
  82. #define ELEMENT_CLOSE_FIND_NEXT_FLAG 0x00040000
  83. // Set if the element has a CERT_ARCHIVED_PROP_ID
  84. #define ELEMENT_ARCHIVED_FLAG 0x00080000
  85. #define ELEMENT_TYPE_CACHE 1
  86. #define ELEMENT_TYPE_LINK_CONTEXT 2
  87. #define ELEMENT_TYPE_EXTERNAL 3
  88. #define ELEMENT_TYPE_COLLECTION 4
  89. typedef struct _CONTEXT_NOCOPY_INFO {
  90. PFN_CRYPT_FREE pfnFree;
  91. void *pvFree;
  92. } CONTEXT_NOCOPY_INFO, *PCONTEXT_NOCOPY_INFO;
  93. // Identical contexts (having the same SHA1 hash) can share the same encoded
  94. // byte array and decoded info data structure.
  95. //
  96. // CreateShareElement() creates with dwRefCnt of 1. FindShareElement() finds
  97. // an existing and increments dwRefCnt. ReleaseShareElement() decrements
  98. // dwRefCnt and frees when 0.
  99. typedef struct _SHARE_ELEMENT SHARE_ELEMENT, *PSHARE_ELEMENT;
  100. struct _SHARE_ELEMENT {
  101. BYTE rgbSha1Hash[SHA1_HASH_LEN];
  102. DWORD dwContextType;
  103. BYTE *pbEncoded; // allocated
  104. DWORD cbEncoded;
  105. void *pvInfo; // allocated
  106. DWORD dwRefCnt;
  107. PSHARE_ELEMENT pNext;
  108. PSHARE_ELEMENT pPrev;
  109. };
  110. // The CONTEXT_ELEMENT is inserted before the CERT_CONTEXT, CRL_CONTEXT or
  111. // CTL_CONTEXT. The dwContextType used is 0 based and not 1 based. For
  112. // example, dwContextType = CERT_STORE_CERTIFICATE_CONTEXT - 1.
  113. struct _CONTEXT_ELEMENT {
  114. DWORD dwElementType;
  115. DWORD dwContextType;
  116. DWORD dwFlags;
  117. LONG lRefCnt;
  118. // For ELEMENT_TYPE_CACHE, pEle points to itself. Otherwise, pEle points
  119. // to the element being linked to and the pEle is addRef'ed. The
  120. // cached element is found by iterating through the pEle's until pEle
  121. // points to itself.
  122. PCONTEXT_ELEMENT pEle;
  123. PCERT_STORE pStore;
  124. PCONTEXT_ELEMENT pNext;
  125. PCONTEXT_ELEMENT pPrev;
  126. PCERT_STORE pProvStore;
  127. PCONTEXT_NOCOPY_INFO pNoCopyInfo;
  128. // When nonNULL, the context's pbEncoded and pInfo aren't allocated.
  129. // Instead, use the shared element's pbEncoded and pInfo. When
  130. // context element is freed, the pSharedEle is ReleaseShareElement()'ed.
  131. PSHARE_ELEMENT pShareEle; // RefCnt'ed
  132. union {
  133. CONTEXT_CACHE_INFO Cache; // ELEMENT_TYPE_CACHE
  134. CONTEXT_EXTERNAL_INFO External; // ELEMENT_TYPE_EXTERNAL
  135. CONTEXT_COLLECTION_INFO Collection; // ELEMENT_TYPE_COLLECTION
  136. };
  137. };
  138. struct _PROP_ELEMENT {
  139. DWORD dwPropId;
  140. DWORD dwFlags;
  141. BYTE *pbData;
  142. DWORD cbData;
  143. PPROP_ELEMENT pNext;
  144. PPROP_ELEMENT pPrev;
  145. };
  146. #define STORE_LINK_DELETED_FLAG 0x00010000
  147. struct _CERT_STORE_LINK {
  148. DWORD dwFlags;
  149. LONG lRefCnt;
  150. // Whatever is passed to CertAddStoreToCollection
  151. DWORD dwUpdateFlags;
  152. DWORD dwPriority;
  153. PCERT_STORE pCollection;
  154. PCERT_STORE pSibling; // CertStoreDuplicate'd.
  155. PCERT_STORE_LINK pNext;
  156. PCERT_STORE_LINK pPrev;
  157. };
  158. // Store types
  159. #define STORE_TYPE_CACHE 1
  160. #define STORE_TYPE_EXTERNAL 2
  161. #define STORE_TYPE_COLLECTION 3
  162. // CACHE store may have CACHE or LINK_CONTEXT elements. Until deleted,
  163. // the store has a reference count to.
  164. // EXTERNAL store only has EXTERNAL elements. These elements are always
  165. // deleted, wherein, the store doesn't hold a refCnt.
  166. // COLLECTION store has COLLECTION elements. These elements
  167. // are always deleted, wherein, the store doesn't hold a refCnt.
  168. struct _CERT_STORE {
  169. DWORD dwStoreType;
  170. LONG lRefCnt;
  171. HCRYPTPROV hCryptProv;
  172. DWORD dwFlags;
  173. DWORD dwState;
  174. CRITICAL_SECTION CriticalSection;
  175. PCONTEXT_ELEMENT rgpContextListHead[CONTEXT_COUNT];
  176. PCERT_STORE_LINK pStoreListHead; // COLLECTION
  177. PPROP_ELEMENT pPropHead; // properties for entire store
  178. // For CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG
  179. // Incremented for each context duplicated
  180. LONG lDeferCloseRefCnt;
  181. // Event handle set by CertControlStore(CERT_STORE_CTRL_AUTO_RESYNC)
  182. HANDLE hAutoResyncEvent;
  183. // Store provider info
  184. LONG lStoreProvRefCnt;
  185. HANDLE hStoreProvWait;
  186. HCRYPTOIDFUNCADDR hStoreProvFuncAddr;
  187. CERT_STORE_PROV_INFO StoreProvInfo;
  188. };
  189. //+-------------------------------------------------------------------------
  190. // Store states
  191. //--------------------------------------------------------------------------
  192. #define STORE_STATE_DELETED 0
  193. #define STORE_STATE_NULL 1
  194. #define STORE_STATE_OPENING 2
  195. #define STORE_STATE_OPEN 3
  196. #define STORE_STATE_DEFER_CLOSING 4
  197. #define STORE_STATE_CLOSING 5
  198. #define STORE_STATE_CLOSED 6
  199. inline PCONTEXT_ELEMENT ToContextElement(
  200. IN PCCERT_CONTEXT pCertContext
  201. )
  202. {
  203. if (pCertContext)
  204. return (PCONTEXT_ELEMENT)
  205. (((BYTE *) pCertContext) - sizeof(CONTEXT_ELEMENT));
  206. else
  207. return NULL;
  208. }
  209. inline PCCERT_CONTEXT ToCertContext(
  210. IN PCONTEXT_ELEMENT pEle
  211. )
  212. {
  213. if (pEle)
  214. return (PCCERT_CONTEXT)
  215. (((BYTE *) pEle) + sizeof(CONTEXT_ELEMENT));
  216. else
  217. return NULL;
  218. }
  219. DECLARE_API( help )
  220. {
  221. INIT_API();
  222. while (*lpArgumentString == ' ')
  223. lpArgumentString++;
  224. if (*lpArgumentString == '\0') {
  225. dprintf("certexts help:\n\n");
  226. dprintf("!context {[s|v|u|x|p]} address - Dump cert, CRL or CTL context\n");
  227. dprintf("!ele {[s|v|u|x|p]} address - Dump cert, CRL or CTL element\n");
  228. dprintf("!cert {[s|v|u|x|p]} address - Dump encoded cert\n");
  229. dprintf("!crl {[s|v|u|x|p]} address - Dump encoded crl\n");
  230. dprintf("!ctl {[s|v|u|x|p]} address - Dump encoded ctl\n");
  231. dprintf("!store {[s|v|x|p]} address - Dump certificate store\n");
  232. dprintf("!chain {[s|v|x|p]} address - Dump certificate chain context\n");
  233. dprintf("!help [cmd] - Displays this list or gives details on command\n");
  234. dprintf("\n");
  235. dprintf("Options:\n");
  236. dprintf(" s - Short, brief display\n");
  237. dprintf(" v - Verbose display\n");
  238. dprintf(" u - UI display\n");
  239. dprintf(" x - Display eXtensions\n");
  240. dprintf(" p - Display Properties\n");
  241. } else {
  242. if (*lpArgumentString == '!')
  243. lpArgumentString++;
  244. if (strcmp(lpArgumentString, "xyz") == 0) {
  245. dprintf("!xyz - Invalid command\n");
  246. } else {
  247. dprintf("Invalid command and/or no help available\n");
  248. }
  249. }
  250. }
  251. //+-------------------------------------------------------------------------
  252. // Error output routines
  253. //--------------------------------------------------------------------------
  254. void PrintError(LPCSTR pszMsg)
  255. {
  256. dprintf("%s\n", pszMsg);
  257. }
  258. void PrintLastError(LPCSTR pszMsg)
  259. {
  260. DWORD dwErr = GetLastError();
  261. dprintf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  262. }
  263. //+-------------------------------------------------------------------------
  264. // CertExts allocation and free routines
  265. //--------------------------------------------------------------------------
  266. LPVOID
  267. WINAPI
  268. CertExtsAlloc(
  269. IN UINT cbBytes
  270. )
  271. {
  272. LPVOID pv;
  273. if (NULL == (pv = (LPVOID) LocalAlloc(LPTR, cbBytes))) {
  274. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  275. PrintLastError("CertExtsAlloc");
  276. }
  277. return pv;
  278. }
  279. LPVOID
  280. WINAPI
  281. CertExtsRealloc(
  282. IN LPVOID pvOrg,
  283. IN UINT cbBytes
  284. )
  285. {
  286. LPVOID pv;
  287. if (NULL == (pv = pvOrg ?
  288. (LPVOID) LocalReAlloc((HLOCAL)pvOrg, cbBytes, LMEM_MOVEABLE) :
  289. (LPVOID) LocalAlloc(NONZEROLPTR, cbBytes))) {
  290. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  291. PrintLastError("CertExtsRealloc");
  292. }
  293. return pv;
  294. }
  295. VOID
  296. WINAPI
  297. CertExtsFree(
  298. IN LPVOID pv
  299. )
  300. {
  301. if (pv)
  302. LocalFree((HLOCAL)pv);
  303. }
  304. LPCSTR FileTimeText(FILETIME *pft)
  305. {
  306. static char buf[80];
  307. FILETIME ftLocal;
  308. struct tm ctm;
  309. SYSTEMTIME st;
  310. FileTimeToLocalFileTime(pft, &ftLocal);
  311. if (FileTimeToSystemTime(&ftLocal, &st))
  312. {
  313. ctm.tm_sec = st.wSecond;
  314. ctm.tm_min = st.wMinute;
  315. ctm.tm_hour = st.wHour;
  316. ctm.tm_mday = st.wDay;
  317. ctm.tm_mon = st.wMonth-1;
  318. ctm.tm_year = st.wYear-1900;
  319. ctm.tm_wday = st.wDayOfWeek;
  320. ctm.tm_yday = 0;
  321. ctm.tm_isdst = 0;
  322. strcpy(buf, asctime(&ctm));
  323. buf[strlen(buf)-1] = 0;
  324. if (st.wMilliseconds) {
  325. char *pch = buf + strlen(buf);
  326. sprintf(pch, " <milliseconds:: %03d>", st.wMilliseconds);
  327. }
  328. }
  329. else
  330. sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
  331. pft->dwLowDateTime);
  332. return buf;
  333. }
  334. #define CROW 16
  335. void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
  336. {
  337. ULONG cb, i;
  338. if (cbSize == 0) {
  339. dprintf("%s NO Value Bytes\n", pszHdr);
  340. return;
  341. }
  342. while (cbSize > 0)
  343. {
  344. dprintf("%s", pszHdr);
  345. cb = min(CROW, cbSize);
  346. cbSize -= cb;
  347. for (i = 0; i<cb; i++)
  348. dprintf(" %02X", pb[i]);
  349. for (i = cb; i<CROW; i++)
  350. dprintf(" ");
  351. dprintf(" '");
  352. for (i = 0; i<cb; i++)
  353. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  354. dprintf("%c", pb[i]);
  355. else
  356. dprintf(".");
  357. pb += cb;
  358. dprintf("'\n");
  359. }
  360. }
  361. BOOL GetEncodedBlob(
  362. IN LPVOID pvAddr,
  363. OUT BYTE **ppbEncoded,
  364. OUT DWORD *pcbEncoded
  365. )
  366. {
  367. BOOL fResult;
  368. BYTE rgbTagLength[6];
  369. BYTE *pbEncoded = NULL;
  370. DWORD cbEncoded = 0;
  371. LONG lLen;
  372. DWORD cbLen;
  373. DWORD cbContent;
  374. const BYTE *pbContent;
  375. __try {
  376. memset(rgbTagLength, 0, sizeof(rgbTagLength));
  377. ReadMemory(pvAddr, rgbTagLength, sizeof(rgbTagLength), NULL);
  378. } __except (EXCEPTION_EXECUTE_HANDLER) {
  379. dprintf("Unable to read encoded blob at 0x%p\n", pvAddr);
  380. goto ErrorReturn;
  381. }
  382. lLen = Asn1UtilExtractContent(rgbTagLength, sizeof(rgbTagLength),
  383. &cbContent, &pbContent);
  384. if (lLen <= 0 || cbContent == CMSG_INDEFINITE_LENGTH) {
  385. dprintf("Unable to decode ASN1 tag/length at 0x%p\n", pvAddr);
  386. goto ErrorReturn;
  387. }
  388. cbEncoded = (DWORD)lLen + cbContent;
  389. if (NULL == (pbEncoded = (BYTE *) CertExtsAlloc(cbEncoded)))
  390. goto ErrorReturn;
  391. __try {
  392. memset(pbEncoded, 0, cbEncoded);
  393. ReadMemory(pvAddr, pbEncoded, cbEncoded, NULL);
  394. } __except (EXCEPTION_EXECUTE_HANDLER) {
  395. dprintf("Unable to read encoded blob at 0x%p .. 0x%p\n", pvAddr,
  396. ((BYTE *) pvAddr) + cbEncoded - 1);
  397. goto ErrorReturn;
  398. }
  399. fResult = TRUE;
  400. CommonReturn:
  401. *ppbEncoded = pbEncoded;
  402. *pcbEncoded = cbEncoded;
  403. return fResult;
  404. ErrorReturn:
  405. CertExtsFree(pbEncoded);
  406. pbEncoded = NULL;
  407. cbEncoded = 0;
  408. fResult = FALSE;
  409. goto CommonReturn;
  410. }
  411. void DisplaySerialNumber(
  412. PCRYPT_INTEGER_BLOB pSerialNumber
  413. )
  414. {
  415. DWORD cb;
  416. BYTE *pb;
  417. for (cb = pSerialNumber->cbData,
  418. pb = pSerialNumber->pbData + (cb - 1); cb > 0; cb--, pb--) {
  419. dprintf(" %02X", *pb);
  420. }
  421. dprintf("\n");
  422. }
  423. void DisplayThumbprint(
  424. LPCSTR pszHash,
  425. BYTE *pbHash,
  426. DWORD cbHash
  427. )
  428. {
  429. dprintf("%s Thumbprint:: ", pszHash);
  430. if (cbHash == 0)
  431. dprintf("???");
  432. else {
  433. ULONG cb;
  434. while (cbHash > 0) {
  435. cb = min(4, cbHash);
  436. cbHash -= cb;
  437. for (; cb > 0; cb--, pbHash++)
  438. dprintf("%02X", *pbHash);
  439. dprintf(" ");
  440. }
  441. }
  442. dprintf("\n");
  443. }
  444. void DisplayName(
  445. IN PCERT_NAME_BLOB pName
  446. )
  447. {
  448. DWORD csz;
  449. LPSTR psz;
  450. csz = CertNameToStrA(
  451. X509_ASN_ENCODING,
  452. pName,
  453. CERT_X500_NAME_STR + CERT_NAME_STR_REVERSE_FLAG,
  454. NULL, // psz
  455. 0); // csz
  456. if (psz = (LPSTR) CertExtsAlloc(csz)) {
  457. CertNameToStrA(
  458. X509_ASN_ENCODING,
  459. pName,
  460. CERT_X500_NAME_STR + CERT_NAME_STR_REVERSE_FLAG,
  461. psz,
  462. csz);
  463. dprintf(" %s\n", psz);
  464. CertExtsFree(psz);
  465. } else
  466. dprintf(" ???\n");
  467. }
  468. //+-------------------------------------------------------------------------
  469. // Returns OID's name string. If not found returns L"???".
  470. //--------------------------------------------------------------------------
  471. LPCWSTR GetOIDName(LPCSTR pszOID, DWORD dwGroupId = 0)
  472. {
  473. PCCRYPT_OID_INFO pInfo;
  474. if (pInfo = CryptFindOIDInfo(
  475. CRYPT_OID_INFO_OID_KEY,
  476. (void *) pszOID,
  477. dwGroupId
  478. )) {
  479. if (L'\0' != pInfo->pwszName[0])
  480. return pInfo->pwszName;
  481. }
  482. return L"???";
  483. }
  484. ALG_ID GetAlgid(LPCSTR pszOID, DWORD dwGroupId = 0)
  485. {
  486. PCCRYPT_OID_INFO pInfo;
  487. if (pInfo = CryptFindOIDInfo(
  488. CRYPT_OID_INFO_OID_KEY,
  489. (void *) pszOID,
  490. dwGroupId
  491. ))
  492. return pInfo->Algid;
  493. return 0;
  494. }
  495. void PrintExtensions(
  496. IN DWORD cExt,
  497. IN PCERT_EXTENSION pExt,
  498. IN DWORD dwDisplayFlags
  499. )
  500. {
  501. DWORD i;
  502. if (0 == (dwDisplayFlags & (DISPLAY_VERBOSE_FLAG | DISPLAY_EXT_FLAG)))
  503. return;
  504. for (i = 0; i < cExt; i++, pExt++) {
  505. DWORD cbFormat;
  506. LPSTR pszObjId = pExt->pszObjId;
  507. if (pszObjId == NULL)
  508. pszObjId = "<NULL OBJID>";
  509. LPSTR pszCritical = pExt->fCritical ? "TRUE" : "FALSE";
  510. dprintf("Extension[%d] %s (%S) Critical: %s::\n",
  511. i, pszObjId, GetOIDName(pszObjId), pszCritical);
  512. PrintBytes(" ", pExt->Value.pbData, pExt->Value.cbData);
  513. cbFormat = 0;
  514. if (CryptFormatObject(
  515. X509_ASN_ENCODING,
  516. 0, // dwFormatType
  517. CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
  518. NULL, // pFormatStruct,
  519. pszObjId,
  520. pExt->Value.pbData,
  521. pExt->Value.cbData,
  522. NULL,
  523. &cbFormat
  524. ) && cbFormat) {
  525. BYTE *pbFormat = NULL;
  526. if (pbFormat = (BYTE *) CertExtsAlloc(cbFormat)) {
  527. if (CryptFormatObject(
  528. X509_ASN_ENCODING,
  529. 0, // dwFormatType
  530. CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
  531. NULL, // pFormatStruct,
  532. pszObjId,
  533. pExt->Value.pbData,
  534. pExt->Value.cbData,
  535. pbFormat,
  536. &cbFormat
  537. )) {
  538. dprintf("--- Decoded ---\n");
  539. dprintf("%S\n", pbFormat);
  540. }
  541. CertExtsFree(pbFormat);
  542. }
  543. }
  544. }
  545. }
  546. typedef struct _PROP_INFO {
  547. DWORD dwPropId;
  548. LPCSTR pszPropName;
  549. } PROP_INFO, *PPROP_INFO;
  550. const PROP_INFO rgPropInfo[] = {
  551. CERT_KEY_PROV_HANDLE_PROP_ID, "KeyProvHandle",
  552. CERT_KEY_PROV_INFO_PROP_ID, "KeyProvInfo",
  553. CERT_SHA1_HASH_PROP_ID, "Sha1Hash",
  554. CERT_MD5_HASH_PROP_ID, "MD5Hash",
  555. CERT_KEY_CONTEXT_PROP_ID, "KeyContext",
  556. CERT_KEY_SPEC_PROP_ID, "KeySpec",
  557. CERT_IE30_RESERVED_PROP_ID, "IE30Reserved",
  558. CERT_PUBKEY_HASH_RESERVED_PROP_ID, "PubKeyHashReserved",
  559. CERT_ENHKEY_USAGE_PROP_ID, "EnhKeyUsage",
  560. CERT_NEXT_UPDATE_LOCATION_PROP_ID, "NextUpdateLocation",
  561. CERT_FRIENDLY_NAME_PROP_ID, "FriendlyName",
  562. CERT_PVK_FILE_PROP_ID, "PvkFile",
  563. CERT_DESCRIPTION_PROP_ID, "Description",
  564. CERT_ACCESS_STATE_PROP_ID, "AccessState",
  565. CERT_SIGNATURE_HASH_PROP_ID, "SignatureHash",
  566. CERT_SMART_CARD_DATA_PROP_ID, "SmartCartData",
  567. CERT_EFS_PROP_ID, "EFS",
  568. CERT_FORTEZZA_DATA_PROP_ID, "FortezzaData",
  569. CERT_ARCHIVED_PROP_ID, "Archived",
  570. CERT_KEY_IDENTIFIER_PROP_ID, "KeyIdentifier",
  571. CERT_AUTO_ENROLL_PROP_ID, "AutoEnroll",
  572. CERT_STORE_LOCALIZED_NAME_PROP_ID, "LocalizedName",
  573. 0, "???"
  574. };
  575. LPCSTR GetPropName(
  576. IN DWORD dwPropId
  577. )
  578. {
  579. const PROP_INFO *pInfo;
  580. for (pInfo = rgPropInfo; pInfo->dwPropId; pInfo++) {
  581. if (dwPropId == pInfo->dwPropId)
  582. return pInfo->pszPropName;
  583. }
  584. return "???";
  585. }
  586. void PrintProperties(
  587. IN PPROP_ELEMENT pProp,
  588. IN DWORD dwDisplayFlags
  589. )
  590. {
  591. DWORD i;
  592. if (0 == (dwDisplayFlags & (DISPLAY_VERBOSE_FLAG | DISPLAY_PROP_FLAG)))
  593. return;
  594. i = 0;
  595. while (pProp) {
  596. PROP_ELEMENT Prop;
  597. __try {
  598. memset(&Prop, 0, sizeof(Prop));
  599. ReadMemory((LPVOID) pProp, &Prop, sizeof(Prop), NULL);
  600. } __except (EXCEPTION_EXECUTE_HANDLER) {
  601. dprintf("Unable to read Property Element at 0x%p\n", pProp);
  602. goto ErrorReturn;
  603. }
  604. dprintf("PropId %ld (0x%lx) %s ::\n", Prop.dwPropId, Prop.dwPropId,
  605. GetPropName(Prop.dwPropId));
  606. if (Prop.dwFlags)
  607. dprintf(" Property dwFlags: 0x%lx\n", Prop.dwFlags);
  608. if (Prop.cbData) {
  609. BYTE *pbData;
  610. if (pbData = (BYTE *) CertExtsAlloc(Prop.cbData)) {
  611. __try {
  612. memset(pbData, 0, Prop.cbData);
  613. ReadMemory((LPVOID) Prop.pbData, pbData, Prop.cbData, NULL);
  614. PrintBytes(" ", pbData, Prop.cbData);
  615. } __except (EXCEPTION_EXECUTE_HANDLER) {
  616. dprintf("Unable to read Property at 0x%p .. 0x%p\n",
  617. Prop.pbData, Prop.pbData + Prop.cbData - 1);
  618. }
  619. CertExtsFree(pbData);
  620. }
  621. } else
  622. dprintf(" NO Property Bytes\n");
  623. pProp = Prop.pNext;
  624. if (i++ > MAX_PROP_CNT) {
  625. dprintf("Exceeded maximum prop count of %d\n", MAX_PROP_CNT);
  626. break;
  627. }
  628. }
  629. CommonReturn:
  630. return;
  631. ErrorReturn:
  632. goto CommonReturn;
  633. }
  634. void DisplayCert(
  635. IN PCCERT_CONTEXT pCert,
  636. IN DWORD dwDisplayFlags
  637. )
  638. {
  639. dprintf("Version:: %d\n", pCert->pCertInfo->dwVersion);
  640. dprintf("Subject::");
  641. DisplayName(&pCert->pCertInfo->Subject);
  642. dprintf("Issuer::");
  643. DisplayName(&pCert->pCertInfo->Issuer);
  644. dprintf("SerialNumber::");
  645. DisplaySerialNumber(&pCert->pCertInfo->SerialNumber);
  646. dprintf("NotBefore:: %s\n", FileTimeText(&pCert->pCertInfo->NotBefore));
  647. dprintf("NotAfter:: %s\n", FileTimeText(&pCert->pCertInfo->NotAfter));
  648. {
  649. BYTE rgbHash[MAX_HASH_LEN];
  650. DWORD cbHash = MAX_HASH_LEN;
  651. CertGetCertificateContextProperty(
  652. pCert,
  653. CERT_SHA1_HASH_PROP_ID,
  654. rgbHash,
  655. &cbHash
  656. );
  657. DisplayThumbprint("SHA1", rgbHash, cbHash);
  658. }
  659. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  660. LPSTR pszObjId;
  661. ALG_ID aiPubKey;
  662. DWORD dwBitLen;
  663. pszObjId = pCert->pCertInfo->SignatureAlgorithm.pszObjId;
  664. if (pszObjId == NULL)
  665. pszObjId = "<NULL OBJID>";
  666. dprintf("SignatureAlgorithm:: %s (%S)\n",
  667. pszObjId, GetOIDName(pszObjId, CRYPT_SIGN_ALG_OID_GROUP_ID));
  668. if (pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData) {
  669. dprintf("SignatureAlgorithm.Parameters::\n");
  670. PrintBytes(" ",
  671. pCert->pCertInfo->SignatureAlgorithm.Parameters.pbData,
  672. pCert->pCertInfo->SignatureAlgorithm.Parameters.cbData);
  673. }
  674. pszObjId = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
  675. if (pszObjId == NULL)
  676. pszObjId = "<NULL OBJID>";
  677. dprintf("SubjectPublicKeyInfo.Algorithm:: %s (%S)\n",
  678. pszObjId, GetOIDName(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID));
  679. aiPubKey = GetAlgid(pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID);
  680. if (pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData)
  681. {
  682. dprintf("SubjectPublicKeyInfo.Algorithm.Parameters::\n");
  683. PrintBytes(" ",
  684. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
  685. pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
  686. }
  687. dprintf("SubjectPublicKeyInfo.PublicKey");
  688. if (0 != (dwBitLen = CertGetPublicKeyLength(
  689. X509_ASN_ENCODING,
  690. &pCert->pCertInfo->SubjectPublicKeyInfo)))
  691. dprintf(" (BitLength: %d)", dwBitLen);
  692. if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits)
  693. dprintf(" (UnusedBits: %d)",
  694. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cUnusedBits);
  695. dprintf("::\n");
  696. if (pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData) {
  697. PrintBytes(" ",
  698. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  699. pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
  700. } else
  701. dprintf(" No public key\n");
  702. }
  703. PrintExtensions(pCert->pCertInfo->cExtension,
  704. pCert->pCertInfo->rgExtension, dwDisplayFlags);
  705. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  706. CRYPTUI_VIEWCERTIFICATE_STRUCTW CertViewInfo;
  707. memset(&CertViewInfo, 0, sizeof(CertViewInfo));
  708. CertViewInfo.pCertContext = pCert;
  709. CertViewInfo.dwSize = sizeof(CertViewInfo);
  710. if (!CryptUIDlgViewCertificateW(
  711. &CertViewInfo,
  712. NULL // pfPropertiesChanged
  713. ))
  714. PrintLastError("CryptUIDlgViewCertificateW");
  715. }
  716. }
  717. void PrintCrlEntries(DWORD cEntry, PCRL_ENTRY pEntry, DWORD dwDisplayFlags)
  718. {
  719. DWORD i;
  720. for (i = 0; i < cEntry; i++, pEntry++) {
  721. {
  722. dprintf(" [%d] SerialNumber::", i);
  723. DisplaySerialNumber(&pEntry->SerialNumber);
  724. }
  725. dprintf(" [%d] RevocationDate:: %s\n", i,
  726. FileTimeText(&pEntry->RevocationDate));
  727. if (dwDisplayFlags & (DISPLAY_VERBOSE_FLAG | DISPLAY_EXT_FLAG)) {
  728. if (pEntry->cExtension == 0)
  729. dprintf(" [%d] Extensions:: NONE\n", i);
  730. else {
  731. dprintf(" [%d] Extensions::\n", i);
  732. PrintExtensions(pEntry->cExtension, pEntry->rgExtension,
  733. dwDisplayFlags);
  734. }
  735. }
  736. }
  737. }
  738. void DisplayCrl(
  739. IN PCCRL_CONTEXT pCrl,
  740. IN DWORD dwDisplayFlags
  741. )
  742. {
  743. dprintf("Issuer::\n");
  744. DisplayName(&pCrl->pCrlInfo->Issuer);
  745. dprintf("ThisUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->ThisUpdate));
  746. dprintf("NextUpdate:: %s\n", FileTimeText(&pCrl->pCrlInfo->NextUpdate));
  747. {
  748. BYTE rgbHash[MAX_HASH_LEN];
  749. DWORD cbHash = MAX_HASH_LEN;
  750. CertGetCRLContextProperty(
  751. pCrl,
  752. CERT_SHA1_HASH_PROP_ID,
  753. rgbHash,
  754. &cbHash
  755. );
  756. DisplayThumbprint("SHA1", rgbHash, cbHash);
  757. }
  758. PrintExtensions(pCrl->pCrlInfo->cExtension, pCrl->pCrlInfo->rgExtension,
  759. dwDisplayFlags);
  760. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  761. if (pCrl->pCrlInfo->cCRLEntry == 0)
  762. dprintf("Entries:: NONE\n");
  763. else {
  764. dprintf("Entries::\n");
  765. PrintCrlEntries(pCrl->pCrlInfo->cCRLEntry,
  766. pCrl->pCrlInfo->rgCRLEntry, dwDisplayFlags);
  767. }
  768. }
  769. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  770. CRYPTUI_VIEWCRL_STRUCTW CrlViewInfo;
  771. memset(&CrlViewInfo, 0, sizeof(CrlViewInfo));
  772. CrlViewInfo.pCRLContext = pCrl;
  773. CrlViewInfo.dwSize = sizeof(CrlViewInfo);
  774. if (!CryptUIDlgViewCRLW(
  775. &CrlViewInfo
  776. ))
  777. PrintLastError("CryptUIDlgViewCRLW");
  778. }
  779. }
  780. static void PrintCtlEntries(
  781. IN PCCTL_CONTEXT pCtl,
  782. IN DWORD dwDisplayFlags
  783. )
  784. {
  785. PCTL_INFO pInfo = pCtl->pCtlInfo;
  786. DWORD cEntry = pInfo->cCTLEntry;
  787. PCTL_ENTRY pEntry = pInfo->rgCTLEntry;
  788. DWORD i;
  789. for (i = 0; i < cEntry; i++, pEntry++) {
  790. dprintf(" [%d] SubjectIdentifier::\n", i);
  791. PrintBytes(" ",
  792. pEntry->SubjectIdentifier.pbData,
  793. pEntry->SubjectIdentifier.cbData);
  794. }
  795. }
  796. void DisplayCtl(
  797. IN PCCTL_CONTEXT pCtl,
  798. IN DWORD dwDisplayFlags
  799. )
  800. {
  801. PCTL_INFO pInfo = pCtl->pCtlInfo;
  802. dprintf("Version:: %d\n", pInfo->dwVersion);
  803. {
  804. DWORD cId;
  805. LPSTR *ppszId;
  806. DWORD i;
  807. dprintf("SubjectUsage::\n");
  808. cId = pInfo->SubjectUsage.cUsageIdentifier;
  809. ppszId = pInfo->SubjectUsage.rgpszUsageIdentifier;
  810. if (cId == 0)
  811. dprintf(" No Usage Identifiers\n");
  812. for (i = 0; i < cId; i++, ppszId++)
  813. dprintf(" [%d] %s\n", i, *ppszId);
  814. }
  815. if (pInfo->ListIdentifier.cbData) {
  816. dprintf("ListIdentifier::\n");
  817. PrintBytes(" ",
  818. pInfo->ListIdentifier.pbData,
  819. pInfo->ListIdentifier.cbData);
  820. }
  821. if (pInfo->SequenceNumber.cbData) {
  822. dprintf("SequenceNumber::");
  823. DisplaySerialNumber(&pInfo->SequenceNumber);
  824. }
  825. dprintf("ThisUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->ThisUpdate));
  826. dprintf("NextUpdate:: %s\n", FileTimeText(&pCtl->pCtlInfo->NextUpdate));
  827. {
  828. BYTE rgbHash[MAX_HASH_LEN];
  829. DWORD cbHash = MAX_HASH_LEN;
  830. CertGetCTLContextProperty(
  831. pCtl,
  832. CERT_SHA1_HASH_PROP_ID,
  833. rgbHash,
  834. &cbHash
  835. );
  836. DisplayThumbprint("SHA1", rgbHash, cbHash);
  837. }
  838. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  839. LPSTR pszObjId;
  840. pszObjId = pInfo->SubjectAlgorithm.pszObjId;
  841. if (pszObjId == NULL)
  842. pszObjId = "<NULL OBJID>";
  843. dprintf("SubjectAlgorithm:: %s\n", pszObjId);
  844. if (pInfo->SubjectAlgorithm.Parameters.cbData) {
  845. dprintf("SubjectAlgorithm.Parameters::\n");
  846. PrintBytes(" ",
  847. pInfo->SubjectAlgorithm.Parameters.pbData,
  848. pInfo->SubjectAlgorithm.Parameters.cbData);
  849. }
  850. }
  851. PrintExtensions(pInfo->cExtension, pInfo->rgExtension, dwDisplayFlags);
  852. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  853. DWORD dwSignerCount;
  854. DWORD cbData;
  855. cbData = sizeof(dwSignerCount);
  856. if (!CryptMsgGetParam(
  857. pCtl->hCryptMsg,
  858. CMSG_SIGNER_COUNT_PARAM,
  859. 0, // dwIndex
  860. &dwSignerCount,
  861. &cbData)) {
  862. dprintf("----- Signer -----\n");
  863. PrintLastError("CryptMsgGetParam(SIGNER_COUNT)");
  864. } else if (0 == dwSignerCount)
  865. dprintf("----- No Signers -----\n");
  866. else {
  867. DWORD dwSignerIndex;
  868. for (dwSignerIndex = 0; dwSignerIndex < dwSignerCount;
  869. dwSignerIndex++) {
  870. DWORD dwFlags;
  871. PCCERT_CONTEXT pSigner;
  872. dwFlags = CMSG_USE_SIGNER_INDEX_FLAG;
  873. if (CryptMsgGetAndVerifySigner(
  874. pCtl->hCryptMsg,
  875. 0, // cSignerStore
  876. NULL, // rghSignerStore
  877. dwFlags,
  878. &pSigner,
  879. &dwSignerIndex
  880. )) {
  881. dprintf("----- Signer [%d] -----\n", dwSignerIndex);
  882. DisplayCert(pSigner, 0);
  883. CertFreeCertificateContext(pSigner);
  884. } else {
  885. DWORD dwErr = GetLastError();
  886. if (CRYPT_E_NO_TRUSTED_SIGNER == dwErr)
  887. dprintf("----- No Trusted Signer [%d] -----\n",
  888. dwSignerIndex);
  889. else {
  890. dprintf("----- Signer [%d] -----\n", dwSignerIndex);
  891. PrintLastError("CryptMsgGetAndVerifySigner");
  892. }
  893. }
  894. }
  895. }
  896. }
  897. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG) {
  898. if (pInfo->cCTLEntry == 0)
  899. dprintf("----- No Entries -----\n");
  900. else {
  901. dprintf("----- Entries -----\n");
  902. PrintCtlEntries(pCtl, dwDisplayFlags);
  903. }
  904. }
  905. if (dwDisplayFlags & DISPLAY_UI_FLAG) {
  906. CRYPTUI_VIEWCTL_STRUCTW CtlViewInfo;
  907. memset(&CtlViewInfo, 0, sizeof(CtlViewInfo));
  908. CtlViewInfo.pCTLContext = pCtl;
  909. CtlViewInfo.dwSize = sizeof(CtlViewInfo);
  910. if (!CryptUIDlgViewCTLW(
  911. &CtlViewInfo
  912. ))
  913. PrintLastError("CryptUIDlgViewCTLW");
  914. }
  915. }
  916. #define MAX_LINK_DEPTH 20
  917. PPROP_ELEMENT GetCachePropHead(
  918. IN PCONTEXT_ELEMENT pEle
  919. )
  920. {
  921. DWORD dwInnerDepth;
  922. if (ELEMENT_TYPE_CACHE == pEle->dwElementType)
  923. return pEle->Cache.pPropHead;
  924. pEle = pEle->pEle;
  925. // Skip past any links to get to the cache element
  926. dwInnerDepth = 0;
  927. while (pEle && dwInnerDepth++ < MAX_LINK_DEPTH) {
  928. CONTEXT_ELEMENT Ele;
  929. __try {
  930. memset(&Ele, 0, sizeof(Ele));
  931. ReadMemory((LPVOID) pEle, &Ele, sizeof(Ele), NULL);
  932. } __except (EXCEPTION_EXECUTE_HANDLER) {
  933. dprintf("Unable to read Context Element at 0x%p\n", pEle);
  934. return NULL;
  935. }
  936. if (ELEMENT_TYPE_CACHE == Ele.dwElementType)
  937. return Ele.Cache.pPropHead;
  938. pEle = Ele.pEle;
  939. }
  940. return NULL;
  941. }
  942. void DisplayContextElement(
  943. IN PCONTEXT_ELEMENT pEle,
  944. IN DWORD dwDisplayFlags,
  945. IN BOOL fNext = FALSE
  946. )
  947. {
  948. DWORD i;
  949. i = 0;
  950. while (pEle) {
  951. CONTEXT_ELEMENT Ele;
  952. const void *pvContext = (const void *) ((BYTE *) pEle +
  953. sizeof(CONTEXT_ELEMENT));
  954. __try {
  955. memset(&Ele, 0, sizeof(Ele));
  956. ReadMemory((LPVOID) pEle, &Ele, sizeof(Ele), NULL);
  957. } __except (EXCEPTION_EXECUTE_HANDLER) {
  958. dprintf("Unable to read Context Element at 0x%p\n", pEle);
  959. goto ErrorReturn;
  960. }
  961. dprintf("==== ");
  962. switch (Ele.dwContextType + 1) {
  963. case CERT_STORE_CERTIFICATE_CONTEXT:
  964. dprintf("Certificate");
  965. break;
  966. case CERT_STORE_CRL_CONTEXT:
  967. dprintf("CRL");
  968. break;
  969. case CERT_STORE_CTL_CONTEXT:
  970. dprintf("CTL");
  971. break;
  972. default:
  973. dprintf("ContextType[%ld]", Ele.dwContextType);
  974. }
  975. dprintf("[");
  976. if (fNext)
  977. dprintf("%ld : ", i);
  978. dprintf("0x%p] ====\n", pvContext);
  979. if (0 == (dwDisplayFlags & DISPLAY_SHORT_FLAG)) {
  980. dprintf("Element[0x%p]:: Type: ", pEle);
  981. switch (Ele.dwElementType) {
  982. case ELEMENT_TYPE_CACHE:
  983. dprintf("CACHE");
  984. break;
  985. case ELEMENT_TYPE_LINK_CONTEXT:
  986. dprintf("LINK");
  987. break;
  988. case ELEMENT_TYPE_EXTERNAL:
  989. dprintf("EXTERNAL");
  990. break;
  991. case ELEMENT_TYPE_COLLECTION:
  992. dprintf("COLLECTION");
  993. break;
  994. default:
  995. dprintf("%ld", Ele.dwElementType);
  996. }
  997. dprintf(" RefCnt: %ld", Ele.lRefCnt);
  998. dprintf(" Flags: 0x%lx", Ele.dwFlags);
  999. if (Ele.pEle != pEle)
  1000. dprintf(" pEle: 0x%p", Ele.pEle);
  1001. dprintf(" NextContext: 0x%p", ToCertContext(Ele.pNext));
  1002. dprintf(" PrevContext: 0x%p", ToCertContext(Ele.pPrev));
  1003. dprintf(" Store: 0x%p", Ele.pStore);
  1004. dprintf(" ProvStore: 0x%p", Ele.pProvStore);
  1005. dprintf("\n");
  1006. switch (Ele.dwContextType + 1) {
  1007. case CERT_STORE_CERTIFICATE_CONTEXT:
  1008. {
  1009. CERT_CONTEXT CertContext;
  1010. BYTE *pbEncoded;
  1011. DWORD cbEncoded;
  1012. PCCERT_CONTEXT pCert;
  1013. __try {
  1014. memset(&CertContext, 0, sizeof(CertContext));
  1015. ReadMemory(pvContext, &CertContext,
  1016. sizeof(CertContext), NULL);
  1017. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1018. dprintf("Unable to read CertContext at 0x%p\n",
  1019. pvContext);
  1020. break;
  1021. }
  1022. if (!GetEncodedBlob(CertContext.pbCertEncoded,
  1023. &pbEncoded, &cbEncoded))
  1024. break;
  1025. pCert = CertCreateCertificateContext(
  1026. X509_ASN_ENCODING,
  1027. pbEncoded,
  1028. cbEncoded
  1029. );
  1030. if (pCert) {
  1031. DisplayCert(pCert, dwDisplayFlags);
  1032. CertFreeCertificateContext(pCert);
  1033. } else
  1034. PrintLastError("CertCreateCertificateContext");
  1035. CertExtsFree(pbEncoded);
  1036. }
  1037. break;
  1038. case CERT_STORE_CRL_CONTEXT:
  1039. {
  1040. CRL_CONTEXT CrlContext;
  1041. BYTE *pbEncoded;
  1042. DWORD cbEncoded;
  1043. PCCRL_CONTEXT pCrl;
  1044. __try {
  1045. memset(&CrlContext, 0, sizeof(CrlContext));
  1046. ReadMemory(pvContext, &CrlContext,
  1047. sizeof(CrlContext), NULL);
  1048. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1049. dprintf("Unable to read CrlContext at 0x%p\n",
  1050. pvContext);
  1051. break;
  1052. }
  1053. if (!GetEncodedBlob(CrlContext.pbCrlEncoded,
  1054. &pbEncoded, &cbEncoded))
  1055. break;
  1056. pCrl = CertCreateCRLContext(
  1057. X509_ASN_ENCODING,
  1058. pbEncoded,
  1059. cbEncoded
  1060. );
  1061. if (pCrl) {
  1062. DisplayCrl(pCrl, dwDisplayFlags);
  1063. CertFreeCRLContext(pCrl);
  1064. } else
  1065. PrintLastError("CertCreateCRLContext");
  1066. CertExtsFree(pbEncoded);
  1067. }
  1068. break;
  1069. case CERT_STORE_CTL_CONTEXT:
  1070. {
  1071. CTL_CONTEXT CtlContext;
  1072. BYTE *pbEncoded;
  1073. DWORD cbEncoded;
  1074. PCCTL_CONTEXT pCtl;
  1075. __try {
  1076. memset(&CtlContext, 0, sizeof(CtlContext));
  1077. ReadMemory(pvContext, &CtlContext,
  1078. sizeof(CtlContext), NULL);
  1079. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1080. dprintf("Unable to read CtlContext at 0x%p\n",
  1081. pvContext);
  1082. break;
  1083. }
  1084. if (!GetEncodedBlob(CtlContext.pbCtlEncoded,
  1085. &pbEncoded, &cbEncoded))
  1086. break;
  1087. pCtl = CertCreateCTLContext(
  1088. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1089. pbEncoded,
  1090. cbEncoded
  1091. );
  1092. if (pCtl) {
  1093. DisplayCtl(pCtl, dwDisplayFlags);
  1094. CertFreeCTLContext(pCtl);
  1095. } else
  1096. PrintLastError("CertCreateCTLContext");
  1097. CertExtsFree(pbEncoded);
  1098. }
  1099. break;
  1100. }
  1101. PrintProperties(GetCachePropHead(&Ele), dwDisplayFlags);
  1102. }
  1103. if (!fNext)
  1104. break;
  1105. pEle = Ele.pNext;
  1106. if (i++ > MAX_CONTEXT_CNT) {
  1107. dprintf("Exceeded maximum context count of %d\n", MAX_CONTEXT_CNT);
  1108. break;
  1109. }
  1110. }
  1111. CommonReturn:
  1112. return;
  1113. ErrorReturn:
  1114. goto CommonReturn;
  1115. }
  1116. void DisplayContext(
  1117. IN const void *pvContext,
  1118. IN DWORD dwDisplayFlags
  1119. )
  1120. {
  1121. if (((const void *)(UINT_PTR) sizeof(CONTEXT_ELEMENT)) > pvContext) {
  1122. dprintf("Invalid, NULL Context address\n");
  1123. return;
  1124. }
  1125. DisplayContextElement(
  1126. ToContextElement((PCCERT_CONTEXT) pvContext),
  1127. dwDisplayFlags
  1128. );
  1129. }
  1130. void DisplayStore(
  1131. IN PCERT_STORE pStore,
  1132. IN DWORD dwDisplayFlags,
  1133. IN DWORD dwNest
  1134. )
  1135. {
  1136. CERT_STORE Store;
  1137. PCERT_STORE_LINK pStoreLink;
  1138. DWORD i;
  1139. __try {
  1140. memset(&Store, 0, sizeof(Store));
  1141. ReadMemory((LPVOID) pStore, &Store, sizeof(Store), NULL);
  1142. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1143. dprintf("Unable to read Store at 0x%p\n", pStore);
  1144. goto ErrorReturn;
  1145. }
  1146. dprintf("Store[0x%p]:: Type: ", pStore);
  1147. switch (Store.dwStoreType) {
  1148. case STORE_TYPE_CACHE:
  1149. dprintf("CACHE");
  1150. break;
  1151. case STORE_TYPE_EXTERNAL:
  1152. dprintf("EXTERNAL");
  1153. break;
  1154. case STORE_TYPE_COLLECTION:
  1155. dprintf("COLLECTION");
  1156. break;
  1157. default:
  1158. dprintf("%ld", Store.dwStoreType);
  1159. }
  1160. dprintf(" RefCnt: %ld", Store.lRefCnt);
  1161. dprintf(" Flags: 0x%lx", Store.dwFlags);
  1162. dprintf(" State: ");
  1163. switch (Store.dwState) {
  1164. case STORE_STATE_DELETED:
  1165. dprintf("DELETED");
  1166. break;
  1167. case STORE_STATE_NULL:
  1168. dprintf("NULL");
  1169. break;
  1170. case STORE_STATE_OPENING:
  1171. dprintf("OPENING");
  1172. break;
  1173. case STORE_STATE_OPEN:
  1174. dprintf("OPEN");
  1175. break;
  1176. case STORE_STATE_DEFER_CLOSING:
  1177. dprintf("DEFER_CLOSING");
  1178. break;
  1179. case STORE_STATE_CLOSING:
  1180. dprintf("CLOSING");
  1181. break;
  1182. case STORE_STATE_CLOSED:
  1183. dprintf("CLOSED");
  1184. break;
  1185. default:
  1186. dprintf("%ld", Store.dwState);
  1187. }
  1188. dprintf("\n");
  1189. PrintProperties(Store.pPropHead, dwDisplayFlags | DISPLAY_PROP_FLAG);
  1190. for (i = 0; i < CONTEXT_COUNT; i++)
  1191. DisplayContextElement(Store.rgpContextListHead[i], dwDisplayFlags,
  1192. TRUE);
  1193. i = 0;
  1194. pStoreLink = Store.pStoreListHead;
  1195. while (pStoreLink) {
  1196. CERT_STORE_LINK StoreLink;
  1197. DWORD j;
  1198. __try {
  1199. memset(&StoreLink, 0, sizeof(StoreLink));
  1200. ReadMemory((LPVOID) pStoreLink, &StoreLink, sizeof(StoreLink),
  1201. NULL);
  1202. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1203. dprintf("Unable to read StoreLink at 0x%p\n", pStoreLink);
  1204. goto ErrorReturn;
  1205. }
  1206. dprintf("###### SiblingStore[%ld, %ld] ######\n", dwNest, i);
  1207. dprintf("Link[0x%p]:: Flags: 0x%lx", pStoreLink, StoreLink.dwFlags);
  1208. dprintf(" RefCnt: %ld", StoreLink.lRefCnt);
  1209. dprintf(" UpdateFlags: 0x%lx", StoreLink.dwUpdateFlags);
  1210. dprintf(" Priority: %ld", StoreLink.dwPriority);
  1211. dprintf("\n");
  1212. if (dwNest > MAX_STORE_NEST_CNT) {
  1213. dprintf("Exceeded maximum store nest count of %d\n",
  1214. MAX_STORE_NEST_CNT);
  1215. break;
  1216. }
  1217. DisplayStore(StoreLink.pSibling, dwDisplayFlags, dwNest + 1);
  1218. pStoreLink = StoreLink.pNext;
  1219. if (i++ > MAX_STORE_SIBLING_CNT) {
  1220. dprintf("Exceeded maximum store sibling count of %d\n",
  1221. MAX_STORE_SIBLING_CNT);
  1222. break;
  1223. }
  1224. }
  1225. CommonReturn:
  1226. return;
  1227. ErrorReturn:
  1228. goto CommonReturn;
  1229. }
  1230. DWORD GetDisplayFlags(
  1231. IN OUT LPSTR *lppArgumentString
  1232. )
  1233. {
  1234. DWORD dwDisplayFlags = 0;
  1235. LPSTR lpArgumentString = *lppArgumentString;
  1236. while (TRUE) {
  1237. while (*lpArgumentString == ' ')
  1238. lpArgumentString++;
  1239. if (*lpArgumentString == 's') {
  1240. dwDisplayFlags |= DISPLAY_SHORT_FLAG;
  1241. lpArgumentString++;
  1242. } else if (*lpArgumentString == 'v') {
  1243. dwDisplayFlags |= DISPLAY_VERBOSE_FLAG;
  1244. lpArgumentString++;
  1245. } else if (*lpArgumentString == 'u') {
  1246. dwDisplayFlags |= DISPLAY_UI_FLAG;
  1247. lpArgumentString++;
  1248. } else if (*lpArgumentString == 'x') {
  1249. dwDisplayFlags |= DISPLAY_EXT_FLAG;
  1250. lpArgumentString++;
  1251. } else if (*lpArgumentString == 'p') {
  1252. dwDisplayFlags |= DISPLAY_PROP_FLAG;
  1253. lpArgumentString++;
  1254. } else
  1255. break;
  1256. }
  1257. *lppArgumentString = lpArgumentString;
  1258. return dwDisplayFlags;
  1259. }
  1260. //
  1261. // context {[s|v|u|x|p]} address
  1262. //
  1263. DECLARE_API( context )
  1264. {
  1265. DWORD dwDisplayFlags;
  1266. const void *pvContext;
  1267. INIT_API();
  1268. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1269. pvContext = (const void *)(ULONG_PTR) GetExpression(lpArgumentString);
  1270. if (NULL == pvContext) {
  1271. dprintf("Invalid, NULL address\n");
  1272. return;
  1273. }
  1274. DisplayContext(
  1275. pvContext,
  1276. dwDisplayFlags
  1277. );
  1278. }
  1279. //
  1280. // ele {[s|v|u|x|p]} address
  1281. //
  1282. DECLARE_API( ele )
  1283. {
  1284. DWORD dwDisplayFlags;
  1285. PCONTEXT_ELEMENT pEle;
  1286. INIT_API();
  1287. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1288. pEle = (PCONTEXT_ELEMENT)(ULONG_PTR) GetExpression(lpArgumentString);
  1289. if (NULL == pEle) {
  1290. dprintf("Invalid, NULL address\n");
  1291. return;
  1292. }
  1293. DisplayContextElement(
  1294. pEle,
  1295. dwDisplayFlags
  1296. );
  1297. }
  1298. //
  1299. // store {[s|v|x|p]} address
  1300. //
  1301. DECLARE_API( store )
  1302. {
  1303. DWORD dwDisplayFlags;
  1304. PCERT_STORE pStore;
  1305. INIT_API();
  1306. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1307. dwDisplayFlags &= ~DISPLAY_UI_FLAG;
  1308. pStore = (PCERT_STORE)(ULONG_PTR) GetExpression(lpArgumentString);
  1309. if (NULL == pStore) {
  1310. dprintf("Invalid, NULL address\n");
  1311. return;
  1312. }
  1313. dprintf("###### Parent Store ######\n");
  1314. DisplayStore(
  1315. pStore,
  1316. dwDisplayFlags,
  1317. 0 // dwNest
  1318. );
  1319. }
  1320. //
  1321. // cert {[s|v|u|x|p]} address
  1322. //
  1323. DECLARE_API( cert )
  1324. {
  1325. DWORD dwDisplayFlags;
  1326. LPVOID pvAddr;
  1327. BYTE *pbEncoded = NULL;
  1328. DWORD cbEncoded;
  1329. PCCERT_CONTEXT pCert = NULL;
  1330. INIT_API();
  1331. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1332. pvAddr = (LPVOID)(ULONG_PTR) GetExpression(lpArgumentString);
  1333. if (NULL == pvAddr) {
  1334. dprintf("Invalid, NULL address\n");
  1335. goto ErrorReturn;
  1336. }
  1337. //dprintf("Expression:: 0x%p\n", pvAddr);
  1338. if (!GetEncodedBlob(pvAddr, &pbEncoded, &cbEncoded))
  1339. goto ErrorReturn;
  1340. pCert = CertCreateCertificateContext(
  1341. X509_ASN_ENCODING,
  1342. pbEncoded,
  1343. cbEncoded
  1344. );
  1345. if (pCert == NULL) {
  1346. PrintLastError("CertCreateCertificateContext");
  1347. goto ErrorReturn;
  1348. }
  1349. dprintf("===== Certificate =====\n");
  1350. DisplayCert(pCert, dwDisplayFlags);
  1351. CommonReturn:
  1352. CertExtsFree(pbEncoded);
  1353. CertFreeCertificateContext(pCert);
  1354. return;
  1355. ErrorReturn:
  1356. goto CommonReturn;
  1357. }
  1358. //
  1359. // crl {[s|v|u|x|p]} address
  1360. //
  1361. DECLARE_API( crl )
  1362. {
  1363. DWORD dwDisplayFlags;
  1364. LPVOID pvAddr;
  1365. BYTE *pbEncoded = NULL;
  1366. DWORD cbEncoded;
  1367. PCCRL_CONTEXT pCrl = NULL;
  1368. INIT_API();
  1369. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1370. pvAddr = (LPVOID)(ULONG_PTR) GetExpression(lpArgumentString);
  1371. if (NULL == pvAddr) {
  1372. dprintf("Invalid, NULL address\n");
  1373. goto ErrorReturn;
  1374. }
  1375. //dprintf("Expression:: 0x%p\n", pvAddr);
  1376. if (!GetEncodedBlob(pvAddr, &pbEncoded, &cbEncoded))
  1377. goto ErrorReturn;
  1378. pCrl = CertCreateCRLContext(
  1379. X509_ASN_ENCODING,
  1380. pbEncoded,
  1381. cbEncoded
  1382. );
  1383. if (pCrl == NULL) {
  1384. PrintLastError("CertCreateCRLContext");
  1385. goto ErrorReturn;
  1386. }
  1387. dprintf("===== CRL =====\n");
  1388. DisplayCrl(pCrl, dwDisplayFlags);
  1389. CommonReturn:
  1390. CertExtsFree(pbEncoded);
  1391. CertFreeCRLContext(pCrl);
  1392. return;
  1393. ErrorReturn:
  1394. goto CommonReturn;
  1395. }
  1396. //
  1397. // ctl {[s|v|u|x|p]} address
  1398. //
  1399. DECLARE_API( ctl )
  1400. {
  1401. DWORD dwDisplayFlags;
  1402. LPVOID pvAddr;
  1403. BYTE *pbEncoded = NULL;
  1404. DWORD cbEncoded;
  1405. PCCTL_CONTEXT pCtl = NULL;
  1406. INIT_API();
  1407. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1408. pvAddr = (LPVOID)(ULONG_PTR) GetExpression(lpArgumentString);
  1409. if (NULL == pvAddr) {
  1410. dprintf("Invalid, NULL address\n");
  1411. goto ErrorReturn;
  1412. }
  1413. //dprintf("Expression:: 0x%p\n", pvAddr);
  1414. if (!GetEncodedBlob(pvAddr, &pbEncoded, &cbEncoded))
  1415. goto ErrorReturn;
  1416. pCtl = CertCreateCTLContext(
  1417. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1418. pbEncoded,
  1419. cbEncoded
  1420. );
  1421. if (pCtl == NULL) {
  1422. PrintLastError("CertCreateCTLContext");
  1423. goto ErrorReturn;
  1424. }
  1425. dprintf("===== CTL =====\n");
  1426. DisplayCtl(pCtl, dwDisplayFlags);
  1427. CommonReturn:
  1428. CertExtsFree(pbEncoded);
  1429. CertFreeCTLContext(pCtl);
  1430. return;
  1431. ErrorReturn:
  1432. goto CommonReturn;
  1433. }
  1434. //+---------------------------------------------------------------------------
  1435. //
  1436. // Synopsis: Chain Display Functions
  1437. //
  1438. //----------------------------------------------------------------------------
  1439. LPCSTR rgszErrorStatus[] = {
  1440. "CERT_TRUST_IS_NOT_TIME_VALID", // 0x00000001
  1441. "CERT_TRUST_IS_NOT_TIME_NESTED", // 0x00000002
  1442. "CERT_TRUST_IS_REVOKED", // 0x00000004
  1443. "CERT_TRUST_IS_NOT_SIGNATURE_VALID", // 0x00000008
  1444. "CERT_TRUST_IS_NOT_VALID_FOR_USAGE", // 0x00000010
  1445. "CERT_TRUST_IS_UNTRUSTED_ROOT", // 0x00000020
  1446. "CERT_TRUST_REVOCATION_STATUS_UNKNOWN", // 0x00000040
  1447. "CERT_TRUST_IS_CYCLIC", // 0x00000080
  1448. "Unknown Error Status", // 0x00000100
  1449. "Unknown Error Status", // 0x00000200
  1450. "Unknown Error Status", // 0x00000400
  1451. "Unknown Error Status", // 0x00000800
  1452. "Unknown Error Status", // 0x00001000
  1453. "Unknown Error Status", // 0x00002000
  1454. "Unknown Error Status", // 0x00004000
  1455. "Unknown Error Status", // 0x00008000
  1456. "CERT_TRUST_IS_PARTIAL_CHAIN", // 0x00010000
  1457. "CERT_TRUST_CTL_IS_NOT_TIME_VALID", // 0x00020000
  1458. "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID", // 0x00040000
  1459. "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE", // 0x00080000
  1460. "Unknown Error Status",
  1461. "Unknown Error Status",
  1462. "Unknown Error Status",
  1463. "Unknown Error Status",
  1464. "Unknown Error Status",
  1465. "Unknown Error Status",
  1466. "Unknown Error Status",
  1467. "Unknown Error Status",
  1468. "Unknown Error Status",
  1469. "Unknown Error Status",
  1470. "Unknown Error Status",
  1471. "Unknown Error Status",
  1472. "Unknown Error Status",
  1473. "Unknown Error Status"
  1474. };
  1475. LPCSTR rgszInfoStatus[] = {
  1476. "CERT_TRUST_HAS_EXACT_MATCH_ISSUER",// 0x00000001
  1477. "CERT_TRUST_HAS_KEY_MATCH_ISSUER", // 0x00000002
  1478. "CERT_TRUST_HAS_NAME_MATCH_ISSUER", // 0x00000004
  1479. "CERT_TRUST_IS_SELF_SIGNED", // 0x00000008
  1480. "Unknown Info Status", // 0x00000010
  1481. "Unknown Info Status", // 0x00000020
  1482. "Unknown Info Status", // 0x00000040
  1483. "Unknown Info Status", // 0x00000080
  1484. "Unknown Info Status", // 0x00000100
  1485. "Unknown Info Status", // 0x00000200
  1486. "Unknown Info Status", // 0x00000400
  1487. "Unknown Info Status", // 0x00000800
  1488. "Unknown Info Status", // 0x00001000
  1489. "Unknown Info Status", // 0x00002000
  1490. "Unknown Info Status", // 0x00004000
  1491. "Unknown Info Status", // 0x00008000
  1492. "CERT_TRUST_IS_COMPLEX_CHAIN", // 0x00010000
  1493. "Unknown Info Status", // 0x00020000
  1494. "Unknown Info Status", // 0x00040000
  1495. "Unknown Info Status", // 0x00080000
  1496. "Unknown Info Status", // 0x00100000
  1497. "Unknown Info Status", // 0x00200000
  1498. "Unknown Info Status", // 0x00400000
  1499. "Unknown Info Status", // 0x00800000
  1500. "Unknown Info Status", // 0x01000000
  1501. "Unknown Info Status", // 0x02000000
  1502. "Unknown Info Status", // 0x04000000
  1503. "Unknown Info Status", // 0x08000000
  1504. "Unknown Info Status", // 0x10000000
  1505. "Unknown Info Status", // 0x20000000
  1506. "Unknown Info Status", // 0x40000000
  1507. "Unknown Info Status" // 0x80000000
  1508. };
  1509. void DisplayTrustStatus(
  1510. IN PCERT_TRUST_STATUS pStatus
  1511. )
  1512. {
  1513. DWORD dwMask;
  1514. DWORD cCount;
  1515. dprintf(
  1516. "Trust Status (E=0x%lx,I=0x%lx)\n\n",
  1517. pStatus->dwErrorStatus,
  1518. pStatus->dwInfoStatus
  1519. );
  1520. dwMask = 1;
  1521. for ( cCount = 0; cCount < 32; cCount++ )
  1522. {
  1523. if ( pStatus->dwErrorStatus & dwMask )
  1524. {
  1525. if ( strcmp( rgszErrorStatus[ cCount ], "Unknown Error Status" ) != 0 )
  1526. {
  1527. dprintf("%s\n", rgszErrorStatus[ cCount ]);
  1528. }
  1529. }
  1530. dwMask = dwMask << 1;
  1531. }
  1532. dwMask = 1;
  1533. for ( cCount = 0; cCount < 32; cCount++ )
  1534. {
  1535. if ( pStatus->dwInfoStatus & dwMask )
  1536. {
  1537. if ( strcmp( rgszInfoStatus[ cCount ], "Unknown Info Status" ) != 0 )
  1538. {
  1539. dprintf("%s\n", rgszInfoStatus[ cCount ]);
  1540. }
  1541. }
  1542. dwMask = dwMask << 1;
  1543. }
  1544. dprintf("\n");
  1545. }
  1546. void DisplayChainElement(
  1547. IN PCERT_CHAIN_ELEMENT pElement,
  1548. IN DWORD dwDisplayFlags
  1549. )
  1550. {
  1551. CERT_CHAIN_ELEMENT Element;
  1552. __try {
  1553. memset(&Element, 0, sizeof(Element));
  1554. ReadMemory((LPVOID) pElement, &Element, sizeof(Element), NULL);
  1555. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1556. dprintf("Unable to read Chain Element at 0x%p\n", pElement);
  1557. return;
  1558. }
  1559. DisplayContext( Element.pCertContext, dwDisplayFlags );
  1560. dprintf("\n");
  1561. DisplayTrustStatus( &Element.TrustStatus );
  1562. }
  1563. void DisplaySimpleChain(
  1564. IN PCERT_SIMPLE_CHAIN pChain,
  1565. IN DWORD dwDisplayFlags
  1566. )
  1567. {
  1568. CERT_SIMPLE_CHAIN Chain;
  1569. DWORD cElement;
  1570. PCERT_CHAIN_ELEMENT *ppElement = NULL;
  1571. if (NULL == pChain)
  1572. return;
  1573. __try {
  1574. memset(&Chain, 0, sizeof(Chain));
  1575. ReadMemory((LPVOID) pChain, &Chain, sizeof(Chain), NULL);
  1576. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1577. dprintf("Unable to read Simple Chain at 0x%p\n", pChain);
  1578. goto ErrorReturn;
  1579. }
  1580. DisplayTrustStatus( &Chain.TrustStatus );
  1581. dprintf("Chain Element Count = %d\n", Chain.cElement);
  1582. if (MAX_CHAIN_ELEMENT_CNT < Chain.cElement) {
  1583. dprintf("Exceeded maximum chain element count of %d\n",
  1584. MAX_CHAIN_ELEMENT_CNT);
  1585. goto ErrorReturn;
  1586. }
  1587. if (Chain.cElement) {
  1588. if (NULL == (ppElement = (PCERT_CHAIN_ELEMENT *) CertExtsAlloc(
  1589. Chain.cElement * sizeof(PCERT_CHAIN_ELEMENT))))
  1590. goto ErrorReturn;
  1591. __try {
  1592. memset(ppElement, 0, Chain.cElement * sizeof(PCERT_CHAIN_ELEMENT));
  1593. ReadMemory((LPVOID) Chain.rgpElement, ppElement,
  1594. Chain.cElement * sizeof(PCERT_CHAIN_ELEMENT), NULL);
  1595. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1596. dprintf("Unable to read ChainElement pointers at 0x%p\n",
  1597. Chain.rgpElement);
  1598. goto ErrorReturn;
  1599. }
  1600. }
  1601. for ( cElement = 0; cElement < Chain.cElement; cElement++ )
  1602. {
  1603. dprintf("Chain Element [%d]\n", cElement);
  1604. DisplayChainElement( ppElement[ cElement ], dwDisplayFlags );
  1605. }
  1606. CommonReturn:
  1607. CertExtsFree(ppElement);
  1608. return;
  1609. ErrorReturn:
  1610. goto CommonReturn;
  1611. }
  1612. void DisplayChain(
  1613. IN PCCERT_CHAIN_CONTEXT pChainContext,
  1614. IN DWORD dwDisplayFlags
  1615. )
  1616. {
  1617. CERT_CHAIN_CONTEXT ChainContext;
  1618. DWORD cChain;
  1619. PCERT_SIMPLE_CHAIN *ppChain = NULL;
  1620. if (NULL == pChainContext)
  1621. return;
  1622. __try {
  1623. memset(&ChainContext, 0, sizeof(ChainContext));
  1624. ReadMemory((LPVOID) pChainContext, &ChainContext,
  1625. sizeof(ChainContext), NULL);
  1626. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1627. dprintf("Unable to read ChainContext at 0x%p\n", pChainContext);
  1628. goto ErrorReturn;
  1629. }
  1630. dprintf("Chain Context\n\n");
  1631. DisplayTrustStatus( (PCERT_TRUST_STATUS)&ChainContext.TrustStatus );
  1632. dprintf("Simple Chain Count = %d\n\n", ChainContext.cChain );
  1633. if (MAX_SIMPLE_CHAIN_CNT < ChainContext.cChain) {
  1634. dprintf("Exceeded maximum simple chain count of %d\n",
  1635. MAX_SIMPLE_CHAIN_CNT);
  1636. goto ErrorReturn;
  1637. }
  1638. if (ChainContext.cChain) {
  1639. if (NULL == (ppChain = (PCERT_SIMPLE_CHAIN *) CertExtsAlloc(
  1640. ChainContext.cChain * sizeof(PCERT_SIMPLE_CHAIN))))
  1641. goto ErrorReturn;
  1642. __try {
  1643. memset(ppChain, 0,
  1644. ChainContext.cChain * sizeof(PCERT_SIMPLE_CHAIN));
  1645. ReadMemory((LPVOID) ChainContext.rgpChain, ppChain,
  1646. ChainContext.cChain * sizeof(PCERT_SIMPLE_CHAIN), NULL);
  1647. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1648. dprintf("Unable to read SimpleChain pointers at 0x%p\n",
  1649. ChainContext.rgpChain);
  1650. goto ErrorReturn;
  1651. }
  1652. }
  1653. for ( cChain = 0; cChain < ChainContext.cChain; cChain++ )
  1654. {
  1655. dprintf("Simple Chain [%d]\n", cChain);
  1656. DisplaySimpleChain( ppChain[ cChain ], dwDisplayFlags );
  1657. }
  1658. CommonReturn:
  1659. CertExtsFree(ppChain);
  1660. return;
  1661. ErrorReturn:
  1662. goto CommonReturn;
  1663. }
  1664. //
  1665. // chain {[s|v|x|p]} address
  1666. //
  1667. DECLARE_API( chain )
  1668. {
  1669. DWORD dwDisplayFlags;
  1670. PCCERT_CHAIN_CONTEXT pChainContext;
  1671. INIT_API();
  1672. dwDisplayFlags = GetDisplayFlags(&lpArgumentString);
  1673. dwDisplayFlags &= ~DISPLAY_UI_FLAG;
  1674. pChainContext = (PCCERT_CHAIN_CONTEXT)(ULONG_PTR) GetExpression(lpArgumentString);
  1675. if (NULL == pChainContext) {
  1676. dprintf("Invalid, NULL address\n");
  1677. return;
  1678. }
  1679. DisplayChain(
  1680. pChainContext,
  1681. dwDisplayFlags
  1682. );
  1683. }