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.

690 lines
16 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Template.cpp
  4. Content: Implementation of CTemplate.
  5. History: 10-02-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "Template.h"
  10. #include "OID.h"
  11. #include "Common.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Exported functions.
  15. //
  16. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  17. Function : CreateTemplateObject
  18. Synopsis : Create a ITemplate object and populate the porperties with
  19. data from the key usage extension of the specified certificate.
  20. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
  21. ITemplate ** ppITemplate - Pointer to pointer to ITemplate object.
  22. Remark :
  23. ------------------------------------------------------------------------------*/
  24. HRESULT CreateTemplateObject (PCCERT_CONTEXT pCertContext,
  25. ITemplate ** ppITemplate)
  26. {
  27. HRESULT hr = S_OK;
  28. CComObject<CTemplate> * pCTemplate = NULL;
  29. DebugTrace("Entering CreateTemplateObject().\n");
  30. //
  31. // Sanity check.
  32. //
  33. ATLASSERT(pCertContext);
  34. ATLASSERT(ppITemplate);
  35. try
  36. {
  37. //
  38. // Create the object. Note that the ref count will still be 0
  39. // after the object is created.
  40. //
  41. if (FAILED(hr = CComObject<CTemplate>::CreateInstance(&pCTemplate)))
  42. {
  43. DebugTrace("Error [%#x]: CComObject<CTemplate>::CreateInstance() failed.\n", hr);
  44. goto ErrorExit;
  45. }
  46. //
  47. // Initialize object.
  48. //
  49. if (FAILED(hr = pCTemplate->Init(pCertContext)))
  50. {
  51. DebugTrace("Error [%#x]: pCTemplate::Init() failed.\n", hr);
  52. goto ErrorExit;
  53. }
  54. //
  55. // Return interface pointer to caller.
  56. //
  57. if (FAILED(hr = pCTemplate->QueryInterface(ppITemplate)))
  58. {
  59. DebugTrace("Error [%#x]: pCTemplate->QueryInterface() failed.\n", hr);
  60. goto ErrorExit;
  61. }
  62. }
  63. catch(...)
  64. {
  65. hr = E_POINTER;
  66. DebugTrace("Exception: invalid parameter.\n");
  67. goto ErrorExit;
  68. }
  69. CommonExit:
  70. DebugTrace("Entering CreateTemplateObject().\n");
  71. return hr;
  72. ErrorExit:
  73. //
  74. // Sanity check.
  75. //
  76. ATLASSERT(FAILED(hr));
  77. //
  78. // Free resource.
  79. //
  80. if (pCTemplate)
  81. {
  82. delete pCTemplate;
  83. }
  84. goto CommonExit;
  85. }
  86. ////////////////////////////////////////////////////////////////////////////////
  87. //
  88. // CTemplate
  89. //
  90. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  91. Function : CTemplate::get_IsPresent
  92. Synopsis : Check to see if the template extension is present.
  93. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive result.
  94. Remark :
  95. ------------------------------------------------------------------------------*/
  96. STDMETHODIMP CTemplate::get_IsPresent (VARIANT_BOOL * pVal)
  97. {
  98. HRESULT hr = S_OK;
  99. DebugTrace("Entering CTemplate::get_IsPresent().\n");
  100. try
  101. {
  102. //
  103. // Lock access to this object.
  104. //
  105. m_Lock.Lock();
  106. //
  107. // Return result.
  108. //
  109. *pVal = m_bIsPresent;
  110. }
  111. catch(...)
  112. {
  113. hr = E_POINTER;
  114. DebugTrace("Exception: invalid parameter.\n");
  115. goto ErrorExit;
  116. }
  117. UnlockExit:
  118. //
  119. // Unlock access to this object.
  120. //
  121. m_Lock.Unlock();
  122. DebugTrace("Leaving CTemplate::get_IsPresent().\n");
  123. return hr;
  124. ErrorExit:
  125. //
  126. // Sanity check.
  127. //
  128. ATLASSERT(FAILED(hr));
  129. ReportError(hr);
  130. goto UnlockExit;
  131. }
  132. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  133. Function : CTemplate::get_IsCritical
  134. Synopsis : Check to see if the template extension is marked critical.
  135. Parameter: VARIANT_BOOL * pVal - Pointer to VARIANT_BOOL to receive result.
  136. Remark :
  137. ------------------------------------------------------------------------------*/
  138. STDMETHODIMP CTemplate::get_IsCritical (VARIANT_BOOL * pVal)
  139. {
  140. HRESULT hr = S_OK;
  141. DebugTrace("Entering CTemplate::get_IsCritical().\n");
  142. try
  143. {
  144. //
  145. // Lock access to this object.
  146. //
  147. m_Lock.Lock();
  148. //
  149. // Return result.
  150. //
  151. *pVal = m_bIsCritical;
  152. }
  153. catch(...)
  154. {
  155. hr = E_POINTER;
  156. DebugTrace("Exception: invalid parameter.\n");
  157. goto ErrorExit;
  158. }
  159. UnlockExit:
  160. //
  161. // Unlock access to this object.
  162. //
  163. m_Lock.Unlock();
  164. DebugTrace("Leaving CTemplate::get_IsCritical().\n");
  165. return hr;
  166. ErrorExit:
  167. //
  168. // Sanity check.
  169. //
  170. ATLASSERT(FAILED(hr));
  171. ReportError(hr);
  172. goto UnlockExit;
  173. }
  174. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  175. Function : CTemplate::get_Name
  176. Synopsis : Get the name of szOID_ENROLL_CERTTYPE_EXTENSION.
  177. Parameter: BSTR * pVal - Pointer to BSTR to receive result.
  178. Remark :
  179. ------------------------------------------------------------------------------*/
  180. STDMETHODIMP CTemplate::get_Name (BSTR * pVal)
  181. {
  182. HRESULT hr = S_OK;
  183. DebugTrace("Entering CTemplate::get_Name().\n");
  184. try
  185. {
  186. //
  187. // Lock access to this object.
  188. //
  189. m_Lock.Lock();
  190. //
  191. // Check parameters.
  192. //
  193. if (NULL == pVal)
  194. {
  195. hr = E_INVALIDARG;
  196. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  197. goto ErrorExit;
  198. }
  199. //
  200. // Return result.
  201. //
  202. if (FAILED(hr = m_bstrName.CopyTo(pVal)))
  203. {
  204. DebugTrace("Error [%#x]: m_bstrName.CopyTo() failed.\n", hr);
  205. goto ErrorExit;
  206. }
  207. }
  208. catch(...)
  209. {
  210. hr = E_POINTER;
  211. DebugTrace("Exception: invalid parameter.\n");
  212. goto ErrorExit;
  213. }
  214. UnlockExit:
  215. //
  216. // Unlock access to this object.
  217. //
  218. m_Lock.Unlock();
  219. DebugTrace("Leaving CTemplate::get_Name().\n");
  220. return hr;
  221. ErrorExit:
  222. //
  223. // Sanity check.
  224. //
  225. ATLASSERT(FAILED(hr));
  226. ReportError(hr);
  227. goto UnlockExit;
  228. }
  229. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  230. Function : CTemplate::get_OID
  231. Synopsis : Get the OID for szOID_CERTIFICATE_TEMPLATE.
  232. Parameter: IOID * pVal - Pointer to IOID to receive result.
  233. Remark :
  234. ------------------------------------------------------------------------------*/
  235. STDMETHODIMP CTemplate::get_OID (IOID ** pVal)
  236. {
  237. HRESULT hr = S_OK;
  238. DebugTrace("Entering CTemplate::get_OID().\n");
  239. try
  240. {
  241. //
  242. // Lock access to this object.
  243. //
  244. m_Lock.Lock();
  245. //
  246. // Sanity check.
  247. //
  248. ATLASSERT(m_pIOID);
  249. //
  250. // Return interface pointer to user.
  251. //
  252. if (FAILED(hr = m_pIOID->QueryInterface(pVal)))
  253. {
  254. DebugTrace("Error [%#x]: m_pIOID->QueryInterface() failed.\n", hr);
  255. goto ErrorExit;
  256. }
  257. }
  258. catch(...)
  259. {
  260. hr = E_POINTER;
  261. DebugTrace("Exception: invalid parameter.\n");
  262. goto ErrorExit;
  263. }
  264. UnlockExit:
  265. //
  266. // Unlock access to this object.
  267. //
  268. m_Lock.Unlock();
  269. DebugTrace("Leaving CTemplate::get_OID().\n");
  270. return hr;
  271. ErrorExit:
  272. //
  273. // Sanity check.
  274. //
  275. ATLASSERT(FAILED(hr));
  276. ReportError(hr);
  277. goto UnlockExit;
  278. }
  279. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  280. Function : CTemplate::get_MajorVersion
  281. Synopsis : Return the major version number of szOID_CERTIFICATE_TEMPLATE.
  282. Parameter: long * pVal - Pointer to long to receive value.
  283. Remark :
  284. ------------------------------------------------------------------------------*/
  285. STDMETHODIMP CTemplate::get_MajorVersion (long * pVal)
  286. {
  287. HRESULT hr = S_OK;
  288. DebugTrace("Entering CTemplate::get_MajorVersion().\n");
  289. try
  290. {
  291. //
  292. // Lock access to this object.
  293. //
  294. m_Lock.Lock();
  295. //
  296. // Return result.
  297. //
  298. *pVal = (long) m_dwMajorVersion;
  299. }
  300. catch(...)
  301. {
  302. hr = E_POINTER;
  303. DebugTrace("Exception: invalid parameter.\n");
  304. goto ErrorExit;
  305. }
  306. UnlockExit:
  307. //
  308. // Unlock access to this object.
  309. //
  310. m_Lock.Unlock();
  311. DebugTrace("Leaving CTemplate::get_MajorVersion().\n");
  312. return hr;
  313. ErrorExit:
  314. //
  315. // Sanity check.
  316. //
  317. ATLASSERT(FAILED(hr));
  318. ReportError(hr);
  319. goto UnlockExit;
  320. }
  321. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  322. Function : CTemplate::get_MinorVersion
  323. Synopsis : Return the minor version number of szOID_CERTIFICATE_TEMPLATE.
  324. Parameter: long * pVal - Pointer to long to receive value.
  325. Remark :
  326. ------------------------------------------------------------------------------*/
  327. STDMETHODIMP CTemplate::get_MinorVersion (long * pVal)
  328. {
  329. HRESULT hr = S_OK;
  330. DebugTrace("Entering CTemplate::get_MinorVersion().\n");
  331. try
  332. {
  333. //
  334. // Lock access to this object.
  335. //
  336. m_Lock.Lock();
  337. //
  338. // Return result.
  339. //
  340. *pVal = (long) m_dwMinorVersion;
  341. }
  342. catch(...)
  343. {
  344. hr = E_POINTER;
  345. DebugTrace("Exception: invalid parameter.\n");
  346. goto ErrorExit;
  347. }
  348. UnlockExit:
  349. //
  350. // Unlock access to this object.
  351. //
  352. m_Lock.Unlock();
  353. DebugTrace("Leaving CTemplate::get_MinorVersion().\n");
  354. return hr;
  355. ErrorExit:
  356. //
  357. // Sanity check.
  358. //
  359. ATLASSERT(FAILED(hr));
  360. ReportError(hr);
  361. goto UnlockExit;
  362. }
  363. ////////////////////////////////////////////////////////////////////////////////
  364. //
  365. // Private methods.
  366. //
  367. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  368. Function : CTemplate::Init
  369. Synopsis : Initialize the object.
  370. Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT.
  371. Remark : This method is not part of the COM interface (it is a normal C++
  372. member function). We need it to initialize the object created
  373. internally by us with CERT_CONTEXT.
  374. Since it is only a normal C++ member function, this function can
  375. only be called from a C++ class pointer, not an interface pointer.
  376. ------------------------------------------------------------------------------*/
  377. STDMETHODIMP CTemplate::Init (PCCERT_CONTEXT pCertContext)
  378. {
  379. HRESULT hr = S_OK;
  380. PCERT_EXTENSION pExtension = NULL;
  381. CRYPT_DATA_BLOB CertTypeBlob = {0, NULL};
  382. CRYPT_DATA_BLOB CertTempBlob = {0, NULL};
  383. PCERT_NAME_VALUE pCertType = NULL;
  384. PCERT_TEMPLATE_EXT pCertTemp = NULL;
  385. CComPtr<IOID> pIOID = NULL;
  386. DebugTrace("Entering CTemplate::Init().\n");
  387. //
  388. // Sanity check.
  389. //
  390. ATLASSERT(pCertContext);
  391. //
  392. // Find the szOID_ENROLL_CERTTYPE_EXTENSION extension.
  393. //
  394. if (pExtension = ::CertFindExtension(szOID_ENROLL_CERTTYPE_EXTENSION,
  395. pCertContext->pCertInfo->cExtension,
  396. pCertContext->pCertInfo->rgExtension))
  397. {
  398. //
  399. // Decode the extension.
  400. //
  401. if (FAILED(hr = ::DecodeObject(X509_UNICODE_ANY_STRING,
  402. pExtension->Value.pbData,
  403. pExtension->Value.cbData,
  404. &CertTypeBlob)))
  405. {
  406. //
  407. // Downlevel CryptDecodeObject() would return 0x80070002 if it does
  408. // not know how to decode it. So remap to CAPICOM_E_NOT_SUPPORTED.
  409. //
  410. if ((HRESULT) 0x80070002 == hr)
  411. {
  412. hr = CAPICOM_E_NOT_SUPPORTED;
  413. }
  414. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  415. goto ErrorExit;
  416. }
  417. pCertType = (PCERT_NAME_VALUE) CertTypeBlob.pbData;
  418. //
  419. // Set values.
  420. //
  421. m_bIsPresent = VARIANT_TRUE;
  422. if (pExtension->fCritical)
  423. {
  424. m_bIsCritical = VARIANT_TRUE;
  425. }
  426. if (!(m_bstrName = (LPWSTR) pCertType->Value.pbData))
  427. {
  428. hr = E_OUTOFMEMORY;
  429. DebugTrace("Error [%#x]: m_bstrName = (LPWSTR) pCertType->Value.pbData failed.\n", hr);
  430. goto ErrorExit;
  431. }
  432. }
  433. //
  434. // Find the szOID_CERTIFICATE_TEMPLATE extension.
  435. //
  436. if (pExtension = ::CertFindExtension(szOID_CERTIFICATE_TEMPLATE,
  437. pCertContext->pCertInfo->cExtension,
  438. pCertContext->pCertInfo->rgExtension))
  439. {
  440. //
  441. // Decode the basic constraints extension.
  442. //
  443. if (FAILED(hr = ::DecodeObject(szOID_CERTIFICATE_TEMPLATE,
  444. pExtension->Value.pbData,
  445. pExtension->Value.cbData,
  446. &CertTempBlob)))
  447. {
  448. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  449. goto ErrorExit;
  450. }
  451. pCertTemp = (PCERT_TEMPLATE_EXT) CertTempBlob.pbData;
  452. if (FAILED(hr = ::CreateOIDObject(pCertTemp->pszObjId, TRUE, &pIOID)))
  453. {
  454. DebugTrace("Error [%#x]: CreateOIDObject() failed.\n", hr);
  455. goto ErrorExit;
  456. }
  457. //
  458. // Set values.
  459. //
  460. m_bIsPresent = VARIANT_TRUE;
  461. if (pExtension->fCritical)
  462. {
  463. m_bIsCritical = VARIANT_TRUE;
  464. }
  465. m_dwMajorVersion = pCertTemp->dwMajorVersion;
  466. if (pCertTemp->fMinorVersion)
  467. {
  468. m_dwMinorVersion = pCertTemp->dwMinorVersion;
  469. }
  470. if (0 == m_bstrName.Length())
  471. {
  472. if (FAILED(hr = pIOID->get_FriendlyName(&m_bstrName)))
  473. {
  474. DebugTrace("Error [%#x]: pIOID->get_FriendlyName() failed.\n", hr);
  475. goto ErrorExit;
  476. }
  477. }
  478. }
  479. else
  480. {
  481. if (FAILED(hr = ::CreateOIDObject(NULL, TRUE, &pIOID)))
  482. {
  483. DebugTrace("Error [%#x]: CreateOIDObject() failed.\n", hr);
  484. goto ErrorExit;
  485. }
  486. }
  487. if (!(m_pIOID = pIOID))
  488. {
  489. hr = CAPICOM_E_INTERNAL;
  490. DebugTrace("Error [%#x]: m_pIOID = pIOID failed.\n", hr);
  491. goto ErrorExit;
  492. }
  493. CommonExit:
  494. //
  495. // Free resources.
  496. //
  497. if (CertTypeBlob.pbData)
  498. {
  499. ::CoTaskMemFree((LPVOID) CertTypeBlob.pbData);
  500. }
  501. if (CertTempBlob.pbData)
  502. {
  503. ::CoTaskMemFree((LPVOID) CertTempBlob.pbData);
  504. }
  505. DebugTrace("Leaving CTemplate::Init().\n");
  506. return hr;
  507. ErrorExit:
  508. //
  509. // Sanity check.
  510. //
  511. ATLASSERT(FAILED(hr));
  512. //
  513. // Free resources.
  514. //
  515. if (m_pIOID)
  516. {
  517. m_pIOID.Release();
  518. }
  519. m_bstrName.Empty();
  520. goto CommonExit;
  521. }