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.

610 lines
16 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Signers.cpp
  4. Content: Implementation of CSigners.
  5. History: 11-15-99 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "Signers.h"
  10. #include "CertHlpr.h"
  11. #include "MsgHlpr.h"
  12. #include "Signer2.h"
  13. ////////////////////////////////////////////////////////////////////////////////
  14. //
  15. // Exported functions.
  16. //
  17. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  18. Function : CreateSignersObject
  19. Synopsis : Create an ISigners collection object, and load the object with
  20. signers from the specified signed message for a specified level.
  21. Parameter: HCRYPTMSG hMsg - Message handle.
  22. DWORD dwLevel - Signature level (1 based).
  23. HCERTSTORE hStore - Additional store.
  24. DWORD dwCurrentSafety - Current safety setting.
  25. ISigners ** ppISigners - Pointer to pointer ISigners to receive
  26. interface pointer.
  27. Remark :
  28. ------------------------------------------------------------------------------*/
  29. HRESULT CreateSignersObject (HCRYPTMSG hMsg,
  30. DWORD dwLevel,
  31. HCERTSTORE hStore,
  32. DWORD dwCurrentSafety,
  33. ISigners ** ppISigners)
  34. {
  35. HRESULT hr = S_OK;
  36. CComObject<CSigners> * pCSigners = NULL;
  37. DebugTrace("Entering CreateSignersObject().\n");
  38. //
  39. // Sanity check.
  40. //
  41. ATLASSERT(hMsg);
  42. ATLASSERT(dwLevel);
  43. ATLASSERT(ppISigners);
  44. try
  45. {
  46. //
  47. // Create the object. Note that the ref count will still be 0
  48. // after the object is created.
  49. //
  50. if (FAILED(hr = CComObject<CSigners>::CreateInstance(&pCSigners)))
  51. {
  52. DebugTrace("Error [%#x]: CComObject<CSigners>::CreateInstance() failed.\n", hr);
  53. goto ErrorExit;
  54. }
  55. //
  56. // Now load all signers from the specified signed message.
  57. //
  58. if (FAILED(hr = pCSigners->LoadMsgSigners(hMsg, dwLevel, hStore, dwCurrentSafety)))
  59. {
  60. DebugTrace("Error [%#x]: pCSigners->LoadMsgSigners() failed.\n");
  61. goto ErrorExit;
  62. }
  63. //
  64. // Return ISigners pointer to caller.
  65. //
  66. if (FAILED(hr = pCSigners->QueryInterface(ppISigners)))
  67. {
  68. DebugTrace("Error [%#x]: pCSigners->QueryInterface() failed.\n", hr);
  69. goto ErrorExit;
  70. }
  71. }
  72. catch(...)
  73. {
  74. hr = E_INVALIDARG;
  75. DebugTrace("Exception: invalid parameter.\n");
  76. goto ErrorExit;
  77. }
  78. CommonExit:
  79. DebugTrace("Leaving CreateSignersObject().\n");
  80. return hr;
  81. ErrorExit:
  82. //
  83. // Sanity check.
  84. //
  85. ATLASSERT(FAILED(hr));
  86. //
  87. // Free resource.
  88. //
  89. if (pCSigners)
  90. {
  91. delete pCSigners;
  92. }
  93. goto CommonExit;
  94. }
  95. #if (0)
  96. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  97. Function : CreateSignersObject
  98. Synopsis : Create an ISigners collection object, and load the object with
  99. signers from the specified CRYPT_PROVIDER_DATA.
  100. Parameter: CRYPT_PROVIDER_DATA * pProvData
  101. ISigners ** ppISigners - Pointer to pointer ISigners to receive
  102. interface pointer.
  103. Remark :
  104. ------------------------------------------------------------------------------*/
  105. HRESULT CreateSignersObject (CRYPT_PROVIDER_DATA * pProvData,
  106. ISigners ** ppISigners)
  107. {
  108. HRESULT hr = S_OK;
  109. CComObject<CSigners> * pCSigners = NULL;
  110. DebugTrace("Entering CreateSignersObject().\n");
  111. //
  112. // Sanity check.
  113. //
  114. ATLASSERT(pProvData);
  115. ATLASSERT(ppISigners);
  116. try
  117. {
  118. //
  119. // Create the object. Note that the ref count will still be 0
  120. // after the object is created.
  121. //
  122. if (FAILED(hr = CComObject<CSigners>::CreateInstance(&pCSigners)))
  123. {
  124. DebugTrace("Error [%#x]: CComObject<CSigners>::CreateInstance() failed.\n", hr);
  125. goto ErrorExit;
  126. }
  127. //
  128. // Now load all signers from the specified signed code.
  129. //
  130. if (FAILED(hr = pCSigners->LoadCodeSigners(pProvData)))
  131. {
  132. DebugTrace("Error [%#x]: pCSigners->LoadCodeSigners() failed.\n");
  133. goto ErrorExit;
  134. }
  135. //
  136. // Return ISigners pointer to caller.
  137. //
  138. if (FAILED(hr = pCSigners->QueryInterface(ppISigners)))
  139. {
  140. DebugTrace("Error [%#x]: pCSigners->QueryInterface() failed.\n", hr);
  141. goto ErrorExit;
  142. }
  143. }
  144. catch(...)
  145. {
  146. hr = E_INVALIDARG;
  147. DebugTrace("Exception: invalid parameter.\n");
  148. goto ErrorExit;
  149. }
  150. CommonExit:
  151. DebugTrace("Leaving CreateSignersObject().\n");
  152. return hr;
  153. ErrorExit:
  154. //
  155. // Sanity check.
  156. //
  157. ATLASSERT(FAILED(hr));
  158. //
  159. // Free resource.
  160. //
  161. if (pCSigners)
  162. {
  163. delete pCSigners;
  164. }
  165. goto CommonExit;
  166. }
  167. #endif
  168. /////////////////////////////////////////////////////////////////////////////
  169. //
  170. // CSigners
  171. //
  172. ////////////////////////////////////////////////////////////////////////////////
  173. //
  174. // Non COM functions.
  175. //
  176. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  177. Function : CSigners::Add
  178. Synopsis : Add a signer to the collection.
  179. Parameter: PCCERT_CONTEXT pCertContext - Cert of signer.
  180. CRYPT_ATTRIBUTES * pAuthAttrs - Pointer to CRYPT_ATTRIBUTES
  181. of authenticated attributes.
  182. PCCERT_CHAIN_CONTEXT pChainContext - Chain context.
  183. Remark : This method is not part of the COM interface (it is a normal C++
  184. member function). We need it to initialize the object created
  185. internally by us.
  186. Since it is only a normal C++ member function, this function can
  187. only be called from a C++ class pointer, not an interface pointer.
  188. ------------------------------------------------------------------------------*/
  189. STDMETHODIMP CSigners::Add (PCCERT_CONTEXT pCertContext,
  190. CRYPT_ATTRIBUTES * pAuthAttrs,
  191. PCCERT_CHAIN_CONTEXT pChainContext)
  192. {
  193. HRESULT hr = S_OK;
  194. char szIndex[33];
  195. CComBSTR bstrIndex;
  196. CComPtr<ISigner2> pISigner2 = NULL;
  197. DebugTrace("Entering CSigners::Add().\n");
  198. //
  199. // Sanity check.
  200. //
  201. ATLASSERT(pCertContext);
  202. ATLASSERT(pAuthAttrs);
  203. try
  204. {
  205. //
  206. // Make sure we still have room to add.
  207. //
  208. if ((m_coll.size() + 1) > m_coll.max_size())
  209. {
  210. hr = CAPICOM_E_OUT_OF_RESOURCE;
  211. DebugTrace("Error [%#x]: Maximum entries (%#x) reached for Signers collection.\n",
  212. hr, m_coll.size() + 1);
  213. goto ErrorExit;
  214. }
  215. //
  216. // Create an ISigner object. Note that the ref count will still be 0
  217. // after the object is created.
  218. //
  219. if (FAILED(hr = ::CreateSignerObject(pCertContext,
  220. pAuthAttrs,
  221. pChainContext,
  222. m_dwCurrentSafety,
  223. &pISigner2)))
  224. {
  225. DebugTrace("Error [%#x]: CreateSignerObject() failed.\n", hr);
  226. goto ErrorExit;
  227. }
  228. //
  229. // BSTR index of numeric value.
  230. //
  231. wsprintfA(szIndex, "%#08x", m_coll.size() + 1);
  232. if (!(bstrIndex = szIndex))
  233. {
  234. hr = E_OUTOFMEMORY;
  235. DebugTrace("Error [%#x]: bstrIndex = szIndex failed.\n", hr);
  236. goto ErrorExit;
  237. }
  238. //
  239. // Now add signer to collection map.
  240. //
  241. // Note that the overloaded = operator for CComPtr will
  242. // automatically AddRef to the object. Also, when the CComPtr
  243. // is deleted (happens when the Remove or map destructor is called),
  244. // the CComPtr destructor will automatically Release the object.
  245. //
  246. m_coll[bstrIndex] = pISigner2;
  247. }
  248. catch(...)
  249. {
  250. hr = CAPICOM_E_INTERNAL;
  251. DebugTrace("Exception: internal error.\n");
  252. goto ErrorExit;
  253. }
  254. CommonExit:
  255. DebugTrace("Leaving CSigners::Add().\n");
  256. return hr;
  257. ErrorExit:
  258. //
  259. // Sanity check.
  260. //
  261. ATLASSERT(FAILED(hr));
  262. goto CommonExit;
  263. }
  264. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  265. Function : CSigners::LoadMsgSigners
  266. Synopsis : Load all signers from a specified signed message.
  267. Parameter: HCRYPTMSG hMsg - Message handle.
  268. DWORD dwLevel - Signature level (1-based).
  269. HCERTSTORE hStore - Additional store.
  270. DWORD dwCurrentSafety - Current safety setting.
  271. Remark :
  272. ------------------------------------------------------------------------------*/
  273. STDMETHODIMP CSigners::LoadMsgSigners (HCRYPTMSG hMsg,
  274. DWORD dwLevel,
  275. HCERTSTORE hStore,
  276. DWORD dwCurrentSafety)
  277. {
  278. HRESULT hr = S_OK;
  279. DWORD dwNumSigners = 0;
  280. DWORD cbSigners = sizeof(dwNumSigners);
  281. DWORD dwSigner;
  282. DebugTrace("Entering CSigners::LoadMsgSigners().\n");
  283. //
  284. // Sanity check.
  285. //
  286. ATLASSERT(hMsg);
  287. ATLASSERT(dwLevel);
  288. //
  289. // MUST set current safety first.
  290. //
  291. m_dwCurrentSafety = dwCurrentSafety;
  292. //
  293. // Which signature level?
  294. //
  295. if (1 == dwLevel)
  296. {
  297. //
  298. // Get number of content signers (first level signers).
  299. //
  300. if (!::CryptMsgGetParam(hMsg,
  301. CMSG_SIGNER_COUNT_PARAM,
  302. 0,
  303. (void **) &dwNumSigners,
  304. &cbSigners))
  305. {
  306. hr = HRESULT_FROM_WIN32(::GetLastError());
  307. DebugTrace("Error [%#x]: CryptMsgGetParam() failed to get CMSG_SIGNER_COUNT_PARAM.\n", hr);
  308. goto ErrorExit;
  309. }
  310. //
  311. // Go through each content signer.
  312. //
  313. for (dwSigner = 0; dwSigner < dwNumSigners; dwSigner++)
  314. {
  315. PCERT_CONTEXT pCertContext = NULL;
  316. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  317. CMSG_SIGNER_INFO * pSignerInfo = NULL;
  318. CRYPT_DATA_BLOB SignerInfoBlob = {0, NULL};
  319. //
  320. // Get signer info.
  321. //
  322. if (FAILED(hr = ::GetMsgParam(hMsg,
  323. CMSG_SIGNER_INFO_PARAM,
  324. dwSigner,
  325. (void**) &SignerInfoBlob.pbData,
  326. &SignerInfoBlob.cbData)))
  327. {
  328. DebugTrace("Error [%#x]: GetMsgParam() failed to get CMSG_SIGNER_INFO_PARAM for signer #%d.\n", hr, dwSigner);
  329. goto ErrorExit;
  330. }
  331. pSignerInfo = (CMSG_SIGNER_INFO *) SignerInfoBlob.pbData;
  332. //
  333. // Find the cert in the message.
  334. //
  335. if (FAILED(hr = ::FindSignerCertInMessage(hMsg,
  336. &pSignerInfo->Issuer,
  337. &pSignerInfo->SerialNumber,
  338. &pCertContext)))
  339. {
  340. ::CoTaskMemFree(SignerInfoBlob.pbData);
  341. DebugTrace("Error [%#x]: FindSignerCertInMessage() failed.\n", hr);
  342. goto ErrorExit;
  343. }
  344. //
  345. // Build the chain.
  346. //
  347. if (FAILED(hr = ::BuildChain(pCertContext,
  348. hStore,
  349. CERT_CHAIN_POLICY_BASE,
  350. &pChainContext)))
  351. {
  352. DebugTrace("Error [%#x]: BuildChain() failed.\n", hr);
  353. goto ErrorExit;
  354. }
  355. //
  356. // Add the signer.
  357. //
  358. hr = Add((PCERT_CONTEXT) pCertContext, &pSignerInfo->AuthAttrs, pChainContext);
  359. ::CertFreeCertificateChain(pChainContext);
  360. ::CertFreeCertificateContext(pCertContext);
  361. ::CoTaskMemFree(SignerInfoBlob.pbData);
  362. if (FAILED(hr))
  363. {
  364. DebugTrace("Error [%#x]: CSigners::Add() failed.\n", hr);
  365. goto ErrorExit;
  366. }
  367. }
  368. }
  369. else
  370. {
  371. //
  372. // For version 1 and 2, should never reach here.
  373. //
  374. hr = CAPICOM_E_INTERNAL;
  375. goto CommonExit;
  376. }
  377. CommonExit:
  378. DebugTrace("Leaving CSigners::LoadMsgSigners().\n");
  379. return hr;
  380. ErrorExit:
  381. //
  382. // Sanity check.
  383. //
  384. ATLASSERT(FAILED(hr));
  385. //
  386. // Free resources.
  387. //
  388. m_coll.clear();
  389. goto CommonExit;
  390. }
  391. #if (0)
  392. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  393. Function : CSigners::LoadCodeSigners
  394. Synopsis : Load all signers from a specified signed code.
  395. Parameter: CRYPT_PROVIDER_DATA * pProvData
  396. Remark :
  397. ------------------------------------------------------------------------------*/
  398. STDMETHODIMP CSigners::LoadCodeSigners (CRYPT_PROVIDER_DATA * pProvData)
  399. {
  400. HRESULT hr = S_OK;
  401. PCRYPT_PROVIDER_SGNR pProvSigner = NULL;
  402. PCRYPT_PROVIDER_CERT pProvCert = NULL;
  403. DebugTrace("Entering CSigners::LoadCodeSigners().\n");
  404. //
  405. // Sanity check.
  406. //
  407. ATLASSERT(pProvData);
  408. //
  409. // Get provider signer data.
  410. //
  411. if (!(pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
  412. {
  413. hr = CAPICOM_E_INTERNAL;
  414. DebugTrace("Internal error [%#x]: WTHelperGetProvSignerFromChain() failed.\n", hr);
  415. goto ErrorExit;
  416. }
  417. if (!(pProvCert = WTHelperGetProvCertFromChain(pProvSigner, 0)))
  418. {
  419. hr = CAPICOM_E_INTERNAL;
  420. DebugTrace("Internal error [%#x]: WTHelperGetProvCertFromChain() failed.\n", hr);
  421. goto ErrorExit;
  422. }
  423. //
  424. // Add the signer.
  425. //
  426. if (FAILED(hr = Add(pProvCert->pCert, &pProvSigner->psSigner->AuthAttrs, pProvSigner->pChainContext)))
  427. {
  428. hr = CAPICOM_E_INTERNAL;
  429. DebugTrace("Internal error [%#x]: CSigners::Add() failed.\n", hr);
  430. goto ErrorExit;
  431. }
  432. //
  433. // Add timestamper if available.
  434. //
  435. // Note: Authenticode only supports one counter signer (the timestamper).
  436. //
  437. if (pProvSigner->csCounterSigners)
  438. {
  439. //
  440. // Sanity check.
  441. //
  442. ATLASSERT(1 == pProvSigner->csCounterSigners);
  443. if (!(pProvCert = WTHelperGetProvCertFromChain(pProvSigner->pasCounterSigners, 0)))
  444. {
  445. hr = CAPICOM_E_INTERNAL;
  446. DebugTrace("Internal error [%#x]: WTHelperGetProvCertFromChain() failed.\n", hr);
  447. goto ErrorExit;
  448. }
  449. //
  450. // Add the signer.
  451. //
  452. if (FAILED(hr = Add(pProvCert->pCert,
  453. &pProvSigner->pasCounterSigners->psSigner->AuthAttrs,
  454. pProvSigner->pasCounterSigners->pChainContext)))
  455. {
  456. hr = CAPICOM_E_INTERNAL;
  457. DebugTrace("Internal error [%#x]: CSigners::Add() failed.\n", hr);
  458. goto ErrorExit;
  459. }
  460. }
  461. CommonExit:
  462. DebugTrace("Leaving CSigners::LoadCodeSigners().\n");
  463. return hr;
  464. ErrorExit:
  465. //
  466. // Sanity check.
  467. //
  468. ATLASSERT(FAILED(hr));
  469. //
  470. // Free resources.
  471. //
  472. m_coll.clear();
  473. goto CommonExit;
  474. }
  475. #endif