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