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.

439 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998-2001.
  5. //
  6. // File: AutoCert.cpp
  7. //
  8. // Contents: implementation of the CAutoCertRequest class.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include <gpedit.h>
  13. #include "AutoCert.h"
  14. #include "storegpe.h"
  15. USE_HANDLE_MACROS("CERTMGR(AutoCert.cpp)")
  16. ////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. CAutoCertRequest::CAutoCertRequest (const PCCTL_CONTEXT pCTLContext, CCertStore& rCertStore) :
  20. CCTL (pCTLContext, rCertStore, CERTMGR_AUTO_CERT_REQUEST),
  21. m_pCertTypeExtension (0),
  22. m_pEnhKeyUsageExtension (0),
  23. m_bCANamesEnumerated (false),
  24. m_hCertType (0)
  25. {
  26. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  27. }
  28. CAutoCertRequest::~CAutoCertRequest()
  29. {
  30. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  31. if ( m_hCertType )
  32. {
  33. VERIFY (SUCCEEDED (::CACloseCertType (m_hCertType)));
  34. }
  35. }
  36. HRESULT CAutoCertRequest::GetCertTypeName(CString & certTypeName)
  37. {
  38. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  39. HRESULT hResult = S_OK;
  40. if ( CERTMGR_LOG_STORE_GPE != GetCertStore().m_objecttype &&
  41. CERTMGR_LOG_STORE_RSOP != GetCertStore().m_objecttype )
  42. {
  43. hResult = E_FAIL;
  44. return hResult;
  45. }
  46. CCertStore* pStore = reinterpret_cast <CCertStore*>(&GetCertStore());
  47. if(pStore == NULL)
  48. {
  49. hResult = E_FAIL;
  50. return hResult;
  51. }
  52. if ( m_szCertTypeName.IsEmpty () )
  53. {
  54. bool bFound = false;
  55. hResult = E_FAIL;
  56. PCERT_EXTENSION pCertTypeExtension = GetCertTypeExtension ();
  57. if ( pCertTypeExtension )
  58. {
  59. DWORD cbValue = 0;
  60. if ( ::CryptDecodeObject(
  61. CRYPT_ASN_ENCODING,
  62. X509_UNICODE_ANY_STRING,
  63. pCertTypeExtension->Value.pbData,
  64. pCertTypeExtension->Value.cbData,
  65. 0,
  66. 0,
  67. &cbValue) )
  68. {
  69. CERT_NAME_VALUE* pCNValue = (CERT_NAME_VALUE*)
  70. ::LocalAlloc(LPTR, cbValue);
  71. if ( pCNValue )
  72. {
  73. if ( ::CryptDecodeObject(
  74. CRYPT_ASN_ENCODING,
  75. X509_UNICODE_ANY_STRING,
  76. pCertTypeExtension->Value.pbData,
  77. pCertTypeExtension->Value.cbData,
  78. 0,
  79. pCNValue,
  80. &cbValue) )
  81. {
  82. LPWSTR pszCertTypeName = (LPWSTR) pCNValue->Value.pbData;
  83. CString CAName;
  84. HCERTTYPE hCertType = 0;
  85. hResult = ::CAFindCertTypeByName ( pszCertTypeName,
  86. NULL,
  87. (pStore->IsMachineStore()?CT_ENUM_MACHINE_TYPES:CT_ENUM_USER_TYPES),
  88. &hCertType);
  89. if ( SUCCEEDED (hResult) )
  90. {
  91. WCHAR** pawszPropertyValue = 0;
  92. hResult = ::CAGetCertTypeProperty (hCertType,
  93. CERTTYPE_PROP_FRIENDLY_NAME,
  94. &pawszPropertyValue);
  95. ASSERT (SUCCEEDED (hResult));
  96. if ( SUCCEEDED (hResult) )
  97. {
  98. if ( pawszPropertyValue[0] )
  99. {
  100. m_szCertTypeName = pawszPropertyValue[0];
  101. bFound = true;
  102. m_hCertType = hCertType;
  103. }
  104. else
  105. {
  106. VERIFY (SUCCEEDED (::CAFreeCertTypeProperty (hCertType,
  107. pawszPropertyValue)));
  108. }
  109. }
  110. if ( !bFound )
  111. {
  112. hResult = ::CACloseCertType (hCertType);
  113. ASSERT (SUCCEEDED (hResult));
  114. }
  115. }
  116. }
  117. else
  118. {
  119. DWORD dwErr = GetLastError ();
  120. DisplaySystemError (NULL, dwErr);
  121. hResult = HRESULT_FROM_WIN32 (dwErr);
  122. }
  123. ::LocalFree (pCNValue);
  124. }
  125. else
  126. {
  127. hResult = E_OUTOFMEMORY;
  128. }
  129. }
  130. else
  131. {
  132. DWORD dwErr = GetLastError ();
  133. DisplaySystemError (NULL, dwErr);
  134. hResult = HRESULT_FROM_WIN32 (dwErr);
  135. }
  136. }
  137. // If all calls succeded but it still wasn't found, then fail anyway.
  138. if ( SUCCEEDED (hResult) && !bFound )
  139. hResult = E_FAIL;
  140. }
  141. if ( SUCCEEDED (hResult) )
  142. certTypeName = m_szCertTypeName;
  143. return hResult;
  144. }
  145. PCERT_EXTENSION CAutoCertRequest::GetCertTypeExtension()
  146. {
  147. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  148. if ( !m_pCertTypeExtension )
  149. {
  150. m_pCertTypeExtension = ::CertFindExtension (
  151. szOID_ENROLL_CERTTYPE_EXTENSION,
  152. GetCTLContext ()->pCtlInfo->cExtension,
  153. GetCTLContext ()->pCtlInfo->rgExtension);
  154. ASSERT (m_pCertTypeExtension);
  155. if ( !m_pCertTypeExtension )
  156. {
  157. DisplaySystemError (NULL, GetLastError ());
  158. }
  159. }
  160. return m_pCertTypeExtension;
  161. }
  162. PCERT_EXTENSION CAutoCertRequest::GetEnhancedKeyUsageExtension()
  163. {
  164. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  165. if ( !m_pEnhKeyUsageExtension )
  166. {
  167. m_pEnhKeyUsageExtension = ::CertFindExtension (
  168. szOID_ENHANCED_KEY_USAGE,
  169. GetCTLContext ()->pCtlInfo->cExtension,
  170. GetCTLContext ()->pCtlInfo->rgExtension);
  171. ASSERT (m_pEnhKeyUsageExtension);
  172. if ( !m_pEnhKeyUsageExtension )
  173. {
  174. DWORD dwErr = GetLastError ();
  175. if ( dwErr )
  176. DisplaySystemError (NULL, dwErr);
  177. }
  178. }
  179. return m_pEnhKeyUsageExtension;
  180. }
  181. HRESULT CAutoCertRequest::GetUsages(CString & usages)
  182. {
  183. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  184. HRESULT hResult = S_OK;
  185. if ( m_szUsages.IsEmpty () )
  186. {
  187. hResult = E_FAIL;
  188. PCERT_EXTENSION pEnhKeyUsageExtension = GetEnhancedKeyUsageExtension ();
  189. ASSERT (pEnhKeyUsageExtension);
  190. if ( pEnhKeyUsageExtension )
  191. {
  192. DWORD cbEnhKeyUsage = 0;
  193. if ( ::CryptDecodeObject(CRYPT_ASN_ENCODING,
  194. szOID_ENHANCED_KEY_USAGE,
  195. pEnhKeyUsageExtension->Value.pbData,
  196. pEnhKeyUsageExtension->Value.cbData,
  197. 0, NULL, &cbEnhKeyUsage) )
  198. {
  199. PCERT_ENHKEY_USAGE pEnhKeyUsage = (PCERT_ENHKEY_USAGE)
  200. ::LocalAlloc (LPTR, cbEnhKeyUsage);
  201. if ( pEnhKeyUsage )
  202. {
  203. if ( ::CryptDecodeObject (CRYPT_ASN_ENCODING,
  204. szOID_ENHANCED_KEY_USAGE,
  205. pEnhKeyUsageExtension->Value.pbData,
  206. pEnhKeyUsageExtension->Value.cbData,
  207. 0, pEnhKeyUsage, &cbEnhKeyUsage) )
  208. {
  209. CString usageName;
  210. for (DWORD dwIndex = 0;
  211. dwIndex < pEnhKeyUsage->cUsageIdentifier;
  212. dwIndex++)
  213. {
  214. if ( MyGetOIDInfo (usageName,
  215. pEnhKeyUsage->rgpszUsageIdentifier[dwIndex]) )
  216. {
  217. // add delimeter if not first iteration
  218. if ( dwIndex )
  219. m_szUsages += _T(", ");
  220. m_szUsages += usageName;
  221. }
  222. }
  223. hResult = S_OK;
  224. }
  225. else
  226. DisplaySystemError (NULL, GetLastError());
  227. ::LocalFree (pEnhKeyUsage);
  228. }
  229. else
  230. {
  231. hResult = E_OUTOFMEMORY;
  232. }
  233. }
  234. else
  235. DisplaySystemError (NULL, GetLastError());
  236. }
  237. }
  238. if ( SUCCEEDED (hResult) )
  239. usages = m_szUsages;
  240. return hResult;
  241. }
  242. // To get CAs, enumerate CAs on DS, get certs, get hash, compare with stored hash
  243. // in CTL, if match found, call GetCAInfoFromDS
  244. HRESULT CAutoCertRequest::BuildCANameList()
  245. {
  246. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  247. HRESULT hResult = S_OK;
  248. if ( !m_bCANamesEnumerated )
  249. {
  250. m_bCANamesEnumerated = true;
  251. // To get CAs, enumerate CAs on DS, get certs, get hash, compare with stored hash
  252. // in CTL, if match found, call GetCAInfoFromDS
  253. CWaitCursor waitCursor;
  254. HCAINFO hCAInfo = 0;
  255. DWORD dwCACnt = 0;
  256. HCAINFO* pCAList = 0;
  257. UINT nIndex = 0;
  258. PCCERT_CONTEXT* ppCertContext = NULL;
  259. DWORD cbHash = 20;
  260. hResult = ::CAEnumFirstCA (NULL, 0, &hCAInfo);
  261. if ( SUCCEEDED (hResult) )
  262. dwCACnt = ::CACountCAs (hCAInfo);
  263. if ( dwCACnt > 0 )
  264. {
  265. pCAList = new HCAINFO[dwCACnt];
  266. ppCertContext = new PCCERT_CONTEXT[dwCACnt];
  267. if ( pCAList && ppCertContext )
  268. {
  269. nIndex = 0;
  270. while (SUCCEEDED (hResult) && hCAInfo && nIndex < dwCACnt)
  271. {
  272. pCAList[nIndex] = hCAInfo;
  273. hResult = ::CAGetCACertificate (hCAInfo, &ppCertContext[nIndex]);
  274. ASSERT (SUCCEEDED (hResult));
  275. nIndex++;
  276. hResult = ::CAEnumNextCA (hCAInfo, &hCAInfo);
  277. }
  278. PCCTL_CONTEXT pCTLContext = GetCTLContext ();
  279. if ( pCTLContext )
  280. {
  281. PCTL_INFO pCTLInfo = pCTLContext->pCtlInfo;
  282. DWORD cCTLEntry = pCTLInfo->cCTLEntry;
  283. PCTL_ENTRY rgCTLEntry = pCTLInfo->rgCTLEntry;
  284. const size_t HASH_SIZE = 20;
  285. BYTE pbHash[HASH_SIZE];
  286. for (UINT nCAHash = 0; nCAHash < cCTLEntry; nCAHash++)
  287. {
  288. for (UINT nCertContextIndex = 0; nCertContextIndex < dwCACnt; nCertContextIndex++)
  289. {
  290. cbHash = HASH_SIZE;
  291. if (::CertGetCertificateContextProperty (ppCertContext[nCertContextIndex],
  292. CERT_SHA1_HASH_PROP_ID,
  293. pbHash,
  294. &cbHash) )
  295. {
  296. // Compare pbHash with pCAHash;
  297. if ( !memcmp (pbHash,
  298. rgCTLEntry[nCAHash].SubjectIdentifier.pbData,
  299. rgCTLEntry[nCAHash].SubjectIdentifier.cbData) )
  300. {
  301. LPWSTR *awszCAName = NULL;
  302. LPWSTR *awszCADisplayName = NULL;
  303. //
  304. // Add this CA to the list of
  305. // CA's.
  306. //
  307. // get the name of the CA
  308. hResult = ::CAGetCAProperty (pCAList[nCertContextIndex],
  309. CA_PROP_NAME,
  310. &awszCAName);
  311. if (SUCCEEDED (hResult) && awszCAName && awszCAName[0] )
  312. {
  313. // get the display name of the CA
  314. hResult = ::CAGetCAProperty (pCAList[nCertContextIndex],
  315. CA_PROP_DISPLAY_NAME,
  316. &awszCADisplayName);
  317. if ( SUCCEEDED(hResult) && awszCADisplayName && awszCADisplayName[0] )
  318. {
  319. m_CANameList.AddHead (awszCAName[0]);
  320. m_CADisplayNameList.AddHead (awszCADisplayName[0]);
  321. }
  322. }
  323. if ( awszCAName )
  324. {
  325. CAFreeCAProperty(pCAList[nCertContextIndex], awszCAName);
  326. }
  327. if ( awszCADisplayName )
  328. {
  329. CAFreeCAProperty(pCAList[nCertContextIndex], awszCADisplayName);
  330. }
  331. break;
  332. }
  333. }
  334. else
  335. {
  336. DWORD dwErr = GetLastError ();
  337. hResult = HRESULT_FROM_WIN32 (dwErr);
  338. DisplaySystemError (NULL, dwErr);
  339. break;
  340. }
  341. }
  342. }
  343. }
  344. for (UINT nCAListIndex = 0; nCAListIndex < dwCACnt; nCAListIndex++)
  345. {
  346. hResult = ::CACloseCA (pCAList[nCAListIndex]);
  347. ASSERT (SUCCEEDED (hResult));
  348. ::CertFreeCertificateContext (ppCertContext[nCAListIndex]);
  349. }
  350. }
  351. else
  352. {
  353. hResult = E_OUTOFMEMORY;
  354. }
  355. if ( pCAList )
  356. delete [] pCAList;
  357. if ( ppCertContext )
  358. delete [] ppCertContext;
  359. }
  360. }
  361. return hResult;
  362. }
  363. CStringList& CAutoCertRequest::GetCANameList(bool fDisplayName)
  364. {
  365. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  366. BuildCANameList ();
  367. return fDisplayName?m_CADisplayNameList:m_CANameList;
  368. }
  369. HCERTTYPE CAutoCertRequest::GetCertType()
  370. {
  371. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  372. if ( !m_hCertType )
  373. {
  374. CString name;
  375. GetCertTypeName (name); // generates m_hCertType
  376. }
  377. return m_hCertType;
  378. }