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.

599 lines
19 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2002.
  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. pStore->AddRef ();
  63. m_storeList.AddTail (pStore);
  64. }
  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. // security review 2/22/2002 BryanWal ok
  393. ::ZeroMemory (pszName, cbData * sizeof (WCHAR));
  394. bResult = ::CertGetCTLContextProperty (
  395. m_pCTLContext,
  396. CERT_FRIENDLY_NAME_PROP_ID,
  397. pszName,
  398. &cbData);
  399. ASSERT (bResult);
  400. if ( bResult )
  401. {
  402. m_szFriendlyName = pszName;
  403. }
  404. else
  405. {
  406. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  407. }
  408. delete [] pszName;
  409. }
  410. }
  411. else
  412. {
  413. if ( GetLastError () == CRYPT_E_NOT_FOUND )
  414. {
  415. VERIFY (m_szFriendlyName.LoadString (IDS_NONE));
  416. }
  417. else
  418. {
  419. ASSERT (0);
  420. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  421. }
  422. }
  423. }
  424. _TRACE (-1, L"Leaving CCTL::GetFriendlyName\n");
  425. return m_szFriendlyName;
  426. }
  427. SPECIAL_STORE_TYPE CCTL::GetStoreType() const
  428. {
  429. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype ||
  430. CERTMGR_CTL == m_objecttype);
  431. return m_rCertStore.GetStoreType ();
  432. }
  433. void CCTL::Refresh()
  434. {
  435. m_szEffectiveDate = L"";
  436. m_szFriendlyName = L"";
  437. m_szIssuerName = L"";
  438. m_szNextUpdate = L"";
  439. m_szPurpose = L"";
  440. }
  441. BOOL CCTL::DeleteFromStore()
  442. {
  443. _TRACE (1, L"Entering CCTL::DeleteFromStore\n");
  444. BOOL bResult = FALSE;
  445. PCCTL_CONTEXT pCTLContext = GetNewCTLContext ();
  446. if ( pCTLContext )
  447. {
  448. bResult = ::CertDeleteCTLFromStore (pCTLContext);
  449. if ( bResult )
  450. {
  451. m_rCertStore.InvalidateCertCount ();
  452. m_rCertStore.SetDirty ();
  453. m_rCertStore.SetDeleting ();
  454. HRESULT hr = m_rCertStore.Commit ();
  455. m_rCertStore.SetAdding ();
  456. if ( SUCCEEDED (hr) )
  457. m_rCertStore.Resync ();
  458. else
  459. bResult = FALSE;
  460. }
  461. m_rCertStore.Close ();
  462. }
  463. _TRACE (-1, L"Leaving CCTL::DeleteFromStore\n");
  464. return bResult;
  465. }
  466. PCCTL_CONTEXT CCTL::GetNewCTLContext()
  467. {
  468. _TRACE (1, L"Entering CCTL::GetNewCTLContext\n");
  469. PCCTL_CONTEXT pCTLContext = 0;
  470. HCERTSTORE hCertStore = m_rCertStore.GetStoreHandle ();
  471. if ( hCertStore )
  472. {
  473. DWORD cbData = 20;
  474. BYTE certHash[20];
  475. BOOL bReturn = ::CertGetCTLContextProperty (
  476. m_pCTLContext,
  477. CERT_SHA1_HASH_PROP_ID,
  478. certHash,
  479. &cbData);
  480. ASSERT (bReturn);
  481. if ( bReturn )
  482. {
  483. CRYPT_DATA_BLOB blob = {sizeof (certHash), certHash};
  484. pCTLContext = CertFindCTLInStore(
  485. hCertStore,
  486. 0,
  487. 0,
  488. CTL_FIND_SHA1_HASH,
  489. &blob,
  490. 0);
  491. if ( pCTLContext )
  492. {
  493. ::CertFreeCTLContext (m_pCTLContext);
  494. m_pCTLContext = ::CertDuplicateCTLContext (pCTLContext);
  495. }
  496. }
  497. }
  498. _TRACE (-1, L"Leaving CCTL::GetNewCTLContext\n");
  499. return pCTLContext;
  500. }
  501. CString CCTL::GetSHAHash()
  502. {
  503. // _TRACE (1, L"Entering CCTL::GetSHAHash\n");
  504. ASSERT (m_pCTLContext);
  505. if ( m_pCTLContext && m_szSHAHash.IsEmpty ())
  506. {
  507. m_szSHAHash = GetGenericHash (CERT_SHA1_HASH_PROP_ID);
  508. }
  509. // _TRACE (-1, L"Leaving CCTL::GetSHAHash\n");
  510. return m_szSHAHash;
  511. }
  512. CString CCTL::GetGenericHash(DWORD dwPropId)
  513. {
  514. // _TRACE (1, L"Entering CCTL::GetGenericHash\n");
  515. CString szHash;
  516. DWORD cbData = 0;
  517. BOOL bReturn = ::CertGetCTLContextProperty (
  518. m_pCTLContext,
  519. dwPropId,
  520. NULL,
  521. &cbData);
  522. if ( bReturn )
  523. {
  524. cbData += 2; // for null terminator
  525. BYTE* pCTLHash = new BYTE[cbData];
  526. if ( pCTLHash )
  527. {
  528. // security review 2/22/2002 BryanWal ok
  529. ::ZeroMemory (pCTLHash, cbData);
  530. bReturn = CertGetCTLContextProperty (
  531. m_pCTLContext,
  532. dwPropId,
  533. pCTLHash,
  534. &cbData);
  535. ASSERT (bReturn);
  536. if ( bReturn )
  537. {
  538. DataToHex (pCTLHash, szHash, cbData, false);
  539. }
  540. delete [] pCTLHash;
  541. }
  542. }
  543. // _TRACE (-1, L"Leaving CCTL::GetGenericHash\n");
  544. return szHash;
  545. }