Leaked source code of windows server 2003
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.

605 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: tfindclt.cpp
  8. //
  9. // Contents: FindCertsByIssuer, CertFindChainInStore APIs test
  10. //
  11. // See Usage() for list of test options.
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 21-May-96 philh created
  17. // 07-Jun-96 HelleS Added printing the command line
  18. // and Failed or Passed at the end.
  19. // 01-Mar-98 philh Added to call CertFindChainInStore
  20. //
  21. //--------------------------------------------------------------------------
  22. #define CERT_CHAIN_FIND_BY_ISSUER_PARA_HAS_EXTRA_FIELDS 1
  23. #include <windows.h>
  24. #include <assert.h>
  25. #include "wincrypt.h"
  26. #include "certtest.h"
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <memory.h>
  31. #include <time.h>
  32. static struct
  33. {
  34. LPCSTR pszName;
  35. DWORD dwKeySpec;
  36. } KeyTypes[] = {
  37. "Sign", AT_SIGNATURE,
  38. "Xchg", AT_KEYEXCHANGE
  39. };
  40. #define NKEYTYPES (sizeof(KeyTypes)/sizeof(KeyTypes[0]))
  41. static DWORD dwDisplayFlags = 0;
  42. static void Usage(void)
  43. {
  44. printf("Usage: tfindclt [options] [<Issuer CertFilename> [<KeyType>]]\n");
  45. printf("Options are:\n");
  46. printf(" -CompareKey\n");
  47. printf(" -ComplexChain\n");
  48. printf(" -CacheOnly\n");
  49. printf(" -NoKey\n");
  50. printf("\n");
  51. printf(" -c<SystemStore> - Chain System Store\n");
  52. printf(" -C<FileSystemStore> - Chain File System Store\n");
  53. printf(" -u<OID String> - Usage OID string -u1.3.6.1.5.5.7.3.3\n");
  54. printf(" -S[<FileName>] - Use issuer cert's subject name (default)\n");
  55. printf(" -I[<FileName>] - Use issuer cert's issuer name\n");
  56. printf(" -b - Brief\n");
  57. printf(" -v - Verbose\n");
  58. printf(" -h - This message\n");
  59. printf("\n");
  60. printf("KeyType (case insensitive):\n");
  61. int i;
  62. for (i = 0; i < NKEYTYPES; i++)
  63. printf(" %s\n", KeyTypes[i].pszName);
  64. printf("\n");
  65. }
  66. //+---------------------------------------------------------------------------
  67. //
  68. // Synopsis: Chain Display Functions
  69. //
  70. //----------------------------------------------------------------------------
  71. LPSTR rgszErrorStatus[] = {
  72. "CERT_TRUST_IS_NOT_TIME_VALID",
  73. "CERT_TRUST_IS_NOT_TIME_NESTED",
  74. "CERT_TRUST_IS_REVOKED",
  75. "CERT_TRUST_IS_NOT_SIGNATURE_VALID",
  76. "CERT_TRUST_IS_NOT_VALID_FOR_USAGE",
  77. "CERT_TRUST_IS_UNTRUSTED_ROOT",
  78. "CERT_TRUST_REVOCATION_STATUS_UNKNOWN",
  79. "Unknown Error Status",
  80. "Unknown Error Status",
  81. "Unknown Error Status",
  82. "Unknown Error Status",
  83. "Unknown Error Status",
  84. "Unknown Error Status",
  85. "Unknown Error Status",
  86. "Unknown Error Status",
  87. "Unknown Error Status",
  88. "CERT_TRUST_IS_PARTIAL_CHAIN",
  89. "CERT_TRUST_CTL_IS_NOT_TIME_VALID",
  90. "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID",
  91. "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE",
  92. "Unknown Error Status",
  93. "Unknown Error Status",
  94. "Unknown Error Status",
  95. "Unknown Error Status",
  96. "Unknown Error Status",
  97. "Unknown Error Status",
  98. "Unknown Error Status",
  99. "Unknown Error Status",
  100. "Unknown Error Status",
  101. "Unknown Error Status",
  102. "Unknown Error Status",
  103. "Unknown Error Status",
  104. "Unknown Error Status",
  105. "Unknown Error Status"
  106. };
  107. LPSTR rgszInfoStatus[] = {
  108. "CERT_TRUST_HAS_EXACT_MATCH_ISSUER",// 0x00000001
  109. "CERT_TRUST_HAS_KEY_MATCH_ISSUER", // 0x00000002
  110. "CERT_TRUST_HAS_NAME_MATCH_ISSUER", // 0x00000004
  111. "Unknown Info Status", // 0x00000008
  112. "Unknown Info Status", // 0x00000010
  113. "Unknown Info Status", // 0x00000020
  114. "Unknown Info Status", // 0x00000040
  115. "Unknown Info Status", // 0x00000080
  116. "Unknown Info Status", // 0x00000100
  117. "Unknown Info Status", // 0x00000200
  118. "Unknown Info Status", // 0x00000400
  119. "Unknown Info Status", // 0x00000800
  120. "Unknown Info Status", // 0x00001000
  121. "Unknown Info Status", // 0x00002000
  122. "Unknown Info Status", // 0x00004000
  123. "Unknown Info Status", // 0x00008000
  124. "CERT_TRUST_IS_SELF_SIGNED", // 0x00010000
  125. "Unknown Info Status", // 0x00020000
  126. "Unknown Info Status", // 0x00040000
  127. "Unknown Info Status", // 0x00080000
  128. "Unknown Info Status", // 0x00100000
  129. "Unknown Info Status", // 0x00200000
  130. "Unknown Info Status", // 0x00400000
  131. "Unknown Info Status", // 0x00800000
  132. "Unknown Info Status", // 0x01000000
  133. "Unknown Info Status", // 0x02000000
  134. "Unknown Info Status", // 0x04000000
  135. "Unknown Info Status", // 0x08000000
  136. "CERT_TRUST_IS_COMPLEX_CHAIN", // 0x10000000
  137. "Unknown Info Status", // 0x20000000
  138. "Unknown Info Status", // 0x40000000
  139. "Unknown Info Status" // 0x80000000
  140. };
  141. void DisplayTrustStatus(
  142. IN const CERT_TRUST_STATUS *pStatus
  143. )
  144. {
  145. DWORD dwMask;
  146. DWORD cCount;
  147. printf(
  148. "Trust Status (E=0x%lx,I=0x%lx)\n\n",
  149. pStatus->dwErrorStatus,
  150. pStatus->dwInfoStatus
  151. );
  152. dwMask = 1;
  153. for ( cCount = 0; cCount < 32; cCount++ )
  154. {
  155. if ( pStatus->dwErrorStatus & dwMask )
  156. {
  157. if ( strcmp( rgszErrorStatus[ cCount ], "Unknown Error Status" ) != 0 )
  158. {
  159. printf("%s\n", rgszErrorStatus[ cCount ]);
  160. }
  161. }
  162. dwMask = dwMask << 1;
  163. }
  164. dwMask = 1;
  165. for ( cCount = 0; cCount < 32; cCount++ )
  166. {
  167. if ( pStatus->dwInfoStatus & dwMask )
  168. {
  169. if ( strcmp( rgszInfoStatus[ cCount ], "Unknown Info Status" ) != 0 )
  170. {
  171. printf("%s\n", rgszInfoStatus[ cCount ]);
  172. }
  173. }
  174. dwMask = dwMask << 1;
  175. }
  176. printf("\n");
  177. }
  178. void DisplayChainElement(
  179. IN PCERT_CHAIN_ELEMENT pElement
  180. )
  181. {
  182. DisplayCert( pElement->pCertContext, dwDisplayFlags );
  183. printf("\n");
  184. DisplayTrustStatus( &pElement->TrustStatus );
  185. }
  186. void DisplaySimpleChain(
  187. IN PCERT_SIMPLE_CHAIN pChain
  188. )
  189. {
  190. DWORD cElement;
  191. DisplayTrustStatus( &pChain->TrustStatus );
  192. printf("Chain Element Count = %d\n", pChain->cElement);
  193. for ( cElement = 0; cElement < pChain->cElement; cElement++ )
  194. {
  195. printf("Chain Element [%d]\n", cElement);
  196. DisplayChainElement( pChain->rgpElement[ cElement ]);
  197. }
  198. }
  199. void DisplayComplexChain(
  200. IN PCCERT_CHAIN_CONTEXT pChainContext
  201. )
  202. {
  203. DWORD cChain;
  204. if (NULL == pChainContext)
  205. return;
  206. DisplayTrustStatus(&pChainContext->TrustStatus );
  207. printf("\n");
  208. printf("Simple Chain Count = %d\n\n", pChainContext->cChain );
  209. for ( cChain = 0; cChain < pChainContext->cChain; cChain++ )
  210. {
  211. printf("Simple Chain [%d]\n", cChain);
  212. DisplaySimpleChain( pChainContext->rgpChain[ cChain ]);
  213. }
  214. }
  215. #define FIND_BY_ISSUER_ARG 0x1539beef
  216. BOOL WINAPI FindByIssuerCallback(
  217. IN PCCERT_CONTEXT pCert,
  218. IN void *pvFindArg
  219. )
  220. {
  221. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)
  222. printf(">>>>> FindByIssuerCallback <<<<<\n");
  223. if (pvFindArg != (void *) FIND_BY_ISSUER_ARG)
  224. printf("failed => wrong pvFindArg\n");
  225. return TRUE;
  226. }
  227. static BOOL CreateChainByIssuer(
  228. IN HCERTSTORE hChainStore,
  229. IN DWORD dwFindFlags,
  230. IN LPCSTR pszUsageIdentifier,
  231. IN DWORD dwKeySpec,
  232. IN DWORD cIssuer,
  233. IN PCERT_NAME_BLOB rgIssuer
  234. )
  235. {
  236. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  237. DWORD dwChainIndex = 0;
  238. DWORD dwIssuerChainIndex = 0;
  239. DWORD dwIssuerElementIndex = 0;
  240. CERT_CHAIN_FIND_BY_ISSUER_PARA FindPara;
  241. memset(&FindPara, 0, sizeof(FindPara));
  242. FindPara.cbSize = sizeof(FindPara);
  243. FindPara.pszUsageIdentifier = pszUsageIdentifier;
  244. FindPara.dwKeySpec = dwKeySpec;
  245. FindPara.cIssuer = cIssuer;
  246. FindPara.rgIssuer = rgIssuer;
  247. FindPara.pfnFindCallback = FindByIssuerCallback;
  248. FindPara.pvFindArg = (void *) FIND_BY_ISSUER_ARG;
  249. FindPara.pdwIssuerChainIndex = &dwIssuerChainIndex;
  250. FindPara.pdwIssuerElementIndex = &dwIssuerElementIndex;
  251. while (pChainContext = CertFindChainInStore(
  252. hChainStore,
  253. dwCertEncodingType,
  254. dwFindFlags,
  255. CERT_CHAIN_FIND_BY_ISSUER,
  256. &FindPara,
  257. pChainContext
  258. )) {
  259. printf("\n");
  260. printf("======================= CHAIN[%d,%d] %d =======================\n",
  261. dwIssuerChainIndex, dwIssuerElementIndex, dwChainIndex);
  262. dwChainIndex++;
  263. DisplayComplexChain(pChainContext);
  264. dwIssuerChainIndex = 0;
  265. dwIssuerElementIndex = 0;
  266. }
  267. if (0 == dwChainIndex)
  268. printf(">>>> No Chains <<<<\n");
  269. return TRUE;
  270. }
  271. static BOOL AllocAndGetEncodedIssuer(
  272. LPSTR pszCertFilename,
  273. BOOL fUseIssuerName,
  274. PCERT_NAME_BLOB pIssuer
  275. )
  276. {
  277. BOOL fResult;
  278. BYTE *pbEncodedCert = NULL;
  279. DWORD cbEncodedCert;
  280. PCCERT_CONTEXT pCert = NULL;
  281. BYTE *pbEncodedIssuer;
  282. DWORD cbEncodedIssuer;
  283. if (!ReadDERFromFile(pszCertFilename, &pbEncodedCert, &cbEncodedCert)) {
  284. PrintLastError("AllocAndGetEncodedIssuer::ReadDERFromFile");
  285. goto ErrorReturn;
  286. }
  287. if (NULL == (pCert = CertCreateCertificateContext(
  288. dwCertEncodingType,
  289. pbEncodedCert,
  290. cbEncodedCert
  291. ))) {
  292. PrintLastError("AllocAndGetEncodedIssuer::CertCreateCertificateContext");
  293. goto ErrorReturn;
  294. }
  295. if (fUseIssuerName) {
  296. cbEncodedIssuer = pCert->pCertInfo->Issuer.cbData;
  297. pbEncodedIssuer = pCert->pCertInfo->Issuer.pbData;
  298. } else {
  299. cbEncodedIssuer = pCert->pCertInfo->Subject.cbData;
  300. pbEncodedIssuer = pCert->pCertInfo->Subject.pbData;
  301. }
  302. pIssuer->pbData = (BYTE *) TestAlloc(cbEncodedIssuer);
  303. if (pIssuer->pbData == NULL) goto ErrorReturn;
  304. memcpy(pIssuer->pbData, pbEncodedIssuer, cbEncodedIssuer);
  305. pIssuer->cbData = cbEncodedIssuer;
  306. fResult = TRUE;
  307. goto CommonReturn;
  308. ErrorReturn:
  309. fResult = FALSE;
  310. CommonReturn:
  311. if (pbEncodedCert)
  312. TestFree(pbEncodedCert);
  313. if (pCert)
  314. CertFreeCertificateContext(pCert);
  315. return fResult;
  316. }
  317. int _cdecl main(int argc, char * argv[])
  318. {
  319. HRESULT hr;
  320. int ReturnStatus;
  321. BOOL fUseIssuerName = FALSE;
  322. LPSTR pszCertFilename = NULL;
  323. LPSTR pszKeyType = NULL;
  324. DWORD dwKeySpec;
  325. #define MAX_ISSUER_CNT 32
  326. DWORD cIssuer = 0;
  327. CERT_NAME_BLOB rgIssuer[MAX_ISSUER_CNT];
  328. PCERT_CHAIN pCertChains = NULL;
  329. DWORD cbCertChains;
  330. DWORD cCertChains;
  331. DWORD i,j;
  332. HCERTSTORE hChainStore = NULL;
  333. LPSTR pszUsageIdentifier = NULL;
  334. DWORD dwFindFlags = 0;
  335. while (--argc>0)
  336. {
  337. if (**++argv == '-')
  338. {
  339. if (0 == _stricmp(argv[0]+1, "CompareKey")) {
  340. dwFindFlags |= CERT_CHAIN_FIND_BY_ISSUER_COMPARE_KEY_FLAG;
  341. } else if (0 == _stricmp(argv[0]+1, "ComplexChain")) {
  342. dwFindFlags |= CERT_CHAIN_FIND_BY_ISSUER_COMPLEX_CHAIN_FLAG;
  343. } else if (0 == _stricmp(argv[0]+1, "CacheOnly")) {
  344. dwFindFlags |= CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG;
  345. } else if (0 == _stricmp(argv[0]+1, "NoKey")) {
  346. dwFindFlags |= CERT_CHAIN_FIND_BY_ISSUER_NO_KEY_FLAG;
  347. } else {
  348. switch(argv[0][1])
  349. {
  350. case 'c':
  351. case 'C':
  352. if (hChainStore) {
  353. printf("Only one chain store allowed\n");
  354. goto BadUsage;
  355. }
  356. if (NULL == (hChainStore =
  357. OpenSystemStoreOrFile(
  358. argv[0][1] == 'c', // fSystemStore
  359. argv[0]+2,
  360. 0 // dwFlags
  361. )))
  362. goto BadUsage;
  363. break;
  364. case 'S':
  365. case 'I':
  366. if ('S' == argv[0][1])
  367. fUseIssuerName = FALSE;
  368. else
  369. fUseIssuerName = TRUE;
  370. if (argv[0][2]) {
  371. if (MAX_ISSUER_CNT <= cIssuer) {
  372. printf("Exceeded Maximum Issuer Count %d\n",
  373. MAX_ISSUER_CNT);
  374. goto BadUsage;
  375. } else {
  376. if (!AllocAndGetEncodedIssuer(argv[0]+2,
  377. fUseIssuerName, &rgIssuer[cIssuer]))
  378. goto ErrorReturn;
  379. cIssuer++;
  380. }
  381. }
  382. break;
  383. case 'u':
  384. pszUsageIdentifier = argv[0]+2;
  385. break;
  386. case 'b':
  387. dwDisplayFlags |= DISPLAY_BRIEF_FLAG;
  388. break;
  389. case 'v':
  390. dwDisplayFlags |= DISPLAY_VERBOSE_FLAG;
  391. break;
  392. case 'h':
  393. default:
  394. goto BadUsage;
  395. }
  396. }
  397. } else {
  398. if (pszCertFilename == NULL)
  399. pszCertFilename = argv[0];
  400. else if(pszKeyType == NULL)
  401. pszKeyType = argv[0];
  402. else {
  403. printf("Too many arguments\n");
  404. goto BadUsage;
  405. }
  406. }
  407. }
  408. printf("command line: %s\n", GetCommandLine());
  409. if (dwDisplayFlags & DISPLAY_VERBOSE_FLAG)
  410. dwDisplayFlags &= ~DISPLAY_BRIEF_FLAG;
  411. if (pszCertFilename == NULL || *pszCertFilename == '\0') {
  412. if (0 == cIssuer) {
  413. rgIssuer[0].cbData = 0;
  414. rgIssuer[0].pbData = NULL;
  415. printf("Match any Issuer\n");
  416. }
  417. } else if (MAX_ISSUER_CNT <= cIssuer) {
  418. printf("Exceeded Maximum Issuer Count %d\n", MAX_ISSUER_CNT);
  419. goto BadUsage;
  420. } else {
  421. if (!AllocAndGetEncodedIssuer(pszCertFilename, fUseIssuerName,
  422. &rgIssuer[cIssuer]))
  423. goto ErrorReturn;
  424. cIssuer++;
  425. }
  426. if (NULL == hChainStore && 1 < cIssuer) {
  427. printf("Only one issuer for FindCertsByIssuer\n");
  428. goto BadUsage;
  429. }
  430. dwKeySpec = 0;
  431. if (pszKeyType) {
  432. DWORD KeyIdx;
  433. for (KeyIdx = 0; KeyIdx < NKEYTYPES; KeyIdx++) {
  434. if (_stricmp(pszKeyType, KeyTypes[KeyIdx].pszName) == 0) {
  435. dwKeySpec = KeyTypes[KeyIdx].dwKeySpec;
  436. break;
  437. }
  438. }
  439. if (dwKeySpec == 0) {
  440. printf("Bad KeyType: %s\n", pszKeyType);
  441. goto BadUsage;
  442. }
  443. } else
  444. printf("Match any key type\n");
  445. if (hChainStore) {
  446. if (CreateChainByIssuer(
  447. hChainStore,
  448. dwFindFlags,
  449. pszUsageIdentifier,
  450. dwKeySpec,
  451. cIssuer,
  452. rgIssuer
  453. ))
  454. goto SuccessReturn;
  455. else
  456. goto ErrorReturn;
  457. }
  458. cbCertChains = 0;
  459. hr = FindCertsByIssuer(
  460. NULL, // pCertChains
  461. &cbCertChains,
  462. &cCertChains,
  463. rgIssuer[0].pbData,
  464. rgIssuer[0].cbData,
  465. NULL, // pwszPurpose "ClientAuth" or "CodeSigning"
  466. dwKeySpec
  467. );
  468. if (cbCertChains == 0) {
  469. if (hr == CRYPT_E_NOT_FOUND)
  470. printf("NO Certificate Chains\n");
  471. else {
  472. SetLastError((DWORD) hr);
  473. PrintLastError("FindCertsByIssuer");
  474. }
  475. goto ErrorReturn;
  476. }
  477. if (NULL == (pCertChains = (PCERT_CHAIN) TestAlloc(cbCertChains)))
  478. goto ErrorReturn;
  479. if (FAILED(hr = FindCertsByIssuer(
  480. pCertChains,
  481. &cbCertChains,
  482. &cCertChains,
  483. rgIssuer[0].pbData,
  484. rgIssuer[0].cbData,
  485. NULL, // pwszPurpose "ClientAuth" or "CodeSigning"
  486. dwKeySpec
  487. ))) {
  488. SetLastError((DWORD) hr);
  489. PrintLastError("FindCertsByIssuer");
  490. goto ErrorReturn;
  491. }
  492. for (i = 0; i < cCertChains; i++) {
  493. PCRYPT_KEY_PROV_INFO pKeyInfo = &pCertChains[i].keyLocatorInfo;
  494. printf("\n");
  495. printf("##### Chain %d #####\n", i);
  496. printf("Key Provider:: %d", pKeyInfo->dwProvType);
  497. if (pKeyInfo->pwszProvName)
  498. printf(" %S", pKeyInfo->pwszProvName);
  499. if (pKeyInfo->dwFlags)
  500. printf(" Flags: 0x%x", pKeyInfo->dwFlags);
  501. if (pKeyInfo->pwszContainerName)
  502. printf(" Container: %S", pKeyInfo->pwszContainerName);
  503. if (pKeyInfo->cProvParam)
  504. printf(" Params: %d", pKeyInfo->cProvParam);
  505. if (pKeyInfo->dwKeySpec)
  506. printf(" KeySpec: %d", pKeyInfo->dwKeySpec);
  507. printf("\n");
  508. for (j = 0; j < pCertChains[i].cCerts; j++) {
  509. PCCERT_CONTEXT pCert;
  510. if (pCert = CertCreateCertificateContext(
  511. dwCertEncodingType,
  512. pCertChains[i].certs[j].pbData,
  513. pCertChains[i].certs[j].cbData
  514. )) {
  515. printf("===== %d =====\n", j);
  516. DisplayCert(pCert, dwDisplayFlags);
  517. CertFreeCertificateContext(pCert);
  518. } else {
  519. printf("Unable to decode cert %d\n", j);
  520. PrintLastError("CertCreateCertificateContext");
  521. }
  522. }
  523. }
  524. SuccessReturn:
  525. ReturnStatus = 0;
  526. goto CommonReturn;
  527. BadUsage:
  528. Usage();
  529. ErrorReturn:
  530. ReturnStatus = -1;
  531. CommonReturn:
  532. while (cIssuer--)
  533. TestFree(rgIssuer[cIssuer].pbData);
  534. if (pCertChains)
  535. TestFree(pCertChains);
  536. if (hChainStore) {
  537. if (!CertCloseStore(hChainStore, 0))
  538. PrintLastError("CertCloseStore(ChainStore)");
  539. }
  540. if (!ReturnStatus)
  541. printf("Passed\n");
  542. else
  543. printf("Failed\n");
  544. return ReturnStatus;
  545. }