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.

480 lines
11 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: ExtendedKeyUsage.cpp
  4. Content: Implementation of CExtendedKeyUsage.
  5. History: 11-15-99 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "ExtendedKeyUsage.h"
  10. #include "CertHlpr.h"
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Exported functions.
  14. //
  15. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  16. Function : CreateExtendedKeyUsageObject
  17. Synopsis : Create an IExtendedKeyUsage object and populate the object
  18. with EKU data from the certificate.
  19. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
  20. IExtendedKeyUsage ** ppIExtendedKeyUsage - Pointer to pointer to
  21. IExtendedKeyUsage
  22. object.
  23. Remark :
  24. ------------------------------------------------------------------------------*/
  25. HRESULT CreateExtendedKeyUsageObject (PCCERT_CONTEXT pCertContext,
  26. IExtendedKeyUsage ** ppIExtendedKeyUsage)
  27. {
  28. HRESULT hr = S_OK;
  29. CComObject<CExtendedKeyUsage> * pCExtendedKeyUsage = NULL;
  30. DebugTrace("Entering CreateExtendedKeyUsageObject().\n");
  31. //
  32. // Sanity check.
  33. //
  34. ATLASSERT(pCertContext);
  35. ATLASSERT(ppIExtendedKeyUsage);
  36. try
  37. {
  38. //
  39. // Create the object. Note that the ref count will still be 0
  40. // after the object is created.
  41. //
  42. if (FAILED(hr = CComObject<CExtendedKeyUsage>::CreateInstance(&pCExtendedKeyUsage)))
  43. {
  44. DebugTrace("Error [%#x]: CComObject<CExtendedKeyUsage>::CreateInstance() failed.\n", hr);
  45. goto ErrorExit;
  46. }
  47. //
  48. // Initialize object.
  49. //
  50. if (FAILED(hr = pCExtendedKeyUsage->Init(pCertContext)))
  51. {
  52. DebugTrace("Error [%#x]: pCExtendedKeyUsage->Init() failed.\n", hr);
  53. goto ErrorExit;
  54. }
  55. //
  56. // Return interface pointer to caller.
  57. //
  58. if (FAILED(hr = pCExtendedKeyUsage->QueryInterface(ppIExtendedKeyUsage)))
  59. {
  60. DebugTrace("Error [%#x]: pCExtendedKeyUsage->QueryInterface() failed.\n", hr);
  61. goto ErrorExit;
  62. }
  63. }
  64. catch(...)
  65. {
  66. hr = E_POINTER;
  67. DebugTrace("Exception: invalid parameter.\n");
  68. goto ErrorExit;
  69. }
  70. CommonExit:
  71. DebugTrace("Leaving CreateExtendedKeyUsageObject().\n");
  72. return hr;
  73. ErrorExit:
  74. //
  75. // Sanity check.
  76. //
  77. ATLASSERT(FAILED(hr));
  78. if (pCExtendedKeyUsage)
  79. {
  80. delete pCExtendedKeyUsage;
  81. }
  82. goto CommonExit;
  83. }
  84. ////////////////////////////////////////////////////////////////////////////////
  85. //
  86. // CExtendedKeyUsage
  87. //
  88. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  89. Function : CExtendedKeyUsage::get_IsPresent
  90. Synopsis : Check to see if the EKU extension is present.
  91. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive result.
  92. Remark : Note that this function may return VARIANT_TRUE even if there is
  93. no EKU extension found in the certificate, because CAPI will
  94. take intersection of EKU with EKU extended property (i.e. no
  95. EKU extension, but there is EKU extended property.)
  96. ------------------------------------------------------------------------------*/
  97. STDMETHODIMP CExtendedKeyUsage::get_IsPresent (VARIANT_BOOL * pVal)
  98. {
  99. HRESULT hr = S_OK;
  100. DebugTrace("Entering CExtendedKeyUsage::get_IsPresent().\n");
  101. try
  102. {
  103. //
  104. // Lock access to this object.
  105. //
  106. m_Lock.Lock();
  107. //
  108. // Check parameters.
  109. //
  110. if (NULL == pVal)
  111. {
  112. hr = E_INVALIDARG;
  113. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  114. goto ErrorExit;
  115. }
  116. //
  117. // Return result.
  118. //
  119. *pVal = m_bIsPresent;
  120. }
  121. catch(...)
  122. {
  123. hr = E_POINTER;
  124. DebugTrace("Exception: invalid parameter.\n");
  125. goto ErrorExit;
  126. }
  127. UnlockExit:
  128. //
  129. // Unlock access to this object.
  130. //
  131. m_Lock.Unlock();
  132. DebugTrace("Leaving CExtendedKeyUsage::get_IsPresent().\n");
  133. return hr;
  134. ErrorExit:
  135. //
  136. // Sanity check.
  137. //
  138. ATLASSERT(FAILED(hr));
  139. ReportError(hr);
  140. goto UnlockExit;
  141. }
  142. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  143. Function : CExtendedKeyUsage::get_IsCritical
  144. Synopsis : Check to see if the EKU extension is marked critical.
  145. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive result.
  146. Remark :
  147. ------------------------------------------------------------------------------*/
  148. STDMETHODIMP CExtendedKeyUsage::get_IsCritical (VARIANT_BOOL * pVal)
  149. {
  150. HRESULT hr = S_OK;
  151. DebugTrace("Entering CExtendedKeyUsage::get_IsCritical().\n");
  152. try
  153. {
  154. //
  155. // Lock access to this object.
  156. //
  157. m_Lock.Lock();
  158. //
  159. // Check parameters.
  160. //
  161. if (NULL == pVal)
  162. {
  163. hr = E_INVALIDARG;
  164. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  165. goto ErrorExit;
  166. }
  167. //
  168. // Return result.
  169. //
  170. *pVal = m_bIsCritical;
  171. }
  172. catch(...)
  173. {
  174. hr = E_POINTER;
  175. DebugTrace("Exception: invalid parameter.\n");
  176. goto ErrorExit;
  177. }
  178. UnlockExit:
  179. //
  180. // Unlock access to this object.
  181. //
  182. m_Lock.Unlock();
  183. DebugTrace("Leaving CExtendedKeyUsage::get_IsCritical().\n");
  184. return hr;
  185. ErrorExit:
  186. //
  187. // Sanity check.
  188. //
  189. ATLASSERT(FAILED(hr));
  190. ReportError(hr);
  191. goto UnlockExit;
  192. }
  193. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  194. Function : CExtendedKeyUsage::get_EKUs
  195. Synopsis : Return an EKUs collection object representing all EKUs in the
  196. certificate.
  197. Parameter: IEKUs ** pVal - Pointer to pointer to IEKUs to receive the
  198. interface pointer.
  199. Remark :
  200. ------------------------------------------------------------------------------*/
  201. STDMETHODIMP CExtendedKeyUsage::get_EKUs (IEKUs ** pVal)
  202. {
  203. HRESULT hr = S_OK;
  204. DebugTrace("Entering CExtendedKeyUsage::get_EKUs().\n");
  205. try
  206. {
  207. //
  208. // Lock access to this object.
  209. //
  210. m_Lock.Lock();
  211. //
  212. // Check parameters.
  213. //
  214. if (NULL == pVal)
  215. {
  216. hr = E_INVALIDARG;
  217. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  218. goto ErrorExit;
  219. }
  220. //
  221. // Sanity check.
  222. //
  223. ATLASSERT(m_pIEKUs);
  224. //
  225. // Return interface pointer to user.
  226. //
  227. if (FAILED(hr = m_pIEKUs->QueryInterface(pVal)))
  228. {
  229. DebugTrace("Error [%#x]: m_pIEKUs->QueryInterface() failed.\n", hr);
  230. goto ErrorExit;
  231. }
  232. }
  233. catch(...)
  234. {
  235. hr = E_POINTER;
  236. DebugTrace("Exception: invalid parameter.\n");
  237. goto ErrorExit;
  238. }
  239. UnlockExit:
  240. //
  241. // Unlock access to this object.
  242. //
  243. m_Lock.Unlock();
  244. DebugTrace("Leaving CExtendedKeyUsage::get_EKUs().\n");
  245. return hr;
  246. ErrorExit:
  247. //
  248. // Sanity check.
  249. //
  250. ATLASSERT(FAILED(hr));
  251. ReportError(hr);
  252. goto UnlockExit;
  253. }
  254. ////////////////////////////////////////////////////////////////////////////////
  255. //
  256. // Private methods.
  257. //
  258. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  259. Function : CExtendedKeyUsage::Init
  260. Synopsis : Initialize the object.
  261. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
  262. Remark : This method is not part of the COM interface (it is a normal C++
  263. member function). We need it to initialize the object created
  264. internally by us with CERT_CONTEXT.
  265. Since it is only a normal C++ member function, this function can
  266. only be called from a C++ class pointer, not an interface pointer.
  267. ------------------------------------------------------------------------------*/
  268. STDMETHODIMP CExtendedKeyUsage::Init (PCCERT_CONTEXT pCertContext)
  269. {
  270. HRESULT hr = S_OK;
  271. PCERT_ENHKEY_USAGE pUsage = NULL;
  272. VARIANT_BOOL bIsPresent = VARIANT_FALSE;
  273. VARIANT_BOOL bIsCritical = VARIANT_FALSE;
  274. CERT_EXTENSION * pCertExtension;
  275. DebugTrace("Entering CExtendedKeyUsage::Init().\n");
  276. //
  277. // Sanity check.
  278. //
  279. ATLASSERT(pCertContext);
  280. //
  281. // Get EKU usages (extension and property).
  282. //
  283. hr = ::GetEnhancedKeyUsage(pCertContext, 0, &pUsage);
  284. switch (hr)
  285. {
  286. case S_OK:
  287. {
  288. //
  289. // See if EKU present or not, if so, we mark it as PRESENT,
  290. // otherwise, we mark it as NOT PRESENT (which means
  291. // is valid for all usages).
  292. //
  293. if (0 != pUsage->cUsageIdentifier)
  294. {
  295. //
  296. // Mark as present.
  297. //
  298. bIsPresent = VARIANT_TRUE;
  299. }
  300. break;
  301. }
  302. case CERT_E_WRONG_USAGE:
  303. {
  304. //
  305. // No valid usage. So marked as PRESENT.
  306. //
  307. hr = S_OK;
  308. bIsPresent = VARIANT_TRUE;
  309. break;
  310. }
  311. default:
  312. {
  313. DebugTrace("Error [%#x]: GetEnhancedKeyUsage() failed.\n", hr);
  314. goto ErrorExit;
  315. break;
  316. }
  317. }
  318. //
  319. // Find the extension to see if mark critical.
  320. //
  321. if (pCertExtension = ::CertFindExtension(szOID_ENHANCED_KEY_USAGE ,
  322. pCertContext->pCertInfo->cExtension,
  323. pCertContext->pCertInfo->rgExtension))
  324. {
  325. //
  326. // Need to do this since CAPI takes the intersection of EKU with
  327. // EKU extended property, which means we may not have a EKU extension
  328. // in the cert at all.
  329. //
  330. if (pCertExtension->fCritical)
  331. {
  332. bIsCritical = VARIANT_TRUE;
  333. }
  334. }
  335. //
  336. // Create the EKUs collection object.
  337. //
  338. if (FAILED(hr = ::CreateEKUsObject(pUsage, &m_pIEKUs)))
  339. {
  340. DebugTrace("Error [%#x]: CreateEKUsObject() failed.\n", hr);
  341. goto CommonExit;
  342. }
  343. //
  344. // Update member variables.
  345. //
  346. m_bIsPresent = bIsPresent;
  347. m_bIsCritical = bIsCritical;
  348. CommonExit:
  349. //
  350. // Free resource.
  351. //
  352. if (pUsage)
  353. {
  354. ::CoTaskMemFree(pUsage);
  355. }
  356. DebugTrace("Leaving CExtendedKeyUsage::Init().\n");
  357. return hr;
  358. ErrorExit:
  359. //
  360. // Sanity check.
  361. //
  362. ATLASSERT(FAILED(hr));
  363. goto CommonExit;
  364. }