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.

546 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: CTL.cpp
  7. //
  8. // Contents: implementation of the CCTL class.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "CTL.h"
  13. #include "certifct.h"
  14. USE_HANDLE_MACROS("CERTMGR(ctl.cpp)")
  15. ////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CCTL::CCTL (const PCCTL_CONTEXT pCTLContext,
  19. CCertStore& rCertStore,
  20. CertificateManagerObjectType objectType,
  21. CTypedPtrList<CPtrList, CCertStore*>* pStoreList) :
  22. CCertMgrCookie (objectType),
  23. m_pCTLContext (::CertDuplicateCTLContext (pCTLContext)),
  24. m_rCertStore (rCertStore),
  25. m_pStoreCollection (0),
  26. m_hExtraStore (0)
  27. {
  28. _TRACE (1, L"Entering CCTL::CCTL\n");
  29. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  30. CERTMGR_CTL == m_objecttype);
  31. m_rCertStore.AddRef ();
  32. ASSERT (m_pCTLContext);
  33. if ( m_pCTLContext )
  34. m_pCTLInfo = m_pCTLContext->pCtlInfo;
  35. m_pStoreCollection = new CCertStore (CERTMGR_LOG_STORE, CERT_STORE_PROV_COLLECTION, 0,
  36. L"", L"", L"", L"", NO_SPECIAL_TYPE, 0, rCertStore.m_pConsole);
  37. if ( m_pStoreCollection )
  38. {
  39. m_pStoreCollection->AddStoreToCollection (m_rCertStore);
  40. m_hExtraStore = CertOpenStore(
  41. CERT_STORE_PROV_MSG,
  42. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  43. NULL,
  44. NULL,
  45. (const void *) pCTLContext->hCryptMsg);
  46. if ( m_hExtraStore )
  47. m_pStoreCollection->AddStoreToCollection (m_hExtraStore);
  48. else
  49. {
  50. _TRACE (0, L"CertOpenStore (CERT_STORE_PROV_MSG) failed: 0x%x\n",
  51. GetLastError ());
  52. }
  53. if ( pStoreList )
  54. {
  55. for (POSITION pos = pStoreList->GetHeadPosition (); pos; )
  56. {
  57. CCertStore* pStore = pStoreList->GetNext (pos);
  58. ASSERT (pStore);
  59. if ( pStore )
  60. {
  61. m_pStoreCollection->AddStoreToCollection (*pStore);
  62. }
  63. pStore->AddRef ();
  64. m_storeList.AddTail (pStore);
  65. }
  66. }
  67. }
  68. _TRACE (-1, L"Leaving CCTL::CCTL\n");
  69. }
  70. CCTL::~CCTL()
  71. {
  72. _TRACE (1, L"Entering CCTL::~CCTL\n");
  73. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  74. CERTMGR_CTL == m_objecttype);
  75. if ( m_pStoreCollection )
  76. {
  77. delete m_pStoreCollection;
  78. m_pStoreCollection = 0;
  79. }
  80. CCertStore* pStore = 0;
  81. // Clean up store list
  82. while (!m_storeList.IsEmpty () )
  83. {
  84. pStore = m_storeList.RemoveHead ();
  85. ASSERT (pStore);
  86. if ( pStore )
  87. pStore->Release ();
  88. }
  89. if ( m_hExtraStore )
  90. {
  91. CertCloseStore (m_hExtraStore, 0);
  92. m_hExtraStore = 0;
  93. }
  94. m_rCertStore.Release ();
  95. if ( m_pCTLContext )
  96. ::CertFreeCTLContext (m_pCTLContext);
  97. _TRACE (-1, L"Leaving CCTL::~CCTL\n");
  98. }
  99. PCCTL_CONTEXT CCTL::GetCTLContext() const
  100. {
  101. _TRACE (1, L"Entering CCTL::GetCTLContext\n");
  102. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  103. CERTMGR_CTL == m_objecttype);
  104. _TRACE (-1, L"Leaving CCTL::GetCTLContext\n");
  105. return m_pCTLContext;
  106. }
  107. CCertStore& CCTL::GetCertStore() const
  108. {
  109. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  110. CERTMGR_CTL == m_objecttype);
  111. return m_rCertStore;
  112. }
  113. CString CCTL::GetIssuerName ()
  114. {
  115. _TRACE (1, L"Entering CCTL::GetIssuerName\n");
  116. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  117. CERTMGR_CTL == m_objecttype);
  118. ASSERT (m_pCTLInfo);
  119. if ( m_pCTLInfo )
  120. {
  121. // Decode issuer name if not already present
  122. if ( m_szIssuerName.IsEmpty () )
  123. {
  124. HRESULT hResult = GetSignerInfo (m_szIssuerName);
  125. if ( !SUCCEEDED (hResult) )
  126. VERIFY (m_szIssuerName.LoadString (IDS_NOT_AVAILABLE));
  127. }
  128. }
  129. _TRACE (-1, L"Leaving CCTL::GetIssuerName\n");
  130. return m_szIssuerName;
  131. }
  132. CString CCTL::GetEffectiveDate()
  133. {
  134. _TRACE (1, L"Entering CCTL::GetEffectiveDate\n");
  135. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  136. CERTMGR_CTL == m_objecttype);
  137. ASSERT (m_pCTLInfo);
  138. if ( m_pCTLInfo )
  139. {
  140. // Format date/time string if not already present
  141. if ( m_szEffectiveDate.IsEmpty () )
  142. {
  143. HRESULT hResult = FormatDate (m_pCTLInfo->ThisUpdate, m_szEffectiveDate);
  144. if ( !SUCCEEDED (hResult) )
  145. m_szEffectiveDate = _T("");
  146. }
  147. }
  148. else
  149. m_szEffectiveDate = _T("");
  150. _TRACE (-1, L"Leaving CCTL::GetEffectiveDate\n");
  151. return m_szEffectiveDate;
  152. }
  153. CString CCTL::GetNextUpdate()
  154. {
  155. _TRACE (1, L"Entering CCTL::GetNextUpdate\n");
  156. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  157. CERTMGR_CTL == m_objecttype);
  158. ASSERT (m_pCTLInfo);
  159. if ( m_pCTLInfo )
  160. {
  161. // Format date/time string if not already present
  162. if ( m_szNextUpdate.IsEmpty () )
  163. {
  164. HRESULT hResult = FormatDate (m_pCTLInfo->NextUpdate, m_szNextUpdate);
  165. if ( !SUCCEEDED (hResult) )
  166. m_szNextUpdate = _T("");
  167. }
  168. }
  169. else
  170. m_szNextUpdate = _T("");
  171. _TRACE (-1, L"Leaving CCTL::GetNextUpdate\n");
  172. return m_szNextUpdate;
  173. }
  174. CString CCTL::GetPurpose()
  175. {
  176. _TRACE (1, L"Entering CCTL::GetPurpose\n");
  177. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  178. CERTMGR_CTL == m_objecttype);
  179. ASSERT (m_pCTLInfo);
  180. if ( m_pCTLInfo )
  181. {
  182. // Format date/time string if not already present
  183. if ( m_szPurpose.IsEmpty () )
  184. FormatEnhancedKeyUsagePropertyString (m_szPurpose);
  185. }
  186. _TRACE (-1, L"Leaving CCTL::GetPurpose\n");
  187. return m_szPurpose;
  188. }
  189. void CCTL::FormatEnhancedKeyUsagePropertyString (CString& string)
  190. {
  191. _TRACE (1, L"Entering CCTL::FormatEnhancedKeyUsagePropertyString\n");
  192. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  193. CERTMGR_CTL == m_objecttype);
  194. ASSERT (m_pCTLInfo);
  195. if ( m_pCTLInfo )
  196. {
  197. CString usageName;
  198. CTL_USAGE& usage = m_pCTLInfo->SubjectUsage;
  199. for (DWORD dwIndex = 0; dwIndex < usage.cUsageIdentifier; dwIndex++)
  200. {
  201. if ( MyGetOIDInfo (usageName, usage.rgpszUsageIdentifier[dwIndex]) )
  202. {
  203. // add delimeter if not first iteration
  204. if ( dwIndex )
  205. string += _T(", ");
  206. string += usageName;
  207. }
  208. }
  209. }
  210. _TRACE (-1, L"Leaving CCTL::FormatEnhancedKeyUsagePropertyString\n");
  211. }
  212. HRESULT CCTL::GetSignerInfo (CString & signerName)
  213. {
  214. _TRACE (1, L"Entering CCTL::GetSignerInfo\n");
  215. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  216. CERTMGR_CTL == m_objecttype);
  217. HRESULT hResult = S_OK;
  218. //
  219. // Use CryptMsg to crack the encoded PKCS7 Signed Message
  220. //
  221. HCRYPTMSG hMsg = ::CryptMsgOpenToDecode (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  222. 0,
  223. 0,
  224. 0,
  225. NULL,
  226. NULL);
  227. ASSERT (hMsg);
  228. if ( hMsg )
  229. {
  230. BOOL bResult = ::CryptMsgUpdate (hMsg, m_pCTLContext->pbCtlEncoded,
  231. m_pCTLContext->cbCtlEncoded, TRUE);
  232. ASSERT (bResult);
  233. if ( bResult )
  234. {
  235. //
  236. // get the encoded signer BLOB
  237. //
  238. DWORD cbEncodedSigner = 0;
  239. bResult = ::CryptMsgGetParam (hMsg, CMSG_ENCODED_SIGNER, 0, NULL,
  240. &cbEncodedSigner);
  241. if ( bResult && cbEncodedSigner )
  242. {
  243. BYTE* pbEncodedSigner = (PBYTE) ::LocalAlloc (LPTR, cbEncodedSigner);
  244. if ( pbEncodedSigner )
  245. {
  246. bResult = ::CryptMsgGetParam (hMsg, CMSG_ENCODED_SIGNER, 0,
  247. pbEncodedSigner, &cbEncodedSigner);
  248. ASSERT (bResult);
  249. if ( bResult )
  250. {
  251. DWORD cbSignerInfo = 0;
  252. //
  253. // decode the EncodedSigner info
  254. //
  255. bResult = ::CryptDecodeObject (
  256. PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
  257. PKCS7_SIGNER_INFO,
  258. pbEncodedSigner,
  259. cbEncodedSigner,
  260. 0,
  261. NULL,
  262. &cbSignerInfo);
  263. ASSERT (bResult);
  264. if ( bResult )
  265. {
  266. PCMSG_SIGNER_INFO pbSignerInfo = (PCMSG_SIGNER_INFO) ::LocalAlloc (LPTR, cbSignerInfo);
  267. if ( pbSignerInfo )
  268. {
  269. bResult = ::CryptDecodeObject (
  270. PKCS_7_ASN_ENCODING|CRYPT_ASN_ENCODING,
  271. PKCS7_SIGNER_INFO,
  272. pbEncodedSigner,
  273. cbEncodedSigner,
  274. 0,
  275. pbSignerInfo,
  276. &cbSignerInfo);
  277. ASSERT (bResult);
  278. if ( bResult )
  279. {
  280. DWORD cbCertInfo = 0;
  281. //
  282. // get the signers cert context
  283. //
  284. bResult = ::CryptMsgGetParam (hMsg,
  285. CMSG_SIGNER_CERT_INFO_PARAM,
  286. 0,
  287. NULL,
  288. &cbCertInfo);
  289. ASSERT (bResult);
  290. if ( bResult && cbEncodedSigner )
  291. {
  292. CERT_INFO* pCertInfo = (CERT_INFO *) ::LocalAlloc (LPTR, cbCertInfo);
  293. if ( pCertInfo )
  294. {
  295. bResult = ::CryptMsgGetParam (hMsg,
  296. CMSG_SIGNER_CERT_INFO_PARAM,
  297. 0,
  298. pCertInfo,
  299. &cbCertInfo);
  300. ASSERT (bResult);
  301. if ( bResult )
  302. {
  303. CCertificate* pCert =
  304. m_pStoreCollection->GetSubjectCertificate (pCertInfo);
  305. if ( pCert )
  306. {
  307. signerName = pCert->GetSubjectName ();
  308. pCert->Release ();
  309. }
  310. else
  311. hResult = E_FAIL;
  312. }
  313. ::LocalFree (pCertInfo);
  314. }
  315. else
  316. {
  317. hResult = E_OUTOFMEMORY;
  318. }
  319. }
  320. }
  321. ::LocalFree (pbSignerInfo);
  322. }
  323. else
  324. {
  325. hResult = E_OUTOFMEMORY;
  326. }
  327. }
  328. }
  329. ::LocalFree (pbEncodedSigner);
  330. }
  331. else
  332. {
  333. hResult = E_OUTOFMEMORY;
  334. }
  335. }
  336. else
  337. hResult = E_FAIL;
  338. }
  339. bResult = ::CryptMsgClose (hMsg);
  340. ASSERT (bResult);
  341. }
  342. else
  343. hResult = E_UNEXPECTED;
  344. _TRACE (-1, L"Leaving CCTL::GetSignerInfo\n");
  345. return hResult;
  346. }
  347. int CCTL::CompareEffectiveDate (const CCTL& ctl) const
  348. {
  349. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  350. CERTMGR_CTL == m_objecttype);
  351. int compVal = 0;
  352. ASSERT (m_pCTLInfo && ctl.m_pCTLInfo);
  353. if ( m_pCTLInfo && ctl.m_pCTLInfo )
  354. {
  355. compVal = ::CompareFileTime (&m_pCTLInfo->ThisUpdate,
  356. &ctl.m_pCTLInfo->ThisUpdate);
  357. }
  358. return compVal;
  359. }
  360. int CCTL::CompareNextUpdate (const CCTL& ctl) const
  361. {
  362. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  363. CERTMGR_CTL == m_objecttype);
  364. int compVal = 0;
  365. ASSERT (m_pCTLInfo && ctl.m_pCTLInfo);
  366. if ( m_pCTLInfo && ctl.m_pCTLInfo )
  367. {
  368. compVal = ::CompareFileTime (&m_pCTLInfo->NextUpdate,
  369. &ctl.m_pCTLInfo->NextUpdate);
  370. }
  371. return compVal;
  372. }
  373. CString CCTL::GetFriendlyName()
  374. {
  375. _TRACE (1, L"Entering CCTL::GetFriendlyName\n");
  376. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  377. CERTMGR_CTL == m_objecttype);
  378. ASSERT (m_pCTLContext);
  379. if ( m_pCTLContext && m_szFriendlyName.IsEmpty () )
  380. {
  381. DWORD cbData = 0;
  382. BOOL bResult = ::CertGetCTLContextProperty (
  383. m_pCTLContext,
  384. CERT_FRIENDLY_NAME_PROP_ID,
  385. NULL,
  386. &cbData);
  387. if ( bResult )
  388. {
  389. LPWSTR pszName = new WCHAR[cbData];
  390. if ( pszName )
  391. {
  392. ::ZeroMemory (pszName, cbData * sizeof (WCHAR));
  393. bResult = ::CertGetCTLContextProperty (
  394. m_pCTLContext,
  395. CERT_FRIENDLY_NAME_PROP_ID,
  396. pszName,
  397. &cbData);
  398. ASSERT (bResult);
  399. if ( bResult )
  400. {
  401. m_szFriendlyName = pszName;
  402. }
  403. else
  404. {
  405. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  406. }
  407. delete [] pszName;
  408. }
  409. }
  410. else
  411. {
  412. if ( GetLastError () == CRYPT_E_NOT_FOUND )
  413. {
  414. VERIFY (m_szFriendlyName.LoadString (IDS_NONE));
  415. }
  416. else
  417. {
  418. ASSERT (0);
  419. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  420. }
  421. }
  422. }
  423. _TRACE (-1, L"Leaving CCTL::GetFriendlyName\n");
  424. return m_szFriendlyName;
  425. }
  426. SPECIAL_STORE_TYPE CCTL::GetStoreType() const
  427. {
  428. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  429. CERTMGR_CTL == m_objecttype);
  430. return m_rCertStore.GetStoreType ();
  431. }
  432. void CCTL::Refresh()
  433. {
  434. m_szEffectiveDate = L"";
  435. m_szFriendlyName = L"";
  436. m_szIssuerName = L"";
  437. m_szNextUpdate = L"";
  438. m_szPurpose = L"";
  439. }
  440. BOOL CCTL::DeleteFromStore()
  441. {
  442. _TRACE (1, L"Entering CCTL::DeleteFromStore\n");
  443. BOOL bResult = FALSE;
  444. PCCTL_CONTEXT pCTLContext = GetNewCTLContext ();
  445. if ( pCTLContext )
  446. {
  447. bResult = ::CertDeleteCTLFromStore (pCTLContext);
  448. if ( bResult )
  449. {
  450. m_rCertStore.InvalidateCertCount ();
  451. m_rCertStore.SetDirty ();
  452. HRESULT hr = m_rCertStore.Commit ();
  453. if ( SUCCEEDED (hr) )
  454. m_rCertStore.Resync ();
  455. else
  456. bResult = FALSE;
  457. }
  458. m_rCertStore.Close ();
  459. }
  460. _TRACE (-1, L"Leaving CCTL::DeleteFromStore\n");
  461. return bResult;
  462. }
  463. PCCTL_CONTEXT CCTL::GetNewCTLContext()
  464. {
  465. _TRACE (1, L"Entering CCTL::GetNewCTLContext\n");
  466. PCCTL_CONTEXT pCTLContext = 0;
  467. HCERTSTORE hCertStore = m_rCertStore.GetStoreHandle ();
  468. if ( hCertStore )
  469. {
  470. DWORD cbData = 20;
  471. BYTE certHash[20];
  472. BOOL bReturn = ::CertGetCTLContextProperty (
  473. m_pCTLContext,
  474. CERT_SHA1_HASH_PROP_ID,
  475. &certHash,
  476. &cbData);
  477. ASSERT (bReturn);
  478. if ( bReturn )
  479. {
  480. CRYPT_DATA_BLOB blob = {sizeof (certHash), certHash};
  481. pCTLContext = CertFindCTLInStore(
  482. hCertStore,
  483. 0,
  484. 0,
  485. CTL_FIND_SHA1_HASH,
  486. &blob,
  487. 0);
  488. if ( pCTLContext )
  489. {
  490. ::CertFreeCTLContext (m_pCTLContext);
  491. m_pCTLContext = ::CertDuplicateCTLContext (pCTLContext);
  492. }
  493. }
  494. }
  495. _TRACE (-1, L"Leaving CCTL::GetNewCTLContext\n");
  496. return pCTLContext;
  497. }