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.

354 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: ctlfunc.cpp
  8. //
  9. // Contents: Certificate Verify CTL Usage Dispatch Functions
  10. //
  11. // Functions: I_CertCTLUsageFuncDllMain
  12. // CertVerifyCTLUsage
  13. //
  14. // History: 29-Apr-97 philh created
  15. //--------------------------------------------------------------------------
  16. #include "global.hxx"
  17. #include <dbgdef.h>
  18. static HCRYPTOIDFUNCSET hUsageFuncSet;
  19. typedef BOOL (WINAPI *PFN_CERT_DLL_VERIFY_CTL_USAGE)(
  20. IN DWORD dwEncodingType,
  21. IN DWORD dwSubjectType,
  22. IN void *pvSubject,
  23. IN PCTL_USAGE pSubjectUsage,
  24. IN DWORD dwFlags,
  25. IN OPTIONAL PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  26. IN OUT PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus
  27. );
  28. //+-------------------------------------------------------------------------
  29. // Dll initialization
  30. //--------------------------------------------------------------------------
  31. BOOL
  32. WINAPI
  33. I_CertCTLUsageFuncDllMain(
  34. HMODULE hModule,
  35. ULONG ulReason,
  36. LPVOID lpReserved)
  37. {
  38. BOOL fRet;
  39. switch (ulReason) {
  40. case DLL_PROCESS_ATTACH:
  41. if (NULL == (hUsageFuncSet = CryptInitOIDFunctionSet(
  42. CRYPT_OID_VERIFY_CTL_USAGE_FUNC,
  43. 0))) // dwFlags
  44. goto CryptInitOIDFunctionSetError;
  45. break;
  46. case DLL_PROCESS_DETACH:
  47. case DLL_THREAD_DETACH:
  48. default:
  49. break;
  50. }
  51. fRet = TRUE;
  52. CommonReturn:
  53. return fRet;
  54. ErrorReturn:
  55. fRet = FALSE;
  56. goto CommonReturn;
  57. TRACE_ERROR(CryptInitOIDFunctionSetError)
  58. }
  59. static void ZeroUsageStatus(
  60. IN OUT PCTL_VERIFY_USAGE_STATUS pUsageStatus)
  61. {
  62. pUsageStatus->dwError = 0;
  63. pUsageStatus->dwFlags = 0;
  64. if (pUsageStatus->ppCtl)
  65. *pUsageStatus->ppCtl = NULL;
  66. pUsageStatus->dwCtlEntryIndex = 0;
  67. if (pUsageStatus->ppSigner)
  68. *pUsageStatus->ppSigner = NULL;
  69. pUsageStatus->dwSignerIndex = 0;
  70. }
  71. //+-------------------------------------------------------------------------
  72. // Remember the "most interesting" error
  73. //--------------------------------------------------------------------------
  74. static void UpdateUsageError(
  75. IN DWORD dwNewError,
  76. IN OUT DWORD *pdwError
  77. )
  78. {
  79. if (0 != dwNewError) {
  80. DWORD dwError = *pdwError;
  81. if ((DWORD) CRYPT_E_NOT_IN_CTL == dwNewError ||
  82. (DWORD) CRYPT_E_NO_VERIFY_USAGE_DLL == dwError
  83. ||
  84. ((DWORD) CRYPT_E_NOT_IN_CTL != dwError &&
  85. (DWORD) CRYPT_E_NO_TRUSTED_SIGNER != dwError &&
  86. (DWORD) CRYPT_E_NO_VERIFY_USAGE_CHECK != dwNewError))
  87. *pdwError = dwNewError;
  88. }
  89. }
  90. static BOOL VerifyDefaultUsage(
  91. IN DWORD dwEncodingType,
  92. IN DWORD dwSubjectType,
  93. IN void *pvSubject,
  94. IN PCTL_USAGE pSubjectUsage,
  95. IN DWORD dwFlags,
  96. IN OPTIONAL PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  97. IN OUT PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus
  98. )
  99. {
  100. BOOL fResult;
  101. DWORD dwError = (DWORD) CRYPT_E_NO_VERIFY_USAGE_DLL;
  102. LPWSTR pwszDllList; // _alloca'ed
  103. DWORD cchDllList;
  104. DWORD cchDll;
  105. void *pvFuncAddr;
  106. HCRYPTOIDFUNCADDR hFuncAddr;
  107. // Iterate through the installed default functions.
  108. // Setting pwszDll to NULL searches the installed list. Setting
  109. // hFuncAddr to NULL starts the search at the beginning.
  110. hFuncAddr = NULL;
  111. while (CryptGetDefaultOIDFunctionAddress(
  112. hUsageFuncSet,
  113. dwEncodingType,
  114. NULL, // pwszDll
  115. 0, // dwFlags
  116. &pvFuncAddr,
  117. &hFuncAddr)) {
  118. ZeroUsageStatus(pVerifyUsageStatus);
  119. fResult = ((PFN_CERT_DLL_VERIFY_CTL_USAGE) pvFuncAddr)(
  120. dwEncodingType,
  121. dwSubjectType,
  122. pvSubject,
  123. pSubjectUsage,
  124. dwFlags,
  125. pVerifyUsagePara,
  126. pVerifyUsageStatus);
  127. if (fResult) {
  128. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  129. goto CommonReturn;
  130. } else
  131. // Unable to verify usage for this installed
  132. // function. However, remember any "interesting"
  133. // errors.
  134. UpdateUsageError(pVerifyUsageStatus->dwError, &dwError);
  135. }
  136. if (!CryptGetDefaultOIDDllList(
  137. hUsageFuncSet,
  138. dwEncodingType,
  139. NULL, // pszDllList
  140. &cchDllList)) goto GetDllListError;
  141. __try {
  142. pwszDllList = (LPWSTR) _alloca(cchDllList * sizeof(WCHAR));
  143. } __except(EXCEPTION_EXECUTE_HANDLER) {
  144. goto OutOfMemory;
  145. }
  146. if (!CryptGetDefaultOIDDllList(
  147. hUsageFuncSet,
  148. dwEncodingType,
  149. pwszDllList,
  150. &cchDllList)) goto GetDllListError;
  151. for (; 0 != (cchDll = wcslen(pwszDllList)); pwszDllList += cchDll + 1) {
  152. if (CryptGetDefaultOIDFunctionAddress(
  153. hUsageFuncSet,
  154. dwEncodingType,
  155. pwszDllList,
  156. 0, // dwFlags
  157. &pvFuncAddr,
  158. &hFuncAddr)) {
  159. ZeroUsageStatus(pVerifyUsageStatus);
  160. fResult = ((PFN_CERT_DLL_VERIFY_CTL_USAGE) pvFuncAddr)(
  161. dwEncodingType,
  162. dwSubjectType,
  163. pvSubject,
  164. pSubjectUsage,
  165. dwFlags,
  166. pVerifyUsagePara,
  167. pVerifyUsageStatus);
  168. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  169. if (fResult)
  170. goto CommonReturn;
  171. else
  172. // Unable to verify usage for this registered
  173. // function. However, remember any "interesting"
  174. // errors.
  175. UpdateUsageError(pVerifyUsageStatus->dwError, &dwError);
  176. }
  177. }
  178. goto ErrorReturn;
  179. CommonReturn:
  180. return fResult;
  181. ErrorReturn:
  182. pVerifyUsageStatus->dwError = dwError;
  183. fResult = FALSE;
  184. goto CommonReturn;
  185. TRACE_ERROR(GetDllListError)
  186. TRACE_ERROR(OutOfMemory)
  187. }
  188. static BOOL VerifyOIDUsage(
  189. IN DWORD dwEncodingType,
  190. IN DWORD dwSubjectType,
  191. IN void *pvSubject,
  192. IN PCTL_USAGE pSubjectUsage,
  193. IN DWORD dwFlags,
  194. IN OPTIONAL PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  195. IN OUT PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus
  196. )
  197. {
  198. BOOL fResult;
  199. HCRYPTOIDFUNCADDR hFuncAddr;
  200. PVOID pvFuncAddr;
  201. if (pSubjectUsage && pSubjectUsage->cUsageIdentifier > 0 &&
  202. CryptGetOIDFunctionAddress(
  203. hUsageFuncSet,
  204. dwEncodingType,
  205. pSubjectUsage->rgpszUsageIdentifier[0],
  206. 0, // dwFlags
  207. &pvFuncAddr,
  208. &hFuncAddr)) {
  209. ZeroUsageStatus(pVerifyUsageStatus);
  210. fResult = ((PFN_CERT_DLL_VERIFY_CTL_USAGE) pvFuncAddr)(
  211. dwEncodingType,
  212. dwSubjectType,
  213. pvSubject,
  214. pSubjectUsage,
  215. dwFlags,
  216. pVerifyUsagePara,
  217. pVerifyUsageStatus);
  218. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  219. } else {
  220. pVerifyUsageStatus->dwError = (DWORD) CRYPT_E_NO_VERIFY_USAGE_DLL;
  221. fResult = FALSE;
  222. }
  223. return fResult;
  224. }
  225. //+-------------------------------------------------------------------------
  226. // Verify that a subject is trusted for the specified usage by finding a
  227. // signed and time valid CTL with the usage identifiers and containing the
  228. // the subject. A subject can be identified by either its certificate context
  229. // or any identifier such as its SHA1 hash.
  230. //
  231. // See CertFindSubjectInCTL for definition of dwSubjectType and pvSubject
  232. // parameters.
  233. //
  234. // Via pVerifyUsagePara, the caller can specify the stores to be searched
  235. // to find the CTL. The caller can also specify the stores containing
  236. // acceptable CTL signers. By setting the ListIdentifier, the caller
  237. // can also restrict to a particular signer CTL list.
  238. //
  239. // Via pVerifyUsageStatus, the CTL containing the subject, the subject's
  240. // index into the CTL's array of entries, and the signer of the CTL
  241. // are returned. If the caller is interested, ppCtl and ppSigner can be set
  242. // to NULL. Returned contexts must be freed via the store's free context APIs.
  243. //
  244. // If the CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG isn't set, then, a time
  245. // invalid CTL in one of the CtlStores may be replaced. When replaced, the
  246. // CERT_VERIFY_UPDATED_CTL_FLAG is set in pVerifyUsageStatus->dwFlags.
  247. //
  248. // If the CERT_VERIFY_TRUSTED_SIGNERS_FLAG is set, then, only the
  249. // SignerStores specified in pVerifyUsageStatus are searched to find
  250. // the signer. Otherwise, the SignerStores provide additional sources
  251. // to find the signer's certificate.
  252. //
  253. // If CERT_VERIFY_NO_TIME_CHECK_FLAG is set, then, the CTLs aren't checked
  254. // for time validity.
  255. //
  256. // If CERT_VERIFY_ALLOW_MORE_USAGE_FLAG is set, then, the CTL may contain
  257. // additional usage identifiers than specified by pSubjectUsage. Otherwise,
  258. // the found CTL will contain the same usage identifers and no more.
  259. //
  260. // CertVerifyCTLUsage will be implemented as a dispatcher to OID installable
  261. // functions. First, it will try to find an OID function matching the first
  262. // usage object identifier in the pUsage sequence. Next, it will dispatch
  263. // to the default CertDllVerifyCTLUsage functions.
  264. //
  265. // If the subject is trusted for the specified usage, then, TRUE is
  266. // returned. Otherwise, FALSE is returned with dwError set to one of the
  267. // following:
  268. // CRYPT_E_NO_VERIFY_USAGE_DLL
  269. // CRYPT_E_NO_VERIFY_USAGE_CHECK
  270. // CRYPT_E_VERIFY_USAGE_OFFLINE
  271. // CRYPT_E_NOT_IN_CTL
  272. // CRYPT_E_NO_TRUSTED_SIGNER
  273. //--------------------------------------------------------------------------
  274. BOOL
  275. WINAPI
  276. CertVerifyCTLUsage(
  277. IN DWORD dwEncodingType,
  278. IN DWORD dwSubjectType,
  279. IN void *pvSubject,
  280. IN PCTL_USAGE pSubjectUsage,
  281. IN DWORD dwFlags,
  282. IN OPTIONAL PCTL_VERIFY_USAGE_PARA pVerifyUsagePara,
  283. IN OUT PCTL_VERIFY_USAGE_STATUS pVerifyUsageStatus
  284. )
  285. {
  286. BOOL fResult;
  287. assert(NULL == pVerifyUsagePara || pVerifyUsagePara->cbSize >=
  288. sizeof(CTL_VERIFY_USAGE_PARA));
  289. assert(pVerifyUsageStatus && pVerifyUsageStatus->cbSize >=
  290. sizeof(CTL_VERIFY_USAGE_STATUS));
  291. if (pVerifyUsagePara && pVerifyUsagePara->cbSize <
  292. sizeof(CTL_VERIFY_USAGE_PARA))
  293. goto InvalidArg;
  294. if (NULL == pVerifyUsageStatus || pVerifyUsageStatus->cbSize <
  295. sizeof(CTL_VERIFY_USAGE_STATUS))
  296. goto InvalidArg;
  297. fResult = VerifyOIDUsage(
  298. dwEncodingType,
  299. dwSubjectType,
  300. pvSubject,
  301. pSubjectUsage,
  302. dwFlags,
  303. pVerifyUsagePara,
  304. pVerifyUsageStatus);
  305. if (!fResult) {
  306. DWORD dwError = pVerifyUsageStatus->dwError;
  307. fResult = VerifyDefaultUsage(
  308. dwEncodingType,
  309. dwSubjectType,
  310. pvSubject,
  311. pSubjectUsage,
  312. dwFlags,
  313. pVerifyUsagePara,
  314. pVerifyUsageStatus);
  315. if (!fResult) {
  316. UpdateUsageError(pVerifyUsageStatus->dwError, &dwError);
  317. ZeroUsageStatus(pVerifyUsageStatus);
  318. pVerifyUsageStatus->dwError = dwError;
  319. SetLastError(dwError);
  320. }
  321. }
  322. CommonReturn:
  323. return fResult;
  324. ErrorReturn:
  325. fResult = FALSE;
  326. goto CommonReturn;
  327. SET_ERROR(InvalidArg, E_INVALIDARG)
  328. }