2 * Copyright 2001 Rein Klazes
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
36 #include "wintrust_priv.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
42 /***********************************************************************
43 * DllMain (WINTRUST.@)
45 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
49 case DLL_PROCESS_ATTACH:
50 DisableThreadLibraryCalls( inst );
56 /***********************************************************************
57 * TrustIsCertificateSelfSigned (WINTRUST.@)
59 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
64 ret = CertCompareCertificateName(cert->dwCertEncodingType,
65 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
69 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
72 DWORD err = ERROR_SUCCESS;
73 CRYPT_PROVIDER_DATA *provData;
76 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
78 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
81 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
83 provData->padwTrustStepErrors =
84 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
85 if (!provData->padwTrustStepErrors)
87 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
89 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
90 if (!provData->u.pPDSip)
92 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
94 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
95 if (!provData->psPfns)
97 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
98 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
101 err = GetLastError();
105 data->hWVTStateData = (HANDLE)provData;
106 provData->pWintrustData = data;
107 if (hwnd == INVALID_HANDLE_VALUE)
108 provData->hWndParent = GetDesktopWindow();
110 provData->hWndParent = hwnd;
111 provData->pgActionID = actionID;
112 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
114 if (provData->psPfns->pfnInitialize)
116 err = provData->psPfns->pfnInitialize(provData);
120 if (provData->psPfns->pfnObjectTrust)
122 err = provData->psPfns->pfnObjectTrust(provData);
126 if (provData->psPfns->pfnSignatureTrust)
128 err = provData->psPfns->pfnSignatureTrust(provData);
132 if (provData->psPfns->pfnCertificateTrust)
134 err = provData->psPfns->pfnCertificateTrust(provData);
138 if (provData->psPfns->pfnFinalPolicy)
139 err = provData->psPfns->pfnFinalPolicy(provData);
143 err = ERROR_OUTOFMEMORY;
147 WINTRUST_Free(provData->padwTrustStepErrors);
148 WINTRUST_Free(provData->u.pPDSip);
149 WINTRUST_Free(provData->psPfns);
150 WINTRUST_Free(provData);
153 TRACE("returning %08x\n", err);
157 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
160 DWORD err = ERROR_SUCCESS;
161 CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
163 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
167 if (provData->psPfns->pfnCleanupPolicy)
168 err = provData->psPfns->pfnCleanupPolicy(provData);
170 WINTRUST_Free(provData->padwTrustStepErrors);
171 WINTRUST_Free(provData->u.pPDSip);
172 WINTRUST_Free(provData->psPfns);
173 WINTRUST_Free(provData);
174 data->hWVTStateData = NULL;
176 TRACE("returning %08x\n", err);
180 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
185 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
187 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
188 WINTRUST_DefaultClose(hwnd, actionID, data);
189 TRACE("returning %08x\n", err);
193 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
196 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
197 /* Undocumented: the published software action is passed a path,
198 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
200 LPCWSTR path = (LPCWSTR)data->u.pFile;
201 LPWIN_TRUST_SUBJECT_FILE subjectFile =
202 (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
203 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
205 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
206 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
207 fileInfo.pcwszFilePath = path;
208 fileInfo.hFile = subjectFile->hFile;
209 wintrust_data.u.pFile = &fileInfo;
210 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
211 wintrust_data.dwUIChoice = WTD_UI_NONE;
213 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
216 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
218 TRACE("%p\n", pFile);
221 TRACE("cbStruct: %d\n", pFile->cbStruct);
222 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
223 TRACE("hFile: %p\n", pFile->hFile);
224 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
228 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
230 TRACE("%p\n", catalog);
233 TRACE("cbStruct: %d\n", catalog->cbStruct);
234 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
235 TRACE("pcwszCatalogFilePath: %s\n",
236 debugstr_w(catalog->pcwszCatalogFilePath));
237 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
238 TRACE("pcwszMemberFilePath: %s\n",
239 debugstr_w(catalog->pcwszMemberFilePath));
240 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
241 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
242 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
243 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
247 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
252 TRACE("cbStruct: %d\n", blob->cbStruct);
253 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
254 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
255 TRACE("cbMemObject: %d\n", blob->cbMemObject);
256 TRACE("pbMemObject: %p\n", blob->pbMemObject);
257 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
258 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
262 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
267 TRACE("cbStruct: %d\n", sgnr->cbStruct);
268 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
269 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
270 TRACE("chStores: %d\n", sgnr->chStores);
274 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
279 TRACE("cbStruct: %d\n", cert->cbStruct);
280 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
281 TRACE("psCertContext: %p\n", cert->psCertContext);
282 TRACE("chStores: %d\n", cert->chStores);
283 TRACE("dwFlags: %08x\n", cert->dwFlags);
284 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
288 static void dump_wintrust_data(WINTRUST_DATA *data)
293 TRACE("cbStruct: %d\n", data->cbStruct);
294 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
295 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
296 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
297 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
298 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
299 switch (data->dwUnionChoice)
301 case WTD_CHOICE_FILE:
302 dump_file_info(data->u.pFile);
304 case WTD_CHOICE_CATALOG:
305 dump_catalog_info(data->u.pCatalog);
307 case WTD_CHOICE_BLOB:
308 dump_blob_info(data->u.pBlob);
310 case WTD_CHOICE_SIGNER:
311 dump_sgnr_info(data->u.pSgnr);
313 case WTD_CHOICE_CERT:
314 dump_cert_info(data->u.pCert);
317 TRACE("dwStateAction: %d\n", data->dwStateAction);
318 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
319 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
320 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
321 TRACE("dwUIContext: %d\n", data->dwUIContext);
325 /***********************************************************************
326 * WinVerifyTrust (WINTRUST.@)
328 * Verifies an object by calling the specified trust provider.
331 * hwnd [I] Handle to a caller window.
332 * ActionID [I] Pointer to a GUID that identifies the action to perform.
333 * ActionData [I] Information used by the trust provider to verify the object.
337 * Failure: A TRUST_E_* error code.
340 * Trust providers can be found at:
341 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
343 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
345 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
346 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
347 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
348 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
349 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
350 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
351 LONG err = ERROR_SUCCESS;
352 WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
354 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
355 dump_wintrust_data(ActionData);
357 /* Support for known old-style callers: */
358 if (IsEqualGUID(ActionID, &published_software))
359 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
362 /* Check known actions to warn of possible problems */
363 if (!IsEqualGUID(ActionID, &unknown) &&
364 !IsEqualGUID(ActionID, &generic_verify_v2) &&
365 !IsEqualGUID(ActionID, &generic_cert_verify) &&
366 !IsEqualGUID(ActionID, &generic_chain_verify))
367 WARN("unknown action %s, default behavior may not be right\n",
368 debugstr_guid(ActionID));
369 switch (actionData->dwStateAction)
371 case WTD_STATEACTION_IGNORE:
372 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
374 case WTD_STATEACTION_VERIFY:
375 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
377 case WTD_STATEACTION_CLOSE:
378 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
381 FIXME("unimplemented for %d\n", actionData->dwStateAction);
385 TRACE("returning %08x\n", err);
389 /***********************************************************************
390 * WinVerifyTrustEx (WINTRUST.@)
392 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
393 WINTRUST_DATA* ActionData )
395 return WinVerifyTrust(hwnd, ActionID, ActionData);
398 /***********************************************************************
399 * WTHelperGetProvSignerFromChain (WINTRUST.@)
401 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
402 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
403 DWORD idxCounterSigner)
405 CRYPT_PROVIDER_SGNR *sgnr;
407 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
410 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
412 sgnr = &pProvData->pasSigners[idxSigner];
415 if (idxCounterSigner >= sgnr->csCounterSigners ||
416 !sgnr->pasCounterSigners)
418 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
420 TRACE("returning %p\n", sgnr);
424 /***********************************************************************
425 * WTHelperGetProvCertFromChain (WINTRUST.@)
427 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
428 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
430 CRYPT_PROVIDER_CERT *cert;
432 TRACE("(%p %d)\n", pSgnr, idxCert);
434 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
436 cert = &pSgnr->pasCertChain[idxCert];
437 TRACE("returning %p\n", cert);
441 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
442 CRYPT_PROVIDER_DATA* pProvData,
445 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
448 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
450 for (i = 0; i < pProvData->csProvPrivData; i++)
451 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
453 privdata = &pProvData->pasProvPrivData[i];
460 /***********************************************************************
461 * WTHelperProvDataFromStateData (WINTRUST.@)
463 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
465 TRACE("%p\n", hStateData);
466 return (CRYPT_PROVIDER_DATA *)hStateData;
469 /***********************************************************************
470 * WTHelperGetFileName(WINTRUST.@)
472 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
475 if (data->dwUnionChoice == WTD_CHOICE_FILE)
476 return data->u.pFile->pcwszFilePath;
481 /***********************************************************************
482 * WTHelperGetFileHandle(WINTRUST.@)
484 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
487 if (data->dwUnionChoice == WTD_CHOICE_FILE)
488 return data->u.pFile->hFile;
490 return INVALID_HANDLE_VALUE;
493 static const WCHAR Software_Publishing[] = {
494 'S','o','f','t','w','a','r','e','\\',
495 'M','i','c','r','o','s','o','f','t','\\',
496 'W','i','n','d','o','w','s','\\',
497 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
498 'W','i','n','t','r','u','s','t','\\',
499 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
500 'S','o','f','t','w','a','r','e',' ',
501 'P','u','b','l','i','s','h','i','n','g',0 };
502 static const WCHAR State[] = { 'S','t','a','t','e',0 };
504 /***********************************************************************
505 * WintrustGetRegPolicyFlags (WINTRUST.@)
507 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
512 TRACE("%p\n", pdwPolicyFlags);
515 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
516 KEY_READ, NULL, &key, NULL);
519 DWORD size = sizeof(DWORD);
521 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
526 /* Failed to query, create and return default value */
527 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
528 WTPF_OFFLINEOKNBU_COM |
529 WTPF_OFFLINEOKNBU_IND |
532 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
537 /***********************************************************************
538 * WintrustSetRegPolicyFlags (WINTRUST.@)
540 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
545 TRACE("%x\n", dwPolicyFlags);
547 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
548 NULL, 0, KEY_WRITE, NULL, &key, NULL);
551 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
555 if (r) SetLastError(r);
556 return r == ERROR_SUCCESS;
559 /* Utility functions */
560 void * WINAPI WINTRUST_Alloc(DWORD cb)
562 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
565 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
567 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
570 void WINAPI WINTRUST_Free(void *p)
572 HeapFree(GetProcessHeap(), 0, p);
575 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
580 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
581 (data->chStores + 1) * sizeof(HCERTSTORE));
584 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
589 data->pahStores[data->chStores++] = CertDuplicateStore(store);
593 SetLastError(ERROR_OUTOFMEMORY);
597 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
598 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
602 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
604 SetLastError(ERROR_INVALID_PARAMETER);
609 FIXME("unimplemented for counter signers\n");
610 SetLastError(ERROR_INVALID_PARAMETER);
614 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
615 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
618 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
621 if (data->pasSigners)
623 if (idxSigner < data->csSigners)
624 memmove(&data->pasSigners[idxSigner],
625 &data->pasSigners[idxSigner + 1],
626 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
628 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
630 /* The PSDK says psSigner should be allocated using pfnAlloc, but
631 * it doesn't say anything about ownership. Since callers are
632 * internal, assume ownership is passed, and just store the
635 memcpy(&data->pasSigners[idxSigner], sgnr,
636 sizeof(CRYPT_PROVIDER_SGNR));
639 memset(&data->pasSigners[idxSigner], 0,
640 sizeof(CRYPT_PROVIDER_SGNR));
644 SetLastError(ERROR_OUTOFMEMORY);
648 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
649 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
655 FIXME("unimplemented for counter signers\n");
656 SetLastError(ERROR_INVALID_PARAMETER);
659 if (data->pasSigners[idxSigner].csCertChain)
660 data->pasSigners[idxSigner].pasCertChain =
661 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
662 (data->pasSigners[idxSigner].csCertChain + 1) *
663 sizeof(CRYPT_PROVIDER_CERT));
666 data->pasSigners[idxSigner].pasCertChain =
667 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
668 data->pasSigners[idxSigner].csCertChain = 0;
670 if (data->pasSigners[idxSigner].pasCertChain)
672 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
673 data->pasSigners[idxSigner].csCertChain];
675 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
676 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
677 data->pasSigners[idxSigner].csCertChain++;
681 SetLastError(ERROR_OUTOFMEMORY);
685 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
686 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
690 TRACE("(%p, %p)\n", data, pPrivData2Add);
692 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
694 SetLastError(ERROR_INVALID_PARAMETER);
695 WARN("invalid struct size\n");
698 if (data->csProvPrivData)
699 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
700 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
703 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
704 data->csProvPrivData = 0;
706 if (data->pasProvPrivData)
710 for (i = 0; i < data->csProvPrivData; i++)
711 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
714 data->pasProvPrivData[i] = *pPrivData2Add;
715 if (i == data->csProvPrivData)
716 data->csProvPrivData++;
719 SetLastError(ERROR_OUTOFMEMORY);