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.

840 lines
21 KiB

  1. #include <stdio.h>
  2. #include <tchar.h>
  3. #include <malloc.h>
  4. // iis metabase includes
  5. #define INITGUID // must be before iadmw.h
  6. #include <iadmw.h> // Interface header
  7. #include <iiscnfg.h> // MD_ & IIS_MD_ defines
  8. // other includes
  9. #include <wincrypt.h>
  10. #include <xenroll.h>
  11. #include <cryptui.h>
  12. #include "utils.h"
  13. const CLSID CLSID_CEnroll =
  14. {0x43F8F289, 0x7A20, 0x11D0, {0x8F, 0x06, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xE1}};
  15. const IID IID_IEnroll =
  16. {0xacaa7838, 0x4585, 0x11d1, {0xab, 0x57, 0x00, 0xc0, 0x4f, 0xc2, 0x95, 0xe1}};
  17. #define ARRAYSIZE(x)\
  18. (sizeof(x)/sizeof(x[0]))
  19. int g_iDo_A = FALSE;
  20. int g_iDo_B = FALSE;
  21. int g_iDo_C = FALSE;
  22. // prototypes
  23. void ShowHelp(void);
  24. int DoStuff(void);
  25. int PrintCertDescList(void);
  26. DWORD CheckCertConstraints(PCCERT_CONTEXT pCC);
  27. // begin
  28. void ShowHelp(void)
  29. {
  30. _tprintf(_T("Certificate Looker test program\n\n"));
  31. _tprintf(_T("Usage:Certlook.exe [-b] [-c]\n\n"));
  32. _tprintf(_T("no parameters opens the 'MY' store\n"));
  33. _tprintf(_T(" -b opens the 'CA' store\n"));
  34. _tprintf(_T(" -c opens the 'ROOT' store\n"));
  35. return;
  36. }
  37. int __cdecl main(int argc,char *argv[])
  38. {
  39. int iRet = 0;
  40. int argno;
  41. char * pArg = NULL;
  42. char * pCmdStart = NULL;
  43. TCHAR szFilePath1[_MAX_PATH];
  44. TCHAR szFilePath2[_MAX_PATH];
  45. TCHAR szParamString_Z[_MAX_PATH];
  46. int iDoVersion = FALSE;
  47. int iGotParamZ = FALSE;
  48. *szFilePath1 = '\0';
  49. *szFilePath2 = '\0';
  50. *szParamString_Z = '\0';
  51. _tcscpy(szFilePath1,_T(""));
  52. _tcscpy(szFilePath2,_T(""));
  53. _tcscpy(szParamString_Z,_T(""));
  54. for(argno=1; argno<argc; argno++)
  55. {
  56. if ( argv[argno][0] == '-' || argv[argno][0] == '/' )
  57. {
  58. switch (argv[argno][1])
  59. {
  60. case 'a':
  61. case 'A':
  62. g_iDo_A = TRUE;
  63. break;
  64. case 'b':
  65. case 'B':
  66. g_iDo_B = TRUE;
  67. break;
  68. case 'c':
  69. case 'C':
  70. g_iDo_C = TRUE;
  71. break;
  72. case 'v':
  73. case 'V':
  74. iDoVersion = TRUE;
  75. break;
  76. case 'z':
  77. case 'Z':
  78. // Get the string for this flag
  79. pArg = CharNextA(argv[argno]);
  80. pArg = CharNextA(pArg);
  81. if (*pArg == ':')
  82. {
  83. char szTempString[_MAX_PATH];
  84. pArg = CharNextA(pArg);
  85. // Check if it's quoted
  86. if (*pArg == '\"')
  87. {
  88. pArg = CharNextA(pArg);
  89. pCmdStart = pArg;
  90. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  91. }
  92. else
  93. {
  94. pCmdStart = pArg;
  95. while (*pArg){pArg = CharNextA(pArg);}
  96. }
  97. *pArg = '\0';
  98. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  99. // Convert to unicode
  100. #if defined(UNICODE) || defined(_UNICODE)
  101. MultiByteToWideChar(CP_ACP, 0, szTempString, -1, (LPWSTR) szParamString_Z, _MAX_PATH);
  102. #else
  103. _tcscpy(szParamString_Z,szTempString);
  104. #endif
  105. iGotParamZ = TRUE;
  106. }
  107. break;
  108. case '?':
  109. goto main_exit_with_help;
  110. break;
  111. }
  112. }
  113. else
  114. {
  115. if (_tcsicmp(szFilePath1, _T("")) == 0)
  116. {
  117. // if no arguments, then get the filename portion
  118. #if defined(UNICODE) || defined(_UNICODE)
  119. MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath1, _MAX_PATH);
  120. #else
  121. _tcscpy(szFilePath1,argv[argno]);
  122. #endif
  123. }
  124. else
  125. {
  126. if (_tcsicmp(szFilePath2, _T("")) == 0)
  127. {
  128. // if no arguments, then get the filename portion
  129. #if defined(UNICODE) || defined(_UNICODE)
  130. MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath2, _MAX_PATH);
  131. #else
  132. _tcscpy(szFilePath2,argv[argno]);
  133. #endif
  134. }
  135. }
  136. }
  137. }
  138. iRet = DoStuff();
  139. if (TRUE == iDoVersion)
  140. {
  141. // output the version
  142. _tprintf(_T("1\n\n"));
  143. iRet = 10;
  144. goto main_exit_gracefully;
  145. }
  146. /*
  147. if (_tcsicmp(szFilePath1, _T("")) == 0)
  148. {
  149. goto main_exit_with_help;
  150. }
  151. */
  152. goto main_exit_gracefully;
  153. main_exit_gracefully:
  154. exit(iRet);
  155. main_exit_with_help:
  156. ShowHelp();
  157. exit(iRet);
  158. }
  159. int DoStuff(void)
  160. {
  161. int iReturn = FALSE;
  162. PrintCertDescList();
  163. goto DoStuff_Exit;
  164. DoStuff_Exit:
  165. return iReturn;
  166. }
  167. BOOL ViewCertificateDialog(CRYPT_HASH_BLOB* pcrypt_hash, HWND hWnd)
  168. {
  169. BOOL bReturn = FALSE;
  170. HCERTSTORE hStore = NULL;
  171. PCCERT_CONTEXT pCert = NULL;
  172. hStore = CertOpenStore(
  173. CERT_STORE_PROV_SYSTEM,
  174. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  175. NULL,
  176. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  177. _T("MY")
  178. );
  179. if (hStore != NULL)
  180. {
  181. // Now we need to find cert by hash
  182. //CRYPT_HASH_BLOB crypt_hash;
  183. //crypt_hash.cbData = hash.GetSize();
  184. //crypt_hash.pbData = hash.GetData();
  185. pCert = CertFindCertificateInStore(hStore,
  186. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  187. 0, CERT_FIND_HASH, (LPVOID)pcrypt_hash, NULL);
  188. }
  189. if (pCert)
  190. {
  191. BOOL fPropertiesChanged;
  192. CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
  193. HCERTSTORE hCertStore = ::CertDuplicateStore(hStore);
  194. ::ZeroMemory (&vcs, sizeof (vcs));
  195. vcs.dwSize = sizeof (vcs);
  196. vcs.hwndParent = hWnd;
  197. vcs.dwFlags = 0;
  198. vcs.cStores = 1;
  199. vcs.rghStores = &hCertStore;
  200. vcs.pCertContext = pCert;
  201. ::CryptUIDlgViewCertificate(&vcs, &fPropertiesChanged);
  202. ::CertCloseStore (hCertStore, 0);
  203. bReturn = TRUE;
  204. }
  205. else
  206. {
  207. // it failed
  208. }
  209. if (pCert != NULL)
  210. ::CertFreeCertificateContext(pCert);
  211. if (hStore != NULL)
  212. ::CertCloseStore(hStore, 0);
  213. return bReturn;
  214. }
  215. BOOL
  216. GetKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  217. CERT_ENHKEY_USAGE ** pKeyUsage,
  218. BOOL fPropertiesOnly,
  219. HRESULT * phRes)
  220. {
  221. DWORD cb = 0;
  222. BOOL bRes = FALSE;
  223. if (!CertGetEnhancedKeyUsage(pCertContext,
  224. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  225. NULL,
  226. &cb))
  227. {
  228. *phRes = HRESULT_FROM_WIN32(GetLastError());
  229. goto ErrExit;
  230. }
  231. if (NULL == (*pKeyUsage = (CERT_ENHKEY_USAGE *)malloc(cb)))
  232. {
  233. *phRes = E_OUTOFMEMORY;
  234. goto ErrExit;
  235. }
  236. if (!CertGetEnhancedKeyUsage (pCertContext,
  237. fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
  238. *pKeyUsage,
  239. &cb))
  240. {
  241. free(*pKeyUsage);
  242. *phRes = HRESULT_FROM_WIN32(GetLastError());
  243. goto ErrExit;
  244. }
  245. *phRes = S_OK;
  246. bRes = TRUE;
  247. ErrExit:
  248. return bRes;
  249. }
  250. BOOL
  251. ContainsKeyUsageProperty(PCCERT_CONTEXT pCertContext,
  252. HRESULT * phRes
  253. )
  254. {
  255. BOOL bRes = FALSE;
  256. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  257. if (GetKeyUsageProperty(pCertContext, &pKeyUsage, FALSE, phRes))
  258. {
  259. if (pKeyUsage->cUsageIdentifier == 0)
  260. {
  261. _tprintf(_T("cUsageIdentifier=0 <---\n"));
  262. bRes = TRUE;
  263. }
  264. else
  265. {
  266. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  267. {
  268. // Our friends from CAPI made this property ASCII even for
  269. // UNICODE program
  270. if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_PKIX_KP_SERVER_AUTH) != NULL)
  271. {
  272. _tprintf(_T("cUsageIdentifier=szOID_PKIX_KP_SERVER_AUTH\n"));
  273. bRes = TRUE;
  274. break;
  275. }
  276. if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_SERVER_GATED_CRYPTO) != NULL)
  277. {
  278. _tprintf(_T("cUsageIdentifier=szOID_SERVER_GATED_CRYPTO\n"));
  279. bRes = TRUE;
  280. break;
  281. }
  282. if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_SGC_NETSCAPE) != NULL)
  283. {
  284. _tprintf(_T("cUsageIdentifier=szOID_SGC_NETSCAPE\n"));
  285. bRes = TRUE;
  286. break;
  287. }
  288. }
  289. }
  290. if (pKeyUsage){free(pKeyUsage);}
  291. }
  292. return bRes;
  293. }
  294. BOOL
  295. GetNameString(PCCERT_CONTEXT pCertContext,
  296. DWORD type,
  297. DWORD flag,
  298. WCHAR * TheName,
  299. HRESULT * phRes)
  300. {
  301. BOOL bRes = FALSE;
  302. LPTSTR pName = NULL;
  303. DWORD cchName = CertGetNameString(pCertContext, type, flag, NULL, NULL, 0);
  304. if (cchName > 1)
  305. {
  306. pName = (LPTSTR) malloc(cchName);
  307. if (pName)
  308. {
  309. bRes = (1 != CertGetNameString(pCertContext, type, flag, NULL, pName, cchName));
  310. ZeroMemory(TheName,sizeof(TheName));
  311. memcpy(TheName,pName,cchName);
  312. }
  313. }
  314. else
  315. {
  316. *phRes = HRESULT_FROM_WIN32(GetLastError());
  317. }
  318. return bRes;
  319. }
  320. BOOL
  321. GetFriendlyName(PCCERT_CONTEXT pCertContext,
  322. WCHAR * TheName,
  323. HRESULT * phRes)
  324. {
  325. BOOL bRes = FALSE;
  326. DWORD cb;
  327. TCHAR * pName = NULL;
  328. if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cb))
  329. {
  330. pName = (LPTSTR) malloc(cb);
  331. if (pName)
  332. {
  333. if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pName, &cb))
  334. {
  335. pName[cb] = 0;
  336. bRes = TRUE;
  337. ZeroMemory(TheName,sizeof(TheName));
  338. memcpy(TheName,pName,cb);
  339. }
  340. else
  341. {
  342. *phRes = HRESULT_FROM_WIN32(GetLastError());
  343. }
  344. }
  345. else
  346. {
  347. *phRes = HRESULT_FROM_WIN32(GetLastError());
  348. }
  349. }
  350. else
  351. {
  352. *phRes = HRESULT_FROM_WIN32(GetLastError());
  353. }
  354. return bRes;
  355. }
  356. BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
  357. {
  358. PCCRYPT_OID_INFO pOIDInfo;
  359. if (NULL != (pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pszObjId, 0)))
  360. {
  361. if ((DWORD)wcslen(pOIDInfo->pwszName)+1 <= stringSize)
  362. {
  363. wcscpy(string, pOIDInfo->pwszName);
  364. }
  365. else
  366. {
  367. return FALSE;
  368. }
  369. }
  370. else
  371. {
  372. return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
  373. }
  374. return TRUE;
  375. }
  376. BOOL
  377. FormatEnhancedKeyUsageString(PCCERT_CONTEXT pCertContext,
  378. BOOL fPropertiesOnly,
  379. BOOL fMultiline,
  380. HRESULT * phRes)
  381. {
  382. CERT_ENHKEY_USAGE * pKeyUsage = NULL;
  383. WCHAR szText[255];
  384. BOOL bRes = FALSE;
  385. if (GetKeyUsageProperty(pCertContext, &pKeyUsage, fPropertiesOnly, phRes))
  386. {
  387. _tprintf(_T("EnhancedKeyUsage="));
  388. // loop for each usage and add it to the display string
  389. for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
  390. {
  391. if (!(bRes = MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i])))
  392. break;
  393. // add delimeter if not first iteration
  394. wprintf(szText);
  395. wprintf(L",");
  396. }
  397. wprintf(L"\n");
  398. free (pKeyUsage);
  399. }
  400. return bRes;
  401. }
  402. BOOL PrintCertDescription(PCCERT_CONTEXT pCert)
  403. {
  404. BOOL bRes = FALSE;
  405. HRESULT hRes = 0;
  406. DWORD cb;
  407. UINT i, j;
  408. CERT_NAME_INFO * pNameInfo;
  409. WCHAR wCA_Name[255];
  410. if (pCert == NULL)
  411. goto ErrExit;
  412. if (!CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  413. pCert->pCertInfo->Subject.pbData,
  414. pCert->pCertInfo->Subject.cbData,
  415. 0, NULL, &cb)
  416. || NULL == (pNameInfo = (CERT_NAME_INFO *)_alloca(cb))
  417. || !CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  418. pCert->pCertInfo->Subject.pbData,
  419. pCert->pCertInfo->Subject.cbData,
  420. 0,
  421. pNameInfo, &cb)
  422. )
  423. {
  424. goto ErrExit;
  425. }
  426. for (i = 0; i < pNameInfo->cRDN; i++)
  427. {
  428. CERT_RDN_VALUE_BLOB Blobber;
  429. CERT_RDN rdn = pNameInfo->rgRDN[i];
  430. for (j = 0; j < rdn.cRDNAttr; j++)
  431. {
  432. CERT_RDN_ATTR attr = rdn.rgRDNAttr[j];
  433. Blobber = (CERT_RDN_VALUE_BLOB) attr.Value;
  434. WCHAR TempString[255];
  435. ZeroMemory(TempString,sizeof(TempString));
  436. memcpy(TempString, Blobber.pbData,Blobber.cbData);
  437. if (strcmp(attr.pszObjId, szOID_COMMON_NAME) == 0)
  438. {
  439. _tprintf(_T("szOID_COMMON_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  440. }
  441. else if (strcmp(attr.pszObjId, szOID_COUNTRY_NAME) == 0)
  442. {
  443. _tprintf(_T("szOID_COUNTRY_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  444. }
  445. else if (strcmp(attr.pszObjId, szOID_LOCALITY_NAME) == 0)
  446. {
  447. _tprintf(_T("szOID_LOCALITY_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  448. }
  449. else if (strcmp(attr.pszObjId, szOID_STATE_OR_PROVINCE_NAME) == 0)
  450. {
  451. _tprintf(_T("szOID_STATE_OR_PROVINCE_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  452. }
  453. else if (strcmp(attr.pszObjId, szOID_ORGANIZATION_NAME) == 0)
  454. {
  455. _tprintf(_T("szOID_ORGANIZATION_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  456. }
  457. else if (strcmp(attr.pszObjId, szOID_ORGANIZATIONAL_UNIT_NAME) == 0)
  458. {
  459. _tprintf(_T("szOID_ORGANIZATIONAL_UNIT_NAME="));wprintf(TempString);_tprintf(_T("\n"));
  460. }
  461. }
  462. }
  463. // issued to
  464. if (!GetNameString(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, wCA_Name, &hRes))
  465. {
  466. goto ErrExit;
  467. }
  468. _tprintf(_T("Name="));wprintf(wCA_Name);_tprintf(_T("\n"));
  469. if (wCA_Name){free(wCA_Name);}
  470. /*
  471. // expiration date
  472. if (!FormatDateString(desc.m_ExpirationDate, pCert->pCertInfo->NotAfter, FALSE, FALSE))
  473. {
  474. goto ErrExit;
  475. }
  476. */
  477. // purpose
  478. if (!FormatEnhancedKeyUsageString(pCert, FALSE, FALSE, &hRes))
  479. {
  480. // According to local experts, we should also use certs without this property set
  481. _tprintf(_T("There is no EnhancedKeyUsage on this one.\n"));
  482. //goto ErrExit;
  483. }
  484. // friendly name
  485. if (GetFriendlyName(pCert, wCA_Name, &hRes))
  486. {
  487. _tprintf(_T("FriendlyName="));wprintf(wCA_Name);_tprintf(_T("\n"));
  488. if (wCA_Name){free(wCA_Name);}
  489. }
  490. bRes = TRUE;
  491. ErrExit:
  492. return bRes;
  493. }
  494. HCERTSTORE OpenMyStore(IEnroll * pEnroll, HRESULT * phResult)
  495. {
  496. HCERTSTORE hStore = NULL;
  497. BSTR bstrStoreName = NULL;
  498. BSTR bstrStoreType = NULL;
  499. long dwStoreFlags;
  500. if(SUCCEEDED(pEnroll->get_MyStoreNameWStr(&bstrStoreName)))
  501. {
  502. if(SUCCEEDED(pEnroll->get_MyStoreTypeWStr(&bstrStoreType)))
  503. {
  504. if(SUCCEEDED(pEnroll->get_MyStoreFlags(&dwStoreFlags)))
  505. {
  506. size_t store_type_len = wcslen(bstrStoreType);
  507. char * szStoreProvider = (char *)_alloca(store_type_len + 1);
  508. //ASSERT(szStoreProvider != NULL);
  509. size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
  510. //ASSERT(n != -1);
  511. // this converter doesn't set zero byte!!!
  512. szStoreProvider[n] = '\0';
  513. if (g_iDo_B)
  514. {
  515. _tprintf(_T("CertOpenStore:CA\n"));
  516. hStore = CertOpenStore(
  517. CERT_STORE_PROV_SYSTEM,
  518. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  519. NULL,
  520. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  521. L"CA");
  522. }
  523. else if (g_iDo_C)
  524. {
  525. _tprintf(_T("CertOpenStore:ROOT\n"));
  526. hStore = CertOpenStore(
  527. CERT_STORE_PROV_SYSTEM,
  528. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  529. NULL,
  530. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  531. L"ROOT");
  532. }
  533. else
  534. {
  535. wprintf(L"CertOpenStore:%s\n",bstrStoreName);
  536. hStore = CertOpenStore(
  537. szStoreProvider,
  538. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  539. NULL,
  540. dwStoreFlags,
  541. bstrStoreName
  542. );
  543. }
  544. }
  545. }
  546. }
  547. if (bstrStoreName) {CoTaskMemFree(bstrStoreName);}
  548. if (bstrStoreType) {CoTaskMemFree(bstrStoreType);}
  549. if (hStore == NULL){*phResult = HRESULT_FROM_WIN32(GetLastError());}
  550. return hStore;
  551. }
  552. IEnroll * GetEnrollObject(void)
  553. {
  554. HRESULT hRes = 0;
  555. IEnroll * pEnroll;
  556. BOOL bPleaseDoCoUninit = FALSE;
  557. hRes = CoInitialize(NULL);
  558. if(FAILED(hRes))
  559. {
  560. return NULL;
  561. }
  562. bPleaseDoCoUninit = TRUE;
  563. hRes = CoCreateInstance(CLSID_CEnroll,NULL,CLSCTX_INPROC_SERVER,IID_IEnroll,(void **)&pEnroll);
  564. // now we need to change defaults for this
  565. // object to LOCAL_MACHINE
  566. if (pEnroll != NULL)
  567. {
  568. long dwFlags;
  569. pEnroll->get_MyStoreFlags(&dwFlags);
  570. dwFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
  571. dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
  572. // following call will change Request store flags also
  573. pEnroll->put_MyStoreFlags(dwFlags);
  574. pEnroll->get_GenKeyFlags(&dwFlags);
  575. dwFlags |= CRYPT_EXPORTABLE;
  576. pEnroll->put_GenKeyFlags(dwFlags);
  577. pEnroll->put_KeySpec(AT_KEYEXCHANGE);
  578. pEnroll->put_ProviderType(PROV_RSA_SCHANNEL);
  579. pEnroll->put_DeleteRequestCert(TRUE);
  580. }
  581. else
  582. {
  583. _tprintf(_T("GetEnrollObject failed!\n"));
  584. }
  585. if (bPleaseDoCoUninit)
  586. {
  587. CoUninitialize();
  588. }
  589. return pEnroll;
  590. }
  591. int PrintCertDescList(void)
  592. {
  593. BOOL bRes = FALSE;
  594. HRESULT hRes = 0;
  595. HCERTSTORE hStore = NULL;
  596. int iCount = 0;
  597. // we are looking to MY store only
  598. IEnroll * pXEnroll = GetEnrollObject();
  599. if (!pXEnroll){goto PrintCertDescList_Exit;}
  600. hStore = OpenMyStore(GetEnrollObject(), &hRes);
  601. if (hStore != NULL)
  602. {
  603. PCCERT_CONTEXT pCert = NULL;
  604. // do not include certs with improper usage
  605. while (NULL != (pCert = CertEnumCertificatesInStore(hStore, pCert)))
  606. {
  607. _tprintf(_T("========================================\n"));
  608. if (TRUE == g_iDo_A)
  609. {
  610. AttachFriendlyName(pCert);
  611. }
  612. CheckCertConstraints(pCert);
  613. if (!ContainsKeyUsageProperty(pCert, &hRes))
  614. {
  615. _tprintf(_T("There is a key missing KeyUsage Property. skipping.\n"));
  616. if (SUCCEEDED(hRes) || hRes == CRYPT_E_NOT_FOUND)
  617. continue;
  618. else
  619. goto PrintCertDescList_ExitErr;
  620. }
  621. if (!PrintCertDescription(pCert))
  622. {
  623. if (hRes == CRYPT_E_NOT_FOUND)
  624. continue;
  625. goto PrintCertDescList_ExitErr;
  626. }
  627. }
  628. _tprintf(_T("========================================\n"));
  629. bRes = TRUE;
  630. PrintCertDescList_ExitErr:
  631. if (pCert != NULL){CertFreeCertificateContext(pCert);}
  632. CertCloseStore(hStore, 0);
  633. }
  634. else
  635. {
  636. _tprintf(_T("CertOpenStore failed\n"));
  637. }
  638. PrintCertDescList_Exit:
  639. return bRes;
  640. }
  641. DWORD CheckCertConstraints(PCCERT_CONTEXT pCC)
  642. {
  643. PCERT_EXTENSION pCExt; // returned ext
  644. LPCSTR pszObjId; // Object identifier
  645. DWORD i;
  646. CERT_BASIC_CONSTRAINTS_INFO *pConstraints=NULL;
  647. CERT_BASIC_CONSTRAINTS2_INFO *p2Constraints=NULL;
  648. DWORD ConstraintSize=0;
  649. DWORD RV=ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR;
  650. BOOL Using2=FALSE;
  651. void* ConstraintBlob=NULL;
  652. pszObjId = szOID_BASIC_CONSTRAINTS;
  653. pCExt = CertFindExtension(
  654. pszObjId, // in, Pointer to object identifier
  655. pCC->pCertInfo->cExtension, // in, # of extensions in the array
  656. pCC->pCertInfo->rgExtension); // in, The array of attributes
  657. if (pCExt == NULL) {
  658. pszObjId = szOID_BASIC_CONSTRAINTS2;
  659. pCExt = CertFindExtension(
  660. pszObjId, // in, Pointer to object identifier
  661. pCC->pCertInfo->cExtension, // in, # of extensions in the array
  662. pCC->pCertInfo->rgExtension); // in, The array of attributes
  663. Using2=TRUE;
  664. }
  665. if (pCExt == NULL) {
  666. _tprintf(_T("No BasicConstraints in cert\n"));
  667. goto ret;
  668. }
  669. // Decode extension
  670. if (!CryptDecodeObject(
  671. X509_ASN_ENCODING,
  672. pCExt->pszObjId,
  673. pCExt->Value.pbData,
  674. pCExt->Value.cbData,
  675. 0,
  676. NULL,
  677. &ConstraintSize)) {
  678. _tprintf(_T("Error %d when Decoding extension\n"),GetLastError());
  679. goto ret;
  680. }
  681. ConstraintBlob=malloc(ConstraintSize);
  682. if (ConstraintBlob == NULL)
  683. {
  684. _tprintf(_T("out of memory!!!!...\n"));
  685. goto ret;
  686. }
  687. if (!CryptDecodeObject(
  688. X509_ASN_ENCODING,
  689. pCExt->pszObjId,
  690. pCExt->Value.pbData,
  691. pCExt->Value.cbData,
  692. 0,
  693. (void*)ConstraintBlob,
  694. &ConstraintSize))
  695. {
  696. _tprintf(_T("Error %d when Decoding extension\n"),GetLastError());
  697. goto ret;
  698. }
  699. if (Using2)
  700. {
  701. _tprintf(_T("Using2....\n"));
  702. p2Constraints=(CERT_BASIC_CONSTRAINTS2_INFO*)ConstraintBlob;
  703. if (!p2Constraints->fCA)
  704. {
  705. _tprintf(_T("Yes, there is constraints in here! it's not a CA!\n"));
  706. RV=ERROR_SUCCESS;
  707. }
  708. else
  709. {
  710. _tprintf(_T("Yes, there is constraints in here! it's a CA!\n"));
  711. }
  712. }
  713. else
  714. {
  715. _tprintf(_T("!Using2....\n"));
  716. pConstraints=(CERT_BASIC_CONSTRAINTS_INFO*)ConstraintBlob;
  717. if (((pConstraints->SubjectType.cbData * 8) - pConstraints->SubjectType.cUnusedBits) >= 2)
  718. {
  719. if ((*pConstraints->SubjectType.pbData) & CERT_END_ENTITY_SUBJECT_FLAG)
  720. {
  721. _tprintf(_T("Yes, there is constraints in here! CERT_END_ENTITY_SUBJECT_FLAG = true!\n"));
  722. RV=ERROR_SUCCESS;
  723. }
  724. else
  725. {
  726. _tprintf(_T("Yes, there is constraints in here but CERT_END_ENTITY_SUBJECT_FLAG = false!\n"));
  727. }
  728. }
  729. }
  730. ret:
  731. free(ConstraintBlob);
  732. return (RV);
  733. }