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.

278 lines
8.4 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
  3. File: Policy.cpp
  4. Content: Implementation of various policy callbacks.
  5. History: 10-28-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "Policy.h"
  10. #include "CertHlpr.h"
  11. #include "Common.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Local functions.
  15. //
  16. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  17. Function : HasSigningCapability()
  18. Synopsis : Check to see if the cert has basic signing capability.
  19. certs.
  20. Parameter: PCCERT_CONTEXT pCertContext - cert context.
  21. Remark :
  22. ------------------------------------------------------------------------------*/
  23. static BOOL HasSigningCapability (PCCERT_CONTEXT pCertContext)
  24. {
  25. DWORD cb = 0;
  26. int nValidity = 0;
  27. //
  28. // Sanity check.
  29. //
  30. ATLASSERT(pCertContext);
  31. //
  32. // Check availability of private key.
  33. //
  34. if (!::CertGetCertificateContextProperty(pCertContext,
  35. CERT_KEY_PROV_INFO_PROP_ID,
  36. NULL,
  37. &cb))
  38. {
  39. DebugTrace("Info: HasSigningCapability() - private key not found.\n");
  40. return FALSE;
  41. }
  42. //
  43. // Check cert time validity.
  44. //
  45. if (0 != (nValidity = ::CertVerifyTimeValidity(NULL, pCertContext->pCertInfo)))
  46. {
  47. DebugTrace("Info: HasSigningCapability() - invalid time (%s).\n",
  48. nValidity < 0 ? "not yet valid" : "expired");
  49. return FALSE;
  50. }
  51. return TRUE;
  52. }
  53. ////////////////////////////////////////////////////////////////////////////////
  54. //
  55. // Export functions.
  56. //
  57. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  58. Function : FindDataSigningCertCallback
  59. Synopsis : Callback routine for data signing certs filtering.
  60. Parameter: See CryptUI.h for defination.
  61. Remark : Filter out any cert that is not time valid or has no associated
  62. private key. In the future we should also consider filtering out
  63. certs that do not have signing capability.
  64. Also, note that we are not building chain here, since chain
  65. building is costly, and thus present poor user's experience.
  66. ------------------------------------------------------------------------------*/
  67. BOOL WINAPI FindDataSigningCertCallback (PCCERT_CONTEXT pCertContext,
  68. BOOL * pfInitialSelectedCert,
  69. void * pvCallbackData)
  70. {
  71. BOOL bInclude = FALSE;
  72. DebugTrace("Entering FindDataSigningCertCallback().\n");
  73. //
  74. // Sanity check.
  75. //
  76. ATLASSERT(pCertContext);
  77. //
  78. // First make sure it has basic signing capability.
  79. //
  80. if (!::HasSigningCapability(pCertContext))
  81. {
  82. DebugTrace("Info: FindDataSigningCertCallback() - no basic signing capability..\n");
  83. goto CommonExit;
  84. }
  85. bInclude = TRUE;
  86. CommonExit:
  87. DebugTrace("Leaving FindDataSigningCertCallback().\n");
  88. return bInclude;
  89. }
  90. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  91. Function : FindAuthenticodeCertCallback
  92. Synopsis : Callback routine for Authenticode certs filtering.
  93. Parameter: See CryptUI.h for defination.
  94. Remark : Filter out any cert that is not time valid, has no associated
  95. private key, or code signing OID.
  96. Also, note that we are not building chain here, since chain
  97. building is costly, and thus present poor user's experience.
  98. Instead, we will build the chain and check validity of the cert
  99. selected (see GetSignerCert function).
  100. ------------------------------------------------------------------------------*/
  101. BOOL WINAPI FindAuthenticodeCertCallback (PCCERT_CONTEXT pCertContext,
  102. BOOL * pfInitialSelectedCert,
  103. void * pvCallbackData)
  104. {
  105. HRESULT hr = S_OK;
  106. BOOL bInclude = FALSE;
  107. CRYPT_DATA_BLOB DataBlob = {0, NULL};
  108. PCERT_ENHKEY_USAGE pUsage = NULL;
  109. DebugTrace("Entering FindAuthenticodeCertCallback().\n");
  110. //
  111. // First make sure it has basic signing capability.
  112. //
  113. if (!::HasSigningCapability(pCertContext))
  114. {
  115. DebugTrace("Info: FindAuthenticodeCertCallback() - no basic signing capability..\n");
  116. goto CommonExit;
  117. }
  118. //
  119. // Get EKU (extension and property).
  120. //
  121. if (FAILED(hr = ::GetEnhancedKeyUsage(pCertContext, 0, &pUsage)))
  122. {
  123. DebugTrace("Info: FindAuthenticodeCertCallback() - GetEnhancedKeyUsage() failed.\n", hr);
  124. goto CommonExit;
  125. }
  126. //
  127. // Any usage?
  128. //
  129. if (!pUsage)
  130. {
  131. DebugTrace("Info: FindAuthenticodeCertCallback() - not valid for any usage.\n");
  132. goto CommonExit;
  133. }
  134. //
  135. // OK, if good for all usage or code signing OID is explicitly found.
  136. //
  137. if (0 == pUsage->cUsageIdentifier)
  138. {
  139. bInclude = TRUE;
  140. DebugTrace("Info: FindAuthenticodeCertCallback() - valid for all usages.\n");
  141. }
  142. else
  143. {
  144. PCERT_EXTENSION pExtension = NULL;
  145. //
  146. // Look for code signing OID.
  147. //
  148. for (DWORD cUsage = 0; cUsage < pUsage->cUsageIdentifier; cUsage++)
  149. {
  150. if (0 == ::strcmp(szOID_PKIX_KP_CODE_SIGNING, pUsage->rgpszUsageIdentifier[cUsage]))
  151. {
  152. bInclude = TRUE;
  153. DebugTrace("Info: FindAuthenticodeCertCallback() - code signing EKU found.\n");
  154. goto CommonExit;
  155. }
  156. }
  157. //
  158. // We didn't find code signing OID, so look for legacy VeriSign OID.
  159. //
  160. DebugTrace("Info: FindAuthenticodeCertCallback() - no code signing EKU found.\n");
  161. //
  162. // Decode the extension if found.
  163. //
  164. if ((0 == pCertContext->pCertInfo->cExtension) ||
  165. (!(pExtension = ::CertFindExtension(szOID_KEY_USAGE_RESTRICTION,
  166. pCertContext->pCertInfo->cExtension,
  167. pCertContext->pCertInfo->rgExtension))))
  168. {
  169. DebugTrace("Info: FindAuthenticodeCertCallback() - no legacy VeriSign OID found either.\n");
  170. goto CommonExit;
  171. }
  172. if (FAILED(hr = ::DecodeObject(X509_KEY_USAGE_RESTRICTION,
  173. pExtension->Value.pbData,
  174. pExtension->Value.cbData,
  175. &DataBlob)))
  176. {
  177. DebugTrace("Info [%#x]: DecodeObject() failed.\n", hr);
  178. goto CommonExit;
  179. }
  180. //
  181. // Now find either of the OIDs.
  182. //
  183. PCERT_KEY_USAGE_RESTRICTION_INFO pInfo = (PCERT_KEY_USAGE_RESTRICTION_INFO) DataBlob.pbData;
  184. DWORD cPolicyId = pInfo->cCertPolicyId;
  185. while (cPolicyId--)
  186. {
  187. DWORD cElementId = pInfo->rgCertPolicyId[cPolicyId].cCertPolicyElementId;
  188. while (cElementId--)
  189. {
  190. if (0 == ::strcmp(pInfo->rgCertPolicyId[cPolicyId].rgpszCertPolicyElementId[cElementId],
  191. SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID) ||
  192. 0 == ::strcmp(pInfo->rgCertPolicyId[cPolicyId].rgpszCertPolicyElementId[cElementId],
  193. SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID))
  194. {
  195. bInclude = TRUE;
  196. DebugTrace("Info: FindAuthenticodeCertCallback() - legacy VeriSign code signing OID found.\n");
  197. goto CommonExit;
  198. }
  199. }
  200. }
  201. }
  202. CommonExit:
  203. //
  204. // Free resources.
  205. //
  206. if (DataBlob.pbData)
  207. {
  208. ::CoTaskMemFree(DataBlob.pbData);
  209. }
  210. if (pUsage)
  211. {
  212. ::CoTaskMemFree(pUsage);
  213. }
  214. DebugTrace("Entering FindAuthenticodeCertCallback().\n");
  215. return bInclude;
  216. }