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