[SHELL32]
[reactos.git] / reactos / dll / win32 / wintrust / wintrust_main.c
1 /*
2 * Copyright 2001 Rein Klazes
3 * Copyright 2007 Juan Lang
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include "config.h"
21
22 #include <stdarg.h>
23
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "winreg.h"
30 #include "guiddef.h"
31 #include "wintrust.h"
32 #include "softpub.h"
33 #include "mscat.h"
34 #include "objbase.h"
35 #include "winuser.h"
36 #include "cryptdlg.h"
37 #include "cryptuiapi.h"
38 #include "wintrust_priv.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
42
43
44 /* Utility functions */
45 void * WINAPI WINTRUST_Alloc(DWORD cb)
46 {
47 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
48 }
49
50 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb) __WINE_ALLOC_SIZE(2);
51 static void* WINTRUST_ReAlloc(void *ptr, DWORD cb)
52 {
53 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
54 }
55
56 void WINAPI WINTRUST_Free(void *p)
57 {
58 HeapFree(GetProcessHeap(), 0, p);
59 }
60
61 /***********************************************************************
62 * DllMain (WINTRUST.@)
63 */
64 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
65 {
66 switch(reason)
67 {
68 case DLL_PROCESS_ATTACH:
69 DisableThreadLibraryCalls( inst );
70 break;
71 }
72 return TRUE;
73 }
74
75 /***********************************************************************
76 * TrustIsCertificateSelfSigned (WINTRUST.@)
77 */
78 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
79 {
80 PCERT_EXTENSION ext;
81 DWORD size;
82 BOOL ret;
83
84 TRACE("%p\n", cert);
85 if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2,
86 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
87 {
88 CERT_AUTHORITY_KEY_ID2_INFO *info;
89
90 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
91 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
92 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
93 &info, &size);
94 if (ret)
95 {
96 if (info->AuthorityCertIssuer.cAltEntry &&
97 info->AuthorityCertSerialNumber.cbData)
98 {
99 PCERT_ALT_NAME_ENTRY directoryName = NULL;
100 DWORD i;
101
102 for (i = 0; !directoryName &&
103 i < info->AuthorityCertIssuer.cAltEntry; i++)
104 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
105 == CERT_ALT_NAME_DIRECTORY_NAME)
106 directoryName =
107 &info->AuthorityCertIssuer.rgAltEntry[i];
108 if (directoryName)
109 {
110 ret = CertCompareCertificateName(cert->dwCertEncodingType,
111 &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer)
112 && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber,
113 &cert->pCertInfo->SerialNumber);
114 }
115 else
116 {
117 FIXME("no supported name type in authority key id2\n");
118 ret = FALSE;
119 }
120 }
121 else if (info->KeyId.cbData)
122 {
123 ret = CertGetCertificateContextProperty(cert,
124 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
125 if (ret && size == info->KeyId.cbData)
126 {
127 LPBYTE buf = CryptMemAlloc(size);
128
129 if (buf)
130 {
131 CertGetCertificateContextProperty(cert,
132 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
133 ret = !memcmp(buf, info->KeyId.pbData, size);
134 CryptMemFree(buf);
135 }
136 else
137 ret = FALSE;
138 }
139 else
140 ret = FALSE;
141 }
142 LocalFree(info);
143 }
144 }
145 else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER,
146 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
147 {
148 CERT_AUTHORITY_KEY_ID_INFO *info;
149
150 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
151 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
152 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
153 &info, &size);
154 if (ret)
155 {
156 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
157 {
158 ret = CertCompareCertificateName(cert->dwCertEncodingType,
159 &info->CertIssuer, &cert->pCertInfo->Issuer) &&
160 CertCompareIntegerBlob(&info->CertSerialNumber,
161 &cert->pCertInfo->SerialNumber);
162 }
163 else if (info->KeyId.cbData)
164 {
165 ret = CertGetCertificateContextProperty(cert,
166 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
167 if (ret && size == info->KeyId.cbData)
168 {
169 LPBYTE buf = CryptMemAlloc(size);
170
171 if (buf)
172 {
173 CertGetCertificateContextProperty(cert,
174 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
175 ret = !memcmp(buf, info->KeyId.pbData, size);
176 CryptMemFree(buf);
177 }
178 else
179 ret = FALSE;
180 }
181 else
182 ret = FALSE;
183 }
184 else
185 ret = FALSE;
186 LocalFree(info);
187 }
188 }
189 else
190 ret = CertCompareCertificateName(cert->dwCertEncodingType,
191 &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
192 return ret;
193 }
194
195 typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
196
197 struct wintrust_step
198 {
199 wintrust_step_func func;
200 DWORD error_index;
201 };
202
203 static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
204 DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
205 {
206 DWORD i, err = ERROR_SUCCESS;
207
208 for (i = 0; !err && i < numSteps; i++)
209 {
210 err = steps[i].func(provData);
211 if (err)
212 err = provData->padwTrustStepErrors[steps[i].error_index];
213 }
214 return err;
215 }
216
217 static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
218 {
219 CRYPT_PROVIDER_DATA *provData;
220
221 provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
222 if (!provData)
223 goto oom;
224 provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
225
226 provData->padwTrustStepErrors =
227 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
228 if (!provData->padwTrustStepErrors)
229 goto oom;
230 provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
231
232 provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
233 if (!provData->u.pPDSip)
234 goto oom;
235 provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
236
237 provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
238 if (!provData->psPfns)
239 goto oom;
240 provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
241 return provData;
242
243 oom:
244 if (provData)
245 {
246 WINTRUST_Free(provData->padwTrustStepErrors);
247 WINTRUST_Free(provData->u.pPDSip);
248 WINTRUST_Free(provData->psPfns);
249 WINTRUST_Free(provData);
250 }
251 return NULL;
252 }
253
254 /* Adds trust steps for each function in psPfns. Assumes steps has at least
255 * 5 entries. Returns the number of steps added.
256 */
257 static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
258 const CRYPT_PROVIDER_FUNCTIONS *psPfns)
259 {
260 DWORD numSteps = 0;
261
262 if (psPfns->pfnInitialize)
263 {
264 steps[numSteps].func = psPfns->pfnInitialize;
265 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
266 }
267 if (psPfns->pfnObjectTrust)
268 {
269 steps[numSteps].func = psPfns->pfnObjectTrust;
270 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
271 }
272 if (psPfns->pfnSignatureTrust)
273 {
274 steps[numSteps].func = psPfns->pfnSignatureTrust;
275 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
276 }
277 if (psPfns->pfnCertificateTrust)
278 {
279 steps[numSteps].func = psPfns->pfnCertificateTrust;
280 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
281 }
282 if (psPfns->pfnFinalPolicy)
283 {
284 steps[numSteps].func = psPfns->pfnFinalPolicy;
285 steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
286 }
287 return numSteps;
288 }
289
290 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
291 WINTRUST_DATA *data)
292 {
293 DWORD err = ERROR_SUCCESS, numSteps = 0;
294 CRYPT_PROVIDER_DATA *provData;
295 BOOL ret;
296 struct wintrust_step verifySteps[5];
297
298 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
299
300 provData = WINTRUST_AllocateProviderData();
301 if (!provData)
302 return ERROR_OUTOFMEMORY;
303
304 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
305 if (!ret)
306 {
307 err = GetLastError();
308 goto error;
309 }
310
311 data->hWVTStateData = provData;
312 provData->pWintrustData = data;
313 if (hwnd == INVALID_HANDLE_VALUE)
314 provData->hWndParent = GetDesktopWindow();
315 else
316 provData->hWndParent = hwnd;
317 provData->pgActionID = actionID;
318 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
319
320 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
321 provData->psPfns);
322 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
323 goto done;
324
325 error:
326 if (provData)
327 {
328 WINTRUST_Free(provData->padwTrustStepErrors);
329 WINTRUST_Free(provData->u.pPDSip);
330 WINTRUST_Free(provData->psPfns);
331 WINTRUST_Free(provData);
332 }
333 done:
334 TRACE("returning %08x\n", err);
335 return err;
336 }
337
338 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
339 WINTRUST_DATA *data)
340 {
341 DWORD err = ERROR_SUCCESS;
342 CRYPT_PROVIDER_DATA *provData = data->hWVTStateData;
343
344 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
345
346 if (provData)
347 {
348 if (provData->psPfns->pfnCleanupPolicy)
349 err = provData->psPfns->pfnCleanupPolicy(provData);
350
351 WINTRUST_Free(provData->padwTrustStepErrors);
352 WINTRUST_Free(provData->u.pPDSip);
353 WINTRUST_Free(provData->psPfns);
354 WINTRUST_Free(provData);
355 data->hWVTStateData = NULL;
356 }
357 TRACE("returning %08x\n", err);
358 return err;
359 }
360
361 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
362 WINTRUST_DATA *data)
363 {
364 LONG err;
365
366 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
367
368 err = WINTRUST_DefaultVerify(hwnd, actionID, data);
369 WINTRUST_DefaultClose(hwnd, actionID, data);
370 TRACE("returning %08x\n", err);
371 return err;
372 }
373
374 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
375 WINTRUST_DATA *data)
376 {
377 WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
378 /* Undocumented: the published software action is passed a path,
379 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
380 */
381 LPWIN_TRUST_SUBJECT_FILE subjectFile = data->pSIPClientData;
382 WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
383
384 TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
385 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
386 fileInfo.pcwszFilePath = subjectFile->lpPath;
387 fileInfo.hFile = subjectFile->hFile;
388 wintrust_data.u.pFile = &fileInfo;
389 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
390 wintrust_data.dwUIChoice = WTD_UI_NONE;
391
392 return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
393 }
394
395 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
396 * action is not stored in the registry and is located in wintrust, not in
397 * cryptdlg along with the rest of the implementation (verified by running the
398 * action with a native wintrust.dll.)
399 */
400 static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
401 {
402 BOOL ret;
403
404 TRACE("(%p)\n", data);
405
406 if (!data->padwTrustStepErrors)
407 return S_FALSE;
408
409 switch (data->pWintrustData->dwUnionChoice)
410 {
411 case WTD_CHOICE_BLOB:
412 if (data->pWintrustData->u.pBlob &&
413 WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO,
414 data->pWintrustData->u.pBlob->cbStruct, pbMemObject) &&
415 data->pWintrustData->u.pBlob->cbMemObject ==
416 sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
417 data->pWintrustData->u.pBlob->pbMemObject)
418 {
419 CERT_VERIFY_CERTIFICATE_TRUST *pCert =
420 (CERT_VERIFY_CERTIFICATE_TRUST *)
421 data->pWintrustData->u.pBlob->pbMemObject;
422
423 if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
424 pCert->pccert)
425 {
426 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
427 DWORD i;
428 SYSTEMTIME sysTime;
429
430 /* Add a signer with nothing but the time to verify, so we can
431 * add a cert to it
432 */
433 GetSystemTime(&sysTime);
434 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
435 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
436 if (!ret)
437 goto error;
438 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
439 pCert->pccert);
440 if (!ret)
441 goto error;
442 for (i = 0; ret && i < pCert->cRootStores; i++)
443 ret = data->psPfns->pfnAddStore2Chain(data,
444 pCert->rghstoreRoots[i]);
445 for (i = 0; ret && i < pCert->cStores; i++)
446 ret = data->psPfns->pfnAddStore2Chain(data,
447 pCert->rghstoreCAs[i]);
448 for (i = 0; ret && i < pCert->cTrustStores; i++)
449 ret = data->psPfns->pfnAddStore2Chain(data,
450 pCert->rghstoreTrust[i]);
451 }
452 else
453 {
454 SetLastError(ERROR_INVALID_PARAMETER);
455 ret = FALSE;
456 }
457 }
458 else
459 {
460 SetLastError(ERROR_INVALID_PARAMETER);
461 ret = FALSE;
462 }
463 break;
464 default:
465 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
466 SetLastError(ERROR_INVALID_PARAMETER);
467 ret = FALSE;
468 }
469
470 error:
471 if (!ret)
472 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
473 GetLastError();
474 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
475 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
476 return ret ? S_OK : S_FALSE;
477 }
478
479 static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
480 WINTRUST_DATA *data)
481 {
482 DWORD err = ERROR_SUCCESS, numSteps = 0;
483 CRYPT_PROVIDER_DATA *provData;
484 BOOL ret;
485 struct wintrust_step verifySteps[5];
486
487 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
488
489 provData = WINTRUST_AllocateProviderData();
490 if (!provData)
491 return ERROR_OUTOFMEMORY;
492
493 ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
494 if (!ret)
495 {
496 err = GetLastError();
497 goto error;
498 }
499 if (!provData->psPfns->pfnObjectTrust)
500 provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
501 /* Not sure why, but native skips the policy check */
502 provData->psPfns->pfnCertCheckPolicy = NULL;
503
504 data->hWVTStateData = provData;
505 provData->pWintrustData = data;
506 if (hwnd == INVALID_HANDLE_VALUE)
507 provData->hWndParent = GetDesktopWindow();
508 else
509 provData->hWndParent = hwnd;
510 provData->pgActionID = actionID;
511 WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
512
513 numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
514 provData->psPfns);
515 err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
516 goto done;
517
518 error:
519 if (provData)
520 {
521 WINTRUST_Free(provData->padwTrustStepErrors);
522 WINTRUST_Free(provData->u.pPDSip);
523 WINTRUST_Free(provData->psPfns);
524 WINTRUST_Free(provData);
525 }
526 done:
527 TRACE("returning %08x\n", err);
528 return err;
529 }
530
531 static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
532 WINTRUST_DATA *data)
533 {
534 LONG err;
535
536 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
537
538 err = WINTRUST_CertVerify(hwnd, actionID, data);
539 WINTRUST_DefaultClose(hwnd, actionID, data);
540 TRACE("returning %08x\n", err);
541 return err;
542 }
543
544 static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
545 WINTRUST_DATA *data)
546 {
547 DWORD stateAction;
548 LONG err = ERROR_SUCCESS;
549
550 if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
551 stateAction = data->dwStateAction;
552 else
553 {
554 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
555 stateAction = WTD_STATEACTION_IGNORE;
556 }
557 switch (stateAction)
558 {
559 case WTD_STATEACTION_IGNORE:
560 err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
561 break;
562 case WTD_STATEACTION_VERIFY:
563 err = WINTRUST_CertVerify(hwnd, actionID, data);
564 break;
565 case WTD_STATEACTION_CLOSE:
566 err = WINTRUST_DefaultClose(hwnd, actionID, data);
567 break;
568 default:
569 FIXME("unimplemented for %d\n", data->dwStateAction);
570 }
571 return err;
572 }
573
574 static void dump_file_info(WINTRUST_FILE_INFO *pFile)
575 {
576 TRACE("%p\n", pFile);
577 if (pFile)
578 {
579 TRACE("cbStruct: %d\n", pFile->cbStruct);
580 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
581 TRACE("hFile: %p\n", pFile->hFile);
582 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
583 }
584 }
585
586 static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
587 {
588 TRACE("%p\n", catalog);
589 if (catalog)
590 {
591 TRACE("cbStruct: %d\n", catalog->cbStruct);
592 TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
593 TRACE("pcwszCatalogFilePath: %s\n",
594 debugstr_w(catalog->pcwszCatalogFilePath));
595 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
596 TRACE("pcwszMemberFilePath: %s\n",
597 debugstr_w(catalog->pcwszMemberFilePath));
598 TRACE("hMemberFile: %p\n", catalog->hMemberFile);
599 TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
600 TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
601 TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
602 }
603 }
604
605 static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
606 {
607 TRACE("%p\n", blob);
608 if (blob)
609 {
610 TRACE("cbStruct: %d\n", blob->cbStruct);
611 TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
612 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
613 TRACE("cbMemObject: %d\n", blob->cbMemObject);
614 TRACE("pbMemObject: %p\n", blob->pbMemObject);
615 TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
616 TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
617 }
618 }
619
620 static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
621 {
622 TRACE("%p\n", sgnr);
623 if (sgnr)
624 {
625 TRACE("cbStruct: %d\n", sgnr->cbStruct);
626 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
627 TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
628 TRACE("chStores: %d\n", sgnr->chStores);
629 }
630 }
631
632 static void dump_cert_info(WINTRUST_CERT_INFO *cert)
633 {
634 TRACE("%p\n", cert);
635 if (cert)
636 {
637 TRACE("cbStruct: %d\n", cert->cbStruct);
638 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
639 TRACE("psCertContext: %p\n", cert->psCertContext);
640 TRACE("chStores: %d\n", cert->chStores);
641 TRACE("dwFlags: %08x\n", cert->dwFlags);
642 TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
643 }
644 }
645
646 static void dump_wintrust_data(WINTRUST_DATA *data)
647 {
648 TRACE("%p\n", data);
649 if (data)
650 {
651 TRACE("cbStruct: %d\n", data->cbStruct);
652 TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
653 TRACE("pSIPClientData: %p\n", data->pSIPClientData);
654 TRACE("dwUIChoice: %d\n", data->dwUIChoice);
655 TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
656 TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
657 switch (data->dwUnionChoice)
658 {
659 case WTD_CHOICE_FILE:
660 dump_file_info(data->u.pFile);
661 break;
662 case WTD_CHOICE_CATALOG:
663 dump_catalog_info(data->u.pCatalog);
664 break;
665 case WTD_CHOICE_BLOB:
666 dump_blob_info(data->u.pBlob);
667 break;
668 case WTD_CHOICE_SIGNER:
669 dump_sgnr_info(data->u.pSgnr);
670 break;
671 case WTD_CHOICE_CERT:
672 dump_cert_info(data->u.pCert);
673 break;
674 }
675 TRACE("dwStateAction: %d\n", data->dwStateAction);
676 TRACE("hWVTStateData: %p\n", data->hWVTStateData);
677 TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
678 TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
679 TRACE("dwUIContext: %d\n", data->dwUIContext);
680 }
681 }
682
683 /***********************************************************************
684 * WinVerifyTrust (WINTRUST.@)
685 *
686 * Verifies an object by calling the specified trust provider.
687 *
688 * PARAMS
689 * hwnd [I] Handle to a caller window.
690 * ActionID [I] Pointer to a GUID that identifies the action to perform.
691 * ActionData [I] Information used by the trust provider to verify the object.
692 *
693 * RETURNS
694 * Success: Zero.
695 * Failure: A TRUST_E_* error code.
696 *
697 * NOTES
698 * Trust providers can be found at:
699 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
700 */
701 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
702 {
703 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
704 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
705 static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
706 static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
707 static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
708 static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
709 static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
710 LONG err = ERROR_SUCCESS;
711 WINTRUST_DATA *actionData = ActionData;
712
713 TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
714 dump_wintrust_data(ActionData);
715
716 /* Support for known old-style callers: */
717 if (IsEqualGUID(ActionID, &published_software))
718 err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
719 else if (IsEqualGUID(ActionID, &cert_action_verify))
720 err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
721 else
722 {
723 DWORD stateAction;
724
725 /* Check known actions to warn of possible problems */
726 if (!IsEqualGUID(ActionID, &unknown) &&
727 !IsEqualGUID(ActionID, &generic_verify_v2) &&
728 !IsEqualGUID(ActionID, &generic_cert_verify) &&
729 !IsEqualGUID(ActionID, &generic_chain_verify))
730 WARN("unknown action %s, default behavior may not be right\n",
731 debugstr_guid(ActionID));
732 if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
733 stateAction = actionData->dwStateAction;
734 else
735 {
736 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
737 stateAction = WTD_STATEACTION_IGNORE;
738 }
739 switch (stateAction)
740 {
741 case WTD_STATEACTION_IGNORE:
742 err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
743 break;
744 case WTD_STATEACTION_VERIFY:
745 err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
746 break;
747 case WTD_STATEACTION_CLOSE:
748 err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
749 break;
750 default:
751 FIXME("unimplemented for %d\n", actionData->dwStateAction);
752 }
753 }
754
755 TRACE("returning %08x\n", err);
756 return err;
757 }
758
759 /***********************************************************************
760 * WinVerifyTrustEx (WINTRUST.@)
761 */
762 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
763 WINTRUST_DATA* ActionData )
764 {
765 return WinVerifyTrust(hwnd, ActionID, ActionData);
766 }
767
768 /***********************************************************************
769 * WTHelperGetProvSignerFromChain (WINTRUST.@)
770 */
771 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
772 CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
773 DWORD idxCounterSigner)
774 {
775 CRYPT_PROVIDER_SGNR *sgnr;
776
777 TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
778 idxCounterSigner);
779
780 if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
781 return NULL;
782 sgnr = &pProvData->pasSigners[idxSigner];
783 if (fCounterSigner)
784 {
785 if (idxCounterSigner >= sgnr->csCounterSigners ||
786 !sgnr->pasCounterSigners)
787 return NULL;
788 sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
789 }
790 TRACE("returning %p\n", sgnr);
791 return sgnr;
792 }
793
794 /***********************************************************************
795 * WTHelperGetProvCertFromChain (WINTRUST.@)
796 */
797 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
798 CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
799 {
800 CRYPT_PROVIDER_CERT *cert;
801
802 TRACE("(%p %d)\n", pSgnr, idxCert);
803
804 if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
805 return NULL;
806 cert = &pSgnr->pasCertChain[idxCert];
807 TRACE("returning %p\n", cert);
808 return cert;
809 }
810
811 CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
812 CRYPT_PROVIDER_DATA* pProvData,
813 GUID* pgProviderID)
814 {
815 CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
816 DWORD i;
817
818 TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
819
820 for (i = 0; i < pProvData->csProvPrivData; i++)
821 if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
822 {
823 privdata = &pProvData->pasProvPrivData[i];
824 break;
825 }
826
827 return privdata;
828 }
829
830 /***********************************************************************
831 * WTHelperProvDataFromStateData (WINTRUST.@)
832 */
833 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
834 {
835 TRACE("%p\n", hStateData);
836 return hStateData;
837 }
838
839 /***********************************************************************
840 * WTHelperGetFileName(WINTRUST.@)
841 */
842 LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
843 {
844 TRACE("%p\n",data);
845 if (data->dwUnionChoice == WTD_CHOICE_FILE)
846 return data->u.pFile->pcwszFilePath;
847 else
848 return NULL;
849 }
850
851 /***********************************************************************
852 * WTHelperGetFileHandle(WINTRUST.@)
853 */
854 HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
855 {
856 TRACE("%p\n",data);
857 if (data->dwUnionChoice == WTD_CHOICE_FILE)
858 return data->u.pFile->hFile;
859 else
860 return INVALID_HANDLE_VALUE;
861 }
862
863 static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
864 {
865 PCCRYPT_OID_INFO **usages = pvArg;
866 DWORD cUsages;
867 BOOL ret;
868
869 if (!*usages)
870 {
871 cUsages = 0;
872 *usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
873 }
874 else
875 {
876 PCCRYPT_OID_INFO *ptr;
877
878 /* Count the existing usages.
879 * FIXME: make sure the new usage doesn't duplicate any in the list?
880 */
881 for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
882 ;
883 *usages = WINTRUST_ReAlloc(*usages,
884 (cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
885 }
886 if (*usages)
887 {
888 (*usages)[cUsages] = pInfo;
889 (*usages)[cUsages + 1] = NULL;
890 ret = TRUE;
891 }
892 else
893 {
894 SetLastError(ERROR_OUTOFMEMORY);
895 ret = FALSE;
896 }
897 return ret;
898 }
899
900 /***********************************************************************
901 * WTHelperGetKnownUsages(WINTRUST.@)
902 *
903 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
904 *
905 * PARAMS
906 * action [In] 1 => allocate and return known usages, 2 => free previously
907 * allocated usages.
908 * usages [In/Out] If action == 1, *usages is set to an array of
909 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
910 * pointer.
911 * If action == 2, *usages is freed.
912 *
913 * RETURNS
914 * TRUE on success, FALSE on failure.
915 */
916 BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
917 {
918 BOOL ret;
919
920 TRACE("(%d, %p)\n", action, usages);
921
922 if (!usages)
923 {
924 SetLastError(ERROR_INVALID_PARAMETER);
925 return FALSE;
926 }
927
928 if (action == 1)
929 {
930 *usages = NULL;
931 ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
932 WINTRUST_enumUsages);
933 }
934 else if (action == 2)
935 {
936 WINTRUST_Free(*usages);
937 *usages = NULL;
938 ret = TRUE;
939 }
940 else
941 {
942 WARN("unknown action %d\n", action);
943 SetLastError(ERROR_INVALID_PARAMETER);
944 ret = FALSE;
945 }
946 return ret;
947 }
948
949 static const WCHAR Software_Publishing[] = {
950 'S','o','f','t','w','a','r','e','\\',
951 'M','i','c','r','o','s','o','f','t','\\',
952 'W','i','n','d','o','w','s','\\',
953 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
954 'W','i','n','t','r','u','s','t','\\',
955 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
956 'S','o','f','t','w','a','r','e',' ',
957 'P','u','b','l','i','s','h','i','n','g',0 };
958 static const WCHAR State[] = { 'S','t','a','t','e',0 };
959
960 /***********************************************************************
961 * WintrustGetRegPolicyFlags (WINTRUST.@)
962 */
963 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
964 {
965 HKEY key;
966 LONG r;
967
968 TRACE("%p\n", pdwPolicyFlags);
969
970 *pdwPolicyFlags = 0;
971 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
972 KEY_READ, NULL, &key, NULL);
973 if (!r)
974 {
975 DWORD size = sizeof(DWORD);
976
977 r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
978 &size);
979 RegCloseKey(key);
980 if (r)
981 {
982 /* Failed to query, create and return default value */
983 *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
984 WTPF_OFFLINEOKNBU_COM |
985 WTPF_OFFLINEOKNBU_IND |
986 WTPF_OFFLINEOK_COM |
987 WTPF_OFFLINEOK_IND;
988 WintrustSetRegPolicyFlags(*pdwPolicyFlags);
989 }
990 }
991 }
992
993 /***********************************************************************
994 * WintrustSetRegPolicyFlags (WINTRUST.@)
995 */
996 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
997 {
998 HKEY key;
999 LONG r;
1000
1001 TRACE("%x\n", dwPolicyFlags);
1002
1003 r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
1004 NULL, 0, KEY_WRITE, NULL, &key, NULL);
1005 if (!r)
1006 {
1007 r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
1008 sizeof(DWORD));
1009 RegCloseKey(key);
1010 }
1011 if (r) SetLastError(r);
1012 return r == ERROR_SUCCESS;
1013 }
1014
1015 /* Utility functions */
1016
1017 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
1018 {
1019 BOOL ret = FALSE;
1020
1021 TRACE("(%p, %p)\n", data, store);
1022
1023 if (data->chStores)
1024 data->pahStores = WINTRUST_ReAlloc(data->pahStores,
1025 (data->chStores + 1) * sizeof(HCERTSTORE));
1026 else
1027 {
1028 data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
1029 data->chStores = 0;
1030 }
1031 if (data->pahStores)
1032 {
1033 data->pahStores[data->chStores++] = CertDuplicateStore(store);
1034 ret = TRUE;
1035 }
1036 else
1037 SetLastError(ERROR_OUTOFMEMORY);
1038 return ret;
1039 }
1040
1041 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
1042 BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
1043 {
1044 BOOL ret = FALSE;
1045
1046 TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
1047
1048 if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
1049 {
1050 SetLastError(ERROR_INVALID_PARAMETER);
1051 return FALSE;
1052 }
1053 if (fCounterSigner)
1054 {
1055 FIXME("unimplemented for counter signers\n");
1056 SetLastError(ERROR_INVALID_PARAMETER);
1057 return FALSE;
1058 }
1059 if (data->csSigners)
1060 data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
1061 (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1062 else
1063 {
1064 data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1065 data->csSigners = 0;
1066 }
1067 if (data->pasSigners)
1068 {
1069 if (idxSigner < data->csSigners)
1070 memmove(&data->pasSigners[idxSigner],
1071 &data->pasSigners[idxSigner + 1],
1072 (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
1073 ret = TRUE;
1074 if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
1075 {
1076 /* The PSDK says psSigner should be allocated using pfnAlloc, but
1077 * it doesn't say anything about ownership. Since callers are
1078 * internal, assume ownership is passed, and just store the
1079 * pointer.
1080 */
1081 memcpy(&data->pasSigners[idxSigner], sgnr,
1082 sizeof(CRYPT_PROVIDER_SGNR));
1083 }
1084 else
1085 memset(&data->pasSigners[idxSigner], 0,
1086 sizeof(CRYPT_PROVIDER_SGNR));
1087 data->csSigners++;
1088 }
1089 else
1090 SetLastError(ERROR_OUTOFMEMORY);
1091 return ret;
1092 }
1093
1094 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
1095 BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
1096 {
1097 BOOL ret = FALSE;
1098
1099 TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
1100 idxSigner, pCert2Add);
1101
1102 if (fCounterSigner)
1103 {
1104 FIXME("unimplemented for counter signers\n");
1105 SetLastError(ERROR_INVALID_PARAMETER);
1106 return FALSE;
1107 }
1108 if (data->pasSigners[idxSigner].csCertChain)
1109 data->pasSigners[idxSigner].pasCertChain =
1110 WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
1111 (data->pasSigners[idxSigner].csCertChain + 1) *
1112 sizeof(CRYPT_PROVIDER_CERT));
1113 else
1114 {
1115 data->pasSigners[idxSigner].pasCertChain =
1116 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
1117 data->pasSigners[idxSigner].csCertChain = 0;
1118 }
1119 if (data->pasSigners[idxSigner].pasCertChain)
1120 {
1121 CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
1122 data->pasSigners[idxSigner].csCertChain];
1123
1124 cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
1125 cert->pCert = CertDuplicateCertificateContext(pCert2Add);
1126 data->pasSigners[idxSigner].csCertChain++;
1127 ret = TRUE;
1128 }
1129 else
1130 SetLastError(ERROR_OUTOFMEMORY);
1131 return ret;
1132 }
1133
1134 BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
1135 CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
1136 {
1137 BOOL ret = FALSE;
1138
1139 TRACE("(%p, %p)\n", data, pPrivData2Add);
1140
1141 if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
1142 {
1143 SetLastError(ERROR_INVALID_PARAMETER);
1144 WARN("invalid struct size\n");
1145 return FALSE;
1146 }
1147 if (data->csProvPrivData)
1148 data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
1149 (data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
1150 else
1151 {
1152 data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
1153 data->csProvPrivData = 0;
1154 }
1155 if (data->pasProvPrivData)
1156 {
1157 DWORD i;
1158
1159 for (i = 0; i < data->csProvPrivData; i++)
1160 if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
1161 break;
1162
1163 data->pasProvPrivData[i] = *pPrivData2Add;
1164 if (i == data->csProvPrivData)
1165 data->csProvPrivData++;
1166 }
1167 else
1168 SetLastError(ERROR_OUTOFMEMORY);
1169 return ret;
1170 }
1171
1172 /***********************************************************************
1173 * OpenPersonalTrustDBDialog (WINTRUST.@)
1174 *
1175 * Opens the certificate manager dialog, showing only the stores that
1176 * contain trusted software publishers.
1177 *
1178 * PARAMS
1179 * hwnd [I] handle of parent window
1180 *
1181 * RETURNS
1182 * TRUE if the dialog could be opened, FALSE if not.
1183 */
1184 BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
1185 {
1186 CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
1187
1188 uiCertMgr.dwSize = sizeof(uiCertMgr);
1189 uiCertMgr.hwndParent = hwnd;
1190 uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
1191 uiCertMgr.pwszTitle = NULL;
1192 uiCertMgr.pszInitUsageOID = NULL;
1193 return CryptUIDlgCertMgr(&uiCertMgr);
1194 }
1195
1196 /***********************************************************************
1197 * WTHelperCertCheckValidSignature
1198 */
1199 HRESULT WINAPI WTHelperCertCheckValidSignature(CRYPT_PROVIDER_DATA *pProvData)
1200 {
1201 FIXME("Stub\n");
1202 return S_OK;
1203 }