comctl32: We can now store binary files in the repository.
[wine] / dlls / 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 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "guiddef.h"
29 #include "wintrust.h"
30 #include "softpub.h"
31 #include "mscat.h"
32 #include "objbase.h"
33 #include "winuser.h"
34 #include "wintrust_priv.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
38
39
40 /***********************************************************************
41  *              DllMain  (WINTRUST.@)
42  */
43 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
44 {
45     switch(reason)
46     {
47     case DLL_PROCESS_ATTACH:
48         DisableThreadLibraryCalls( inst );
49         break;
50     }
51     return TRUE;
52 }
53
54 /***********************************************************************
55  *              TrustIsCertificateSelfSigned (WINTRUST.@)
56  */
57 BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
58 {
59     BOOL ret;
60
61     TRACE("%p\n", cert);
62     ret = CertCompareCertificateName(cert->dwCertEncodingType,
63      &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
64     return ret;
65 }
66
67 static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
68  WINTRUST_DATA *data)
69 {
70     DWORD err = ERROR_SUCCESS;
71     CRYPT_PROVIDER_DATA *provData;
72     BOOL ret;
73
74     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
75
76     provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
77     if (!provData)
78         goto oom;
79     provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
80
81     provData->padwTrustStepErrors =
82      WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
83     if (!provData->padwTrustStepErrors)
84         goto oom;
85     provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
86
87     provData->pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
88     if (!provData->pPDSip)
89         goto oom;
90     provData->pPDSip->cbStruct = sizeof(PROVDATA_SIP);
91
92     provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
93     if (!provData->psPfns)
94         goto oom;
95     provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
96     ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
97     if (!ret)
98     {
99         err = GetLastError();
100         goto error;
101     }
102
103     data->hWVTStateData = (HANDLE)provData;
104     provData->pWintrustData = data;
105     if (hwnd == INVALID_HANDLE_VALUE)
106         provData->hWndParent = GetDesktopWindow();
107     else
108         provData->hWndParent = hwnd;
109     provData->pgActionID = actionID;
110     WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
111
112     err = provData->psPfns->pfnInitialize(provData);
113     if (err)
114         goto done;
115     err = provData->psPfns->pfnObjectTrust(provData);
116     if (err)
117         goto done;
118     err = provData->psPfns->pfnSignatureTrust(provData);
119     if (err)
120         goto done;
121     err = provData->psPfns->pfnCertificateTrust(provData);
122     if (err)
123         goto done;
124     err = provData->psPfns->pfnFinalPolicy(provData);
125     goto done;
126
127 oom:
128     err = ERROR_OUTOFMEMORY;
129 error:
130     if (provData)
131     {
132         WINTRUST_Free(provData->padwTrustStepErrors);
133         WINTRUST_Free(provData->pPDSip);
134         WINTRUST_Free(provData->psPfns);
135         WINTRUST_Free(provData);
136     }
137 done:
138     TRACE("returning %08x\n", err);
139     return err;
140 }
141
142 static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
143  WINTRUST_DATA *data)
144 {
145     DWORD err = ERROR_SUCCESS;
146     CRYPT_PROVIDER_DATA *provData = (CRYPT_PROVIDER_DATA *)data->hWVTStateData;
147
148     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
149
150     if (provData)
151     {
152         err = provData->psPfns->pfnCleanupPolicy(provData);
153         WINTRUST_Free(provData->padwTrustStepErrors);
154         WINTRUST_Free(provData->pPDSip);
155         WINTRUST_Free(provData->psPfns);
156         WINTRUST_Free(provData);
157         data->hWVTStateData = NULL;
158     }
159     TRACE("returning %08x\n", err);
160     return err;
161 }
162
163 static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
164  WINTRUST_DATA *data)
165 {
166     LONG err;
167
168     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
169
170     err = WINTRUST_DefaultVerify(hwnd, actionID, data);
171     WINTRUST_DefaultClose(hwnd, actionID, data);
172     TRACE("returning %08x\n", err);
173     return err;
174 }
175
176 static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
177  WINTRUST_DATA *data)
178 {
179     WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
180     /* Undocumented: the published software action is passed a path,
181      * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
182      */
183     LPCWSTR path = (LPCWSTR)data->pFile;
184     LPWIN_TRUST_SUBJECT_FILE subjectFile =
185      (LPWIN_TRUST_SUBJECT_FILE)data->pSIPClientData;
186     WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
187
188     TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
189     TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
190     fileInfo.pcwszFilePath = path;
191     fileInfo.hFile = subjectFile->hFile;
192     wintrust_data.pFile = &fileInfo;
193     wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
194     wintrust_data.dwUIChoice = WTD_UI_NONE;
195
196     return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
197 }
198
199 /***********************************************************************
200  *              WinVerifyTrust (WINTRUST.@)
201  *
202  * Verifies an object by calling the specified trust provider.
203  *
204  * PARAMS
205  *   hwnd       [I] Handle to a caller window.
206  *   ActionID   [I] Pointer to a GUID that identifies the action to perform.
207  *   ActionData [I] Information used by the trust provider to verify the object.
208  *
209  * RETURNS
210  *   Success: Zero.
211  *   Failure: A TRUST_E_* error code.
212  *
213  * NOTES
214  *   Trust providers can be found at:
215  *   HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
216  */
217 LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
218 {
219     static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
220      0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
221     static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
222     static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
223     LONG err = ERROR_SUCCESS;
224     WINTRUST_DATA *actionData = (WINTRUST_DATA *)ActionData;
225
226     TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
227
228     /* Support for known old-style callers: */
229     if (IsEqualGUID(ActionID, &published_software))
230         err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
231     else
232     {
233         /* Check known actions to warn of possible problems */
234         if (!IsEqualGUID(ActionID, &unknown) &&
235          !IsEqualGUID(ActionID, &generic_verify_v2))
236             WARN("unknown action %s, default behavior may not be right\n",
237              debugstr_guid(ActionID));
238         switch (actionData->dwStateAction)
239         {
240         case WTD_STATEACTION_IGNORE:
241             err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
242             break;
243         case WTD_STATEACTION_VERIFY:
244             err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
245             break;
246         case WTD_STATEACTION_CLOSE:
247             err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
248             break;
249         default:
250             FIXME("unimplemented for %d\n", actionData->dwStateAction);
251         }
252     }
253
254     TRACE("returning %08x\n", err);
255     return err;
256 }
257
258 /***********************************************************************
259  *              WinVerifyTrustEx (WINTRUST.@)
260  */
261 HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
262  WINTRUST_DATA* ActionData )
263 {
264     return WinVerifyTrust(hwnd, ActionID, ActionData);
265 }
266
267 /***********************************************************************
268  *              WTHelperGetProvSignerFromChain (WINTRUST.@)
269  */
270 CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
271  CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
272  DWORD idxCounterSigner)
273 {
274     CRYPT_PROVIDER_SGNR *sgnr;
275
276     TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
277      idxCounterSigner);
278
279     if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
280         return NULL;
281     sgnr = &pProvData->pasSigners[idxSigner];
282     if (fCounterSigner)
283     {
284         if (idxCounterSigner >= sgnr->csCounterSigners ||
285          !sgnr->pasCounterSigners)
286             return NULL;
287         sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
288     }
289     TRACE("returning %p\n", sgnr);
290     return sgnr;
291 }
292
293 /***********************************************************************
294  *              WTHelperGetProvCertFromChain (WINTRUST.@)
295  */
296 CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
297  CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
298 {
299     CRYPT_PROVIDER_CERT *cert;
300
301     TRACE("(%p %d)\n", pSgnr, idxCert);
302
303     if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
304         return NULL;
305     cert = &pSgnr->pasCertChain[idxCert];
306     TRACE("returning %p\n", cert);
307     return cert;
308 }
309
310 /***********************************************************************
311  *              WTHelperProvDataFromStateData (WINTRUST.@)
312  */
313 CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
314 {
315     TRACE("%p\n", hStateData);
316     return (CRYPT_PROVIDER_DATA *)hStateData;
317 }
318
319 static const WCHAR Software_Publishing[] = {
320  'S','o','f','t','w','a','r','e','\\',
321  'M','i','c','r','o','s','o','f','t','\\',
322  'W','i','n','d','o','w','s','\\',
323  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
324  'W','i','n','t','r','u','s','t','\\',
325  'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
326  'S','o','f','t','w','a','r','e',' ',
327  'P','u','b','l','i','s','h','i','n','g',0 };
328 static const WCHAR State[] = { 'S','t','a','t','e',0 };
329
330 /***********************************************************************
331  *              WintrustGetRegPolicyFlags (WINTRUST.@)
332  */
333 void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
334 {
335     HKEY key;
336     LONG r;
337
338     TRACE("%p\n", pdwPolicyFlags);
339
340     *pdwPolicyFlags = 0;
341     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
342      KEY_READ, NULL, &key, NULL);
343     if (!r)
344     {
345         DWORD size = sizeof(DWORD);
346
347         r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
348          &size);
349         RegCloseKey(key);
350         if (r)
351         {
352             /* Failed to query, create and return default value */
353             *pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
354              WTPF_OFFLINEOKNBU_COM |
355              WTPF_OFFLINEOKNBU_IND |
356              WTPF_OFFLINEOK_COM |
357              WTPF_OFFLINEOK_IND;
358             WintrustSetRegPolicyFlags(*pdwPolicyFlags);
359         }
360     }
361 }
362
363 /***********************************************************************
364  *              WintrustSetRegPolicyFlags (WINTRUST.@)
365  */
366 BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
367 {
368     HKEY key;
369     LONG r;
370
371     TRACE("%x\n", dwPolicyFlags);
372
373     r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
374      NULL, 0, KEY_WRITE, NULL, &key, NULL);
375     if (!r)
376     {
377         r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
378          sizeof(DWORD));
379         RegCloseKey(key);
380     }
381     if (r) SetLastError(r);
382     return r == ERROR_SUCCESS;
383 }
384
385 /* Utility functions */
386 void * WINAPI WINTRUST_Alloc(DWORD cb)
387 {
388     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
389 }
390
391 void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb)
392 {
393     return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
394 }
395
396 void WINAPI WINTRUST_Free(void *p)
397 {
398     HeapFree(GetProcessHeap(), 0, p);
399 }
400
401 BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
402 {
403     BOOL ret = FALSE;
404
405     if (data->chStores)
406         data->pahStores = WINTRUST_ReAlloc(data->pahStores,
407          (data->chStores + 1) * sizeof(HCERTSTORE));
408     else
409     {
410         data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
411         data->chStores = 0;
412     }
413     if (data->pahStores)
414     {
415         data->pahStores[data->chStores++] = CertDuplicateStore(store);
416         ret = TRUE;
417     }
418     else
419         SetLastError(ERROR_OUTOFMEMORY);
420     return ret;
421 }
422
423 BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
424  BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
425 {
426     BOOL ret = FALSE;
427
428     if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
429     {
430         SetLastError(ERROR_INVALID_PARAMETER);
431         return FALSE;
432     }
433     if (fCounterSigner)
434     {
435         FIXME("unimplemented for counter signers\n");
436         SetLastError(ERROR_INVALID_PARAMETER);
437         return FALSE;
438     }
439     if (data->csSigners)
440         data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
441          (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
442     else
443     {
444         data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
445         data->csSigners = 0;
446     }
447     if (data->pasSigners)
448     {
449         if (idxSigner < data->csSigners)
450             memmove(&data->pasSigners[idxSigner],
451              &data->pasSigners[idxSigner + 1],
452              (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
453         ret = TRUE;
454         if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
455         {
456             /* The PSDK says psSigner should be allocated using pfnAlloc, but
457              * it doesn't say anything about ownership.  Since callers are
458              * internal, assume ownership is passed, and just store the
459              * pointer.
460              */
461             memcpy(&data->pasSigners[idxSigner], sgnr,
462              sizeof(CRYPT_PROVIDER_SGNR));
463         }
464         else
465             memset(&data->pasSigners[idxSigner], 0,
466              sizeof(CRYPT_PROVIDER_SGNR));
467         data->csSigners++;
468     }
469     else
470         SetLastError(ERROR_OUTOFMEMORY);
471     return ret;
472 }
473
474 BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
475  BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
476 {
477     BOOL ret = FALSE;
478
479     if (fCounterSigner)
480     {
481         FIXME("unimplemented for counter signers\n");
482         SetLastError(ERROR_INVALID_PARAMETER);
483         return FALSE;
484     }
485     if (data->pasSigners[idxSigner].csCertChain)
486         data->pasSigners[idxSigner].pasCertChain =
487          WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
488          (data->pasSigners[idxSigner].csCertChain + 1) *
489          sizeof(CRYPT_PROVIDER_CERT));
490     else
491     {
492         data->pasSigners[idxSigner].pasCertChain =
493          WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
494         data->pasSigners[idxSigner].csCertChain = 0;
495     }
496     if (data->pasSigners[idxSigner].pasCertChain)
497     {
498         CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
499          data->pasSigners[idxSigner].csCertChain];
500
501         cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
502         cert->pCert = CertDuplicateCertificateContext(pCert2Add);
503         data->pasSigners[idxSigner].csCertChain++;
504         ret = TRUE;
505     }
506     else
507         SetLastError(ERROR_OUTOFMEMORY);
508     return ret;
509 }