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.

444 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998-2002.
  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. // security review 2/26/2002 BryanWal ok
  298. ASSERT (pbHash);
  299. if ( !pbHash )
  300. break;
  301. if ( !memcmp (pbHash,
  302. rgCTLEntry[nCAHash].SubjectIdentifier.pbData,
  303. rgCTLEntry[nCAHash].SubjectIdentifier.cbData) )
  304. {
  305. LPWSTR *awszCAName = NULL;
  306. LPWSTR *awszCADisplayName = NULL;
  307. //
  308. // Add this CA to the list of
  309. // CA's.
  310. //
  311. // get the name of the CA
  312. hResult = ::CAGetCAProperty (pCAList[nCertContextIndex],
  313. CA_PROP_NAME,
  314. &awszCAName);
  315. if (SUCCEEDED (hResult) && awszCAName && awszCAName[0] )
  316. {
  317. // get the display name of the CA
  318. hResult = ::CAGetCAProperty (pCAList[nCertContextIndex],
  319. CA_PROP_DISPLAY_NAME,
  320. &awszCADisplayName);
  321. if ( SUCCEEDED(hResult) && awszCADisplayName && awszCADisplayName[0] )
  322. {
  323. m_CANameList.AddHead (awszCAName[0]);
  324. m_CADisplayNameList.AddHead (awszCADisplayName[0]);
  325. }
  326. }
  327. if ( awszCAName )
  328. {
  329. CAFreeCAProperty(pCAList[nCertContextIndex], awszCAName);
  330. }
  331. if ( awszCADisplayName )
  332. {
  333. CAFreeCAProperty(pCAList[nCertContextIndex], awszCADisplayName);
  334. }
  335. break;
  336. }
  337. }
  338. else
  339. {
  340. DWORD dwErr = GetLastError ();
  341. hResult = HRESULT_FROM_WIN32 (dwErr);
  342. DisplaySystemError (NULL, dwErr);
  343. break;
  344. }
  345. }
  346. }
  347. }
  348. for (UINT nCAListIndex = 0; nCAListIndex < dwCACnt; nCAListIndex++)
  349. {
  350. hResult = ::CACloseCA (pCAList[nCAListIndex]);
  351. ASSERT (SUCCEEDED (hResult));
  352. ::CertFreeCertificateContext (ppCertContext[nCAListIndex]);
  353. }
  354. }
  355. else
  356. {
  357. hResult = E_OUTOFMEMORY;
  358. }
  359. if ( pCAList )
  360. delete [] pCAList;
  361. if ( ppCertContext )
  362. delete [] ppCertContext;
  363. }
  364. }
  365. return hResult;
  366. }
  367. CStringList& CAutoCertRequest::GetCANameList(bool fDisplayName)
  368. {
  369. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  370. BuildCANameList ();
  371. return fDisplayName?m_CADisplayNameList:m_CANameList;
  372. }
  373. HCERTTYPE CAutoCertRequest::GetCertType()
  374. {
  375. ASSERT (CERTMGR_AUTO_CERT_REQUEST == m_objecttype);
  376. if ( !m_hCertType )
  377. {
  378. CString name;
  379. GetCertTypeName (name); // generates m_hCertType
  380. }
  381. return m_hCertType;
  382. }