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.

260 lines
7.4 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000 - 2001.
  3. File: MsgHlpr.cpp
  4. Content: Helper functions for messaging.
  5. History: 11-15-99 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "MsgHlpr.h"
  10. ////////////////////////////////////////////////////////////////////////////////
  11. //
  12. // Exported functions.
  13. //
  14. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. Function : GetMsgParam
  16. Synopsis : Allocate memory and retrieve requested message parameter using
  17. CryptGetMsgParam() API.
  18. Parameter: HCRYPTMSG hMsg - Message handler.
  19. DWORD dwMsgType - Message param type to retrieve.
  20. DWORD dwIndex - Index (should be 0 most of the time).
  21. void ** ppvData - Pointer to receive buffer.
  22. DWORD * pcbData - Size of buffer.
  23. Remark :
  24. ------------------------------------------------------------------------------*/
  25. HRESULT GetMsgParam (HCRYPTMSG hMsg,
  26. DWORD dwMsgType,
  27. DWORD dwIndex,
  28. void ** ppvData,
  29. DWORD * pcbData)
  30. {
  31. HRESULT hr = S_OK;
  32. DWORD cbData = 0;
  33. void * pvData = NULL;
  34. DebugTrace("Entering GetMsgParam().\n");
  35. //
  36. // Sanity check.
  37. //
  38. ATLASSERT(ppvData);
  39. ATLASSERT(pcbData);
  40. //
  41. // Determine data buffer size.
  42. //
  43. if (!::CryptMsgGetParam(hMsg,
  44. dwMsgType,
  45. dwIndex,
  46. NULL,
  47. &cbData))
  48. {
  49. hr = HRESULT_FROM_WIN32(::GetLastError());
  50. DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
  51. goto ErrorExit;
  52. }
  53. //
  54. // Allocate memory for buffer.
  55. //
  56. if (!(pvData = (void *) ::CoTaskMemAlloc(cbData)))
  57. {
  58. hr = E_OUTOFMEMORY;
  59. DebugTrace("Error: out of memory.\n");
  60. goto ErrorExit;
  61. }
  62. //
  63. // Now get the data.
  64. //
  65. if (!::CryptMsgGetParam(hMsg,
  66. dwMsgType,
  67. dwIndex,
  68. pvData,
  69. &cbData))
  70. {
  71. hr = HRESULT_FROM_WIN32(::GetLastError());
  72. DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
  73. goto ErrorExit;
  74. }
  75. //
  76. // Return msg param to caller.
  77. //
  78. *ppvData = pvData;
  79. *pcbData = cbData;
  80. CommonExit:
  81. DebugTrace("Leaving GetMsgParam().\n");
  82. return hr;
  83. ErrorExit:
  84. //
  85. // Sanity check.
  86. //
  87. ATLASSERT(FAILED(hr));
  88. //
  89. // Free resources.
  90. //
  91. if (pvData)
  92. {
  93. ::CoTaskMemFree(pvData);
  94. }
  95. goto CommonExit;
  96. }
  97. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  98. Function : FindSignerCertInMessage
  99. Synopsis : Find the signer's cert in the bag of certs of the message for the
  100. specified signer.
  101. Parameter: HCRYPTMSG hMsg - Message handle.
  102. CERT_NAME_BLOB * pIssuerNameBlob - Pointer to issuer' name
  103. blob of signer's cert.
  104. CRYPT_INTEGERT_BLOB * pSerialNumberBlob - Pointer to serial number
  105. blob of signer's cert.
  106. PCERT_CONTEXT * ppCertContext - Pointer to PCERT_CONTEXT
  107. to receive the found
  108. cert, or NULL to only
  109. know the result.
  110. Remark :
  111. ------------------------------------------------------------------------------*/
  112. HRESULT FindSignerCertInMessage (HCRYPTMSG hMsg,
  113. CERT_NAME_BLOB * pIssuerNameBlob,
  114. CRYPT_INTEGER_BLOB * pSerialNumberBlob,
  115. PCERT_CONTEXT * ppCertContext)
  116. {
  117. HRESULT hr = S_OK;
  118. DWORD dwCertCount = 0;
  119. DWORD cbCertCount = sizeof(dwCertCount);
  120. DebugTrace("Entering FindSignerCertInMessage().\n");
  121. //
  122. // Sanity check.
  123. //
  124. ATLASSERT(NULL != hMsg);
  125. ATLASSERT(NULL != pIssuerNameBlob);
  126. ATLASSERT(NULL != pSerialNumberBlob);
  127. ATLASSERT(0 < pIssuerNameBlob->cbData);
  128. ATLASSERT(NULL != pIssuerNameBlob->pbData);
  129. ATLASSERT(0 < pSerialNumberBlob->cbData);
  130. ATLASSERT(NULL != pSerialNumberBlob->pbData);
  131. //
  132. // Get count of certs in message.
  133. //
  134. if (!::CryptMsgGetParam(hMsg,
  135. CMSG_CERT_COUNT_PARAM,
  136. 0,
  137. &dwCertCount,
  138. &cbCertCount))
  139. {
  140. hr = HRESULT_FROM_WIN32(::GetLastError());
  141. DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr);
  142. return hr;
  143. }
  144. //
  145. // See if the signer's cert is in the bag of certs.
  146. //
  147. while (dwCertCount--)
  148. {
  149. PCCERT_CONTEXT pCertContext = NULL;
  150. CRYPT_DATA_BLOB EncodedCertBlob = {0, NULL};
  151. //
  152. // Get a cert from the bag of certs.
  153. //
  154. hr = ::GetMsgParam(hMsg,
  155. CMSG_CERT_PARAM,
  156. dwCertCount,
  157. (void **) &EncodedCertBlob.pbData,
  158. &EncodedCertBlob.cbData);
  159. if (FAILED(hr))
  160. {
  161. DebugTrace("Error [%#x]: GetMsgParam() failed.\n", hr);
  162. return hr;
  163. }
  164. //
  165. // Create a context for the cert.
  166. //
  167. pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  168. (const BYTE *) EncodedCertBlob.pbData,
  169. EncodedCertBlob.cbData);
  170. //
  171. // Free encoded cert blob memory before checking result.
  172. //
  173. ::CoTaskMemFree((LPVOID) EncodedCertBlob.pbData);
  174. if (NULL == pCertContext)
  175. {
  176. hr = HRESULT_FROM_WIN32(::GetLastError());
  177. DebugTrace("Error [%#x]: CertCreateCertificateContext() failed.\n", hr);
  178. return hr;
  179. }
  180. //
  181. // Compare.
  182. //
  183. if (::CertCompareCertificateName(CAPICOM_ASN_ENCODING,
  184. pIssuerNameBlob,
  185. &pCertContext->pCertInfo->Issuer) &&
  186. ::CertCompareIntegerBlob(pSerialNumberBlob,
  187. &pCertContext->pCertInfo->SerialNumber))
  188. {
  189. if (NULL != ppCertContext)
  190. {
  191. *ppCertContext = (PCERT_CONTEXT) pCertContext;
  192. }
  193. else
  194. {
  195. ::CertFreeCertificateContext(pCertContext);
  196. }
  197. return S_OK;
  198. }
  199. else
  200. {
  201. //
  202. // No, keep looking.
  203. //
  204. ::CertFreeCertificateContext(pCertContext);
  205. }
  206. }
  207. //
  208. // If we get here, that means we never found the cert.
  209. //
  210. return CAPICOM_E_SIGNER_NOT_FOUND;
  211. }