Source code of Windows XP (NT5)
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.

448 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: callui.cpp
  8. //
  9. // Contents: Microsoft Internet Security Authenticode Policy Provider
  10. //
  11. // Functions: SoftpubCallUI
  12. //
  13. // *** local functions ***
  14. // _AllocGetOpusInfo
  15. //
  16. // History: 06-Jun-1997 pberkman created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "global.hxx"
  20. #include "trustdb.h"
  21. #include "acui.h"
  22. #include "winsafer.h"
  23. SPC_SP_OPUS_INFO *_AllocGetOpusInfo(CRYPT_PROVIDER_DATA *pProvData, CRYPT_PROVIDER_SGNR *pSigner,
  24. DWORD *pcbOpusInfo);
  25. #define MIN_HASH_LEN 16
  26. #define MAX_HASH_LEN 20
  27. // Returns:
  28. // S_FALSE
  29. // not found in the database
  30. // TRUST_E_SYSTEM_ERROR
  31. // system errors while attempting to do the check
  32. // S_OK
  33. // found in the database
  34. // TRUST_E_EXPLICIT_DISTRUST
  35. // explicitly disallowed in the database or revoked
  36. HRESULT _CheckTrustedPublisher(
  37. CRYPT_PROVIDER_DATA *pProvData,
  38. DWORD dwError,
  39. BOOL fOnlyDisallowed
  40. )
  41. {
  42. CRYPT_PROVIDER_SGNR *pSigner;
  43. PCCERT_CONTEXT pPubCert;
  44. BYTE rgbHash[MAX_HASH_LEN];
  45. CRYPT_DATA_BLOB HashBlob;
  46. HCERTSTORE hStore;
  47. if (CERT_E_REVOKED == dwError)
  48. {
  49. return TRUST_E_EXPLICIT_DISTRUST;
  50. }
  51. pSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
  52. if (NULL == pSigner || pSigner->csCertChain <= 0)
  53. {
  54. return S_FALSE;
  55. }
  56. pPubCert = WTHelperGetProvCertFromChain(pSigner, 0)->pCert;
  57. // Check if disallowed.
  58. // Since the signature component can be altered, must use the signature
  59. // hash
  60. HashBlob.pbData = rgbHash;
  61. HashBlob.cbData = MAX_HASH_LEN;
  62. if (!CertGetCertificateContextProperty(
  63. pPubCert,
  64. CERT_SIGNATURE_HASH_PROP_ID,
  65. rgbHash,
  66. &HashBlob.cbData
  67. ) || MIN_HASH_LEN > HashBlob.cbData)
  68. {
  69. return TRUST_E_SYSTEM_ERROR;
  70. }
  71. hStore = OpenDisallowedStore();
  72. if (hStore)
  73. {
  74. PCCERT_CONTEXT pFoundCert;
  75. pFoundCert = CertFindCertificateInStore(
  76. hStore,
  77. 0, // dwCertEncodingType
  78. 0, // dwFindFlags
  79. CERT_FIND_SIGNATURE_HASH,
  80. (const void *) &HashBlob,
  81. NULL //pPrevCertContext
  82. );
  83. CertCloseStore(hStore, 0);
  84. if (pFoundCert)
  85. {
  86. CertFreeCertificateContext(pFoundCert);
  87. return TRUST_E_EXPLICIT_DISTRUST;
  88. }
  89. }
  90. if (fOnlyDisallowed)
  91. {
  92. return S_FALSE;
  93. }
  94. if (S_OK != dwError)
  95. {
  96. // Everything must be valid to allow a trusted publisher
  97. return S_FALSE;
  98. }
  99. // Check if trusted publisher
  100. hStore = OpenTrustedPublisherStore();
  101. if (hStore)
  102. {
  103. PCCERT_CONTEXT pFoundCert;
  104. pFoundCert = CertFindCertificateInStore(
  105. hStore,
  106. 0, // dwCertEncodingType
  107. 0, // dwFindFlags
  108. CERT_FIND_SIGNATURE_HASH,
  109. (const void *) &HashBlob,
  110. NULL //pPrevCertContext
  111. );
  112. CertCloseStore(hStore, 0);
  113. if (pFoundCert)
  114. {
  115. CertFreeCertificateContext(pFoundCert);
  116. return S_OK;
  117. }
  118. }
  119. return S_FALSE;
  120. }
  121. typedef BOOL (WINAPI *PFN_SAFERI_SEARCH_MATCHING_HASH_RULES)(
  122. IN ALG_ID HashAlgorithm OPTIONAL,
  123. IN PBYTE pHashBytes,
  124. IN DWORD dwHashSize,
  125. IN DWORD dwOriginalImageSize OPTIONAL,
  126. OUT PDWORD pdwFoundLevel,
  127. OUT PDWORD pdwUIFlags
  128. );
  129. // Returns:
  130. // S_FALSE
  131. // not found in the database
  132. // S_OK
  133. // fully trusted in the database
  134. // TRUST_E_EXPLICIT_DISTRUST
  135. // explicitly disallowed in the database
  136. HRESULT _CheckTrustedCodeHash(CRYPT_PROVIDER_DATA *pProvData)
  137. {
  138. static BOOL fGotProcAddr = FALSE;
  139. static PFN_SAFERI_SEARCH_MATCHING_HASH_RULES
  140. pfnCodeAuthzSearchMatchingHashRules = NULL;
  141. DWORD cbHash;
  142. if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] == 0 &&
  143. pProvData->pPDSip && pProvData->pPDSip->psIndirectData)
  144. {
  145. cbHash = pProvData->pPDSip->psIndirectData->Digest.cbData;
  146. }
  147. else
  148. {
  149. cbHash = 0;
  150. }
  151. if (0 == cbHash)
  152. {
  153. return S_FALSE;
  154. }
  155. // wintrust.dll has a static dependency on advapi32.dll. However, not
  156. // all advapi32.dll's will export "SaferiSearchMatchingHashRules"
  157. if (!fGotProcAddr)
  158. {
  159. HMODULE hModule;
  160. hModule = GetModuleHandleA("advapi32.dll");
  161. if (NULL != hModule)
  162. {
  163. pfnCodeAuthzSearchMatchingHashRules =
  164. (PFN_SAFERI_SEARCH_MATCHING_HASH_RULES) GetProcAddress(
  165. hModule, "SaferiSearchMatchingHashRules");
  166. }
  167. fGotProcAddr = TRUE;
  168. }
  169. if (NULL != pfnCodeAuthzSearchMatchingHashRules)
  170. {
  171. __try
  172. {
  173. DWORD dwFoundLevel = 0xFFFFFFFF;
  174. DWORD dwUIFlags = 0;
  175. if (pfnCodeAuthzSearchMatchingHashRules(
  176. CertOIDToAlgId(pProvData->pPDSip->psIndirectData->DigestAlgorithm.pszObjId),
  177. pProvData->pPDSip->psIndirectData->Digest.pbData,
  178. cbHash,
  179. 0, // dwOriginalImageSize
  180. &dwFoundLevel,
  181. &dwUIFlags
  182. ))
  183. {
  184. switch (dwFoundLevel)
  185. {
  186. case SAFER_LEVELID_FULLYTRUSTED:
  187. return S_OK;
  188. case SAFER_LEVELID_DISALLOWED:
  189. return TRUST_E_EXPLICIT_DISTRUST;
  190. }
  191. }
  192. }
  193. __except(EXCEPTION_EXECUTE_HANDLER)
  194. {
  195. }
  196. }
  197. return S_FALSE;
  198. }
  199. HRESULT SoftpubCallUI(CRYPT_PROVIDER_DATA *pProvData, DWORD dwError, BOOL fFinalCall)
  200. {
  201. HRESULT hr;
  202. DWORD dwUIChoice;
  203. if (!(fFinalCall))
  204. {
  205. // TBDTBD: if we want the user to get involved along the way???
  206. return(ERROR_SUCCESS);
  207. }
  208. if (0 == (pProvData->dwProvFlags & WTD_SAFER_FLAG))
  209. {
  210. if (!(pProvData->dwRegPolicySettings & WTPF_ALLOWONLYPERTRUST) &&
  211. (pProvData->pWintrustData->dwUIChoice == WTD_UI_NONE))
  212. {
  213. if (S_OK == dwError)
  214. {
  215. //
  216. // Check for untrusted publisher
  217. //
  218. hr = _CheckTrustedPublisher(pProvData, dwError, TRUE);
  219. if (TRUST_E_EXPLICIT_DISTRUST == hr)
  220. {
  221. return TRUST_E_EXPLICIT_DISTRUST;
  222. }
  223. }
  224. return(dwError);
  225. }
  226. }
  227. //
  228. // Check for trusted or disallowed subject hash
  229. //
  230. hr = _CheckTrustedCodeHash(pProvData);
  231. if (S_FALSE != hr)
  232. {
  233. if (S_OK == hr)
  234. {
  235. // Ensure we always indicate trust.
  236. pProvData->dwFinalError = 0;
  237. }
  238. return hr;
  239. }
  240. //
  241. // Check for trusted or disallowed publisher
  242. //
  243. hr = _CheckTrustedPublisher(pProvData, dwError, FALSE);
  244. if (S_FALSE != hr)
  245. {
  246. if (S_OK == hr)
  247. {
  248. // Ensure we always indicate trust.
  249. pProvData->dwFinalError = 0;
  250. }
  251. return hr;
  252. }
  253. if (pProvData->dwRegPolicySettings & WTPF_ALLOWONLYPERTRUST)
  254. {
  255. if (0 == dwError)
  256. {
  257. return CRYPT_E_SECURITY_SETTINGS;
  258. }
  259. return dwError;
  260. }
  261. dwUIChoice = pProvData->pWintrustData->dwUIChoice;
  262. if ((dwUIChoice == WTD_UI_NONE) ||
  263. ((dwUIChoice == WTD_UI_NOBAD) && (dwError != ERROR_SUCCESS)) ||
  264. ((dwUIChoice == WTD_UI_NOGOOD) && (dwError == ERROR_SUCCESS)))
  265. {
  266. if (0 == dwError)
  267. {
  268. // No explicit trust
  269. pProvData->dwFinalError = TRUST_E_SUBJECT_NOT_TRUSTED;
  270. }
  271. return dwError;
  272. }
  273. //
  274. // call the ui
  275. //
  276. HINSTANCE hModule = NULL;
  277. IPersonalTrustDB *pTrustDB = NULL;
  278. ACUI_INVOKE_INFO aii;
  279. pfnACUIProviderInvokeUI pfn = NULL;
  280. DWORD cbOpusInfo;
  281. CRYPT_PROVIDER_SGNR *pRootSigner;
  282. pRootSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
  283. OpenTrustDB(NULL, IID_IPersonalTrustDB, (LPVOID*)&pTrustDB);
  284. memset(&aii, 0x00, sizeof(ACUI_INVOKE_INFO));
  285. //
  286. // Setup the UI invokation
  287. //
  288. aii.cbSize = sizeof(ACUI_INVOKE_INFO);
  289. aii.hDisplay = pProvData->hWndParent;
  290. aii.pProvData = pProvData;
  291. aii.hrInvokeReason = dwError;
  292. aii.pwcsAltDisplayName = WTHelperGetFileName(pProvData->pWintrustData);
  293. aii.pPersonalTrustDB = (IUnknown *)pTrustDB;
  294. if (pRootSigner)
  295. {
  296. aii.pOpusInfo = _AllocGetOpusInfo(pProvData, pRootSigner, &cbOpusInfo);
  297. }
  298. //
  299. // Load the default authenticode UI.
  300. //
  301. if (hModule = LoadLibraryA(CVP_DLL))
  302. {
  303. pfn = (pfnACUIProviderInvokeUI)GetProcAddress(hModule, "ACUIProviderInvokeUI");
  304. }
  305. //
  306. // Invoke the UI
  307. //
  308. if (pfn)
  309. {
  310. hr = (*pfn)(&aii);
  311. }
  312. else
  313. {
  314. hr = TRUST_E_PROVIDER_UNKNOWN;
  315. pProvData->dwError = hr;
  316. pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_UIPROV] = hr;
  317. DBG_PRINTF((DBG_SS, "Unable to load CRYPTUI.DLL\n"));
  318. }
  319. //
  320. // Return the appropriate code
  321. //
  322. if (pTrustDB)
  323. {
  324. pTrustDB->Release();
  325. }
  326. if (aii.pOpusInfo)
  327. {
  328. TrustFreeDecode(WVT_MODID_SOFTPUB, (BYTE **)&aii.pOpusInfo);
  329. }
  330. if (hModule)
  331. {
  332. FreeLibrary(hModule);
  333. }
  334. return hr;
  335. }
  336. SPC_SP_OPUS_INFO *_AllocGetOpusInfo(CRYPT_PROVIDER_DATA *pProvData, CRYPT_PROVIDER_SGNR *pSigner,
  337. DWORD *pcbOpusInfo)
  338. {
  339. PCRYPT_ATTRIBUTE pAttr;
  340. PSPC_SP_OPUS_INFO pInfo;
  341. pInfo = NULL;
  342. if (!(pSigner->psSigner))
  343. {
  344. goto NoSigner;
  345. }
  346. if (pSigner->psSigner->AuthAttrs.cAttr == 0)
  347. {
  348. goto NoOpusAttribute;
  349. }
  350. if (!(pAttr = CertFindAttribute(SPC_SP_OPUS_INFO_OBJID,
  351. pSigner->psSigner->AuthAttrs.cAttr,
  352. pSigner->psSigner->AuthAttrs.rgAttr)))
  353. {
  354. goto NoOpusAttribute;
  355. }
  356. if (!(pAttr->rgValue))
  357. {
  358. goto NoOpusAttribute;
  359. }
  360. if (!(TrustDecode(WVT_MODID_SOFTPUB, (BYTE **)&pInfo, pcbOpusInfo, 200,
  361. pProvData->dwEncoding, SPC_SP_OPUS_INFO_STRUCT,
  362. pAttr->rgValue->pbData, pAttr->rgValue->cbData, CRYPT_DECODE_NOCOPY_FLAG)))
  363. {
  364. goto DecodeError;
  365. }
  366. return(pInfo);
  367. ErrorReturn:
  368. return(NULL);
  369. TRACE_ERROR_EX(DBG_SS, NoSigner);
  370. TRACE_ERROR_EX(DBG_SS, NoOpusAttribute);
  371. TRACE_ERROR_EX(DBG_SS, DecodeError);
  372. }