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.

3203 lines
70 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 2001
  6. //
  7. // File: url.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #define __dwFILE__ __dwFILE_CERTUTIL_URL_CPP__
  13. #define MAX_MSG_LEN 256
  14. #define MAX_URL_LEN 1024
  15. #define LIST_STATUS_SUBITEM 1
  16. #define LIST_TYPE_SUBITEM 2
  17. #define LIST_URL_SUBITEM 3
  18. #define LIST_TIME_SUBITEM 4
  19. #define DEF_TIMEOUT 15
  20. #define wszCERTIFICATE L"Certificate"
  21. #define wszBASE_CRL_ITEM_TYPE L"Base CRL"
  22. #define wszDELTA_CRL_ITEM_TYPE L"Delta CRL"
  23. #define OBJECT_TYPE_CERT 0x00000001
  24. #define OBJECT_TYPE_CRL 0x00000002
  25. #define OBJECT_TYPE_MSG 0x00000003
  26. #define MAX_ULTOW_BUFFER_SIZE 40
  27. typedef struct _tagOBJECT_INFO
  28. {
  29. DWORD dwType;
  30. union
  31. {
  32. CERT_CONTEXT const *pCert;
  33. CRL_CONTEXT const *pCRL;
  34. WCHAR wszErrInfo[MAX_MSG_LEN];
  35. };
  36. } OBJECT_INFO;
  37. CERT_CONTEXT const *g_pCert;
  38. WCHAR *g_pwszFile = NULL;
  39. CRL_CONTEXT const *g_pCRL;
  40. DWORD g_dwTimeout;
  41. WCHAR const *g_pwszUrl;
  42. DWORD g_dwRetrievalFlags;
  43. static int s_majorURL = 0;
  44. static int s_levelURL = 1;
  45. class CUrlFetch {
  46. public:
  47. virtual ~CUrlFetch() = 0;
  48. virtual int AddListItem(
  49. IN WCHAR const *pwszURL,
  50. IN WCHAR const *pwszStatus,
  51. IN WCHAR const *pwszType,
  52. IN DWORD dwInterval) = 0;
  53. virtual HRESULT UpdateListItemStatus(
  54. IN int nItem,
  55. IN WCHAR const *pwszStatus) = 0;
  56. virtual HRESULT UpdateListItemParam(
  57. IN int nItem,
  58. IN LPARAM lParam) = 0;
  59. virtual HRESULT UpdateListItemTime(
  60. IN int nItem,
  61. IN DWORD dwInterval) = 0;
  62. virtual HRESULT UpdateListItem(
  63. IN int nItem,
  64. IN WCHAR const *pwszURL,
  65. IN WCHAR const *pwszStatus,
  66. IN WCHAR const *pwszType,
  67. IN DWORD dwInterval) = 0;
  68. virtual int DisplayMessageBox(
  69. IN HWND hWnd,
  70. IN LPCWSTR lpText,
  71. IN LPCWSTR lpCaption,
  72. IN UINT uType) = 0;
  73. virtual HCURSOR SetCursor(
  74. IN HCURSOR hCursor) = 0;
  75. virtual VOID Display() = 0;
  76. };
  77. CUrlFetch::~CUrlFetch() {}
  78. class CUrlFetchDialog : CUrlFetch {
  79. public:
  80. CUrlFetchDialog(
  81. IN HWND hwndList)
  82. {
  83. m_hwndList = hwndList;
  84. }
  85. ~CUrlFetchDialog() {}
  86. int AddListItem(
  87. IN WCHAR const *pwszURL,
  88. IN WCHAR const *pwszStatus,
  89. IN WCHAR const *pwszType,
  90. IN DWORD dwInterval);
  91. HRESULT UpdateListItemStatus(
  92. IN int nItem,
  93. IN WCHAR const *pwszStatus);
  94. HRESULT UpdateListItemParam(
  95. IN int nItem,
  96. IN LPARAM lParam);
  97. HRESULT UpdateListItemTime(
  98. IN int nItem,
  99. IN DWORD dwInterval);
  100. HRESULT UpdateListItem(
  101. IN int nItem,
  102. IN WCHAR const *pwszURL,
  103. IN WCHAR const *pwszStatus,
  104. IN WCHAR const *pwszType,
  105. IN DWORD dwInterval);
  106. int DisplayMessageBox(
  107. IN HWND hWnd,
  108. IN LPCWSTR lpText,
  109. IN LPCWSTR lpCaption,
  110. IN UINT uType);
  111. HCURSOR SetCursor(
  112. IN HCURSOR hCursor)
  113. {
  114. return(::SetCursor(hCursor));
  115. }
  116. VOID Display() {}
  117. private:
  118. HWND m_hwndList;
  119. };
  120. #define CII_URL 0
  121. #define CII_TYPE 1
  122. #define CII_STATUS 2
  123. #define CII_MESSAGE 3
  124. #define CII_MAX 4
  125. class CConsoleItem {
  126. public:
  127. CConsoleItem()
  128. {
  129. ZeroMemory(&m_apwsz, sizeof(m_apwsz));
  130. m_dwInterval = 0;
  131. }
  132. ~CConsoleItem()
  133. {
  134. DWORD i;
  135. for (i = 0; i < CII_MAX; i++)
  136. {
  137. if (NULL != m_apwsz[i])
  138. {
  139. LocalFree(m_apwsz[i]);
  140. }
  141. }
  142. }
  143. HRESULT UpdateString(
  144. IN DWORD iString,
  145. IN WCHAR const *pwszNew);
  146. HRESULT UpdateInterval(
  147. IN DWORD dwInterval)
  148. {
  149. m_dwInterval = dwInterval;
  150. return(S_OK);
  151. }
  152. VOID DisplayItem();
  153. private:
  154. WCHAR *m_apwsz[CII_MAX];
  155. DWORD m_dwInterval;
  156. };
  157. HRESULT
  158. CConsoleItem::UpdateString(
  159. IN DWORD iString,
  160. IN WCHAR const *pwszNew)
  161. {
  162. HRESULT hr;
  163. WCHAR *pwsz;
  164. if (iString >= CII_MAX)
  165. {
  166. hr = E_INVALIDARG;
  167. _JumpError(hr, error, "iString");
  168. }
  169. if (NULL != pwszNew)
  170. {
  171. hr = myDupString(pwszNew, &pwsz);
  172. _JumpIfError(hr, error, "myDupString");
  173. if (NULL != m_apwsz[iString])
  174. {
  175. LocalFree(m_apwsz[iString]);
  176. }
  177. m_apwsz[iString] = pwsz;
  178. }
  179. hr = S_OK;
  180. error:
  181. return(hr);
  182. }
  183. VOID
  184. CConsoleItem::DisplayItem()
  185. {
  186. wprintf(
  187. L" %ws \"%ws\" %ws %u\n",
  188. NULL == m_apwsz[CII_STATUS]? L"???" : m_apwsz[CII_STATUS],
  189. NULL == m_apwsz[CII_TYPE]? L"???" : m_apwsz[CII_TYPE],
  190. myLoadResourceString(IDS_TIME_COLON), // "Time:"
  191. m_dwInterval);
  192. if (NULL != m_apwsz[CII_MESSAGE])
  193. {
  194. wprintf(L" %ws\n", m_apwsz[CII_MESSAGE]);
  195. }
  196. if (NULL != m_apwsz[CII_URL])
  197. {
  198. wprintf(L" %ws\n\n", m_apwsz[CII_URL]);
  199. }
  200. }
  201. class CUrlFetchConsole : CUrlFetch {
  202. public:
  203. CUrlFetchConsole()
  204. {
  205. m_cItem = 0;
  206. m_rgpItem = NULL;
  207. }
  208. ~CUrlFetchConsole()
  209. {
  210. if (NULL != m_rgpItem)
  211. {
  212. int i;
  213. for (i = 0; i < m_cItem; i++)
  214. {
  215. delete m_rgpItem[i];
  216. }
  217. LocalFree(m_rgpItem);
  218. }
  219. }
  220. int AddListItem(
  221. IN WCHAR const *pwszURL,
  222. IN WCHAR const *pwszStatus,
  223. IN WCHAR const *pwszType,
  224. IN DWORD dwInterval);
  225. HRESULT UpdateListItemStatus(
  226. IN int nItem,
  227. IN WCHAR const *pwszStatus);
  228. HRESULT UpdateListItemParam(
  229. IN int nItem,
  230. IN LPARAM lParam);
  231. HRESULT UpdateListItemTime(
  232. IN int nItem,
  233. IN DWORD dwInterval);
  234. HRESULT UpdateListItem(
  235. IN int nItem,
  236. IN WCHAR const *pwszURL,
  237. IN WCHAR const *pwszStatus,
  238. IN WCHAR const *pwszType,
  239. IN DWORD dwInterval);
  240. int DisplayMessageBox(
  241. IN HWND hWnd,
  242. IN LPCWSTR lpText,
  243. IN LPCWSTR lpCaption,
  244. IN UINT uType);
  245. HCURSOR SetCursor(
  246. IN HCURSOR hCursor)
  247. {
  248. return(hCursor);
  249. }
  250. VOID Display()
  251. {
  252. if (NULL != m_rgpItem)
  253. {
  254. int i;
  255. for (i = 0; i < m_cItem; i++)
  256. {
  257. if (NULL != m_rgpItem[i])
  258. {
  259. m_rgpItem[i]->DisplayItem();
  260. }
  261. }
  262. }
  263. }
  264. private:
  265. int m_cItem;
  266. CConsoleItem **m_rgpItem;
  267. };
  268. class THREAD_INFO
  269. {
  270. public:
  271. ~THREAD_INFO()
  272. {
  273. delete m_pUrl;
  274. }
  275. CERT_CONTEXT const *m_pCert;
  276. CRL_CONTEXT const *m_pCRL;
  277. CUrlFetch *m_pUrl;
  278. };
  279. HRESULT
  280. GetSimpleName(
  281. OPTIONAL IN CERT_CONTEXT const *pCert,
  282. OPTIONAL IN CRL_CONTEXT const *pCRL,
  283. OUT WCHAR **ppwszSimpleName)
  284. {
  285. HRESULT hr;
  286. CERT_CONTEXT Cert;
  287. CERT_INFO CertInfo;
  288. BYTE Zero;
  289. *ppwszSimpleName = NULL;
  290. if (NULL == pCert)
  291. {
  292. if (NULL == pCRL)
  293. {
  294. hr = E_POINTER;
  295. _JumpError(hr, error, "GetSimpleName NULL parm");
  296. }
  297. ZeroMemory(&Cert, sizeof(Cert));
  298. ZeroMemory(&CertInfo, sizeof(CertInfo));
  299. Cert.dwCertEncodingType = X509_ASN_ENCODING;
  300. //Cert.pbCertEncoded = NULL;
  301. //Cert.cbCertEncoded = NULL;
  302. Cert.pCertInfo = &CertInfo;
  303. Zero = 0;
  304. CertInfo.dwVersion = CERT_V3;
  305. CertInfo.SerialNumber.pbData = &Zero;
  306. CertInfo.SerialNumber.cbData = sizeof(Zero);
  307. CertInfo.SignatureAlgorithm = pCRL->pCrlInfo->SignatureAlgorithm;
  308. CertInfo.Issuer = pCRL->pCrlInfo->Issuer;
  309. CertInfo.NotBefore = pCRL->pCrlInfo->ThisUpdate;
  310. CertInfo.NotAfter = pCRL->pCrlInfo->NextUpdate;
  311. CertInfo.Subject = pCRL->pCrlInfo->Issuer;
  312. //CertInfo.SubjectPublicKeyInfo;
  313. //CertInfo.IssuerUniqueId;
  314. //CertInfo.SubjectUniqueId;
  315. CertInfo.cExtension = pCRL->pCrlInfo->cExtension;
  316. CertInfo.rgExtension = pCRL->pCrlInfo->rgExtension;
  317. pCert = &Cert;
  318. }
  319. hr = myCertGetNameString(
  320. pCert,
  321. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  322. ppwszSimpleName);
  323. _JumpIfError(hr, error, "myCertGetNameString");
  324. error:
  325. return(hr);
  326. }
  327. BOOL
  328. ViewCertificate(
  329. IN CERT_CONTEXT const *pCert,
  330. IN WCHAR const *pwszTitle)
  331. {
  332. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewInfo;
  333. ZeroMemory(&CertViewInfo, sizeof(CertViewInfo));
  334. CertViewInfo.dwSize = sizeof(CertViewInfo);
  335. CertViewInfo.hwndParent = NULL;
  336. CertViewInfo.szTitle = pwszTitle;
  337. CertViewInfo.pCertContext = pCert;
  338. return CryptUIDlgViewCertificate(&CertViewInfo, NULL);
  339. #if 0
  340. Removed due to incompatibility with Win2k.
  341. CryptUIDlgViewContext(
  342. CERT_STORE_CERTIFICATE_CONTEXT,
  343. (VOID const *) pObjInfo->pCert,
  344. hDlg,
  345. myLoadResourceString(IDS_CERTIFICATE), // "Certificate"
  346. 0,
  347. NULL);
  348. #endif
  349. }
  350. BOOL
  351. ViewCrl(
  352. IN CRL_CONTEXT const *pCRL,
  353. IN WCHAR const *pwszTitle)
  354. {
  355. CRYPTUI_VIEWCRL_STRUCT CRLViewInfo;
  356. ZeroMemory(&CRLViewInfo, sizeof(CRLViewInfo));
  357. CRLViewInfo.dwSize = sizeof(CRLViewInfo);
  358. CRLViewInfo.hwndParent = NULL;
  359. CRLViewInfo.szTitle = pwszTitle;
  360. CRLViewInfo.pCRLContext = pCRL;
  361. return CryptUIDlgViewCRL(&CRLViewInfo);
  362. #if 0
  363. Removed due to incompatibility with Win2k.
  364. CryptUIDlgViewContext(
  365. CERT_STORE_CRL_CONTEXT,
  366. (VOID const *) pObjInfo->pCRL,
  367. hDlg,
  368. myLoadResourceString(IDS_CRL), // "CRL"
  369. 0,
  370. NULL);
  371. #endif
  372. }
  373. HRESULT
  374. ReadCertOrCRLFromFile(
  375. IN WCHAR const *pwszFile,
  376. OUT CERT_CONTEXT const **ppCert,
  377. OUT CRL_CONTEXT const **ppCRL)
  378. {
  379. HRESULT hr;
  380. CERT_BLOB Blob;
  381. *ppCert = NULL;
  382. *ppCRL = NULL;
  383. Blob.pbData = NULL;
  384. hr = DecodeFileW(pwszFile, &Blob.pbData, &Blob.cbData, CRYPT_STRING_ANY);
  385. if (S_OK != hr)
  386. {
  387. cuPrintError(IDS_ERR_FORMAT_DECODEFILE, hr);
  388. goto error;
  389. }
  390. *ppCert = CertCreateCertificateContext(
  391. X509_ASN_ENCODING,
  392. Blob.pbData,
  393. Blob.cbData);
  394. if (NULL == *ppCert)
  395. {
  396. hr = myHLastError();
  397. _PrintError2(hr, "CertCreateCertificateContext", hr);
  398. *ppCRL = CertCreateCRLContext(
  399. X509_ASN_ENCODING,
  400. Blob.pbData,
  401. Blob.cbData);
  402. if (NULL == *ppCRL)
  403. {
  404. hr = myHLastError();
  405. _JumpError(hr, error, "CertCreateCRLContext");
  406. }
  407. }
  408. s_majorURL++;
  409. s_levelURL = 1;
  410. hr = cuSaveAsnToFile(
  411. Blob.pbData,
  412. Blob.cbData,
  413. s_majorURL,
  414. s_levelURL,
  415. 0, // iElement
  416. NULL != *ppCert? L".crt" : L".crl");
  417. _PrintIfError(hr, "cuSaveAsnToFile");
  418. hr = S_OK;
  419. error:
  420. if (NULL != Blob.pbData)
  421. {
  422. LocalFree(Blob.pbData);
  423. }
  424. return(hr);
  425. }
  426. BOOL
  427. RetrieveCRLStore(
  428. IN WCHAR const *pwszURL,
  429. OUT HCERTSTORE *phStore)
  430. {
  431. return(CryptRetrieveObjectByUrl(
  432. pwszURL,
  433. CONTEXT_OID_CRL,
  434. CRYPT_WIRE_ONLY_RETRIEVAL |
  435. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  436. g_dwRetrievalFlags,
  437. g_dwTimeout,
  438. (VOID **) phStore,
  439. NULL,
  440. NULL,
  441. NULL,
  442. NULL));
  443. }
  444. BOOL
  445. RetrieveCertStore(
  446. IN WCHAR const *pwszURL,
  447. OUT HCERTSTORE *phStore)
  448. {
  449. return(CryptRetrieveObjectByUrl(
  450. pwszURL,
  451. CONTEXT_OID_CERTIFICATE,
  452. CRYPT_WIRE_ONLY_RETRIEVAL |
  453. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  454. g_dwRetrievalFlags,
  455. g_dwTimeout,
  456. (VOID **) phStore,
  457. NULL,
  458. NULL,
  459. NULL,
  460. NULL));
  461. }
  462. int
  463. CUrlFetchDialog::AddListItem(
  464. IN WCHAR const *pwszURL,
  465. IN WCHAR const *pwszStatus,
  466. IN WCHAR const *pwszType,
  467. IN DWORD dwInterval)
  468. {
  469. LVITEM item;
  470. LRESULT lMsg = 0;
  471. WCHAR wszInterval[MAX_ULTOW_BUFFER_SIZE];
  472. int nListCount = 0;
  473. // Get the list count so we can append to it
  474. nListCount = ListView_GetItemCount(m_hwndList);
  475. ZeroMemory(&item, sizeof(item));
  476. item.iItem = nListCount;
  477. // Add the item
  478. item.mask = 0;
  479. item.iSubItem = 0;
  480. lMsg = SendMessage(m_hwndList, LVM_INSERTITEM, 0, (LPARAM) &item);
  481. // Add the status
  482. item.mask = LVIF_TEXT;
  483. item.iSubItem = LIST_STATUS_SUBITEM - 1;
  484. item.pszText = const_cast<WCHAR *>(pwszStatus);
  485. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nListCount, (LPARAM) &item);
  486. // Add the type
  487. item.iSubItem = LIST_TYPE_SUBITEM - 1;
  488. item.pszText = const_cast<WCHAR *>(pwszType);
  489. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nListCount, (LPARAM) &item);
  490. // Add the URL
  491. item.iSubItem = LIST_URL_SUBITEM - 1;
  492. item.pszText = const_cast<WCHAR *>(pwszURL);
  493. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nListCount, (LPARAM) &item);
  494. // Add the interval
  495. item.iSubItem = LIST_TIME_SUBITEM - 1;
  496. _ultow(dwInterval, wszInterval, 10);
  497. item.pszText = wszInterval;
  498. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nListCount, (LPARAM) &item);
  499. return nListCount;
  500. }
  501. HRESULT
  502. CUrlFetchDialog::UpdateListItemStatus(
  503. IN int nItem,
  504. IN WCHAR const *pwszStatus)
  505. {
  506. LVITEM item;
  507. ZeroMemory(&item, sizeof(item));
  508. item.mask = LVIF_TEXT;
  509. item.iItem = nItem;
  510. item.iSubItem = LIST_STATUS_SUBITEM - 1;
  511. item.pszText = const_cast<WCHAR *>(pwszStatus);
  512. SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  513. return(S_OK);
  514. }
  515. HRESULT
  516. CUrlFetchDialog::UpdateListItemParam(
  517. IN int nItem,
  518. IN LPARAM lParam)
  519. {
  520. LVITEM item;
  521. ZeroMemory(&item, sizeof(item));
  522. item.iItem = nItem;
  523. item.mask = LVIF_PARAM;
  524. item.lParam = lParam;
  525. SendMessage(m_hwndList, LVM_SETITEM, nItem, (LPARAM) &item);
  526. return(S_OK);
  527. }
  528. HRESULT
  529. CUrlFetchDialog::UpdateListItemTime(
  530. IN int nItem,
  531. IN DWORD dwInterval)
  532. {
  533. LVITEM item;
  534. WCHAR wszInterval[MAX_ULTOW_BUFFER_SIZE];
  535. ZeroMemory(&item, sizeof(item));
  536. item.iItem = nItem;
  537. item.mask = LVIF_TEXT;
  538. item.iSubItem = LIST_TIME_SUBITEM - 1;
  539. item.pszText = wszInterval;
  540. _ultow(dwInterval, wszInterval, 10);
  541. SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  542. return(S_OK);
  543. }
  544. HRESULT
  545. CUrlFetchDialog::UpdateListItem(
  546. IN int nItem,
  547. IN WCHAR const *pwszURL,
  548. IN WCHAR const *pwszStatus,
  549. IN WCHAR const *pwszType,
  550. IN DWORD dwInterval)
  551. {
  552. LVITEM item;
  553. LRESULT lMsg = 0;
  554. WCHAR wszInterval[MAX_ULTOW_BUFFER_SIZE];
  555. ZeroMemory(&item, sizeof(item));
  556. item.iItem = nItem;
  557. // Update the status
  558. item.mask = LVIF_TEXT;
  559. item.iSubItem = LIST_STATUS_SUBITEM - 1;
  560. item.pszText = const_cast<WCHAR *>(pwszStatus);
  561. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  562. // Update the type
  563. item.iSubItem = LIST_TYPE_SUBITEM - 1;
  564. item.pszText = const_cast<WCHAR *>(pwszType);
  565. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  566. // Update the URL
  567. item.iSubItem = LIST_URL_SUBITEM - 1;
  568. item.pszText = const_cast<WCHAR *>(pwszURL);
  569. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  570. // Update the interval
  571. item.iSubItem = LIST_TIME_SUBITEM - 1;
  572. _ultow(dwInterval, wszInterval, 10);
  573. item.pszText = wszInterval;
  574. lMsg = SendMessage(m_hwndList, LVM_SETITEMTEXT, nItem, (LPARAM) &item);
  575. return(S_OK);
  576. }
  577. int
  578. CUrlFetchDialog::DisplayMessageBox(
  579. IN HWND hWnd,
  580. IN LPCWSTR lpText,
  581. IN LPCWSTR lpCaption,
  582. IN UINT uType)
  583. {
  584. return(::MessageBox(hWnd, lpText, lpCaption, uType));
  585. }
  586. int
  587. CUrlFetchConsole::AddListItem(
  588. IN WCHAR const *pwszURL,
  589. IN WCHAR const *pwszStatus,
  590. IN WCHAR const *pwszType,
  591. IN DWORD dwInterval)
  592. {
  593. HRESULT hr;
  594. DWORD cb = (m_cItem + 1) * sizeof(*m_rgpItem);
  595. CConsoleItem **rgpItem;
  596. int nItem;
  597. #if 0
  598. wprintf(
  599. L"CUrlFetchConsole::AddListItem(%u: %ws, %ws, %u)\n%ws\n\n",
  600. m_cItem,
  601. pwszStatus,
  602. pwszType,
  603. dwInterval,
  604. pwszURL);
  605. #endif
  606. if (0 == m_cItem)
  607. {
  608. rgpItem = (CConsoleItem **) LocalAlloc(
  609. LMEM_FIXED | LMEM_ZEROINIT,
  610. cb);
  611. }
  612. else
  613. {
  614. rgpItem = (CConsoleItem **) LocalReAlloc(
  615. m_rgpItem,
  616. cb,
  617. LMEM_MOVEABLE);
  618. }
  619. if (NULL == rgpItem)
  620. {
  621. hr = E_OUTOFMEMORY;
  622. _JumpError(hr, error, "LocalAlloc/ReAlloc");
  623. }
  624. m_rgpItem = rgpItem;
  625. nItem = m_cItem++;
  626. m_rgpItem[nItem] = new CConsoleItem;
  627. if (NULL == m_rgpItem[nItem])
  628. {
  629. hr = E_OUTOFMEMORY;
  630. _JumpError(hr, error, "new");
  631. }
  632. hr = UpdateListItem(nItem, pwszURL, pwszStatus, pwszType, dwInterval);
  633. _JumpIfError(hr, error, "UpdateListItem");
  634. error:
  635. return(nItem);
  636. }
  637. HRESULT
  638. CUrlFetchConsole::UpdateListItemStatus(
  639. IN int nItem,
  640. IN WCHAR const *pwszStatus)
  641. {
  642. HRESULT hr;
  643. #if 0
  644. wprintf(
  645. L"CUrlFetchConsole::UpdateListItemStatus(%u: %ws)\n",
  646. nItem,
  647. pwszStatus);
  648. #endif
  649. if (nItem >= m_cItem || NULL == m_rgpItem[nItem])
  650. {
  651. hr = E_INVALIDARG;
  652. _JumpError(hr, error, "new");
  653. }
  654. hr = m_rgpItem[nItem]->UpdateString(CII_STATUS, pwszStatus);
  655. _JumpIfError(hr, error, "UpdateString");
  656. error:
  657. return(hr);
  658. }
  659. HRESULT
  660. CUrlFetchConsole::UpdateListItemParam(
  661. IN int nItem,
  662. IN LPARAM lParam)
  663. {
  664. HRESULT hr;
  665. OBJECT_INFO *pObjInfo = (OBJECT_INFO *) lParam;
  666. #if 0
  667. wprintf(
  668. L"CUrlFetchConsole::UpdateListItemParam(%u: %p): ",
  669. nItem,
  670. lParam);
  671. #endif
  672. if (nItem >= m_cItem || NULL == m_rgpItem[nItem])
  673. {
  674. hr = E_INVALIDARG;
  675. _JumpError(hr, error, "new");
  676. }
  677. switch (pObjInfo->dwType)
  678. {
  679. case OBJECT_TYPE_CERT:
  680. #if 0
  681. wprintf(L"OBJECT_TYPE_CERT\n");
  682. #endif
  683. break;
  684. case OBJECT_TYPE_CRL:
  685. #if 0
  686. wprintf(L"OBJECT_TYPE_CRL\n");
  687. #endif
  688. break;
  689. case OBJECT_TYPE_MSG:
  690. #if 0
  691. wprintf(L"OBJECT_TYPE_MSG\n%ws\n", pObjInfo->wszErrInfo);
  692. #endif
  693. hr = m_rgpItem[nItem]->UpdateString(
  694. CII_MESSAGE,
  695. pObjInfo->wszErrInfo);
  696. _JumpIfError(hr, error, "UpdateString");
  697. break;
  698. default:
  699. #if 0
  700. wprintf(L"???\n");
  701. #endif
  702. break;
  703. }
  704. hr = S_OK;
  705. error:
  706. delete pObjInfo;
  707. return(hr);
  708. }
  709. HRESULT
  710. CUrlFetchConsole::UpdateListItemTime(
  711. IN int nItem,
  712. IN DWORD dwInterval)
  713. {
  714. HRESULT hr;
  715. #if 0
  716. wprintf(
  717. L"CUrlFetchConsole::UpdateListItemTime(%u: %u)\n",
  718. nItem,
  719. dwInterval);
  720. #endif
  721. if (nItem >= m_cItem || NULL == m_rgpItem[nItem])
  722. {
  723. hr = E_INVALIDARG;
  724. _JumpError(hr, error, "new");
  725. }
  726. hr = m_rgpItem[nItem]->UpdateInterval(dwInterval);
  727. _JumpIfError(hr, error, "UpdateInterval");
  728. error:
  729. return(hr);
  730. }
  731. HRESULT
  732. CUrlFetchConsole::UpdateListItem(
  733. IN int nItem,
  734. IN WCHAR const *pwszURL,
  735. IN WCHAR const *pwszStatus,
  736. IN WCHAR const *pwszType,
  737. IN DWORD dwInterval)
  738. {
  739. HRESULT hr;
  740. #if 0
  741. wprintf(
  742. L"CUrlFetchConsole::UpdateListItem(%u: %ws, %ws, %u)\n%ws\n\n",
  743. nItem,
  744. pwszStatus,
  745. pwszType,
  746. dwInterval,
  747. pwszURL);
  748. #endif
  749. if (nItem >= m_cItem || NULL == m_rgpItem[nItem])
  750. {
  751. hr = E_INVALIDARG;
  752. _JumpError(hr, error, "new");
  753. }
  754. hr = m_rgpItem[nItem]->UpdateInterval(dwInterval);
  755. _JumpIfError(hr, error, "UpdateInterval");
  756. hr = m_rgpItem[nItem]->UpdateString(CII_URL, pwszURL);
  757. _JumpIfError(hr, error, "UpdateString");
  758. hr = m_rgpItem[nItem]->UpdateString(CII_STATUS, pwszStatus);
  759. _JumpIfError(hr, error, "UpdateString");
  760. hr = m_rgpItem[nItem]->UpdateString(CII_TYPE, pwszType);
  761. _JumpIfError(hr, error, "UpdateString");
  762. error:
  763. return(hr);
  764. }
  765. int
  766. CUrlFetchConsole::DisplayMessageBox(
  767. IN HWND hWnd,
  768. IN LPCWSTR lpText,
  769. IN LPCWSTR lpCaption,
  770. IN UINT uType)
  771. {
  772. wprintf(L"%ws: %ws\n", lpCaption, lpText);
  773. return(IDOK);
  774. }
  775. BOOL
  776. cuVerifyAKI(
  777. IN DWORD cExt,
  778. IN CERT_EXTENSION const *rgExt,
  779. IN CERT_NAME_BLOB const *pIssuer,
  780. IN CERT_CONTEXT const *pCertIssuer)
  781. {
  782. BOOL fVerified = FALSE;
  783. CERT_EXTENSION const *pExt;
  784. pExt = CertFindExtension(
  785. szOID_AUTHORITY_KEY_IDENTIFIER2,
  786. cExt,
  787. const_cast<CERT_EXTENSION *>(rgExt));
  788. if (NULL != pExt)
  789. {
  790. HRESULT hr;
  791. hr = cuVerifyKeyAuthority(
  792. pIssuer,
  793. pCertIssuer->pCertInfo,
  794. pExt->Value.pbData,
  795. pExt->Value.cbData,
  796. TRUE,
  797. &fVerified);
  798. _JumpIfError(hr, error, "cuVerifyKeyAuthority");
  799. }
  800. else
  801. {
  802. fVerified = TRUE; // no penalty if missing the AKI extension
  803. }
  804. error:
  805. return(fVerified);
  806. }
  807. WCHAR const *
  808. wszCertStatus(
  809. OPTIONAL IN CERT_CONTEXT const *pCert,
  810. IN CERT_CONTEXT const *pCertIssuer)
  811. {
  812. HRESULT hr;
  813. WCHAR const *pwsz;
  814. CERT_REVOCATION_PARA crp;
  815. CERT_REVOCATION_STATUS crs;
  816. UINT ids;
  817. ZeroMemory(&crp, sizeof(crp));
  818. crp.cbSize = sizeof(crp);
  819. ZeroMemory(&crs, sizeof(crs));
  820. crs.cbSize = sizeof(crs);
  821. // verify cert signature with the Issuer Cert public key
  822. if (NULL != pCert)
  823. {
  824. if (!CryptVerifyCertificateSignature(
  825. NULL,
  826. X509_ASN_ENCODING,
  827. pCert->pbCertEncoded,
  828. pCert->cbCertEncoded,
  829. &pCertIssuer->pCertInfo->SubjectPublicKeyInfo))
  830. {
  831. hr = myHLastError();
  832. _PrintError2(hr, "CryptVerifyCertificateSignature", hr);
  833. ids = IDS_STATUS_WRONG_ISSUER; // "Wrong Issuer"
  834. goto error;
  835. }
  836. }
  837. if (0 != CertVerifyTimeValidity(NULL, pCertIssuer->pCertInfo))
  838. {
  839. ids = IDS_STATUS_EXPIRED; // "Expired"
  840. goto error;
  841. }
  842. if (NULL != pCert &&
  843. !cuVerifyAKI(
  844. pCert->pCertInfo->cExtension,
  845. pCert->pCertInfo->rgExtension,
  846. &pCert->pCertInfo->Issuer,
  847. pCertIssuer))
  848. {
  849. ids = IDS_STATUS_BAD_AKI; // "Bad Authority Key Id"
  850. goto error;
  851. }
  852. crp.hCrlStore = CertOpenStore(
  853. CERT_STORE_PROV_SYSTEM_W,
  854. X509_ASN_ENCODING,
  855. NULL, // hProv
  856. cuGetSystemStoreFlags() | CERT_STORE_READONLY_FLAG,
  857. wszCA_CERTSTORE);
  858. if (NULL == crp.hCrlStore)
  859. {
  860. hr = myHLastError();
  861. _JumpError(hr, error, "CertOpenStore");
  862. }
  863. if (!CertVerifyRevocation(
  864. X509_ASN_ENCODING,
  865. CERT_CONTEXT_REVOCATION_TYPE,
  866. 1, // cContext
  867. (VOID **) &pCertIssuer, // rgpContext
  868. 0, // dwFlags
  869. &crp,
  870. &crs))
  871. {
  872. hr = myHLastError();
  873. _PrintError(hr, "CertVerifyRevocation");
  874. if (CRYPT_E_REVOKED == hr || CERT_E_REVOKED == hr)
  875. {
  876. ids = IDS_STATUS_REVOKED; // "Revoked"
  877. }
  878. else
  879. if (CRYPT_E_NO_REVOCATION_CHECK != hr)
  880. {
  881. ids = IDS_STATUS_CANNOT_CHECK_REVOCATION; // "Revocation Check Failed"
  882. }
  883. else
  884. {
  885. ids = IDS_STATUS_NO_CRL; // "No CRL"
  886. }
  887. goto error;
  888. }
  889. ids = NULL != pCert?
  890. IDS_STATUS_VERIFIED : // "Verified"
  891. IDS_STATUS_OK; // "OK"
  892. error:
  893. if (NULL != crp.hCrlStore)
  894. {
  895. CertCloseStore(crp.hCrlStore, CERT_CLOSE_STORE_CHECK_FLAG);
  896. }
  897. pwsz = myLoadResourceString(ids);
  898. if (NULL == pwsz)
  899. {
  900. pwsz = L"???";
  901. }
  902. return(pwsz);
  903. }
  904. BOOL
  905. cuVerifyMinimumBaseCRL(
  906. IN CRL_CONTEXT const *pCRLBase,
  907. IN CRL_CONTEXT const *pCRLDelta)
  908. {
  909. BOOL fVerified = FALSE;
  910. DWORD CRLNumber;
  911. CRLNumber = myCRLNumber(pCRLBase);
  912. if (0 != CRLNumber)
  913. {
  914. CERT_EXTENSION const *pExt;
  915. pExt = CertFindExtension(
  916. szOID_DELTA_CRL_INDICATOR,
  917. pCRLDelta->pCrlInfo->cExtension,
  918. pCRLDelta->pCrlInfo->rgExtension);
  919. if (NULL != pExt)
  920. {
  921. DWORD MinBase;
  922. DWORD cb;
  923. cb = sizeof(MinBase);
  924. MinBase = 0;
  925. if (CryptDecodeObject(
  926. X509_ASN_ENCODING,
  927. X509_INTEGER,
  928. pExt->Value.pbData,
  929. pExt->Value.cbData,
  930. 0,
  931. &MinBase,
  932. &cb))
  933. {
  934. if (CRLNumber >= MinBase)
  935. {
  936. fVerified = TRUE;
  937. }
  938. }
  939. }
  940. }
  941. return(fVerified);
  942. }
  943. HRESULT
  944. GetObjectUrl(
  945. IN char const *pszUrlOid,
  946. IN VOID *pvPara,
  947. IN DWORD dwFlags,
  948. OUT CRYPT_URL_ARRAY **ppUrlArray,
  949. OUT DWORD *pcbUrlArray)
  950. {
  951. HRESULT hr;
  952. CRYPT_URL_ARRAY *pUrlArray = NULL;
  953. DWORD cbUrlArray;
  954. *ppUrlArray = NULL;
  955. if (!CryptGetObjectUrl(
  956. pszUrlOid,
  957. pvPara,
  958. dwFlags,
  959. NULL,
  960. &cbUrlArray,
  961. NULL,
  962. NULL,
  963. NULL))
  964. {
  965. hr = myHLastError();
  966. _PrintError2(hr, "CryptGetObjectUrl", hr);
  967. if (CRYPT_E_NOT_FOUND == hr)
  968. {
  969. hr = S_OK;
  970. goto error;
  971. }
  972. _JumpError(hr, error, "CryptGetObjectUrl");
  973. }
  974. pUrlArray = (CRYPT_URL_ARRAY *) LocalAlloc(LMEM_FIXED, cbUrlArray);
  975. if (NULL == pUrlArray)
  976. {
  977. hr = E_OUTOFMEMORY;
  978. _JumpError(hr, error, "LocalAlloc");
  979. }
  980. if (!CryptGetObjectUrl(
  981. pszUrlOid,
  982. pvPara,
  983. dwFlags,
  984. pUrlArray,
  985. &cbUrlArray,
  986. NULL,
  987. NULL,
  988. NULL))
  989. {
  990. hr = myHLastError();
  991. _JumpError(hr, error, "CryptGetObjectUrl");
  992. }
  993. *ppUrlArray = pUrlArray;
  994. pUrlArray = NULL;
  995. *pcbUrlArray = cbUrlArray;
  996. hr = S_OK;
  997. error:
  998. if (NULL != pUrlArray)
  999. {
  1000. LocalFree(pUrlArray);
  1001. }
  1002. return(hr);
  1003. }
  1004. BOOL
  1005. cuVerifyIDP(
  1006. IN CERT_CONTEXT const *pCertSubject,
  1007. IN CRL_CONTEXT const *pCRL)
  1008. {
  1009. HRESULT hr;
  1010. BOOL fVerified = TRUE;
  1011. CERT_EXTENSION const *pExtCDP;
  1012. CRL_DIST_POINTS_INFO *pCDP = NULL;
  1013. CERT_EXTENSION const *pExtIDP;
  1014. CRL_ISSUING_DIST_POINT *pIDP = NULL;
  1015. DWORD cb;
  1016. DWORD iDistPoint;
  1017. DWORD i;
  1018. // Find the cert CDP extension:
  1019. pExtCDP = CertFindExtension(
  1020. szOID_CRL_DIST_POINTS,
  1021. pCertSubject->pCertInfo->cExtension,
  1022. pCertSubject->pCertInfo->rgExtension);
  1023. if (NULL == pExtCDP)
  1024. {
  1025. hr = CRYPT_E_NOT_FOUND;
  1026. _JumpIfError2(hr, error, "CertFindExtension", hr);
  1027. }
  1028. // Find the CRL IDP extension:
  1029. pExtIDP = CertFindExtension(
  1030. szOID_ISSUING_DIST_POINT,
  1031. pCRL->pCrlInfo->cExtension,
  1032. pCRL->pCrlInfo->rgExtension);
  1033. if (NULL == pExtIDP)
  1034. {
  1035. hr = CRYPT_E_NOT_FOUND;
  1036. _JumpIfError2(hr, error, "CertFindExtension", hr);
  1037. }
  1038. fVerified = FALSE;
  1039. // Decode the cert CDP extension:
  1040. if (!myDecodeObject(
  1041. X509_ASN_ENCODING,
  1042. X509_CRL_DIST_POINTS,
  1043. pExtCDP->Value.pbData,
  1044. pExtCDP->Value.cbData,
  1045. CERTLIB_USE_LOCALALLOC,
  1046. (VOID **) &pCDP,
  1047. &cb))
  1048. {
  1049. hr = myHLastError();
  1050. _JumpError(hr, error, "myDecodeObject");
  1051. }
  1052. // Decode the CRL IDP extension:
  1053. if (!myDecodeObject(
  1054. X509_ASN_ENCODING,
  1055. X509_ISSUING_DIST_POINT,
  1056. pExtIDP->Value.pbData,
  1057. pExtIDP->Value.cbData,
  1058. CERTLIB_USE_LOCALALLOC,
  1059. (VOID **) &pIDP,
  1060. &cb))
  1061. {
  1062. hr = myHLastError();
  1063. _JumpError(hr, error, "myDecodeObject");
  1064. }
  1065. if (CRL_DIST_POINT_FULL_NAME != pIDP->DistPointName.dwDistPointNameChoice)
  1066. {
  1067. hr = CRYPT_E_NOT_FOUND;
  1068. _JumpIfError2(hr, error, "dwDistPointNameChoice", hr);
  1069. }
  1070. for (iDistPoint = 0; iDistPoint < pCDP->cDistPoint; iDistPoint++)
  1071. {
  1072. CERT_ALT_NAME_INFO *pAltNameEntry;
  1073. if (CRL_DIST_POINT_FULL_NAME !=
  1074. pCDP->rgDistPoint[iDistPoint].DistPointName.dwDistPointNameChoice)
  1075. {
  1076. continue;
  1077. }
  1078. pAltNameEntry = &pCDP->rgDistPoint[iDistPoint].DistPointName.FullName;
  1079. for (i = 0; i < pIDP->DistPointName.FullName.cAltEntry; i++)
  1080. {
  1081. DWORD j;
  1082. CERT_ALT_NAME_ENTRY const *pIDPAlt =
  1083. &pIDP->DistPointName.FullName.rgAltEntry[i];
  1084. for (j = 0; j < pAltNameEntry->cAltEntry; j++)
  1085. {
  1086. CERT_ALT_NAME_ENTRY const *pCDPAlt = &pAltNameEntry->rgAltEntry[j];
  1087. BOOL fMatch;
  1088. if (pIDPAlt->dwAltNameChoice != pCDPAlt->dwAltNameChoice)
  1089. {
  1090. continue;
  1091. }
  1092. fMatch = FALSE;
  1093. switch (pIDPAlt->dwAltNameChoice)
  1094. {
  1095. case CERT_ALT_NAME_OTHER_NAME:
  1096. fMatch = 0 == strcmp(
  1097. pIDPAlt->pOtherName->pszObjId,
  1098. pCDPAlt->pOtherName->pszObjId) &&
  1099. myAreBlobsSame(
  1100. pIDPAlt->pOtherName->Value.pbData,
  1101. pIDPAlt->pOtherName->Value.cbData,
  1102. pCDPAlt->pOtherName->Value.pbData,
  1103. pCDPAlt->pOtherName->Value.cbData);
  1104. break;
  1105. case CERT_ALT_NAME_RFC822_NAME:
  1106. fMatch = 0 == lstrcmp(
  1107. pIDPAlt->pwszRfc822Name,
  1108. pCDPAlt->pwszRfc822Name);
  1109. break;
  1110. case CERT_ALT_NAME_DNS_NAME:
  1111. fMatch = 0 == lstrcmp(
  1112. pIDPAlt->pwszDNSName,
  1113. pCDPAlt->pwszDNSName);
  1114. break;
  1115. case CERT_ALT_NAME_DIRECTORY_NAME:
  1116. fMatch = 0 == lstrcmp(
  1117. pIDPAlt->pwszRfc822Name,
  1118. pCDPAlt->pwszRfc822Name);
  1119. break;
  1120. case CERT_ALT_NAME_URL:
  1121. fMatch = 0 == lstrcmp(pIDPAlt->pwszURL, pCDPAlt->pwszURL);
  1122. break;
  1123. case CERT_ALT_NAME_IP_ADDRESS:
  1124. fMatch = myAreBlobsSame(
  1125. pIDPAlt->IPAddress.pbData,
  1126. pIDPAlt->IPAddress.cbData,
  1127. pCDPAlt->IPAddress.pbData,
  1128. pCDPAlt->IPAddress.cbData);
  1129. break;
  1130. case CERT_ALT_NAME_REGISTERED_ID:
  1131. fMatch = 0 == strcmp(
  1132. pIDPAlt->pszRegisteredID,
  1133. pCDPAlt->pszRegisteredID);
  1134. break;
  1135. //case CERT_ALT_NAME_X400_ADDRESS:
  1136. //case CERT_ALT_NAME_EDI_PARTY_NAME:
  1137. default:
  1138. continue;
  1139. }
  1140. if (fMatch)
  1141. {
  1142. fVerified = TRUE;
  1143. break;
  1144. }
  1145. }
  1146. if (fVerified)
  1147. {
  1148. break;
  1149. }
  1150. }
  1151. if (fVerified)
  1152. {
  1153. break;
  1154. }
  1155. }
  1156. error:
  1157. if (NULL != pCDP)
  1158. {
  1159. LocalFree(pCDP);
  1160. }
  1161. if (NULL != pIDP)
  1162. {
  1163. LocalFree(pIDP);
  1164. }
  1165. return(fVerified);
  1166. }
  1167. WCHAR const *
  1168. wszCRLStatus(
  1169. OPTIONAL IN CERT_CONTEXT const *pCertIssuer,
  1170. OPTIONAL IN CERT_CONTEXT const *pCertSubject,
  1171. OPTIONAL IN CRL_CONTEXT const *pCRLBase,
  1172. IN CRL_CONTEXT const *pCRL)
  1173. {
  1174. HRESULT hr;
  1175. WCHAR const *pwsz;
  1176. UINT ids;
  1177. // verify CRL signature with the Issuer Cert public key
  1178. if (NULL == pCertIssuer && NULL != pCertSubject)
  1179. {
  1180. // if the Subject cert is a root, use Subject cert for Issuer cert
  1181. hr = cuVerifySignature(
  1182. pCertSubject->pbCertEncoded,
  1183. pCertSubject->cbCertEncoded,
  1184. &pCertSubject->pCertInfo->SubjectPublicKeyInfo,
  1185. TRUE,
  1186. TRUE);
  1187. if (S_OK == hr)
  1188. {
  1189. pCertIssuer = pCertSubject;
  1190. }
  1191. }
  1192. if (NULL != pCertIssuer)
  1193. {
  1194. if (!CryptVerifyCertificateSignature(
  1195. NULL,
  1196. X509_ASN_ENCODING,
  1197. pCRL->pbCrlEncoded,
  1198. pCRL->cbCrlEncoded,
  1199. &pCertIssuer->pCertInfo->SubjectPublicKeyInfo))
  1200. {
  1201. hr = myHLastError();
  1202. _PrintError2(hr, "CryptVerifyCertificateSignature", hr);
  1203. ids = IDS_STATUS_WRONG_ISSUER; // "Wrong Issuer"
  1204. goto error;
  1205. }
  1206. }
  1207. if (0 != CertVerifyCRLTimeValidity(NULL, pCRL->pCrlInfo))
  1208. {
  1209. ids = IDS_STATUS_EXPIRED; // "Expired"
  1210. goto error;
  1211. }
  1212. if (NULL != pCRLBase &&
  1213. !cuVerifyMinimumBaseCRL(pCRLBase, pCRL))
  1214. {
  1215. ids = IDS_STATUS_OLD_BASE_CRL; // "Old Base CRL"
  1216. goto error;
  1217. }
  1218. if (NULL != pCertIssuer)
  1219. {
  1220. if (!CertCompareCertificateName(
  1221. X509_ASN_ENCODING,
  1222. &pCRL->pCrlInfo->Issuer,
  1223. &pCertSubject->pCertInfo->Issuer))
  1224. {
  1225. ids = IDS_STATUS_BAD_CERT_ISSUER; // "Bad Cert Issuer"
  1226. goto error;
  1227. }
  1228. if (!CertCompareCertificateName(
  1229. X509_ASN_ENCODING,
  1230. &pCRL->pCrlInfo->Issuer,
  1231. &pCertIssuer->pCertInfo->Subject))
  1232. {
  1233. ids = IDS_STATUS_BAD_CA_CERT_SUBJECT; // "Bad CA Cert Subject"
  1234. goto error;
  1235. }
  1236. if (!cuVerifyAKI(
  1237. pCRL->pCrlInfo->cExtension,
  1238. pCRL->pCrlInfo->rgExtension,
  1239. &pCRL->pCrlInfo->Issuer,
  1240. pCertIssuer))
  1241. {
  1242. ids = IDS_STATUS_BAD_AKI; // "Bad Authority Key Id"
  1243. goto error;
  1244. }
  1245. }
  1246. if (NULL != pCertSubject &&
  1247. NULL == pCRLBase &&
  1248. !cuVerifyIDP(pCertSubject, pCRL))
  1249. {
  1250. ids = IDS_STATUS_BAD_IDP; // "No IDP Intersection"
  1251. goto error;
  1252. }
  1253. ids = NULL != pCertIssuer?
  1254. IDS_STATUS_VERIFIED : // "Verified"
  1255. IDS_STATUS_OK; // "OK"
  1256. error:
  1257. pwsz = myLoadResourceString(ids);
  1258. if (NULL == pwsz)
  1259. {
  1260. pwsz = L"???";
  1261. }
  1262. return(pwsz);
  1263. }
  1264. DWORD
  1265. GetCertNumber(
  1266. IN CERT_CONTEXT const *pCert,
  1267. OPTIONAL IN OUT BYTE **ppbHashes,
  1268. OPTIONAL IN OUT DWORD *pcHashes)
  1269. {
  1270. HRESULT hr;
  1271. DWORD CertNumber = MAXDWORD;
  1272. DWORD i;
  1273. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  1274. DWORD cbHash;
  1275. i = MAXDWORD;
  1276. cbHash = sizeof(abHash);
  1277. if (!CertGetCertificateContextProperty(
  1278. pCert,
  1279. CERT_SHA1_HASH_PROP_ID,
  1280. abHash,
  1281. &cbHash))
  1282. {
  1283. hr = myHLastError();
  1284. _JumpError(hr, error, "CertGetCertificateContextProperty");
  1285. }
  1286. if (cbHash != sizeof(abHash))
  1287. {
  1288. _JumpError(E_INVALIDARG, error, "cbHash");
  1289. }
  1290. if (NULL != ppbHashes && NULL != pcHashes)
  1291. {
  1292. for (i = 0; i < *pcHashes; i++)
  1293. {
  1294. if (0 == memcmp(
  1295. abHash,
  1296. &(*ppbHashes)[i * sizeof(abHash)],
  1297. sizeof(abHash)))
  1298. {
  1299. break;
  1300. }
  1301. }
  1302. if (i == *pcHashes)
  1303. {
  1304. if (0 == *pcHashes)
  1305. {
  1306. *ppbHashes = (BYTE *) LocalAlloc(LMEM_FIXED, sizeof(abHash));
  1307. if (NULL == *ppbHashes)
  1308. {
  1309. _JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
  1310. }
  1311. }
  1312. else
  1313. {
  1314. BYTE *pb;
  1315. pb = (BYTE *) LocalReAlloc(
  1316. *ppbHashes,
  1317. (i + 1) * sizeof(abHash),
  1318. LMEM_MOVEABLE);
  1319. if (NULL == pb)
  1320. {
  1321. _JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
  1322. }
  1323. *ppbHashes = pb;
  1324. }
  1325. memcpy(
  1326. &(*ppbHashes)[i * sizeof(abHash)],
  1327. abHash,
  1328. sizeof(abHash));
  1329. (*pcHashes)++;
  1330. }
  1331. }
  1332. CertNumber = i;
  1333. error:
  1334. return(CertNumber);
  1335. }
  1336. VOID
  1337. FillErrorText(
  1338. IN UINT idsFmt,
  1339. IN WCHAR const *pwszFmt2,
  1340. OUT WCHAR *pwsz,
  1341. IN DWORD cwc,
  1342. IN HRESULT hr)
  1343. {
  1344. WCHAR const *pwszFmt;
  1345. WCHAR const *pwszMsg = myGetErrorMessageText(hr, TRUE);
  1346. pwszFmt = myLoadResourceString(idsFmt);
  1347. if (NULL == pwszFmt)
  1348. {
  1349. pwszFmt = pwszFmt2;
  1350. }
  1351. _snwprintf(pwsz, cwc, pwszFmt, pwszMsg);
  1352. pwsz[cwc - 1] = L'\0';
  1353. if (NULL != pwszMsg)
  1354. {
  1355. LocalFree(const_cast<WCHAR *>(pwszMsg));
  1356. }
  1357. }
  1358. VOID
  1359. FillErrorTextRetrieve(
  1360. OUT WCHAR *pwsz,
  1361. IN DWORD cwc,
  1362. IN HRESULT hr)
  1363. {
  1364. FillErrorText(
  1365. IDS_FORMAT_URL_RETRIEVE_ERROR, // "Error retrieving URL: %ws"
  1366. L"Error retrieving URL: %ws",
  1367. pwsz,
  1368. cwc,
  1369. hr);
  1370. }
  1371. VOID
  1372. FillErrorTextExtract(
  1373. OUT WCHAR *pwsz,
  1374. IN DWORD cwc,
  1375. IN HRESULT hr)
  1376. {
  1377. FillErrorText(
  1378. IDS_FORMAT_URL_EXTRACT_ERROR, // "No URLs found: %ws"
  1379. L"No URLs found: %ws",
  1380. pwsz,
  1381. cwc,
  1382. hr);
  1383. }
  1384. BOOL
  1385. RetrieveAndAddAIAUrlToList(
  1386. IN CUrlFetch *pUrl,
  1387. OPTIONAL IN CERT_CONTEXT const *pCert,
  1388. IN WCHAR const *pwszUrl,
  1389. IN DWORD iURL,
  1390. OPTIONAL IN OUT BYTE **ppbHashes,
  1391. OPTIONAL IN OUT DWORD *pcHashes)
  1392. {
  1393. HRESULT hr = S_OK;
  1394. BOOL fRet = FALSE;
  1395. int iItem = 0;
  1396. HCERTSTORE hStore = NULL;
  1397. CERT_CONTEXT const *pAIACert = NULL;
  1398. WCHAR wszUrl[MAX_URL_LEN];
  1399. DWORD cert = 0;
  1400. DWORD dwIntStart = 0;
  1401. DWORD dwIntEnd = 0;
  1402. DWORD dwInterval = 0;
  1403. OBJECT_INFO *pObjInfo = NULL;
  1404. HCURSOR hPrevCur;
  1405. WCHAR const *pwszTypeCert;
  1406. WCHAR *pwszTypeBuffer = NULL;
  1407. s_levelURL++;
  1408. // Add the url to the list view with RETRIEVING status
  1409. iItem = pUrl->AddListItem(
  1410. pwszUrl,
  1411. myLoadResourceString(IDS_STATUS_RETRIEVING), // "Retrieving"
  1412. myLoadResourceString(IDS_AIA_ITEM_TYPE), // "AIA"
  1413. 0);
  1414. // Attempt to retrieve the url
  1415. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1416. dwIntStart = GetTickCount();
  1417. if (!RetrieveCertStore(pwszUrl, &hStore) || NULL == hStore)
  1418. {
  1419. hr = myHLastError();
  1420. pUrl->SetCursor(hPrevCur);
  1421. _PrintErrorStr(hr, "RetrieveCertStore", pwszUrl);
  1422. // Modify the status of this URL on the list to FAILED
  1423. pUrl->UpdateListItemStatus(
  1424. iItem,
  1425. myLoadResourceString(IDS_STATUS_FAILURE)); // "Failed"
  1426. pObjInfo = new OBJECT_INFO;
  1427. if (NULL == pObjInfo)
  1428. {
  1429. _PrintError(E_OUTOFMEMORY, "new");
  1430. }
  1431. else
  1432. {
  1433. pObjInfo->dwType = OBJECT_TYPE_MSG;
  1434. pObjInfo->wszErrInfo[0] = L'\0';
  1435. FillErrorTextRetrieve(
  1436. pObjInfo->wszErrInfo,
  1437. ARRAYSIZE(pObjInfo->wszErrInfo),
  1438. hr);
  1439. pUrl->UpdateListItemParam(iItem, (LPARAM) pObjInfo);
  1440. }
  1441. // Retrieve the next item
  1442. goto error;
  1443. }
  1444. pUrl->SetCursor(hPrevCur);
  1445. // Calculate and update the retrieval interval
  1446. dwIntEnd = GetTickCount();
  1447. dwInterval = (dwIntEnd - dwIntStart) / 1000;
  1448. pUrl->UpdateListItemTime(iItem, dwInterval);
  1449. // Modify the status of this URL on the list to SUCCESS.
  1450. pUrl->UpdateListItemStatus(
  1451. iItem,
  1452. myLoadResourceString(IDS_STATUS_SUCCESS)); // "Success"
  1453. // Add the certificate context to the items
  1454. pwszTypeCert = myLoadResourceString(IDS_CERT_ITEM_TYPE);
  1455. if (NULL == pwszTypeCert)
  1456. {
  1457. pwszTypeCert = wszCERTIFICATE;
  1458. }
  1459. pwszTypeBuffer = (WCHAR *) LocalAlloc(
  1460. LMEM_FIXED,
  1461. (wcslen(pwszTypeCert) + 2 + cwcDWORDSPRINTF + 2) *
  1462. sizeof(WCHAR));
  1463. if (NULL == pwszTypeBuffer)
  1464. {
  1465. _JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
  1466. }
  1467. cert = 0;
  1468. while (TRUE)
  1469. {
  1470. WCHAR const *pwszStatus;
  1471. DWORD CertNumber;
  1472. pAIACert = CertEnumCertificatesInStore(hStore, pAIACert);
  1473. if (NULL == pAIACert)
  1474. {
  1475. break;
  1476. }
  1477. // Add the cert to the list, initially as OK
  1478. _snwprintf(
  1479. wszUrl,
  1480. ARRAYSIZE(wszUrl),
  1481. L"[%d.%d] %ws",
  1482. iURL,
  1483. cert,
  1484. pwszUrl);
  1485. wszUrl[ARRAYSIZE(wszUrl) - 1] = L'\0';
  1486. hr = cuSaveAsnToFile(
  1487. pAIACert->pbCertEncoded,
  1488. pAIACert->cbCertEncoded,
  1489. s_majorURL,
  1490. s_levelURL,
  1491. cert,
  1492. L".crt");
  1493. _PrintIfError(hr, "cuSaveAsnToFile");
  1494. CertNumber = GetCertNumber(pAIACert, ppbHashes, pcHashes);
  1495. wcscpy(pwszTypeBuffer, pwszTypeCert);
  1496. if (MAXDWORD != CertNumber)
  1497. {
  1498. wsprintf(
  1499. &pwszTypeBuffer[wcslen(pwszTypeCert)],
  1500. L" (%u)",
  1501. CertNumber);
  1502. }
  1503. if (0 == cert)
  1504. {
  1505. pUrl->UpdateListItem(
  1506. iItem,
  1507. wszUrl,
  1508. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1509. pwszTypeBuffer,
  1510. dwInterval);
  1511. }
  1512. else
  1513. {
  1514. iItem = pUrl->AddListItem(
  1515. wszUrl,
  1516. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1517. pwszTypeBuffer,
  1518. dwInterval);
  1519. }
  1520. // Check the validity
  1521. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1522. pwszStatus = wszCertStatus(pCert, pAIACert);
  1523. pUrl->SetCursor(hPrevCur);
  1524. pUrl->UpdateListItemStatus(iItem, pwszStatus);
  1525. pObjInfo = new OBJECT_INFO;
  1526. if (NULL == pObjInfo)
  1527. {
  1528. _PrintError(E_OUTOFMEMORY, "new");
  1529. }
  1530. else
  1531. {
  1532. ZeroMemory(pObjInfo, sizeof(*pObjInfo));
  1533. pObjInfo->dwType = OBJECT_TYPE_CERT;
  1534. pObjInfo->pCert = CertDuplicateCertificateContext(pAIACert);
  1535. pUrl->UpdateListItemParam(iItem, (LPARAM) pObjInfo);
  1536. }
  1537. cert++;
  1538. }
  1539. fRet = TRUE;
  1540. error:
  1541. if (NULL != pwszTypeBuffer)
  1542. {
  1543. LocalFree(pwszTypeBuffer);
  1544. }
  1545. return fRet;
  1546. }
  1547. BOOL
  1548. RetrieveAndAddCDPUrlToList(
  1549. IN CUrlFetch *pUrl,
  1550. IN WCHAR const *pwszUrl,
  1551. IN DWORD iURL,
  1552. IN CERT_CONTEXT const *pCertIn,
  1553. OPTIONAL IN CERT_CONTEXT const *pCertIssuer,
  1554. IN CRL_CONTEXT const *pCRLIn)
  1555. {
  1556. HRESULT hr = S_OK;
  1557. BOOL fRet = FALSE;
  1558. int iItem = 0;
  1559. int iDCrlItem = 0;
  1560. HCERTSTORE hStore = NULL;
  1561. HCERTSTORE hDeltaStore = NULL;
  1562. CRL_CONTEXT const *pCRL = NULL;
  1563. CRL_CONTEXT const *pDCRL = NULL;
  1564. WCHAR wszUrl[MAX_URL_LEN];
  1565. WCHAR wszMsg[MAX_MSG_LEN];
  1566. DWORD cCRL;
  1567. DWORD cDCRL;
  1568. DWORD cURL;
  1569. DWORD dwIntStart;
  1570. DWORD dwIntEnd;
  1571. DWORD dwInterval;
  1572. OBJECT_INFO *pObjInfo = NULL;
  1573. CERT_CRL_CONTEXT_PAIR ContextPair;
  1574. CRYPT_URL_ARRAY *pCRLUrlArray = NULL;
  1575. DWORD cbCRLUrlArray;
  1576. OSVERSIONINFO OSInfo;
  1577. WCHAR const *pwszType;
  1578. WCHAR const *pwszTypeDelta;
  1579. DWORD iElement = 0;
  1580. HCURSOR hPrevCur;
  1581. DWORD cwc;
  1582. DWORD cwcDelta;
  1583. WCHAR *pwszTypeBuffer = NULL;
  1584. // Add the url to the list view with RETRIEVING status
  1585. s_levelURL++;
  1586. iItem = pUrl->AddListItem(
  1587. pwszUrl,
  1588. myLoadResourceString(IDS_STATUS_RETRIEVING), // "Retrieving"
  1589. myLoadResourceString(IDS_CDP_ITEM_TYPE), // "CDP"
  1590. 0);
  1591. // Attempt to retrieve the url
  1592. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1593. dwIntStart = GetTickCount();
  1594. if (!RetrieveCRLStore(pwszUrl, &hStore) || NULL == hStore)
  1595. {
  1596. hr = myHLastError();
  1597. pUrl->SetCursor(hPrevCur);
  1598. _PrintErrorStr(hr, "RetrieveCRLStore", pwszUrl);
  1599. // Modify the status of this URL on the list to FAILED
  1600. pUrl->UpdateListItemStatus(iItem, myLoadResourceString(IDS_STATUS_FAILURE)); // "Failed"
  1601. pObjInfo = new OBJECT_INFO;
  1602. if (NULL == pObjInfo)
  1603. {
  1604. _PrintError(E_OUTOFMEMORY, "new");
  1605. }
  1606. else
  1607. {
  1608. pObjInfo->dwType = OBJECT_TYPE_MSG;
  1609. pObjInfo->wszErrInfo[0] = L'\0';
  1610. FillErrorTextRetrieve(
  1611. pObjInfo->wszErrInfo,
  1612. ARRAYSIZE(pObjInfo->wszErrInfo),
  1613. hr);
  1614. pUrl->UpdateListItemParam(iItem, (LPARAM) pObjInfo);
  1615. }
  1616. // Retrieve the next item
  1617. goto error;
  1618. }
  1619. pUrl->SetCursor(hPrevCur);
  1620. // Calculate and update the interval
  1621. dwIntEnd = GetTickCount();
  1622. dwInterval = (dwIntEnd - dwIntStart) / 1000; // Interval in seconds
  1623. pUrl->UpdateListItemTime(iItem, dwInterval);
  1624. // Modify the status of this URL on the list to SUCCESS.
  1625. pUrl->UpdateListItemStatus(
  1626. iItem,
  1627. myLoadResourceString(IDS_STATUS_SUCCESS)); // "Success"
  1628. // If the CRL was successfully retrieved, then check it for
  1629. // a freshness distribution point extension either on the
  1630. // certificate or on the CRL
  1631. ZeroMemory(&ContextPair, sizeof(ContextPair));
  1632. ContextPair.pCertContext = pCertIn;
  1633. pwszType = myLoadResourceString(IDS_BASE_CRL_ITEM_TYPE); // "Base CRL"
  1634. if (NULL == pwszType)
  1635. {
  1636. pwszType = wszBASE_CRL_ITEM_TYPE;
  1637. }
  1638. pwszTypeDelta = myLoadResourceString(IDS_DELTA_CRL_ITEM_TYPE); // "Delta CRL"
  1639. if (NULL == pwszTypeDelta)
  1640. {
  1641. pwszTypeDelta = wszDELTA_CRL_ITEM_TYPE;
  1642. }
  1643. cwc = wcslen(pwszType);
  1644. cwcDelta = wcslen(pwszTypeDelta);
  1645. if (cwc < cwcDelta)
  1646. {
  1647. cwc = cwcDelta;
  1648. }
  1649. pwszTypeBuffer = (WCHAR *) LocalAlloc(
  1650. LMEM_FIXED,
  1651. (cwc + 2 + cwcDWORDSPRINTF + 2) * sizeof(WCHAR));
  1652. if (NULL == pwszTypeBuffer)
  1653. {
  1654. _JumpError(E_OUTOFMEMORY, error, "LocalAlloc");
  1655. }
  1656. cCRL = 0;
  1657. while (TRUE)
  1658. {
  1659. WCHAR const *pwszStatus;
  1660. BOOL fDelta;
  1661. DWORD CRLNumber;
  1662. pCRL = CertEnumCRLsInStore(hStore, pCRL);
  1663. if (NULL == pCRL)
  1664. {
  1665. break;
  1666. }
  1667. hr = cuSaveAsnToFile(
  1668. pCRL->pbCrlEncoded,
  1669. pCRL->cbCrlEncoded,
  1670. s_majorURL,
  1671. s_levelURL,
  1672. iElement++,
  1673. L".crl");
  1674. _PrintIfError(hr, "cuSaveAsnToFile");
  1675. hr = myIsDeltaCRL(pCRL, &fDelta);
  1676. _PrintIfError(hr, "myIsDeltaCRL");
  1677. if (S_OK != hr)
  1678. {
  1679. fDelta = NULL != pCRLIn;
  1680. }
  1681. // Add the CRL to the list, initially as OK
  1682. _snwprintf(
  1683. wszUrl,
  1684. ARRAYSIZE(wszUrl),
  1685. L"[%d.%d] %ws",
  1686. iURL,
  1687. cCRL,
  1688. pwszUrl);
  1689. wszUrl[ARRAYSIZE(wszUrl) - 1] = L'\0';
  1690. wcscpy(pwszTypeBuffer, fDelta? pwszTypeDelta : pwszType);
  1691. CRLNumber = myCRLNumber(pCRL);
  1692. if (0 != CRLNumber)
  1693. {
  1694. wsprintf(
  1695. &pwszTypeBuffer[wcslen(pwszTypeBuffer)],
  1696. L" (%u)",
  1697. CRLNumber);
  1698. }
  1699. if (0 == cCRL)
  1700. {
  1701. pUrl->UpdateListItem(
  1702. iItem,
  1703. wszUrl,
  1704. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1705. pwszTypeBuffer,
  1706. dwInterval);
  1707. }
  1708. else
  1709. {
  1710. iItem = pUrl->AddListItem(
  1711. wszUrl,
  1712. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1713. pwszTypeBuffer,
  1714. dwInterval);
  1715. }
  1716. // Check the CRL
  1717. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1718. pwszStatus = wszCRLStatus(pCertIssuer, pCertIn, NULL, pCRL);
  1719. pUrl->SetCursor(hPrevCur);
  1720. pUrl->UpdateListItemStatus(iItem, pwszStatus);
  1721. // Add the CRL to this param
  1722. pObjInfo = new OBJECT_INFO;
  1723. if (NULL == pObjInfo)
  1724. {
  1725. _PrintError(E_OUTOFMEMORY, "new");
  1726. }
  1727. else
  1728. {
  1729. ZeroMemory(pObjInfo, sizeof(*pObjInfo));
  1730. pObjInfo->dwType = OBJECT_TYPE_CRL;
  1731. pObjInfo->pCRL = CertDuplicateCRLContext(pCRL);
  1732. pUrl->UpdateListItemParam(iItem, (LPARAM) pObjInfo);
  1733. }
  1734. // Get any URLs from this CRL
  1735. ContextPair.pCrlContext = pCRL;
  1736. hr = GetObjectUrl(
  1737. URL_OID_CRL_FRESHEST_CRL, // Freshest CRL URLs: cert+CRL
  1738. (VOID *) &ContextPair,
  1739. CRYPT_GET_URL_FROM_EXTENSION,
  1740. &pCRLUrlArray,
  1741. &cbCRLUrlArray);
  1742. if (S_OK != hr)
  1743. {
  1744. _PrintError(hr, "GetObjectUrl");
  1745. // If this is Win2k, it does not support the freshest CRL
  1746. // extension, so we shouldn't return a failure.
  1747. ZeroMemory(&OSInfo, sizeof(OSInfo));
  1748. OSInfo.dwOSVersionInfoSize = sizeof(OSInfo);
  1749. if (GetVersionEx(&OSInfo))
  1750. {
  1751. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr &&
  1752. OSInfo.dwMajorVersion == 5 &&
  1753. OSInfo.dwMinorVersion == 0)
  1754. {
  1755. // ERROR_FILE_NOT_FOUND is returned when the ASN.1 handler
  1756. // for an extension does not exist.
  1757. continue;
  1758. }
  1759. }
  1760. FillErrorTextExtract(wszMsg, ARRAYSIZE(wszMsg), hr);
  1761. pUrl->DisplayMessageBox(
  1762. NULL,
  1763. wszMsg,
  1764. myLoadResourceString(IDS_GET_OBJECT_URL), // "GetObjectUrl"
  1765. MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  1766. pUrl->AddListItem(
  1767. NULL,
  1768. myLoadResourceString(IDS_STATUS_ERROR), // "Error"
  1769. myLoadResourceString(IDS_NO_ITEM_TYPE), // "None
  1770. 0);
  1771. goto error;
  1772. }
  1773. if (NULL == pCRLUrlArray)
  1774. {
  1775. continue; // No delta CRLs to retrieve
  1776. }
  1777. for (cURL = 0; cURL < pCRLUrlArray->cUrl; cURL++)
  1778. {
  1779. // Add this CRL to the list with proper index with
  1780. // RETRIEVING status
  1781. _snwprintf(
  1782. wszUrl,
  1783. ARRAYSIZE(wszUrl),
  1784. L"[%d.%d.%d] %ws",
  1785. iURL,
  1786. cURL,
  1787. cCRL,
  1788. pCRLUrlArray->rgwszUrl[cURL]);
  1789. wszUrl[ARRAYSIZE(wszUrl) - 1] = L'\0';
  1790. iDCrlItem = pUrl->AddListItem(
  1791. wszUrl,
  1792. myLoadResourceString(IDS_STATUS_RETRIEVING), // "Retrieving"
  1793. myLoadResourceString(IDS_CDP_ITEM_TYPE), // "CDP"
  1794. 0);
  1795. // Now attempt to retrieve the delta CRLs
  1796. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1797. dwIntStart = GetTickCount();
  1798. if (!RetrieveCRLStore(pCRLUrlArray->rgwszUrl[cURL], &hDeltaStore))
  1799. {
  1800. hr = myHLastError();
  1801. pUrl->SetCursor(hPrevCur);
  1802. _PrintErrorStr(hr, "RetrieveCRLStore", pCRLUrlArray->rgwszUrl[cURL]);
  1803. // Modify the status of this URL on the list to FAILED
  1804. pUrl->UpdateListItemStatus(
  1805. iDCrlItem,
  1806. myLoadResourceString(IDS_STATUS_FAILURE)); // "Failed"
  1807. pObjInfo = new OBJECT_INFO;
  1808. if (NULL == pObjInfo)
  1809. {
  1810. _PrintError(E_OUTOFMEMORY, "new");
  1811. }
  1812. else
  1813. {
  1814. pObjInfo->dwType = OBJECT_TYPE_MSG;
  1815. pObjInfo->wszErrInfo[0] = L'\0';
  1816. FillErrorTextRetrieve(
  1817. pObjInfo->wszErrInfo,
  1818. ARRAYSIZE(pObjInfo->wszErrInfo),
  1819. hr);
  1820. pUrl->UpdateListItemParam(iDCrlItem, (LPARAM) pObjInfo);
  1821. }
  1822. // Retrieve the next item
  1823. continue;
  1824. }
  1825. pUrl->SetCursor(hPrevCur);
  1826. // Calculate the retrieval interval and update the list view
  1827. dwIntEnd = GetTickCount();
  1828. dwInterval = (dwIntEnd - dwIntStart) / 1000;
  1829. pUrl->UpdateListItemTime(iDCrlItem, dwInterval);
  1830. // Update the list with SUCCESS status
  1831. pUrl->UpdateListItemStatus(
  1832. iDCrlItem,
  1833. myLoadResourceString(IDS_STATUS_SUCCESS)); // "Success"
  1834. // Update the individual items
  1835. cDCRL = 0;
  1836. while (TRUE)
  1837. {
  1838. DWORD CRLNumberDelta;
  1839. pDCRL = CertEnumCRLsInStore(hDeltaStore, pDCRL);
  1840. if (NULL == pDCRL)
  1841. {
  1842. break;
  1843. }
  1844. hr = cuSaveAsnToFile(
  1845. pDCRL->pbCrlEncoded,
  1846. pDCRL->cbCrlEncoded,
  1847. s_majorURL,
  1848. s_levelURL,
  1849. iElement++,
  1850. L".crl");
  1851. _PrintIfError(hr, "cuSaveAsnToFile");
  1852. // Add the CRL to the list, initially as OK
  1853. _snwprintf(
  1854. wszUrl,
  1855. ARRAYSIZE(wszUrl),
  1856. L"[%d.%d.%d] %ws",
  1857. iURL,
  1858. cDCRL,
  1859. cURL,
  1860. pCRLUrlArray->rgwszUrl[cURL]);
  1861. wszUrl[ARRAYSIZE(wszUrl) - 1] = L'\0';
  1862. wcscpy(pwszTypeBuffer, pwszTypeDelta);
  1863. CRLNumber = myCRLNumber(pCRL);
  1864. if (0 != CRLNumber)
  1865. {
  1866. wsprintf(&pwszTypeBuffer[cwcDelta], L" (%u)", CRLNumber);
  1867. }
  1868. if (0 == cDCRL)
  1869. {
  1870. pUrl->UpdateListItem(
  1871. iDCrlItem,
  1872. wszUrl,
  1873. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1874. pwszTypeBuffer,
  1875. dwInterval);
  1876. }
  1877. else
  1878. {
  1879. iDCrlItem = pUrl->AddListItem(
  1880. wszUrl,
  1881. myLoadResourceString(IDS_STATUS_VERIFYING), // "Verifying"
  1882. pwszTypeBuffer,
  1883. dwInterval);
  1884. }
  1885. // Check the CRL
  1886. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1887. pwszStatus = wszCRLStatus(pCertIssuer, pCertIn, pCRL, pDCRL);
  1888. pUrl->SetCursor(hPrevCur);
  1889. pUrl->UpdateListItemStatus(iDCrlItem, pwszStatus);
  1890. // Re-using the same object, but that's OK since
  1891. // we store it in the list
  1892. pObjInfo = new OBJECT_INFO;
  1893. if (NULL == pObjInfo)
  1894. {
  1895. _PrintError(E_OUTOFMEMORY, "new");
  1896. }
  1897. else
  1898. {
  1899. ZeroMemory(pObjInfo, sizeof(*pObjInfo));
  1900. pObjInfo->dwType = OBJECT_TYPE_CRL;
  1901. pObjInfo->pCRL = CertDuplicateCRLContext(pDCRL);
  1902. pUrl->UpdateListItemParam(iDCrlItem, (LPARAM) pObjInfo);
  1903. }
  1904. cDCRL++;
  1905. }
  1906. }
  1907. cCRL++;
  1908. }
  1909. fRet = TRUE;
  1910. error:
  1911. if (NULL != pwszTypeBuffer)
  1912. {
  1913. LocalFree(pwszTypeBuffer);
  1914. }
  1915. if (NULL != pCRLUrlArray)
  1916. {
  1917. LocalFree(pCRLUrlArray);
  1918. }
  1919. return(fRet);
  1920. }
  1921. DWORD WINAPI
  1922. CDPThreadProc(
  1923. IN VOID *pvParam)
  1924. {
  1925. HRESULT hr;
  1926. DWORD dwRet = 0;
  1927. CRYPT_URL_ARRAY *pUrlArray = NULL;
  1928. DWORD cbUrlArray;
  1929. DWORD cURL;
  1930. WCHAR wszMsg[MAX_MSG_LEN];
  1931. THREAD_INFO *pThreadInfo = (THREAD_INFO *) pvParam;
  1932. CERT_CONTEXT const *pCertIssuer;
  1933. CERT_CHAIN_PARA ChainParams;
  1934. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  1935. HCURSOR hPrevCur;
  1936. CUrlFetch *pUrl = pThreadInfo->m_pUrl;
  1937. // First retrieve the base URLs
  1938. if (NULL != pThreadInfo->m_pCRL)
  1939. {
  1940. CERT_CRL_CONTEXT_PAIR ContextPair;
  1941. // Get any URLs from this CRL
  1942. ContextPair.pCertContext = pThreadInfo->m_pCert;
  1943. ContextPair.pCrlContext = pThreadInfo->m_pCRL;
  1944. hr = GetObjectUrl(
  1945. URL_OID_CRL_FRESHEST_CRL, // Freshest CRL URLs: cert+CRL
  1946. (VOID *) &ContextPair,
  1947. CRYPT_GET_URL_FROM_EXTENSION,
  1948. &pUrlArray,
  1949. &cbUrlArray);
  1950. _PrintIfError(hr, "GetObjectUrl");
  1951. }
  1952. else
  1953. {
  1954. hr = GetObjectUrl(
  1955. URL_OID_CERTIFICATE_CRL_DIST_POINT, // CDP URLs: cert
  1956. (VOID *) pThreadInfo->m_pCert,
  1957. CRYPT_GET_URL_FROM_EXTENSION,
  1958. &pUrlArray,
  1959. &cbUrlArray);
  1960. _PrintIfError(hr, "GetObjectUrl");
  1961. }
  1962. if (S_OK != hr)
  1963. {
  1964. FillErrorTextExtract(wszMsg, ARRAYSIZE(wszMsg), hr);
  1965. pUrl->DisplayMessageBox(
  1966. NULL,
  1967. wszMsg,
  1968. myLoadResourceString(IDS_GET_OBJECT_URL), // "GetObjectUrl"
  1969. MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  1970. pUrl->AddListItem(
  1971. NULL,
  1972. myLoadResourceString(IDS_STATUS_ERROR), // "Error"
  1973. myLoadResourceString(IDS_NO_ITEM_TYPE), // "None"
  1974. 0);
  1975. _JumpError(hr, error, "GetObjectUrl");
  1976. }
  1977. if (NULL == pUrlArray)
  1978. {
  1979. dwRet = 1; // Nothing to retrieve
  1980. pUrl->AddListItem(
  1981. NULL,
  1982. myLoadResourceString(IDS_STATUS_NO_RETRIEVAL), // "No URLs"
  1983. myLoadResourceString(IDS_NO_ITEM_TYPE), // "None"
  1984. 0);
  1985. goto error;
  1986. }
  1987. // Build the chain to get the issuer cert
  1988. ZeroMemory(&ChainParams, sizeof(ChainParams));
  1989. ChainParams.cbSize = sizeof(ChainParams);
  1990. hPrevCur = pUrl->SetCursor(LoadCursor(NULL, IDC_WAIT));
  1991. pCertIssuer = NULL;
  1992. if (NULL != pThreadInfo->m_pCert)
  1993. {
  1994. if (!CertGetCertificateChain(
  1995. HCCE_LOCAL_MACHINE,
  1996. pThreadInfo->m_pCert, // pCertContext
  1997. NULL, // pTime
  1998. NULL, // hAdditionalStore
  1999. &ChainParams, // pChainPara
  2000. 0, // dwFlags
  2001. NULL, // pvReserved
  2002. &pChainContext)) // ppChainContext
  2003. {
  2004. hr = myHLastError();
  2005. _PrintError(hr, "CertGetCertificateChain");
  2006. }
  2007. else
  2008. if (0 < pChainContext->cChain &&
  2009. 1 < pChainContext->rgpChain[0]->cElement)
  2010. {
  2011. pCertIssuer = pChainContext->rgpChain[0]->rgpElement[1]->pCertContext;
  2012. }
  2013. }
  2014. pUrl->SetCursor(hPrevCur);
  2015. for (cURL = 0; cURL < pUrlArray->cUrl; cURL++)
  2016. {
  2017. if (!RetrieveAndAddCDPUrlToList(
  2018. pThreadInfo->m_pUrl,
  2019. pUrlArray->rgwszUrl[cURL],
  2020. cURL,
  2021. pThreadInfo->m_pCert,
  2022. pCertIssuer,
  2023. pThreadInfo->m_pCRL))
  2024. {
  2025. // Do nothing right now
  2026. }
  2027. }
  2028. dwRet = 1;
  2029. error:
  2030. pThreadInfo->m_pUrl->Display();
  2031. if (NULL != pChainContext)
  2032. {
  2033. CertFreeCertificateChain(pChainContext);
  2034. }
  2035. if (NULL != pUrlArray)
  2036. {
  2037. LocalFree(pUrlArray);
  2038. }
  2039. delete pThreadInfo; // Because it was allocated
  2040. return(dwRet);
  2041. }
  2042. DWORD WINAPI
  2043. CertThreadProc(
  2044. IN VOID *pvParam)
  2045. {
  2046. HRESULT hr;
  2047. DWORD dwRet = 0;
  2048. CRYPT_URL_ARRAY *pCertUrlArray = NULL;
  2049. DWORD cbCertUrlArray = 0;
  2050. DWORD cURL;
  2051. WCHAR wszMsg[MAX_MSG_LEN];
  2052. THREAD_INFO *pThreadInfo = (THREAD_INFO *) pvParam;
  2053. BYTE *pbHashes = NULL;
  2054. DWORD cHashes;
  2055. CUrlFetch *pUrl = pThreadInfo->m_pUrl;
  2056. // First retrieve the AIA URLs
  2057. hr = GetObjectUrl(
  2058. URL_OID_CERTIFICATE_ISSUER, // AIA URLs: Cert
  2059. (VOID *) pThreadInfo->m_pCert,
  2060. CRYPT_GET_URL_FROM_EXTENSION,
  2061. &pCertUrlArray,
  2062. &cbCertUrlArray);
  2063. if (S_OK != hr)
  2064. {
  2065. FillErrorTextExtract(wszMsg, ARRAYSIZE(wszMsg), hr);
  2066. pUrl->DisplayMessageBox(
  2067. NULL,
  2068. wszMsg,
  2069. myLoadResourceString(IDS_GET_OBJECT_URL), // "GetObjectUrl"
  2070. MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  2071. pUrl->AddListItem(
  2072. NULL,
  2073. myLoadResourceString(IDS_STATUS_ERROR), // "Error"
  2074. myLoadResourceString(IDS_NO_ITEM_TYPE), // "None"
  2075. 0);
  2076. _JumpError(hr, error, "GetObjectUrl");
  2077. }
  2078. if (NULL == pCertUrlArray)
  2079. {
  2080. dwRet = 1; // Nothing to retrieve
  2081. pUrl->AddListItem(
  2082. NULL,
  2083. myLoadResourceString(IDS_STATUS_NO_RETRIEVAL), // "No URLs"
  2084. myLoadResourceString(IDS_NO_ITEM_TYPE), // "None"
  2085. 0);
  2086. goto error;
  2087. }
  2088. cHashes = 0;
  2089. for (cURL = 0; cURL < pCertUrlArray->cUrl; cURL++)
  2090. {
  2091. if (!RetrieveAndAddAIAUrlToList(
  2092. pThreadInfo->m_pUrl,
  2093. pThreadInfo->m_pCert,
  2094. pCertUrlArray->rgwszUrl[cURL],
  2095. cURL,
  2096. &pbHashes,
  2097. &cHashes))
  2098. {
  2099. // Do nothing right now
  2100. }
  2101. }
  2102. dwRet = 1;
  2103. error:
  2104. pThreadInfo->m_pUrl->Display();
  2105. if (NULL != pbHashes)
  2106. {
  2107. LocalFree(pbHashes);
  2108. }
  2109. if (NULL != pCertUrlArray)
  2110. {
  2111. LocalFree(pCertUrlArray);
  2112. }
  2113. delete pThreadInfo; // Because it was allocated in the calling thread
  2114. return dwRet;
  2115. }
  2116. VOID
  2117. RetrieveCDPUrlsFromCertOrCRL(
  2118. OPTIONAL IN CERT_CONTEXT const *pCert,
  2119. OPTIONAL IN CRL_CONTEXT const *pCRL,
  2120. IN HWND hwndList)
  2121. {
  2122. HRESULT hr;
  2123. DWORD dwThreadId;
  2124. HANDLE hThread = NULL;
  2125. THREAD_INFO *pThreadInfo = NULL;
  2126. pThreadInfo = new THREAD_INFO;
  2127. if (NULL == pThreadInfo)
  2128. {
  2129. _JumpError(E_OUTOFMEMORY, error, "new");
  2130. }
  2131. ZeroMemory(pThreadInfo, sizeof(*pThreadInfo));
  2132. pThreadInfo->m_pCert = pCert;
  2133. pThreadInfo->m_pCRL = pCRL;
  2134. pThreadInfo->m_pUrl = (CUrlFetch *) new CUrlFetchDialog(hwndList);
  2135. if (NULL == pThreadInfo->m_pUrl)
  2136. {
  2137. _JumpError(E_OUTOFMEMORY, error, "new");
  2138. }
  2139. hThread = CreateThread(
  2140. NULL,
  2141. 0,
  2142. CDPThreadProc,
  2143. (VOID *) pThreadInfo,
  2144. 0,
  2145. &dwThreadId);
  2146. if (NULL == hThread)
  2147. {
  2148. hr = myHLastError();
  2149. _JumpError(hr, error, "CreateThread");
  2150. }
  2151. pThreadInfo = NULL;
  2152. error:
  2153. delete pThreadInfo;
  2154. return;
  2155. }
  2156. VOID
  2157. RetrieveAIAUrlsFromCert(
  2158. IN CERT_CONTEXT const *pCert,
  2159. IN HWND hwndList)
  2160. {
  2161. HRESULT hr;
  2162. DWORD dwThreadId;
  2163. HANDLE hThread = NULL;
  2164. THREAD_INFO *pThreadInfo = NULL;
  2165. pThreadInfo = new THREAD_INFO;
  2166. if (NULL == pThreadInfo)
  2167. {
  2168. _JumpError(E_OUTOFMEMORY, error, "new");
  2169. }
  2170. ZeroMemory(pThreadInfo, sizeof(*pThreadInfo));
  2171. pThreadInfo->m_pCert = pCert;
  2172. pThreadInfo->m_pUrl = (CUrlFetch *) new CUrlFetchDialog(hwndList);
  2173. if (NULL == pThreadInfo->m_pUrl)
  2174. {
  2175. _JumpError(E_OUTOFMEMORY, error, "new");
  2176. }
  2177. hThread = CreateThread(
  2178. NULL,
  2179. 0,
  2180. CertThreadProc,
  2181. (VOID *) pThreadInfo,
  2182. 0,
  2183. &dwThreadId);
  2184. if (NULL == hThread)
  2185. {
  2186. hr = myHLastError();
  2187. _JumpError(hr, error, "CreateThread");
  2188. }
  2189. pThreadInfo = NULL;
  2190. error:
  2191. delete pThreadInfo;
  2192. return;
  2193. }
  2194. VOID
  2195. cuDisplayCDPUrlsFromCertOrCRL(
  2196. OPTIONAL IN CERT_CONTEXT const *pCert,
  2197. OPTIONAL IN CRL_CONTEXT const *pCRL)
  2198. {
  2199. HRESULT hr;
  2200. DWORD dwThreadId;
  2201. HANDLE hThread = NULL;
  2202. THREAD_INFO *pThreadInfo = NULL;
  2203. s_majorURL++;
  2204. s_levelURL = 1;
  2205. pThreadInfo = new THREAD_INFO;
  2206. if (NULL == pThreadInfo)
  2207. {
  2208. _JumpError(E_OUTOFMEMORY, error, "new");
  2209. }
  2210. ZeroMemory(pThreadInfo, sizeof(*pThreadInfo));
  2211. pThreadInfo->m_pCert = pCert;
  2212. pThreadInfo->m_pCRL = pCRL;
  2213. pThreadInfo->m_pUrl = (CUrlFetch *) new CUrlFetchConsole();
  2214. if (NULL == pThreadInfo->m_pUrl)
  2215. {
  2216. _JumpError(E_OUTOFMEMORY, error, "new");
  2217. }
  2218. CDPThreadProc(pThreadInfo);
  2219. pThreadInfo = NULL;
  2220. error:
  2221. delete pThreadInfo;
  2222. return;
  2223. }
  2224. VOID
  2225. cuDisplayAIAUrlsFromCert(
  2226. IN CERT_CONTEXT const *pCert)
  2227. {
  2228. HRESULT hr;
  2229. DWORD dwThreadId;
  2230. HANDLE hThread = NULL;
  2231. THREAD_INFO *pThreadInfo = NULL;
  2232. s_majorURL++;
  2233. s_levelURL = 1;
  2234. pThreadInfo = new THREAD_INFO;
  2235. if (NULL == pThreadInfo)
  2236. {
  2237. _JumpError(E_OUTOFMEMORY, error, "new");
  2238. }
  2239. ZeroMemory(pThreadInfo, sizeof(*pThreadInfo));
  2240. pThreadInfo->m_pCert = pCert;
  2241. pThreadInfo->m_pUrl = (CUrlFetch *) new CUrlFetchConsole();
  2242. if (NULL == pThreadInfo->m_pUrl)
  2243. {
  2244. _JumpError(E_OUTOFMEMORY, error, "new");
  2245. }
  2246. CertThreadProc(pThreadInfo);
  2247. pThreadInfo = NULL;
  2248. error:
  2249. delete pThreadInfo;
  2250. return;
  2251. }
  2252. // Update the certificate or CRL name
  2253. VOID
  2254. UpdateCertOrCRLState(
  2255. IN HWND hDlg,
  2256. OPTIONAL IN CERT_CONTEXT const *pCert,
  2257. OPTIONAL IN CRL_CONTEXT const *pCRL)
  2258. {
  2259. HRESULT hr;
  2260. WCHAR *pwszSimpleName = NULL;
  2261. WCHAR const *pwszType;
  2262. hr = GetSimpleName(pCert, pCRL, &pwszSimpleName);
  2263. _PrintIfError(hr, "GetSimpleName");
  2264. if (NULL != pCRL)
  2265. {
  2266. pwszType = myLoadResourceString(IDS_BASE_CRL_ISSUER); // "Base CRL Issuer"
  2267. if (NULL != CertFindExtension(
  2268. szOID_DELTA_CRL_INDICATOR,
  2269. pCRL->pCrlInfo->cExtension,
  2270. pCRL->pCrlInfo->rgExtension))
  2271. {
  2272. pwszType = myLoadResourceString(IDS_DELTA_CRL_ISSUER); // "Delta CRL Issuer"
  2273. }
  2274. }
  2275. else
  2276. {
  2277. pwszType = myLoadResourceString(IDS_CERT_SUBJECT); // "Certificate Subject"
  2278. }
  2279. SetDlgItemText(hDlg, IDC_SUBJECTTYPE, pwszType);
  2280. SetDlgItemText(hDlg, IDC_SIMPLENAME, pwszSimpleName);
  2281. if (NULL != pCRL)
  2282. {
  2283. SendMessage(
  2284. GetDlgItem(hDlg, IDC_RETRIEVECRLS),
  2285. BM_SETCHECK,
  2286. (WPARAM) TRUE,
  2287. (LPARAM) 0);
  2288. SendMessage(
  2289. GetDlgItem(hDlg, IDC_RETRIEVECERTS),
  2290. BM_SETCHECK,
  2291. (WPARAM) FALSE,
  2292. (LPARAM) 0);
  2293. }
  2294. EnableWindow(GetDlgItem(hDlg, IDC_RETRIEVECERTS), NULL == pCRL);
  2295. // Enable the retrieve button
  2296. EnableWindow(GetDlgItem(hDlg, IDC_RETRIEVE), TRUE);
  2297. if (NULL != pwszSimpleName)
  2298. {
  2299. LocalFree(pwszSimpleName);
  2300. }
  2301. }
  2302. INT_PTR CALLBACK
  2303. DlgProc(
  2304. HWND hDlg,
  2305. UINT msg,
  2306. WPARAM wParam,
  2307. LPARAM lParam)
  2308. {
  2309. HRESULT hr;
  2310. HWND hwndList = NULL;
  2311. HWND hwndView = NULL;
  2312. NMHDR *lpnm = NULL;
  2313. LVCOLUMN col;
  2314. LVITEM item;
  2315. OBJECT_INFO *pObjInfo = NULL;
  2316. WCHAR wszUrl[MAX_URL_LEN];
  2317. switch (msg)
  2318. {
  2319. case WM_INITDIALOG:
  2320. // Initialize the controls
  2321. hwndList = GetDlgItem(hDlg, IDC_URLLIST);
  2322. ListView_DeleteAllItems(hwndList);
  2323. ZeroMemory(&col, sizeof(col));
  2324. // Add the status column
  2325. col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH |
  2326. LVCF_ORDER;
  2327. col.fmt = LVCFMT_LEFT;
  2328. col.pszText = const_cast<WCHAR *>(myLoadResourceString(IDS_STATUS_COLUMN)); // "Status"
  2329. col.iSubItem = LIST_STATUS_SUBITEM;
  2330. col.cx = 60;
  2331. col.iOrder = LIST_STATUS_SUBITEM - 1;
  2332. ListView_InsertColumn(hwndList, 0, &col);
  2333. // Add the type column
  2334. col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH |
  2335. LVCF_ORDER;
  2336. col.fmt = LVCFMT_LEFT;
  2337. col.pszText = const_cast<WCHAR *>(myLoadResourceString(IDS_TYPE_COLUMN)); // "Type"
  2338. col.iSubItem = LIST_TYPE_SUBITEM;
  2339. col.cx = 80;
  2340. col.iOrder = LIST_TYPE_SUBITEM - 1;
  2341. ListView_InsertColumn(hwndList, 1, &col);
  2342. // Add the url column
  2343. col.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER;
  2344. col.pszText = const_cast<WCHAR *>(myLoadResourceString(IDS_URL_COLUMN)); // "Url"
  2345. col.iSubItem = LIST_URL_SUBITEM;
  2346. col.cx = 350;
  2347. col.iOrder = LIST_URL_SUBITEM - 1;
  2348. ListView_InsertColumn(hwndList, 2, &col);
  2349. // Add the retrieval time column
  2350. col.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER;
  2351. col.pszText = const_cast<WCHAR *>(myLoadResourceString(IDS_TIME_COLUMN)); // "Retrieval Time"
  2352. col.iSubItem = LIST_TIME_SUBITEM;
  2353. col.cx = 80;
  2354. col.iOrder = LIST_TIME_SUBITEM - 1;
  2355. ListView_InsertColumn(hwndList, 3, &col);
  2356. // Update the certificate name
  2357. SetDlgItemText(hDlg, IDC_SIMPLENAME, myLoadResourceString(IDS_NO_SELECTION)); // "No Selection"
  2358. // Set the control style
  2359. SendDlgItemMessageA(
  2360. hDlg,
  2361. IDC_URLLIST,
  2362. LVM_SETEXTENDEDLISTVIEWSTYLE,
  2363. 0,
  2364. LVS_EX_FULLROWSELECT);
  2365. // Set the default retrieval option to CRLs
  2366. CheckDlgButton(hDlg, IDC_RETRIEVECRLS, BST_CHECKED);
  2367. // Disable the cross-cert radio button
  2368. EnableWindow(GetDlgItem(hDlg, IDC_RETRIEVECROSSCERTS), FALSE);
  2369. // Disable the retrieval button until a cert is selected
  2370. EnableWindow(GetDlgItem(hDlg, IDC_RETRIEVE), FALSE);
  2371. // Set the default timeout value
  2372. SetDlgItemInt(hDlg, IDC_TIMEOUT, DEF_TIMEOUT, FALSE);
  2373. // Clear the LDAP_SIGN flag
  2374. CheckDlgButton(hDlg, IDC_CHK_LDAPSIGN, BST_UNCHECKED);
  2375. // If an ULR was specified, set the text
  2376. if (NULL != g_pwszUrl)
  2377. {
  2378. SetDlgItemText(hDlg, IDC_DOWNLOADURL, g_pwszUrl);
  2379. }
  2380. // If a certificate was specified, update the dialog
  2381. SetDlgItemText(hDlg, IDC_SUBJECTTYPE, L"");
  2382. if (NULL != g_pCert || NULL != g_pCRL)
  2383. {
  2384. // Update the certificate or CRL name
  2385. UpdateCertOrCRLState(hDlg, g_pCert, g_pCRL);
  2386. }
  2387. return TRUE;
  2388. case WM_COMMAND:
  2389. switch (LOWORD(wParam))
  2390. {
  2391. case IDCANCEL:
  2392. EndDialog(hDlg, 0);
  2393. break;
  2394. case IDC_SELECT:
  2395. if (NULL != g_pwszFile)
  2396. {
  2397. LocalFree(g_pwszFile);
  2398. g_pwszFile = NULL;
  2399. }
  2400. hr = myGetOpenFileName(
  2401. hDlg,
  2402. NULL, // hInstance
  2403. IDS_URL_OPEN_TITLE,
  2404. IDS_URL_FILE_FILTER,
  2405. IDS_URL_DEFAULT_EXT,
  2406. OFN_PATHMUSTEXIST |
  2407. OFN_FILEMUSTEXIST |
  2408. OFN_HIDEREADONLY,
  2409. NULL, // no default file
  2410. &g_pwszFile);
  2411. _PrintIfError(hr, "myGetOpenFileName");
  2412. if (S_OK == hr && NULL == g_pwszFile)
  2413. {
  2414. // canceled: see public\sdk\inc\cderr.h for real
  2415. // CommDlgExtendedError errors
  2416. hr = myHError(CommDlgExtendedError());
  2417. if (S_OK == hr)
  2418. {
  2419. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2420. }
  2421. }
  2422. _PrintIfError(hr, "myGetOpenFileName");
  2423. if (S_OK == hr)
  2424. {
  2425. // Load the cert or CRL into memory
  2426. if (NULL != g_pCert || NULL != g_pCRL)
  2427. {
  2428. if (NULL != g_pCert)
  2429. {
  2430. CertFreeCertificateContext(g_pCert);
  2431. g_pCert = NULL;
  2432. }
  2433. if (NULL != g_pCRL)
  2434. {
  2435. CertFreeCRLContext(g_pCRL);
  2436. g_pCRL = NULL;
  2437. }
  2438. ListView_DeleteAllItems(
  2439. GetDlgItem(hDlg, IDC_URLLIST));
  2440. SetDlgItemText(
  2441. hDlg,
  2442. IDC_SIMPLENAME,
  2443. myLoadResourceString(IDS_NO_CERT_SELECTED)); // "No Certificate Selected"
  2444. }
  2445. hr = ReadCertOrCRLFromFile(
  2446. g_pwszFile,
  2447. &g_pCert,
  2448. &g_pCRL);
  2449. if (S_OK != hr)
  2450. {
  2451. MessageBox(
  2452. hDlg,
  2453. myLoadResourceString(IDS_OPEN_FILE_ERROR), // "Error Opening Certificate or CRL File"
  2454. myLoadResourceString(IDS_SELECT_CERT_OR_CRL), // "Select Certificate or CRL"
  2455. MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  2456. break;
  2457. }
  2458. // Update the certificate or CRL name
  2459. UpdateCertOrCRLState(hDlg, g_pCert, g_pCRL);
  2460. }
  2461. break;
  2462. case IDC_RETRIEVE:
  2463. if (BN_CLICKED == HIWORD(wParam))
  2464. {
  2465. // Clear the list
  2466. ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_URLLIST));
  2467. s_majorURL++;
  2468. s_levelURL = 1;
  2469. // Set the current timeout
  2470. g_dwTimeout = (DWORD) (GetDlgItemInt(
  2471. hDlg,
  2472. IDC_TIMEOUT,
  2473. NULL,
  2474. FALSE) * 1000);
  2475. // Get the currently selected item
  2476. if (IsDlgButtonChecked(hDlg, IDC_RETRIEVECERTS))
  2477. {
  2478. // Retrieve URLs from the cert
  2479. if (NULL != g_pCert)
  2480. {
  2481. // Retrieve the list of URLs
  2482. RetrieveAIAUrlsFromCert(
  2483. g_pCert,
  2484. GetDlgItem(hDlg, IDC_URLLIST));
  2485. }
  2486. // Or simply retrieve one URL
  2487. if (0 != GetDlgItemText(
  2488. hDlg,
  2489. IDC_DOWNLOADURL,
  2490. wszUrl,
  2491. ARRAYSIZE(wszUrl)))
  2492. {
  2493. CUrlFetch *pUrl = (CUrlFetch *) new CUrlFetchDialog(GetDlgItem(hDlg, IDC_URLLIST));
  2494. if (NULL == pUrl)
  2495. {
  2496. _PrintError(E_OUTOFMEMORY, "new");
  2497. }
  2498. else
  2499. {
  2500. RetrieveAndAddAIAUrlToList(
  2501. pUrl,
  2502. NULL,
  2503. wszUrl,
  2504. 0,
  2505. NULL,
  2506. NULL);
  2507. delete pUrl;
  2508. }
  2509. }
  2510. }
  2511. else if (IsDlgButtonChecked(hDlg, IDC_RETRIEVECRLS))
  2512. {
  2513. // Retrieve URLs from the cert
  2514. if (NULL != g_pCert || NULL != g_pCRL)
  2515. {
  2516. // Retrieve the list of URLs
  2517. RetrieveCDPUrlsFromCertOrCRL(
  2518. g_pCert,
  2519. g_pCRL,
  2520. GetDlgItem(hDlg, IDC_URLLIST));
  2521. }
  2522. // Or simply retrieve one URL
  2523. if (0 != GetDlgItemText(
  2524. hDlg,
  2525. IDC_DOWNLOADURL,
  2526. wszUrl,
  2527. ARRAYSIZE(wszUrl)))
  2528. {
  2529. CUrlFetch *pUrl = (CUrlFetch *) new CUrlFetchDialog(GetDlgItem(hDlg, IDC_URLLIST));
  2530. if (NULL == pUrl)
  2531. {
  2532. _PrintError(E_OUTOFMEMORY, "new");
  2533. }
  2534. else
  2535. {
  2536. RetrieveAndAddCDPUrlToList(
  2537. pUrl,
  2538. wszUrl,
  2539. 0,
  2540. g_pCert,
  2541. NULL,
  2542. g_pCRL);
  2543. delete pUrl;
  2544. }
  2545. }
  2546. }
  2547. }
  2548. break;
  2549. case IDC_DOWNLOADURL:
  2550. if (EN_CHANGE == HIWORD(wParam))
  2551. {
  2552. if (0 != GetDlgItemText(
  2553. hDlg,
  2554. IDC_DOWNLOADURL,
  2555. wszUrl,
  2556. ARRAYSIZE(wszUrl)))
  2557. {
  2558. EnableWindow(GetDlgItem(hDlg, IDC_RETRIEVE), TRUE);
  2559. }
  2560. else
  2561. {
  2562. if (NULL == g_pCert && NULL == g_pCRL)
  2563. {
  2564. EnableWindow(
  2565. GetDlgItem(hDlg, IDC_RETRIEVE),
  2566. FALSE);
  2567. }
  2568. }
  2569. }
  2570. break;
  2571. case IDC_CHK_LDAPSIGN:
  2572. if (IsDlgButtonChecked(hDlg, IDC_CHK_LDAPSIGN))
  2573. {
  2574. g_dwRetrievalFlags |= CRYPT_LDAP_SIGN_RETRIEVAL;
  2575. }
  2576. else if (g_dwRetrievalFlags != 0)
  2577. {
  2578. g_dwRetrievalFlags &= ~CRYPT_LDAP_SIGN_RETRIEVAL;
  2579. }
  2580. break;
  2581. default:
  2582. break;
  2583. }
  2584. case WM_NOTIFY:
  2585. switch (wParam)
  2586. {
  2587. case IDC_URLLIST:
  2588. lpnm = (NMHDR *) lParam;
  2589. switch (lpnm->code)
  2590. {
  2591. case LVN_ITEMACTIVATE:
  2592. // Display it
  2593. ZeroMemory(&item, sizeof(item));
  2594. item.mask = LVIF_PARAM;
  2595. item.iItem = ((NMITEMACTIVATE *) lParam)->iItem;
  2596. if (ListView_GetItem(
  2597. ((NMITEMACTIVATE *) lParam)->hdr.hwndFrom,
  2598. &item))
  2599. {
  2600. if (NULL != item.lParam)
  2601. {
  2602. pObjInfo = (OBJECT_INFO *) item.lParam;
  2603. switch (pObjInfo->dwType)
  2604. {
  2605. case OBJECT_TYPE_CERT:
  2606. ViewCertificate(
  2607. pObjInfo->pCert,
  2608. myLoadResourceString(IDS_CERTIFICATE)); // "Certificate"
  2609. break;
  2610. case OBJECT_TYPE_CRL:
  2611. ViewCrl(pObjInfo->pCRL, myLoadResourceString(IDS_CRL)); // "CRL"
  2612. break;
  2613. case OBJECT_TYPE_MSG:
  2614. MessageBox(
  2615. hDlg,
  2616. pObjInfo->wszErrInfo,
  2617. myLoadResourceString(IDS_ERROR_INFO), // "Error Information"
  2618. MB_OK);
  2619. break;
  2620. }
  2621. }
  2622. }
  2623. break;
  2624. case LVN_DELETEITEM:
  2625. ZeroMemory(&item, sizeof(item));
  2626. item.mask = LVIF_PARAM;
  2627. item.iItem = ((NMLISTVIEW *) lParam)->iItem;
  2628. if (ListView_GetItem(
  2629. ((NMLISTVIEW *) lParam)->hdr.hwndFrom,
  2630. &item))
  2631. {
  2632. if (NULL != item.lParam)
  2633. {
  2634. pObjInfo = (OBJECT_INFO *) item.lParam;
  2635. switch (pObjInfo->dwType)
  2636. {
  2637. case OBJECT_TYPE_CERT:
  2638. CertFreeCertificateContext(pObjInfo->pCert);
  2639. break;
  2640. case OBJECT_TYPE_CRL:
  2641. CertFreeCRLContext(pObjInfo->pCRL);
  2642. break;
  2643. }
  2644. delete pObjInfo;
  2645. }
  2646. }
  2647. break;
  2648. default:
  2649. break;
  2650. }
  2651. break;
  2652. default:
  2653. break;
  2654. }
  2655. break;
  2656. default:
  2657. break;
  2658. }
  2659. return FALSE;
  2660. }
  2661. //+-------------------------------------------------------------------------
  2662. //
  2663. // IsInternetUrlProtocol -- Checks the protocol portion of the URL and returns
  2664. // TRUE if the protocol is an Internet protocol (http, https, ftp, ldap,
  2665. // mailto, file) and FALSE if it is not.
  2666. //
  2667. //--------------------------------------------------------------------------
  2668. BOOL
  2669. IsInternetUrlProtocol(
  2670. IN WCHAR const *pwszUrl)
  2671. {
  2672. BOOL fRet = FALSE;
  2673. // If NULL, just return FALSE
  2674. if (NULL == pwszUrl)
  2675. {
  2676. goto error;
  2677. }
  2678. // Compare the first few characters to see if they pertain to an Internet
  2679. // protocol
  2680. if (0 == _wcsnicmp(pwszUrl, L"http:", wcslen(L"http:")) ||
  2681. 0 == _wcsnicmp(pwszUrl, L"https:", wcslen(L"https:")) ||
  2682. 0 == _wcsnicmp(pwszUrl, L"ftp:", wcslen(L"ftp:")) ||
  2683. 0 == _wcsnicmp(pwszUrl, L"ldap:", wcslen(L"ldap:")) ||
  2684. 0 == _wcsnicmp(pwszUrl, L"mailto:", wcslen(L"mailto:")) ||
  2685. 0 == _wcsnicmp(pwszUrl, L"file:", wcslen(L"file:")))
  2686. {
  2687. // It's an allowable Internet URL protocol
  2688. fRet = TRUE;
  2689. }
  2690. error:
  2691. return fRet;
  2692. }
  2693. HRESULT
  2694. verbURL(
  2695. IN WCHAR const *pwszOption,
  2696. IN WCHAR const *pwszFileOrURL,
  2697. IN WCHAR const *pwszArg2,
  2698. IN WCHAR const *pwszArg3,
  2699. IN WCHAR const *pwszArg4)
  2700. {
  2701. HRESULT hr;
  2702. INT_PTR nDlg = 0;
  2703. INITCOMMONCONTROLSEX Init;
  2704. HINSTANCE hInstance = (HINSTANCE) GetModuleHandle(NULL);
  2705. // Initialize the listview common controls
  2706. ZeroMemory(&Init, sizeof(Init));
  2707. Init.dwSize = sizeof(Init);
  2708. Init.dwICC = ICC_LISTVIEW_CLASSES;
  2709. if (!InitCommonControlsEx(&Init))
  2710. {
  2711. hr = myHLastError();
  2712. _JumpError(hr, error, "InitCommonControlsEx");
  2713. }
  2714. // If pwszFileOrURL is NULL, just call the dialog box,
  2715. // else determine if it's a file or URL
  2716. if (NULL != pwszFileOrURL)
  2717. {
  2718. // If it's a file, then we need to open it
  2719. if (!IsInternetUrlProtocol(pwszFileOrURL))
  2720. {
  2721. hr = ReadCertOrCRLFromFile(pwszFileOrURL, &g_pCert, &g_pCRL);
  2722. _JumpIfError(hr, error, "ReadCertOrCRLFromFile");
  2723. }
  2724. else // Otherwise just pass it in to the dialog
  2725. {
  2726. g_pwszUrl = pwszFileOrURL;
  2727. }
  2728. }
  2729. nDlg = DialogBox(
  2730. hInstance,
  2731. MAKEINTRESOURCE(IDD_URLTESTDLG),
  2732. NULL,
  2733. DlgProc);
  2734. hr = S_OK;
  2735. error:
  2736. if (NULL != g_pwszFile)
  2737. {
  2738. LocalFree(g_pwszFile);
  2739. g_pwszFile = NULL;
  2740. }
  2741. if (NULL != g_pCert)
  2742. {
  2743. CertFreeCertificateContext(g_pCert);
  2744. g_pCert = NULL;
  2745. }
  2746. if (NULL != g_pCRL)
  2747. {
  2748. CertFreeCRLContext(g_pCRL);
  2749. g_pCRL = NULL;
  2750. }
  2751. return(hr);
  2752. }