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.

801 lines
20 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Attribute.cpp
  4. Content: Implementation of CAttribute.
  5. History: 11-15-99 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "Attribute.h"
  10. #include "Common.h"
  11. #include "Convert.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Exported functions.
  15. //
  16. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  17. Function : CreateAttributebject
  18. Synopsis : Create an IAttribute object and initialize the object with data
  19. from the specified attribute.
  20. Parameter: CRYPT_ATTRIBUTE * pAttribute - Pointer to CRYPT_ATTRIBUTE.
  21. IAttribute ** ppIAttribute - Pointer to pointer IAttribute object.
  22. Remark :
  23. ------------------------------------------------------------------------------*/
  24. HRESULT CreateAttributeObject (CRYPT_ATTRIBUTE * pAttribute,
  25. IAttribute ** ppIAttribute)
  26. {
  27. HRESULT hr = S_OK;
  28. CAPICOM_ATTRIBUTE AttrName;
  29. CComVariant varValue;
  30. CComObject<CAttribute> * pCAttribute = NULL;
  31. DebugTrace("Entering CreateAttributeObject().\n");
  32. //
  33. // Sanity check.
  34. //
  35. ATLASSERT(pAttribute);
  36. ATLASSERT(ppIAttribute);
  37. try
  38. {
  39. //
  40. // Create the object. Note that the ref count will still be 0
  41. // after the object is created.
  42. //
  43. if (FAILED(hr = CComObject<CAttribute>::CreateInstance(&pCAttribute)))
  44. {
  45. DebugTrace("Error [%#x]: CComObject<CAttribute>::CreateInstance() failed.\n", hr);
  46. goto ErrorExit;
  47. }
  48. //
  49. // Determine OID value.
  50. //
  51. if (0 == ::strcmp(pAttribute->pszObjId, szOID_RSA_signingTime))
  52. {
  53. DATE SigningTime;
  54. SYSTEMTIME st;
  55. CRYPT_DATA_BLOB FileTimeBlob = {0, NULL};
  56. if (FAILED(hr = ::DecodeObject(szOID_RSA_signingTime,
  57. pAttribute->rgValue->pbData,
  58. pAttribute->rgValue->cbData,
  59. &FileTimeBlob)))
  60. {
  61. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  62. goto ErrorExit;
  63. }
  64. if (!::FileTimeToSystemTime((FILETIME *) FileTimeBlob.pbData, &st) ||
  65. !::SystemTimeToVariantTime(&st, &SigningTime))
  66. {
  67. hr = HRESULT_FROM_WIN32(::GetLastError());
  68. ::CoTaskMemFree(FileTimeBlob.pbData);
  69. DebugTrace("Error [%#x]: unable to convert FILETIME to DATE.\n", hr);
  70. goto ErrorExit;
  71. }
  72. ::CoTaskMemFree(FileTimeBlob.pbData);
  73. AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
  74. varValue = SigningTime;
  75. varValue.ChangeType(VT_DATE, NULL);
  76. }
  77. else if (0 == ::strcmp(pAttribute->pszObjId, szOID_CAPICOM_DOCUMENT_NAME))
  78. {
  79. CComBSTR bstrName;
  80. CRYPT_DATA_BLOB NameBlob = {0, NULL};
  81. if (FAILED(hr = ::DecodeObject(X509_OCTET_STRING,
  82. pAttribute->rgValue->pbData,
  83. pAttribute->rgValue->cbData,
  84. &NameBlob)))
  85. {
  86. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  87. goto ErrorExit;
  88. }
  89. if (FAILED(hr = ::BlobToBstr((DATA_BLOB *) NameBlob.pbData, &bstrName)))
  90. {
  91. ::CoTaskMemFree(NameBlob.pbData);
  92. DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr);
  93. goto ErrorExit;
  94. }
  95. ::CoTaskMemFree(NameBlob.pbData);
  96. AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME;
  97. varValue = bstrName;
  98. }
  99. else if (0 == ::strcmp(pAttribute->pszObjId, szOID_CAPICOM_DOCUMENT_DESCRIPTION))
  100. {
  101. CComBSTR bstrDesc;
  102. CRYPT_DATA_BLOB DescBlob = {0, NULL};
  103. if (FAILED(hr = ::DecodeObject(X509_OCTET_STRING,
  104. pAttribute->rgValue->pbData,
  105. pAttribute->rgValue->cbData,
  106. &DescBlob)))
  107. {
  108. DebugTrace("Error [%#x]: DecodeObject() failed.\n", hr);
  109. goto ErrorExit;
  110. }
  111. if (FAILED(hr = ::BlobToBstr((DATA_BLOB *) DescBlob.pbData, &bstrDesc)))
  112. {
  113. ::CoTaskMemFree(DescBlob.pbData);
  114. DebugTrace("Error [%#x]: BlobToBstr() failed.\n", hr);
  115. goto ErrorExit;
  116. }
  117. ::CoTaskMemFree(DescBlob.pbData);
  118. AttrName = CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION;
  119. varValue = bstrDesc;
  120. }
  121. else
  122. {
  123. hr = CAPICOM_E_ATTRIBUTE_INVALID_NAME;
  124. DebugTrace("Error [%#x]: Unknown attribute OID (%#s).\n", hr, pAttribute->pszObjId);
  125. goto ErrorExit;
  126. }
  127. //
  128. // Initialize object.
  129. //
  130. if (FAILED(hr = pCAttribute->Init(AttrName, pAttribute->pszObjId, varValue)))
  131. {
  132. DebugTrace("Error [%#x]: pCAttribute->Init() failed.\n", hr);
  133. goto ErrorExit;
  134. }
  135. //
  136. // Return interface pointer to caller.
  137. //
  138. if (FAILED(hr = pCAttribute->QueryInterface(ppIAttribute)))
  139. {
  140. DebugTrace("Error [%#x]: pCAttribute->QueryInterface() failed.\n", hr);
  141. goto ErrorExit;
  142. }
  143. }
  144. catch(...)
  145. {
  146. hr = E_POINTER;
  147. DebugTrace("Exception: invalid parameter.\n");
  148. goto ErrorExit;
  149. }
  150. CommonExit:
  151. DebugTrace("Leaving CreateAttributeObject().\n");
  152. return hr;
  153. ErrorExit:
  154. //
  155. // Sanity check.
  156. //
  157. ATLASSERT(FAILED(hr));
  158. if (pCAttribute)
  159. {
  160. delete pCAttribute;
  161. }
  162. goto CommonExit;
  163. }
  164. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  165. Function : AttributePairIsValid
  166. Synopsis : Check to see if an attribute name and value pair is valid.
  167. Parameter: CAPICOM_ATTRIBUTE AttrName - Attribute name.
  168. VARIANT varValue - Attribute value.
  169. Remark :
  170. ------------------------------------------------------------------------------*/
  171. HRESULT AttributePairIsValid (CAPICOM_ATTRIBUTE AttrName,
  172. VARIANT varValue)
  173. {
  174. HRESULT hr = S_OK;
  175. DebugTrace("Entering AttributePairIsValid()");
  176. //
  177. // Check attribute name and value pair validity.
  178. //
  179. switch (AttrName)
  180. {
  181. case CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME:
  182. {
  183. if (VT_DATE != varValue.vt)
  184. {
  185. hr = CAPICOM_E_ATTRIBUTE_INVALID_VALUE;
  186. DebugTrace("Error [%#x]: attribute name and value type does not match.\n", hr);
  187. }
  188. break;
  189. }
  190. case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME:
  191. case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION:
  192. {
  193. if (VT_BSTR != varValue.vt)
  194. {
  195. hr = CAPICOM_E_ATTRIBUTE_INVALID_VALUE;
  196. DebugTrace("Error [%#x]: attribute data type does not match attribute name type, expecting a BSTR variant.\n", hr);
  197. }
  198. break;
  199. }
  200. default:
  201. {
  202. hr = CAPICOM_E_ATTRIBUTE_INVALID_NAME;
  203. DebugTrace("Error [%#x]: unknown attribute name (%#x).\n", hr, AttrName);
  204. break;
  205. }
  206. }
  207. DebugTrace("Leaving AttributePairIsValid().\n");
  208. return hr;
  209. }
  210. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  211. Function : AttributeIsValid
  212. Synopsis : Check to see if an attribute is valid.
  213. Parameter: IAttribute * pVal - Attribute to be checked.
  214. Remark :
  215. ------------------------------------------------------------------------------*/
  216. HRESULT AttributeIsValid (IAttribute * pAttribute)
  217. {
  218. HRESULT hr = S_OK;
  219. CAPICOM_ATTRIBUTE AttrName;
  220. CComVariant varValue;
  221. DebugTrace("Entering AttributeIsValid()");
  222. //
  223. // Sanity check.
  224. //
  225. ATLASSERT(pAttribute);
  226. //
  227. // Get attribute name.
  228. //
  229. if (FAILED(hr = pAttribute->get_Name(&AttrName)))
  230. {
  231. DebugTrace("Error [%#x]: pVal->get_Name() failed.\n", hr);
  232. goto ErrorExit;
  233. }
  234. //
  235. // Get attribute value.
  236. //
  237. if (FAILED(hr = pAttribute->get_Value(&varValue)))
  238. {
  239. DebugTrace("Error [%#x]: pVal->get_Value() failed.\n", hr);
  240. goto ErrorExit;
  241. }
  242. //
  243. // Check attribute name and value pair validity.
  244. //
  245. if (FAILED(hr = AttributePairIsValid(AttrName, varValue)))
  246. {
  247. DebugTrace("Error [%#x]: AttributePairIsValid() failed.\n", hr);
  248. goto ErrorExit;
  249. }
  250. CommonExit:
  251. DebugTrace("Leaving AttributeIsValid().\n");
  252. return hr;
  253. ErrorExit:
  254. //
  255. // Sanity check.
  256. //
  257. ATLASSERT(FAILED(hr));
  258. goto CommonExit;
  259. }
  260. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  261. Function : AttributeIsSupported
  262. Synopsis : Check to see if an attribute is supported.
  263. Parameter: LPSTR pszObjId - Pointer to attribute OID.
  264. Remark :
  265. ------------------------------------------------------------------------------*/
  266. BOOL AttributeIsSupported (LPSTR pszObjId)
  267. {
  268. //
  269. // Sanity check.
  270. //
  271. ATLASSERT(pszObjId);
  272. return (0 == ::strcmp(pszObjId, szOID_RSA_signingTime) ||
  273. 0 == ::strcmp(pszObjId, szOID_CAPICOM_DOCUMENT_NAME) ||
  274. 0 == ::strcmp(pszObjId, szOID_CAPICOM_DOCUMENT_DESCRIPTION));
  275. }
  276. ///////////////////////////////////////////////////////////////////////////////
  277. //
  278. // CAttribute
  279. //
  280. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  281. Function : CAttribute::get_Name
  282. Synopsis : Return the name of the attribute.
  283. Parameter: CAPICOM_ATTRIBUTE * pVal - Pointer to CAPICOM_ATTRIBUTE to receive
  284. result.
  285. Remark :
  286. ------------------------------------------------------------------------------*/
  287. STDMETHODIMP CAttribute::get_Name (CAPICOM_ATTRIBUTE * pVal)
  288. {
  289. HRESULT hr = S_OK;
  290. DebugTrace("Entering CAttribute::get_Name().\n");
  291. try
  292. {
  293. //
  294. // Lock access to this object.
  295. //
  296. m_Lock.Lock();
  297. //
  298. // Check parameters.
  299. //
  300. if (NULL == pVal)
  301. {
  302. hr = E_INVALIDARG;
  303. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  304. goto ErrorExit;
  305. }
  306. //
  307. // Make sure it is initialized.
  308. //
  309. if (!m_bInitialized)
  310. {
  311. hr = CAPICOM_E_ATTRIBUTE_NAME_NOT_INITIALIZED;
  312. DebugTrace("Error [%#x]: attribute name has not been initialized.\n", hr);
  313. goto ErrorExit;
  314. }
  315. //
  316. // Return result.
  317. //
  318. *pVal = m_AttrName;
  319. }
  320. catch(...)
  321. {
  322. hr = E_POINTER;
  323. DebugTrace("Exception: invalid parameter.\n");
  324. goto ErrorExit;
  325. }
  326. UnlockExit:
  327. //
  328. // Unlock access to this object.
  329. //
  330. m_Lock.Unlock();
  331. DebugTrace("Leaving CAttribute::get_Name().\n");
  332. return hr;
  333. ErrorExit:
  334. //
  335. // Sanity check.
  336. //
  337. ATLASSERT(FAILED(hr));
  338. ReportError(hr);
  339. goto UnlockExit;
  340. }
  341. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  342. Function : CAttribute::put_Name
  343. Synopsis : Set attribute enum name.
  344. Parameter: CAPICOM_ATTRIBUTE newVal - attribute enum name.
  345. Remark :
  346. ------------------------------------------------------------------------------*/
  347. STDMETHODIMP CAttribute::put_Name (CAPICOM_ATTRIBUTE newVal)
  348. {
  349. HRESULT hr = S_OK;
  350. DebugTrace("Entering CAttribute::put_Name().\n");
  351. //
  352. // Lock access to this object.
  353. //
  354. m_Lock.Lock();
  355. //
  356. // Reset value based on EKU name.
  357. //
  358. switch (newVal)
  359. {
  360. case CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME:
  361. {
  362. if (!(m_bstrOID = szOID_RSA_signingTime))
  363. {
  364. hr = E_OUTOFMEMORY;
  365. DebugTrace("Error [%#x]: m_bstrOID = szOID_RSA_signingTime failed.\n", hr);
  366. goto ErrorExit;
  367. }
  368. break;
  369. }
  370. case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME:
  371. {
  372. if (!(m_bstrOID = szOID_CAPICOM_DOCUMENT_NAME))
  373. {
  374. hr = E_OUTOFMEMORY;
  375. DebugTrace("Error [%#x]: m_bstrOID = szOID_CAPICOM_DOCUMENT_NAME failed.\n", hr);
  376. goto ErrorExit;
  377. }
  378. break;
  379. }
  380. case CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION:
  381. {
  382. if (!(m_bstrOID = szOID_CAPICOM_DOCUMENT_DESCRIPTION))
  383. {
  384. hr = E_OUTOFMEMORY;
  385. DebugTrace("Error [%#x]: m_bstrOID = szOID_CAPICOM_DOCUMENT_DESCRIPTION failed.\n", hr);
  386. goto ErrorExit;
  387. }
  388. break;
  389. }
  390. default:
  391. {
  392. hr = E_INVALIDARG;
  393. DebugTrace("Error [%#x]: Unknown attribute name (%#x).\n", hr, newVal);
  394. goto ErrorExit;
  395. }
  396. }
  397. //
  398. // Store name.
  399. //
  400. m_AttrName = newVal;
  401. m_varValue.Clear();
  402. m_bInitialized = TRUE;
  403. UnlockExit:
  404. //
  405. // Unlock access to this object.
  406. //
  407. m_Lock.Unlock();
  408. DebugTrace("Leaving CAttribute::put_Name().\n");
  409. return hr;
  410. ErrorExit:
  411. //
  412. // Sanity check.
  413. //
  414. ATLASSERT(FAILED(hr));
  415. ReportError(hr);
  416. goto UnlockExit;
  417. }
  418. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  419. Function : CAttribute::get_Value
  420. Synopsis : Return the actual value of the attribute.
  421. Parameter: VARIANT * pVal - Pointer to VARIANT to receive value.
  422. Remark : Note: value type varies depending on the attribute type. For
  423. example, szOID_RSA_SigningTime would have a DATE value.
  424. ------------------------------------------------------------------------------*/
  425. STDMETHODIMP CAttribute::get_Value (VARIANT * pVal)
  426. {
  427. HRESULT hr = S_OK;
  428. DebugTrace("Entering CAttribute::get_Value().\n");
  429. try
  430. {
  431. //
  432. // Lock access to this object.
  433. //
  434. m_Lock.Lock();
  435. //
  436. // Check parameters.
  437. //
  438. if (NULL == pVal)
  439. {
  440. hr = E_INVALIDARG;
  441. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  442. goto ErrorExit;
  443. }
  444. //
  445. // Make sure it was set.
  446. //
  447. if (VT_EMPTY == m_varValue.vt)
  448. {
  449. hr = CAPICOM_E_ATTRIBUTE_VALUE_NOT_INITIALIZED;
  450. DebugTrace("Error [%#x]: attribute value has not been initialized.\n", hr);
  451. goto ErrorExit;
  452. }
  453. //
  454. // Return result.
  455. //
  456. if (FAILED(hr = ::VariantCopy(pVal, &m_varValue)))
  457. {
  458. DebugTrace("Error [%#x]: VariantCopy() failed.\n", hr);
  459. goto ErrorExit;
  460. }
  461. }
  462. catch(...)
  463. {
  464. hr = E_POINTER;
  465. DebugTrace("Exception: invalid parameter.\n");
  466. goto ErrorExit;
  467. }
  468. UnlockExit:
  469. //
  470. // Unlock access to this object.
  471. //
  472. m_Lock.Unlock();
  473. DebugTrace("Leaving CAttribute::get_Value().\n");
  474. return hr;
  475. ErrorExit:
  476. //
  477. // Sanity check.
  478. //
  479. ATLASSERT(FAILED(hr));
  480. ReportError(hr);
  481. goto UnlockExit;
  482. return S_OK;
  483. }
  484. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  485. Function : CAttribute::put_Value
  486. Synopsis : Set attribute value.
  487. Parameter: VARIANT newVal - attribute value.
  488. Remark : Note: value type varies depending on the attribute type. For
  489. example, szOID_RSA_SigningTime would have a DATE value.
  490. ------------------------------------------------------------------------------*/
  491. STDMETHODIMP CAttribute::put_Value (VARIANT newVal)
  492. {
  493. HRESULT hr = S_OK;
  494. DebugTrace("Entering CAttribute::put_Value().\n");
  495. try
  496. {
  497. //
  498. // Lock access to this object.
  499. //
  500. m_Lock.Lock();
  501. //
  502. // Make sure it is initialized.
  503. //
  504. if (!m_bInitialized)
  505. {
  506. hr = CAPICOM_E_ATTRIBUTE_NAME_NOT_INITIALIZED;
  507. DebugTrace("Error [%#x]: attribute name has not been initialized.\n", hr);
  508. goto ErrorExit;
  509. }
  510. //
  511. // Make sure data type matches attribute type.
  512. //
  513. if (FAILED(hr = AttributePairIsValid(m_AttrName, newVal)))
  514. {
  515. DebugTrace("Error [%#x]: AttributePairIsValid() failed.\n", hr);
  516. goto ErrorExit;
  517. }
  518. //
  519. // Store value.
  520. //
  521. m_varValue = newVal;
  522. }
  523. catch(...)
  524. {
  525. hr = E_POINTER;
  526. DebugTrace("Exception: invalid parameter.\n");
  527. goto ErrorExit;
  528. }
  529. UnlockExit:
  530. //
  531. // Unlock access to this object.
  532. //
  533. m_Lock.Unlock();
  534. DebugTrace("Leaving CAttribute::put_Value().\n");
  535. return hr;
  536. ErrorExit:
  537. //
  538. // Sanity check.
  539. //
  540. ATLASSERT(FAILED(hr));
  541. ReportError(hr);
  542. goto UnlockExit;
  543. }
  544. ////////////////////////////////////////////////////////////////////////////////
  545. //
  546. // Private methods.
  547. //
  548. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  549. Function : CAttribute::Init
  550. Synopsis : Initialize the object.
  551. Parameter: DWORD AttrName - Enum name of Attribute.
  552. LPSTR lpszOID - Attribute OID string.
  553. VARIANT varValue - Value of attribute (data type depends on
  554. the type of attribute).
  555. Remark : This method is not part of the COM interface (it is a normal C++
  556. member function). We need it to initialize the object created
  557. internally by us with CERT_CONTEXT.
  558. Since it is only a normal C++ member function, this function can
  559. only be called from a C++ class pointer, not an interface pointer.
  560. ------------------------------------------------------------------------------*/
  561. STDMETHODIMP CAttribute::Init (CAPICOM_ATTRIBUTE AttrName,
  562. LPSTR lpszOID,
  563. VARIANT varValue)
  564. {
  565. HRESULT hr = S_OK;
  566. DebugTrace("Entering CAttribute::Init().\n");
  567. //
  568. // Sanity check.
  569. //
  570. ATLASSERT(lpszOID);
  571. //
  572. // Init private members.
  573. //
  574. if (!(m_bstrOID = lpszOID))
  575. {
  576. hr = E_OUTOFMEMORY;
  577. DebugTrace("Error [%#x]: m_bstrOID = lpszOID failed.\n", hr);
  578. goto ErrorExit;
  579. }
  580. m_bInitialized = TRUE;
  581. m_AttrName = AttrName;
  582. m_varValue = varValue;
  583. CommonExit:
  584. DebugTrace("Leaving CAttribute::Init().\n");
  585. return hr;
  586. ErrorExit:
  587. //
  588. // Sanity check.
  589. //
  590. ATLASSERT(FAILED(hr));
  591. //
  592. // Free resources.
  593. //
  594. m_bstrOID.Empty();
  595. goto CommonExit;
  596. }