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.

1530 lines
48 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2002.
  5. //
  6. // File: Certifct.cpp
  7. //
  8. // Contents: Implementation of CCertmgrApp and DLL registration.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "Certifct.h"
  13. #ifdef _DEBUG
  14. #ifndef ALPHA
  15. #define new DEBUG_NEW
  16. #endif
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. USE_HANDLE_MACROS("CERTMGR(Certifct.cpp)")
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. const int FIELD_ISSUER_ALT_NAME = 0x00000001;
  24. const int FIELD_SUBJECT_ALT_NAME = 0x00000002;
  25. const int FIELD_CAN_DELETE = 0x00000004;
  26. const int FIELD_IS_ARCHIVED = 0x00000008;
  27. const int FIELD_TEMPLATE_NAME = 0x00000010;
  28. CCertificate::CCertificate(const PCCERT_CONTEXT pCertContext, CCertStore* pCertStore)
  29. : CCertMgrCookie (CERTMGR_CERTIFICATE),
  30. m_pCertContext (::CertDuplicateCertificateContext (pCertContext)),
  31. m_pCertInfo (0),
  32. m_fieldChecked (0),
  33. m_pCertStore (pCertStore),
  34. m_bCanDelete (false),
  35. m_bIsArchived (false)
  36. {
  37. // _TRACE (1, L"Entering CCertificate::CCertificate\n");
  38. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  39. ASSERT (m_pCertStore);
  40. if ( m_pCertStore )
  41. m_pCertStore->AddRef ();
  42. ASSERT (m_pCertContext);
  43. if ( m_pCertContext )
  44. m_pCertInfo = m_pCertContext->pCertInfo;
  45. // _TRACE (-1, L"Leaving CCertificate::CCertificate\n");
  46. }
  47. CCertificate::~CCertificate()
  48. {
  49. // _TRACE (1, L"Entering CCertificate::~CCertificate\n");
  50. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  51. if ( m_pCertContext )
  52. ::CertFreeCertificateContext (m_pCertContext);
  53. if ( m_pCertStore )
  54. m_pCertStore->Release ();
  55. // _TRACE (-1, L"Leaving CCertificate::~CCertificate\n");
  56. }
  57. CString CCertificate::GetFriendlyName ()
  58. {
  59. // _TRACE (1, L"Entering CCertificate::GetFriendlyName\n");
  60. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  61. ASSERT (m_pCertContext);
  62. if ( m_pCertContext && m_szFriendlyName.IsEmpty () )
  63. {
  64. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  65. DWORD cbData = 0;
  66. BOOL bResult = ::CertGetCertificateContextProperty (
  67. m_pCertContext,
  68. CERT_FRIENDLY_NAME_PROP_ID,
  69. NULL,
  70. &cbData);
  71. if ( bResult )
  72. {
  73. LPWSTR pszName = new WCHAR[cbData];
  74. if ( pszName )
  75. {
  76. // security review 2/22/2002 BryanWal ok
  77. ::ZeroMemory (pszName, cbData*sizeof (WCHAR));
  78. bResult = ::CertGetCertificateContextProperty (
  79. m_pCertContext,
  80. CERT_FRIENDLY_NAME_PROP_ID,
  81. pszName,
  82. &cbData);
  83. ASSERT (bResult);
  84. if ( bResult )
  85. {
  86. m_szFriendlyName = pszName;
  87. }
  88. else
  89. {
  90. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  91. }
  92. delete [] pszName;
  93. }
  94. }
  95. else
  96. {
  97. if ( GetLastError () == CRYPT_E_NOT_FOUND )
  98. {
  99. VERIFY (m_szFriendlyName.LoadString (IDS_NONE));
  100. }
  101. else
  102. {
  103. ASSERT (0);
  104. VERIFY (m_szFriendlyName.LoadString (IDS_NOT_AVAILABLE));
  105. }
  106. }
  107. }
  108. // _TRACE (-1, L"Leaving CCertificate::GetFriendlyName\n");
  109. return m_szFriendlyName;
  110. }
  111. CString CCertificate::GetIssuerName ()
  112. {
  113. // _TRACE (1, L"Entering CCertificate::GetIssuerName\n");
  114. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  115. ASSERT (m_pCertInfo);
  116. if ( m_pCertInfo )
  117. {
  118. // Decode issuer name if not already present
  119. if ( m_szIssuerName.IsEmpty () )
  120. {
  121. m_szIssuerName = ::GetNameString (m_pCertContext, CERT_NAME_ISSUER_FLAG);
  122. }
  123. }
  124. else
  125. return _T("");
  126. // _TRACE (-1, L"Leaving CCertificate::GetIssuerName\n");
  127. return m_szIssuerName;
  128. }
  129. ///////////////////////////////////////////////////////////////////////////
  130. // GetSubjectName ()
  131. //
  132. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  133. // string is a valid return value
  134. // cbName (IN / OUT) - If pszName is NULL, then the required length
  135. // of pszName is returned.
  136. // Otherwise, contains the length of pszName.
  137. ///////////////////////////////////////////////////////////////////////////
  138. CString CCertificate::GetSubjectName()
  139. {
  140. // _TRACE (1, L"Entering CCertificate::GetSubjectName\n");
  141. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  142. ASSERT (m_pCertInfo);
  143. if ( m_pCertInfo )
  144. {
  145. // Decode subject name if not already present
  146. if ( m_szSubjectName.IsEmpty () )
  147. {
  148. m_szSubjectName = ::GetNameString (m_pCertContext, 0);
  149. }
  150. }
  151. else
  152. return _T("");
  153. // _TRACE (-1, L"Leaving CCertificate::GetSubjectName\n");
  154. return m_szSubjectName;
  155. }
  156. ///////////////////////////////////////////////////////////////////////////
  157. // GetValidNotBefore ()
  158. //
  159. // pszDateTime (IN / OPTIONAL) - returns the formatted date and time.
  160. // cbDateTime (IN / OUT) - If pszDateTime is NULL, then the required length
  161. // of pszDateTime is returned.
  162. // Otherwise, contains the length of pszDateTime.
  163. ///////////////////////////////////////////////////////////////////////////
  164. CString CCertificate::GetValidNotBefore()
  165. {
  166. // _TRACE (1, L"Entering CCertificate::GetValidNotBefore\n");
  167. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  168. ASSERT (m_pCertInfo);
  169. if ( m_pCertInfo )
  170. {
  171. // Format date/time string if not already present
  172. if ( m_szValidNotBefore.IsEmpty () )
  173. {
  174. HRESULT hr = FormatDate (m_pCertInfo->NotBefore, m_szValidNotBefore);
  175. if ( !SUCCEEDED (hr) )
  176. return _T("");
  177. }
  178. }
  179. else
  180. return _T("");
  181. // _TRACE (-1, L"Leaving CCertificate::GetValidNotBefore\n");
  182. return m_szValidNotBefore;
  183. }
  184. ///////////////////////////////////////////////////////////////////////////
  185. // GetValidNotAfter ()
  186. //
  187. // pszDateTime (IN / OPTIONAL) - returns the formatted date and time.
  188. // cbDateTime (IN / OUT) - If pszDateTime is NULL, then the required length
  189. // of pszDateTime is returned.
  190. // Otherwise, contains the length of pszDateTime.
  191. ///////////////////////////////////////////////////////////////////////////
  192. CString CCertificate::GetValidNotAfter ()
  193. {
  194. // _TRACE (1, L"Entering CCertificate::GetValidNotAfter\n");
  195. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  196. ASSERT (m_pCertInfo);
  197. if ( m_pCertInfo )
  198. {
  199. // Format date/time string if not already present
  200. if ( m_szValidNotAfter.IsEmpty () )
  201. {
  202. HRESULT hr = FormatDate (m_pCertInfo->NotAfter, m_szValidNotAfter);
  203. if ( !SUCCEEDED (hr) )
  204. m_szValidNotAfter = _T("");
  205. }
  206. }
  207. else
  208. m_szValidNotAfter = _T("");
  209. // _TRACE (-1, L"Leaving CCertificate::GetValidNotAfter\n");
  210. return m_szValidNotAfter;
  211. }
  212. CString CCertificate::GetEnhancedKeyUsage ()
  213. {
  214. // _TRACE (1, L"Entering CCertificate::GetEnhancedKeyUsage\n");
  215. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  216. ASSERT (m_pCertInfo);
  217. if ( m_pCertInfo )
  218. {
  219. // Format date/time string if not already present
  220. if ( m_szEnhancedKeyUsage.IsEmpty () )
  221. {
  222. FormatEnhancedKeyUsagePropertyString (
  223. m_szEnhancedKeyUsage);
  224. }
  225. }
  226. else
  227. m_szEnhancedKeyUsage = _T("");
  228. // _TRACE (-1, L"Leaving CCertificate::GetEnhancedKeyUsage\n");
  229. return m_szEnhancedKeyUsage;
  230. }
  231. bool CCertificate::FormatEnhancedKeyUsagePropertyString (CString& string)
  232. {
  233. // _TRACE (1, L"Entering CCertificate::FormatEnhancedKeyUsagePropertyString\n");
  234. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  235. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  236. BOOL bReturn = TRUE;
  237. DWORD cbUsage = 0;
  238. bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  239. NULL, &cbUsage);
  240. if ( bReturn )
  241. {
  242. CString usageName;
  243. PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE) ::LocalAlloc (LPTR, cbUsage);
  244. if ( pUsage )
  245. {
  246. bReturn = ::CertGetEnhancedKeyUsage (m_pCertContext, 0, // get extension and property
  247. pUsage, &cbUsage);
  248. if ( bReturn )
  249. {
  250. if ( !pUsage->cUsageIdentifier )
  251. {
  252. switch (GetLastError ())
  253. {
  254. case CRYPT_E_NOT_FOUND:
  255. VERIFY (string.LoadString (IDS_ANY));
  256. break;
  257. case 0:
  258. VERIFY (string.LoadString (IDS_NONE));
  259. break;
  260. default:
  261. break;
  262. }
  263. }
  264. else
  265. {
  266. for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
  267. {
  268. if ( MyGetOIDInfo (usageName, pUsage->rgpszUsageIdentifier[dwIndex]) )
  269. {
  270. // add delimeter if not first iteration
  271. if ( dwIndex )
  272. string += _T(", ");
  273. string += usageName;
  274. }
  275. }
  276. }
  277. }
  278. else
  279. {
  280. switch (GetLastError ())
  281. {
  282. case CRYPT_E_NOT_FOUND:
  283. VERIFY (string.LoadString (IDS_ANY));
  284. break;
  285. case 0:
  286. VERIFY (string.LoadString (IDS_NONE));
  287. break;
  288. default:
  289. break;
  290. }
  291. }
  292. ::LocalFree (pUsage);
  293. }
  294. else
  295. {
  296. bReturn = FALSE;
  297. }
  298. }
  299. else
  300. {
  301. switch (GetLastError ())
  302. {
  303. case CRYPT_E_NOT_FOUND:
  304. VERIFY (string.LoadString (IDS_ANY));
  305. break;
  306. case 0:
  307. VERIFY (string.LoadString (IDS_NONE));
  308. break;
  309. default:
  310. break;
  311. }
  312. }
  313. // _TRACE (-1, L"Leaving CCertificate::FormatEnhancedKeyUsagePropertyString\n");
  314. return bReturn ? true : false;
  315. }
  316. ///////////////////////////////////////////////////////////////////////////
  317. // GetAlternateIssuerName ()
  318. //
  319. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  320. // string is a valid return value
  321. // cbName (IN / OUT) - If pszName is NULL, then the required length
  322. // of pszName is returned.
  323. // Otherwise, contains the length of pszName.
  324. ///////////////////////////////////////////////////////////////////////////
  325. CString CCertificate::GetAlternateIssuerName ()
  326. {
  327. // _TRACE (1, L"Entering CCertificate::GetAlternateIssuerName\n");
  328. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  329. ASSERT (m_pCertInfo);
  330. if ( m_pCertInfo )
  331. {
  332. if ( !(m_fieldChecked & FIELD_ISSUER_ALT_NAME) )
  333. {
  334. HRESULT hr = ConvertAltNameToString (_T(szOID_ISSUER_ALT_NAME),
  335. CERT_ALT_NAME_URL, m_szAltIssuerName);
  336. ASSERT (SUCCEEDED (hr));
  337. if ( !SUCCEEDED (hr) )
  338. m_szAltIssuerName = _T("");
  339. m_fieldChecked |= FIELD_ISSUER_ALT_NAME;
  340. }
  341. }
  342. else
  343. m_szAltIssuerName = _T("");
  344. // _TRACE (-1, L"Leaving CCertificate::GetAlternateIssuerName\n");
  345. return m_szAltIssuerName;
  346. }
  347. ///////////////////////////////////////////////////////////////////////////
  348. // GetAlternateSubjectName ()
  349. //
  350. // pszName (IN / OPTIONAL) - returns the alternate issuer name. An empty
  351. // string is a valid return value
  352. // cbName (IN / OUT) - If pszName is NULL, then the required length
  353. // of pszName is returned.
  354. // Otherwise, contains the length of pszName.
  355. ///////////////////////////////////////////////////////////////////////////
  356. CString CCertificate::GetAlternateSubjectName ()
  357. {
  358. // _TRACE (1, L"Entering CCertificate::GetAlternateSubjectName\n");
  359. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  360. ASSERT (m_pCertInfo);
  361. if ( m_pCertInfo )
  362. {
  363. if ( !(m_fieldChecked & FIELD_SUBJECT_ALT_NAME) )
  364. {
  365. HRESULT hr = ConvertAltNameToString (_T(szOID_SUBJECT_ALT_NAME),
  366. CERT_ALT_NAME_URL, m_szAltSubjectName);
  367. if ( !SUCCEEDED (hr) )
  368. m_szAltSubjectName = _T("");
  369. m_fieldChecked |= FIELD_SUBJECT_ALT_NAME;
  370. }
  371. }
  372. else
  373. m_szAltSubjectName = _T("");
  374. // _TRACE (-1, L"Leaving CCertificate::GetAlternateSubjectName\n");
  375. return m_szAltSubjectName;
  376. }
  377. ///////////////////////////////////////////////////////////////////////////
  378. // GetSerialNumber ()
  379. //
  380. // pszSerNum (IN / OPTIONAL) - returns the alternate issuer name. An empty
  381. // string is a valid return value
  382. // cbSerNum (IN / OUT) - If pszSerNum is NULL, then the required length
  383. // of pszSerNum is returned.
  384. // Otherwise, contains the length of pszSerNum.
  385. ///////////////////////////////////////////////////////////////////////////
  386. CString CCertificate::GetSerialNumber ()
  387. {
  388. // _TRACE (1, L"Entering CCertificate::GetSerialNumber\n");
  389. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  390. ASSERT (m_pCertInfo);
  391. if ( m_pCertInfo )
  392. {
  393. // Decode issuer name if not already present
  394. if ( m_szSerNum.IsEmpty () )
  395. {
  396. LPWSTR pwszText = 0;
  397. if ( SUCCEEDED (FormatSerialNoString (&pwszText, & (m_pCertInfo->SerialNumber))) )
  398. {
  399. m_szSerNum = pwszText;
  400. CoTaskMemFree (pwszText);
  401. }
  402. }
  403. }
  404. else
  405. m_szSerNum = _T("");
  406. // _TRACE (-1, L"Leaving CCertificate::GetSerialNumber\n");
  407. return m_szSerNum;
  408. }
  409. //////////////////////////////////////////////////////////////////////////////
  410. // ConvertAltNameToString ()
  411. //
  412. // pszOID (IN) - The OID of the alternate name to retrieve
  413. // dwNameChoice (IN) - The type of alternate name to return
  414. // altName (OUT) - The version of the desired alternate name indicated
  415. // by dwNameChoice
  416. //////////////////////////////////////////////////////////////////////////////
  417. HRESULT CCertificate::ConvertAltNameToString(LPCWSTR pszOID, const DWORD dwNameChoice, CString & altName)
  418. {
  419. // _TRACE (1, L"Entering CCertificate::ConvertAltNameToString\n");
  420. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  421. HRESULT hr = S_OK;
  422. ASSERT (pszOID);
  423. if ( !pszOID )
  424. return E_POINTER;
  425. // Iterate through the extensions until the one indicated by the
  426. // passed-in pszOID is found.
  427. for (DWORD index = 0; index < m_pCertInfo->cExtension; index++)
  428. {
  429. ASSERT (m_pCertInfo->rgExtension);
  430. if ( !m_pCertInfo->rgExtension )
  431. {
  432. hr = E_FAIL;
  433. break;
  434. }
  435. // security review 2/22/2002 BryanWal ok
  436. size_t len = strlen (m_pCertInfo->rgExtension[index].pszObjId);
  437. LPWSTR wcsObjId = new WCHAR[len+1];
  438. if ( wcsObjId )
  439. {
  440. // security review BryanWal 02/02/2002 ok
  441. ::ZeroMemory (wcsObjId, (len + 1) * sizeof (WCHAR));
  442. // security review 2/22/2002 BryanWal ok
  443. mbstowcs (wcsObjId, m_pCertInfo->rgExtension[index].pszObjId, len+1); // last arg includes NULL terminator
  444. if ( !wcscmp (wcsObjId, pszOID) )
  445. {
  446. CERT_ALT_NAME_INFO nameInfo;
  447. DWORD cbNameInfo = sizeof (CERT_ALT_NAME_INFO);
  448. BOOL bResult = CryptDecodeObject(
  449. MY_ENCODING_TYPE,
  450. X509_ALTERNATE_NAME, // in
  451. m_pCertInfo->rgExtension[index].Value.pbData, // in
  452. m_pCertInfo->rgExtension[index].Value.cbData, // in
  453. 0, // in
  454. (void *) &nameInfo, // out
  455. &cbNameInfo); // in/out
  456. ASSERT (bResult);
  457. if ( bResult )
  458. {
  459. // We've found the right extension, now iterate through
  460. // the alternate names until we find the desired type.
  461. for (DWORD dwAltEntryIndex = 0; dwAltEntryIndex < nameInfo.cAltEntry; dwAltEntryIndex++)
  462. {
  463. if ( nameInfo.rgAltEntry[dwAltEntryIndex].dwAltNameChoice ==
  464. dwNameChoice )
  465. {
  466. altName = nameInfo.rgAltEntry[dwAltEntryIndex].pwszURL;
  467. break;
  468. }
  469. }
  470. }
  471. else
  472. hr = E_UNEXPECTED;
  473. break;
  474. }
  475. delete [] wcsObjId;
  476. }
  477. else
  478. {
  479. hr = E_OUTOFMEMORY;
  480. }
  481. }
  482. // _TRACE (-1, L"Leaving CCertificate::ConvertAltNameToString\n");
  483. return hr;
  484. }
  485. CCertStore* CCertificate::GetCertStore() const
  486. {
  487. // _TRACE (0, L"Entering and leaving CCertificate::GetCertStore\n");
  488. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  489. return m_pCertStore;
  490. }
  491. PCCERT_CONTEXT CCertificate::GetCertContext() const
  492. {
  493. // _TRACE (0, L"Entering and leaving CCertificate::GetCertContext\n");
  494. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  495. return m_pCertContext;
  496. }
  497. bool CCertificate::IsValid()
  498. {
  499. // _TRACE (1, L"Entering CCertificate::IsValid\n");
  500. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  501. bool bIsValid = false;
  502. ASSERT (m_pCertInfo);
  503. if ( m_pCertInfo )
  504. {
  505. FILETIME systemTime;
  506. ::GetSystemTimeAsFileTime (&systemTime);
  507. LONG lBefore = ::CompareFileTime (&m_pCertInfo->NotBefore, &systemTime);
  508. LONG lAfter = ::CompareFileTime (&systemTime, &m_pCertInfo->NotAfter);
  509. if ( lBefore < 1 && lAfter < 1 )
  510. bIsValid = true;
  511. }
  512. // _TRACE (-1, L"Leaving CCertificate::IsValid\n");
  513. return bIsValid;
  514. }
  515. const SPECIAL_STORE_TYPE CCertificate::GetStoreType () const
  516. {
  517. // _TRACE (0, L"Entering and leaving CCertificate::GetStoreType\n");
  518. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  519. if ( m_pCertStore )
  520. return m_pCertStore->GetStoreType ();
  521. else
  522. return NO_SPECIAL_TYPE;
  523. }
  524. void CCertificate::Refresh()
  525. {
  526. // _TRACE (1, L"Entering CCertificate::Refresh\n");
  527. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  528. // Clearing all fields forces rereading of the data.
  529. m_szAltIssuerName = L"";
  530. m_szAltSubjectName = L"";
  531. m_szAuthorityKeyID = L"";
  532. m_szEnhancedKeyUsage = L"";
  533. m_szFriendlyName = L"";
  534. m_szIssuerName = L"";
  535. m_szMD5Hash = L"";
  536. m_szPolicyURL = L"";
  537. m_szSerNum = L"";
  538. m_szSHAHash = L"";
  539. m_szSubjectKeyID = L"";
  540. m_szSubjectName = L"";
  541. m_szValidNotAfter = L"";
  542. m_szValidNotBefore = L"";
  543. m_fieldChecked = 0;
  544. // _TRACE (-1, L"Leaving CCertificate::Refresh\n");
  545. }
  546. CString CCertificate::GetMD5Hash()
  547. {
  548. // _TRACE (1, L"Entering CCertificate::GetMD5Hash\n");
  549. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  550. ASSERT (m_pCertContext);
  551. if ( m_pCertContext && m_szMD5Hash.IsEmpty ())
  552. {
  553. m_szMD5Hash = GetGenericHash (CERT_MD5_HASH_PROP_ID);
  554. }
  555. // _TRACE (-1, L"Leaving CCertificate::GetMD5Hash\n");
  556. return m_szMD5Hash;
  557. }
  558. CString CCertificate::GetSHAHash()
  559. {
  560. // _TRACE (1, L"Entering CCertificate::GetSHAHash\n");
  561. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  562. ASSERT (m_pCertContext);
  563. if ( m_pCertContext && m_szSHAHash.IsEmpty ())
  564. {
  565. m_szSHAHash = GetGenericHash (CERT_SHA1_HASH_PROP_ID);
  566. }
  567. // _TRACE (-1, L"Leaving CCertificate::GetSHAHash\n");
  568. return m_szSHAHash;
  569. }
  570. CString CCertificate::GetGenericHash(DWORD dwPropId)
  571. {
  572. // _TRACE (1, L"Entering CCertificate::GetGenericHash\n");
  573. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  574. CString szHash;
  575. DWORD cbData = 0;
  576. BOOL bReturn = ::CertGetCertificateContextProperty (
  577. m_pCertContext,
  578. dwPropId,
  579. NULL,
  580. &cbData);
  581. if ( bReturn )
  582. {
  583. cbData += 2; // for null terminator
  584. BYTE* pCertHash = new BYTE[cbData];
  585. if ( pCertHash )
  586. {
  587. // security review 2/22/2002 BryanWal ok
  588. ::ZeroMemory (pCertHash, cbData);
  589. bReturn = CertGetCertificateContextProperty (
  590. m_pCertContext,
  591. dwPropId,
  592. pCertHash,
  593. &cbData);
  594. ASSERT (bReturn);
  595. if ( bReturn )
  596. {
  597. DataToHex (pCertHash, szHash, cbData, false);
  598. }
  599. delete [] pCertHash;
  600. }
  601. }
  602. // _TRACE (-1, L"Leaving CCertificate::GetGenericHash\n");
  603. return szHash;
  604. }
  605. int CCertificate::CompareExpireDate(const CCertificate & cert) const
  606. {
  607. // _TRACE (1, L"Entering CCertificate::CompareExpireDate\n");
  608. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  609. int compVal = 0;
  610. ASSERT (m_pCertInfo && cert.m_pCertInfo);
  611. if ( m_pCertInfo && cert.m_pCertInfo )
  612. {
  613. compVal = ::CompareFileTime (&m_pCertInfo->NotAfter,
  614. &cert.m_pCertInfo->NotAfter);
  615. }
  616. // _TRACE (-1, L"Leaving CCertificate::CompareExpireDate\n");
  617. return compVal;
  618. }
  619. bool CCertificate::CanDelete()
  620. {
  621. // _TRACE (1, L"Entering CCertificate::CanDelete\n");
  622. if ( m_pCertContext && !(m_fieldChecked & FIELD_CAN_DELETE) )
  623. {
  624. DWORD dwAccessFlags = 0;
  625. DWORD cbData = sizeof (DWORD);
  626. BOOL bResult = ::CertGetCertificateContextProperty (
  627. m_pCertContext,
  628. CERT_ACCESS_STATE_PROP_ID,
  629. &dwAccessFlags,
  630. &cbData);
  631. if ( bResult )
  632. {
  633. if ( dwAccessFlags & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG )
  634. m_bCanDelete = true;
  635. }
  636. m_fieldChecked |= FIELD_CAN_DELETE;
  637. }
  638. // _TRACE (-1, L"Leaving CCertificate::CanDelete\n");
  639. return m_bCanDelete;
  640. }
  641. bool CCertificate::IsReadOnly()
  642. {
  643. bool bResult = false;
  644. if ( m_pCertStore )
  645. bResult = (m_pCertStore->IsReadOnly () || !CanDelete ());
  646. return bResult;
  647. }
  648. bool CCertificate::IsArchived()
  649. {
  650. // _TRACE (1, L"Entering CCertificate::IsArchived\n");
  651. if ( m_pCertContext && !(m_fieldChecked & FIELD_IS_ARCHIVED) )
  652. {
  653. DWORD cbData = sizeof (DWORD);
  654. BOOL bResult = ::CertGetCertificateContextProperty (
  655. m_pCertContext,
  656. CERT_ARCHIVED_PROP_ID,
  657. NULL,
  658. &cbData);
  659. if ( bResult )
  660. {
  661. m_bIsArchived = true;
  662. }
  663. else
  664. m_bIsArchived = false;
  665. m_fieldChecked |= FIELD_IS_ARCHIVED;
  666. }
  667. // _TRACE (-1, L"Leaving CCertificate::IsArchived\n");
  668. return m_bIsArchived;
  669. }
  670. BOOL CCertificate::DeleteFromStore(bool bDoCommit)
  671. {
  672. _TRACE (1, L"Entering CCertificate::DeleteFromStore\n");
  673. BOOL bResult = FALSE;
  674. if ( m_pCertStore )
  675. {
  676. PCCERT_CONTEXT pCertContext = GetNewCertContext ();
  677. if ( pCertContext )
  678. {
  679. bResult = ::CertDeleteCertificateFromStore (pCertContext);
  680. if ( bResult )
  681. {
  682. m_pCertStore->InvalidateCertCount ();
  683. m_pCertStore->SetDirty ();
  684. if ( bDoCommit )
  685. {
  686. m_pCertStore->SetDeleting ();
  687. HRESULT hr = m_pCertStore->Commit ();
  688. m_pCertStore->SetAdding ();
  689. if ( SUCCEEDED (hr) )
  690. m_pCertStore->Resync ();
  691. else
  692. bResult = FALSE;
  693. }
  694. m_pCertStore->Release ();
  695. m_pCertStore = 0;
  696. }
  697. }
  698. }
  699. _TRACE (-1, L"Leaving CCertificate::DeleteFromStore\n");
  700. return bResult;
  701. }
  702. PCCERT_CONTEXT CCertificate::GetNewCertContext()
  703. {
  704. PCCERT_CONTEXT pCertContext = 0;
  705. if ( m_pCertStore )
  706. {
  707. HCERTSTORE hCertStore = m_pCertStore->GetStoreHandle ();
  708. if ( hCertStore )
  709. {
  710. DWORD cbData = 20;
  711. BYTE certHash[20];
  712. BOOL bReturn = ::CertGetCertificateContextProperty (
  713. m_pCertContext,
  714. CERT_SHA1_HASH_PROP_ID,
  715. certHash,
  716. &cbData);
  717. ASSERT (bReturn);
  718. if ( bReturn )
  719. {
  720. CRYPT_DATA_BLOB blob = {sizeof (certHash), certHash};
  721. pCertContext = CertFindCertificateInStore(
  722. hCertStore,
  723. 0,
  724. 0,
  725. CERT_FIND_SHA1_HASH,
  726. &blob,
  727. 0);
  728. if ( pCertContext )
  729. {
  730. ::CertFreeCertificateContext (m_pCertContext);
  731. m_pCertContext = ::CertDuplicateCertificateContext (pCertContext);
  732. }
  733. }
  734. }
  735. }
  736. return pCertContext;
  737. }
  738. CString CCertificate::FormatStatus()
  739. {
  740. CString status;
  741. // security review 2/22/2002 BryanWal ok
  742. status.FormatMessage (L"%1 %2",
  743. (IsReadOnly () ? L"R" : L" "),
  744. (IsArchived () ? L"A" : L" "));
  745. return status;
  746. }
  747. //////////////////////////////////////////////////////////////////////////////////////
  748. // Stolen from private\ispu\ui\cryptui\frmtutil.cpp
  749. //////////////////////////////////////////////////////////////////////////////////////
  750. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  751. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  752. HRESULT CCertificate::FormatSerialNoString(LPWSTR *ppString, CRYPT_INTEGER_BLOB const *pblob)
  753. {
  754. if ( !ppString || !pblob )
  755. return E_POINTER;
  756. DWORD i = 0;
  757. LPBYTE pb;
  758. DWORD numCharsInserted = 0;
  759. //
  760. // calculate size needed
  761. //
  762. pb = &pblob->pbData[pblob->cbData-1];
  763. while (pb >= &pblob->pbData[0])
  764. {
  765. if (numCharsInserted == 4)
  766. {
  767. i += sizeof(WCHAR);
  768. numCharsInserted = 0;
  769. }
  770. else
  771. {
  772. i += 2 * sizeof(WCHAR);
  773. pb--;
  774. numCharsInserted += 2;
  775. }
  776. }
  777. if (NULL == (*ppString = (LPWSTR) CoTaskMemAlloc (i+sizeof(WCHAR))))
  778. {
  779. return E_OUTOFMEMORY;
  780. }
  781. // fill the buffer
  782. i=0;
  783. numCharsInserted = 0;
  784. pb = &pblob->pbData[pblob->cbData-1];
  785. while (pb >= &pblob->pbData[0])
  786. {
  787. if (numCharsInserted == 4)
  788. {
  789. (*ppString)[i++] = L' ';
  790. numCharsInserted = 0;
  791. }
  792. else
  793. {
  794. (*ppString)[i++] = RgwchHex[(*pb & 0xf0) >> 4];
  795. (*ppString)[i++] = RgwchHex[*pb & 0x0f];
  796. pb--;
  797. numCharsInserted += 2;
  798. }
  799. }
  800. (*ppString)[i] = 0;
  801. return S_OK;
  802. }
  803. CString CCertificate::GetDescription()
  804. {
  805. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  806. if ( m_pCertContext && m_szDescription.IsEmpty () )
  807. {
  808. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  809. DWORD cbData = 0;
  810. BOOL bResult = ::CertGetCertificateContextProperty (
  811. m_pCertContext,
  812. CERT_DESCRIPTION_PROP_ID,
  813. NULL,
  814. &cbData);
  815. if ( bResult )
  816. {
  817. LPWSTR pszName = new WCHAR[cbData];
  818. if ( pszName )
  819. {
  820. // security review 2/22/2002 BryanWal ok
  821. ::ZeroMemory (pszName, cbData*sizeof (WCHAR));
  822. bResult = ::CertGetCertificateContextProperty (
  823. m_pCertContext,
  824. CERT_DESCRIPTION_PROP_ID,
  825. pszName,
  826. &cbData);
  827. ASSERT (bResult);
  828. if ( bResult )
  829. {
  830. m_szDescription = pszName;
  831. }
  832. delete [] pszName;
  833. }
  834. }
  835. else
  836. {
  837. DWORD dwErr = GetLastError ();
  838. if ( CRYPT_E_NOT_FOUND == dwErr )
  839. {
  840. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID) found no description.\n");
  841. }
  842. else
  843. {
  844. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID) failed: 0x%x\n", dwErr);
  845. }
  846. }
  847. }
  848. return m_szDescription;
  849. }
  850. HRESULT CCertificate::SetDescription(const CString &szDescription)
  851. {
  852. _TRACE (1, L"Entering CCertificate::SetDescription (%s)\n",
  853. (PCWSTR) szDescription);
  854. HRESULT hr = S_OK;
  855. CRYPT_DATA_BLOB cryptDataBlob;
  856. // security review 2/22/2002 BryanWal ok
  857. ::ZeroMemory (&cryptDataBlob, sizeof (cryptDataBlob));
  858. cryptDataBlob.pbData = (LPBYTE) (PCWSTR) szDescription;
  859. // security review 2/22/2002 BryanWal ok
  860. cryptDataBlob.cbData = (DWORD) (wcslen (szDescription) + 1) * sizeof (WCHAR);
  861. BOOL bResult = ::CertSetCertificateContextProperty (m_pCertContext,
  862. CERT_DESCRIPTION_PROP_ID, 0, &cryptDataBlob);
  863. ASSERT (bResult);
  864. if ( bResult )
  865. {
  866. m_szDescription = szDescription;
  867. }
  868. else
  869. {
  870. DWORD dwErr = GetLastError ();
  871. _TRACE (0, L"CertSetCertificateContextProperty (CERT_DESCRIPTION_PROP_ID, %s) failed: %d\n",
  872. (PCWSTR) szDescription, dwErr);
  873. hr = HRESULT_FROM_WIN32 (dwErr);
  874. }
  875. _TRACE (1, L"Entering CCertificate::SetDescription (%s): 0x%x\n",
  876. (PCWSTR) szDescription, hr);
  877. return hr;
  878. }
  879. HRESULT CCertificate::SetLastModified ()
  880. {
  881. HRESULT hr = S_OK;
  882. if ( m_pCertContext )
  883. {
  884. SYSTEMTIME st;
  885. FILETIME ft;
  886. GetSystemTime (&st);
  887. VERIFY (SystemTimeToFileTime(&st, &ft));
  888. CRYPT_DATA_BLOB cryptDataBlob;
  889. // security review 2/22/2002 BryanWal ok
  890. ::ZeroMemory (&cryptDataBlob, sizeof (cryptDataBlob));
  891. cryptDataBlob.pbData = (LPBYTE) &ft;
  892. cryptDataBlob.cbData = sizeof (FILETIME);
  893. BOOL bResult = ::CertSetCertificateContextProperty (
  894. m_pCertContext,
  895. CERT_DATE_STAMP_PROP_ID, 0, &cryptDataBlob);
  896. ASSERT (bResult);
  897. if ( !bResult )
  898. {
  899. DWORD dwErr = GetLastError ();
  900. _TRACE (0, L"CertSetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: %d\n",
  901. dwErr);
  902. hr = HRESULT_FROM_WIN32 (dwErr);
  903. }
  904. }
  905. return hr;
  906. }
  907. CString CCertificate::GetShortLastModified ()
  908. {
  909. return GetLastModified (DATE_SHORTDATE);
  910. }
  911. CString CCertificate::GetLongLastModified ()
  912. {
  913. return GetLastModified (DATE_LONGDATE);
  914. }
  915. ///////////////////////////////////////////////////////////////////////////////
  916. //
  917. // Method: GetLastModified
  918. // Purpose: Get the date stamp property of the cert and format for display
  919. // Inputs: dwDateFlags - as defined in SDK, specify DATE_SHORTDATE or
  920. // DATE_LONGDATE
  921. // bRetryIfNotPresent - to prevent stack overflow. Used if the property
  922. // is not set, to set the property to the current time and
  923. // retrieve again.
  924. //
  925. // Output: locale-formatted date and time string
  926. //
  927. ///////////////////////////////////////////////////////////////////////////////
  928. CString CCertificate::GetLastModified(DWORD dwDateFlags, bool bRetryIfNotPresent /* true */)
  929. {
  930. _TRACE (1, L"Entering CCertificate::GetLastModified ()\n");
  931. CString szDate;
  932. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  933. if ( m_pCertContext )
  934. {
  935. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  936. FILETIME ft;
  937. // security review 2/22/2002 BryanWal ok
  938. ::ZeroMemory (&ft, sizeof (ft));
  939. DWORD cbData = sizeof (ft);
  940. BOOL bResult = ::CertGetCertificateContextProperty (
  941. m_pCertContext,
  942. CERT_DATE_STAMP_PROP_ID,
  943. &ft,
  944. &cbData);
  945. if ( bResult )
  946. {
  947. VERIFY (SUCCEEDED (FormatDate (ft, szDate, dwDateFlags, true)) );
  948. }
  949. else
  950. {
  951. DWORD dwErr = GetLastError ();
  952. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) returned 0x%x\n",
  953. dwErr);
  954. if ( bRetryIfNotPresent && CRYPT_E_NOT_FOUND == dwErr )
  955. {
  956. // NTRAID# 461474 SAFER: last modified date is being updated
  957. // everytime the rules are refreshed.
  958. GetNewCertContext ();
  959. if ( SUCCEEDED (SetLastModified ()) ) // not present - set the value
  960. {
  961. szDate = GetLastModified (dwDateFlags, false);
  962. CCertStore* pCertStore = GetCertStore ();
  963. if ( pCertStore )
  964. {
  965. pCertStore->SetDirty ();
  966. pCertStore->Commit ();
  967. }
  968. }
  969. }
  970. dwErr = GetLastError ();
  971. if ( CRYPT_E_NOT_FOUND == dwErr )
  972. {
  973. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) found no property.\n");
  974. }
  975. else
  976. {
  977. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: 0x%x\n", dwErr);
  978. }
  979. }
  980. }
  981. _TRACE (-1, L"Leaving CCertificate::GetLastModified (): %s\n", (PCWSTR) szDate);
  982. return szDate;
  983. }
  984. HRESULT CCertificate::GetLastModifiedFileTime (FILETIME& ft)
  985. {
  986. HRESULT hr = S_OK;
  987. ASSERT (CERTMGR_CERTIFICATE == m_objecttype);
  988. ASSERT (m_pCertContext);
  989. if ( m_pCertContext )
  990. {
  991. DWORD cbData = sizeof (ft);
  992. BOOL bResult = ::CertGetCertificateContextProperty (
  993. m_pCertContext,
  994. CERT_DATE_STAMP_PROP_ID,
  995. &ft,
  996. &cbData);
  997. if ( !bResult )
  998. {
  999. DWORD dwErr = GetLastError ();
  1000. if ( CRYPT_E_NOT_FOUND == dwErr )
  1001. {
  1002. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) found no property.\n");
  1003. }
  1004. else
  1005. {
  1006. _TRACE (0, L"CertGetCertificateContextProperty (CERT_DATE_STAMP_PROP_ID) failed: 0x%x\n", dwErr);
  1007. }
  1008. hr = HRESULT_FROM_WIN32 (dwErr);
  1009. }
  1010. }
  1011. else
  1012. hr = E_FAIL;
  1013. return hr;
  1014. }
  1015. BOOL CCertificate::operator==(CCertificate& rCert)
  1016. {
  1017. if ( GetMD5Hash () == rCert.GetMD5Hash () )
  1018. return TRUE;
  1019. else
  1020. return FALSE;
  1021. }
  1022. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1023. CString CCertificate::GetTemplateName()
  1024. {
  1025. if ( m_pCertInfo && !(m_fieldChecked & FIELD_TEMPLATE_NAME) )
  1026. {
  1027. // Iterate through the extensions until szOID_CERTIFICATE_TEMPLATE is found.
  1028. for (DWORD index = 0; index < m_pCertInfo->cExtension; index++)
  1029. {
  1030. ASSERT (m_pCertInfo->rgExtension);
  1031. if ( !m_pCertInfo->rgExtension )
  1032. break;
  1033. // security review 2/22/2002 BryanWal ok
  1034. if ( !strcmp (szOID_CERTIFICATE_TEMPLATE, m_pCertInfo->rgExtension[index].pszObjId) )
  1035. {
  1036. m_szTemplateName = DecodeV2TemplateName (m_pCertInfo);
  1037. if ( m_szTemplateName.IsEmpty () )
  1038. {
  1039. m_szTemplateName = OriginalDecodeV2TemplateName (&(m_pCertInfo->rgExtension[index]));
  1040. }
  1041. break;
  1042. }
  1043. // security review 2/22/2002 BryanWal ok
  1044. else if ( !strcmp (szOID_ENROLL_CERTTYPE_EXTENSION, m_pCertInfo->rgExtension[index].pszObjId) )
  1045. {
  1046. m_szTemplateName = DecodeV1TemplateName (&(m_pCertInfo->rgExtension[index]));
  1047. break;
  1048. }
  1049. }
  1050. m_fieldChecked |= FIELD_TEMPLATE_NAME;
  1051. }
  1052. return m_szTemplateName;
  1053. }
  1054. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1055. CString CCertificate::DecodeV1TemplateName (PCERT_EXTENSION pCertExtension)
  1056. {
  1057. CString szTemplateName;
  1058. ASSERT (pCertExtension);
  1059. if ( pCertExtension )
  1060. {
  1061. DWORD cbValue = 0;
  1062. if ( ::CryptDecodeObject(
  1063. CRYPT_ASN_ENCODING,
  1064. X509_UNICODE_ANY_STRING,
  1065. pCertExtension->Value.pbData,
  1066. pCertExtension->Value.cbData,
  1067. 0,
  1068. 0,
  1069. &cbValue) )
  1070. {
  1071. CERT_NAME_VALUE* pCNValue = (CERT_NAME_VALUE*)
  1072. ::LocalAlloc(LPTR, cbValue);
  1073. if ( pCNValue )
  1074. {
  1075. if ( ::CryptDecodeObject(
  1076. CRYPT_ASN_ENCODING,
  1077. X509_UNICODE_ANY_STRING,
  1078. pCertExtension->Value.pbData,
  1079. pCertExtension->Value.cbData,
  1080. 0,
  1081. pCNValue,
  1082. &cbValue) )
  1083. {
  1084. szTemplateName = (LPWSTR) pCNValue->Value.pbData;
  1085. // NTRAID# 395173 Certificates Snapin:The column "
  1086. // Certificate Template" should contain value of "Template
  1087. // Name" for V1 templates
  1088. HCERTTYPE hCertType = 0;
  1089. HRESULT hr = ::CAFindCertTypeByName (szTemplateName,
  1090. NULL,
  1091. CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES,
  1092. &hCertType);
  1093. if ( SUCCEEDED (hr) )
  1094. {
  1095. PWSTR* rgwszProp = 0;
  1096. hr = ::CAGetCertTypePropertyEx (hCertType,
  1097. CERTTYPE_PROP_FRIENDLY_NAME, &rgwszProp);
  1098. if ( SUCCEEDED (hr) && rgwszProp )
  1099. {
  1100. szTemplateName = *rgwszProp;
  1101. ::CAFreeCertTypeProperty (hCertType, rgwszProp);
  1102. }
  1103. else
  1104. {
  1105. _TRACE (0, L"CAGetCertTypePropertyEx (CERTTYPE_PROP_FRIENDLY_NAME) failed: 0x%x\n", hr);
  1106. }
  1107. ::CACloseCertType (hCertType);
  1108. }
  1109. }
  1110. else
  1111. {
  1112. _TRACE (0, L"CryptDecodeObject (CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, ...) failed: 0x%x\n",
  1113. GetLastError ());
  1114. }
  1115. ::LocalFree (pCNValue);
  1116. }
  1117. }
  1118. else
  1119. {
  1120. _TRACE (0, L"CryptDecodeObject (CRYPT_ASN_ENCODING, X509_UNICODE_ANY_STRING, ...) failed: 0x%x\n",
  1121. GetLastError ());
  1122. }
  1123. }
  1124. return szTemplateName;
  1125. }
  1126. BOOL ConvertSzToWsz (
  1127. OUT WCHAR **ppwsz,
  1128. IN CHAR const *pch,
  1129. IN LONG cch)
  1130. {
  1131. HRESULT hr = S_OK;
  1132. LONG cwc = 0;
  1133. UINT codePage = ::GetACP ();
  1134. *ppwsz = NULL;
  1135. for (;;)
  1136. {
  1137. cwc = ::MultiByteToWideChar (codePage, 0, pch, cch, *ppwsz, cwc);
  1138. if (0 >= cwc)
  1139. {
  1140. hr = HRESULT_FROM_WIN32 (GetLastError());
  1141. _TRACE (0, L"MultiByteToWideChar () failed: 0x%x\n", hr);
  1142. if (NULL != *ppwsz)
  1143. {
  1144. ::LocalFree(*ppwsz);
  1145. *ppwsz = NULL;
  1146. }
  1147. break;
  1148. }
  1149. if (NULL != *ppwsz)
  1150. {
  1151. (*ppwsz)[cwc] = L'\0';
  1152. hr = S_OK;
  1153. break;
  1154. }
  1155. *ppwsz = (WCHAR *) ::LocalAlloc (LMEM_FIXED, (cwc + 1) * sizeof (WCHAR));
  1156. if ( !*ppwsz )
  1157. {
  1158. hr = E_OUTOFMEMORY;
  1159. break;
  1160. }
  1161. }
  1162. if (S_OK != hr)
  1163. {
  1164. ::SetLastError (hr);
  1165. }
  1166. return (S_OK == hr);
  1167. }
  1168. HRESULT GetTemplateDisplayName(
  1169. IN const CString& szTemplateObjId,
  1170. CString& szDisplayName)
  1171. {
  1172. HRESULT hr = S_OK;
  1173. PWSTR pwszDisplayName = NULL;
  1174. HCERTTYPE hCertType = NULL;
  1175. DWORD dwFlags = 0;
  1176. PWSTR* apwszCertTypeName = NULL;
  1177. dwFlags = CT_ENUM_USER_TYPES | CT_ENUM_MACHINE_TYPES;
  1178. hr = ::CAFindCertTypeByName (szTemplateObjId, NULL, dwFlags, &hCertType);
  1179. if ( HRESULT_FROM_WIN32 (ERROR_NOT_FOUND) == hr )
  1180. {
  1181. hr = ::CAFindCertTypeByName (
  1182. szTemplateObjId,
  1183. NULL,
  1184. CT_FIND_BY_OID | dwFlags,
  1185. &hCertType);
  1186. }
  1187. if ( SUCCEEDED (hr) )
  1188. {
  1189. hr = ::CAGetCertTypeProperty (
  1190. hCertType,
  1191. CERTTYPE_PROP_FRIENDLY_NAME,
  1192. &apwszCertTypeName);
  1193. if ( SUCCEEDED (hr) )
  1194. {
  1195. if ( apwszCertTypeName && apwszCertTypeName[0])
  1196. szDisplayName = apwszCertTypeName[0];
  1197. }
  1198. else
  1199. {
  1200. _TRACE (0, L"CAGetCertTypeProperty (CERTTYPE_PROP_FRIENDLY_NAME) failed: 0x%x\n", hr);
  1201. }
  1202. }
  1203. else
  1204. {
  1205. _TRACE (0, L"CAFindCertTypeByName (%s) failed: 0x%x\n", (PCWSTR) szTemplateObjId, hr);
  1206. }
  1207. if ( apwszCertTypeName )
  1208. ::CAFreeCertTypeProperty (hCertType, apwszCertTypeName);
  1209. if ( hCertType )
  1210. ::CACloseCertType (hCertType);
  1211. if ( pwszDisplayName )
  1212. ::LocalFree (pwszDisplayName);
  1213. return hr;
  1214. }
  1215. CString CCertificate::DecodeV2TemplateName (PCERT_INFO pCertInfo)
  1216. {
  1217. CWaitCursor waitCursor;
  1218. CString szTemplateName;
  1219. ASSERT (pCertInfo);
  1220. if ( pCertInfo )
  1221. {
  1222. CERT_EXTENSION* pExt = ::CertFindExtension(
  1223. szOID_CERTIFICATE_TEMPLATE,
  1224. pCertInfo->cExtension,
  1225. pCertInfo->rgExtension);
  1226. if ( pExt )
  1227. {
  1228. DWORD cbTemplate = 0;
  1229. CERT_TEMPLATE_EXT* pTemplate = NULL;
  1230. BOOL bResult = ::CryptDecodeObjectEx(
  1231. X509_ASN_ENCODING,
  1232. X509_CERTIFICATE_TEMPLATE,
  1233. pExt->Value.pbData,
  1234. pExt->Value.cbData,
  1235. CRYPT_DECODE_ALLOC_FLAG, // dwFlags
  1236. NULL, // use LocalAlloc and LocalFree
  1237. &pTemplate,
  1238. &cbTemplate);
  1239. if (bResult && !pTemplate)
  1240. {
  1241. ::SetLastError((DWORD) HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  1242. bResult = FALSE;
  1243. }
  1244. if ( bResult )
  1245. {
  1246. WCHAR *pwszCertTypeObjId = NULL;
  1247. CString szDisplayName;
  1248. if ( ConvertSzToWsz(&pwszCertTypeObjId, pTemplate->pszObjId, -1) )
  1249. {
  1250. HRESULT hr = GetTemplateDisplayName(pwszCertTypeObjId, szDisplayName);
  1251. if ( SUCCEEDED (hr) )
  1252. {
  1253. szTemplateName = szDisplayName;
  1254. }
  1255. if (NULL != pwszCertTypeObjId)
  1256. {
  1257. ::LocalFree(pwszCertTypeObjId);
  1258. }
  1259. if (NULL != pTemplate)
  1260. {
  1261. ::LocalFree(pTemplate);
  1262. }
  1263. }
  1264. }
  1265. }
  1266. }
  1267. return szTemplateName;
  1268. }
  1269. // NTRAID# 247237 Cert UI: Cert Snapin: Certificates snapin should show template name
  1270. CString CCertificate::OriginalDecodeV2TemplateName (PCERT_EXTENSION pCertExtension)
  1271. {
  1272. CString szTemplateName;
  1273. ASSERT (pCertExtension);
  1274. if ( pCertExtension )
  1275. {
  1276. DWORD cbData = 0;
  1277. if ( CryptDecodeObject(X509_ASN_ENCODING,
  1278. szOID_CERTIFICATE_TEMPLATE,
  1279. pCertExtension->Value.pbData,
  1280. pCertExtension->Value.cbData,
  1281. 0,
  1282. NULL,
  1283. &cbData) )
  1284. {
  1285. CERT_TEMPLATE_EXT* pbTemplate = (CERT_TEMPLATE_EXT*) LocalAlloc(LPTR, cbData);
  1286. if ( pbTemplate )
  1287. {
  1288. if ( CryptDecodeObject(X509_ASN_ENCODING,
  1289. szOID_CERTIFICATE_TEMPLATE,
  1290. pCertExtension->Value.pbData,
  1291. pCertExtension->Value.cbData,
  1292. 0,
  1293. pbTemplate,
  1294. &cbData) )
  1295. {
  1296. CString text;
  1297. CString description;
  1298. //copy the extension oid
  1299. if ( pbTemplate->pszObjId )
  1300. {
  1301. MyGetOIDInfo (szTemplateName, pbTemplate->pszObjId);
  1302. }
  1303. }
  1304. else
  1305. {
  1306. _TRACE (0, L"CryptDecodeObject (X509_ASN_ENCODING, szOID_CERTIFICATE_TEMPLATE, ...) failed: 0x%x\n",
  1307. GetLastError ());
  1308. }
  1309. LocalFree (pbTemplate);
  1310. }
  1311. }
  1312. else
  1313. {
  1314. _TRACE (0, L"CryptDecodeObject (X509_ASN_ENCODING, szOID_CERTIFICATE_TEMPLATE, ...) failed: 0x%x\n",
  1315. GetLastError ());
  1316. }
  1317. }
  1318. return szTemplateName;
  1319. }
  1320. void CCertificate::SetStore (CCertStore* pStore)
  1321. {
  1322. if ( !m_pCertStore && !pStore )
  1323. return;
  1324. if ( m_pCertStore && pStore )
  1325. {
  1326. if ( *m_pCertStore == *pStore )
  1327. return; // don't change if the same
  1328. }
  1329. if ( m_pCertStore )
  1330. {
  1331. m_pCertStore->Release ();
  1332. m_pCertStore = 0;
  1333. }
  1334. if ( pStore )
  1335. {
  1336. m_pCertStore = pStore;
  1337. m_pCertStore->AddRef ();
  1338. }
  1339. if ( m_pCertContext )
  1340. {
  1341. PCCERT_CONTEXT pCertContext = GetNewCertContext ();
  1342. ::CertFreeCertificateContext (m_pCertContext);
  1343. m_pCertInfo = 0;
  1344. m_pCertContext = 0;
  1345. m_pCertContext = pCertContext;
  1346. if ( m_pCertContext )
  1347. m_pCertInfo = m_pCertContext->pCertInfo;
  1348. }
  1349. }
  1350. bool CCertificate::IsCertStillInStore() const
  1351. {
  1352. bool bCertFound = false;
  1353. if ( m_pCertStore )
  1354. {
  1355. PCCERT_CONTEXT pFoundCertContext =
  1356. m_pCertStore->FindCertificate (0, CERT_FIND_EXISTING,
  1357. (void*) m_pCertContext, NULL);
  1358. if ( pFoundCertContext )
  1359. {
  1360. ::CertFreeCertificateContext (pFoundCertContext);
  1361. bCertFound = true;
  1362. }
  1363. }
  1364. return bCertFound;
  1365. }