wininet: Fix reporting errors in callbacks.
[wine] / dlls / crypt32 / provstore.c
1 /*
2  * Copyright 2004-2007 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "wine/debug.h"
23 #include "wine/list.h"
24 #include "crypt32_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27
28 typedef struct _WINE_PROVIDERSTORE
29 {
30     WINECRYPT_CERTSTORE             hdr;
31     DWORD                           dwStoreProvFlags;
32     PWINECRYPT_CERTSTORE            memStore;
33     HCERTSTOREPROV                  hStoreProv;
34     PFN_CERT_STORE_PROV_CLOSE       provCloseStore;
35     PFN_CERT_STORE_PROV_WRITE_CERT  provWriteCert;
36     PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert;
37     PFN_CERT_STORE_PROV_WRITE_CRL   provWriteCrl;
38     PFN_CERT_STORE_PROV_DELETE_CRL  provDeleteCrl;
39     PFN_CERT_STORE_PROV_WRITE_CTL   provWriteCtl;
40     PFN_CERT_STORE_PROV_DELETE_CTL  provDeleteCtl;
41     PFN_CERT_STORE_PROV_CONTROL     provControl;
42 } WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
43
44 static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
45 {
46     PWINE_PROVIDERSTORE store = hCertStore;
47
48     TRACE("(%p, %08x)\n", store, dwFlags);
49
50     if (store->provCloseStore)
51         store->provCloseStore(store->hStoreProv, dwFlags);
52     if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
53         CertCloseStore(store->memStore, dwFlags);
54     CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
55 }
56
57 static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, void *cert,
58  void *toReplace, const void **ppStoreContext)
59 {
60     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
61     BOOL ret;
62
63     TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
64
65     if (toReplace)
66         ret = ps->memStore->certs.addContext(ps->memStore, cert, toReplace,
67          ppStoreContext);
68     else
69     {
70         ret = TRUE;
71         if (ps->provWriteCert)
72             ret = ps->provWriteCert(ps->hStoreProv, cert,
73              CERT_STORE_PROV_WRITE_ADD_FLAG);
74         if (ret)
75             ret = ps->memStore->certs.addContext(ps->memStore, cert, NULL,
76              ppStoreContext);
77     }
78     /* dirty trick: replace the returned context's hCertStore with
79      * store.
80      */
81     if (ret && ppStoreContext)
82         (*(PCERT_CONTEXT *)ppStoreContext)->hCertStore = store;
83     return ret;
84 }
85
86 static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
87 {
88     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
89     void *ret;
90
91     ret = ps->memStore->certs.enumContext(ps->memStore, pPrev);
92     if (ret)
93     {
94         /* same dirty trick: replace the returned context's hCertStore with
95          * store.
96          */
97         ((PCERT_CONTEXT)ret)->hCertStore = store;
98     }
99     return ret;
100 }
101
102 static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store, void *cert)
103 {
104     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
105     BOOL ret = TRUE;
106
107     TRACE("(%p, %p)\n", store, cert);
108
109     if (ps->provDeleteCert)
110         ret = ps->provDeleteCert(ps->hStoreProv, cert, 0);
111     if (ret)
112         ret = ps->memStore->certs.deleteContext(ps->memStore, cert);
113     return ret;
114 }
115
116 static BOOL CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
117  void *toReplace, const void **ppStoreContext)
118 {
119     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
120     BOOL ret;
121
122     TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
123
124     if (toReplace)
125         ret = ps->memStore->crls.addContext(ps->memStore, crl, toReplace,
126          ppStoreContext);
127     else
128     {
129         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
130         {
131             SetLastError(ERROR_ACCESS_DENIED);
132             ret = FALSE;
133         }
134         else
135         {
136             ret = TRUE;
137             if (ps->provWriteCrl)
138                 ret = ps->provWriteCrl(ps->hStoreProv, crl,
139                  CERT_STORE_PROV_WRITE_ADD_FLAG);
140             if (ret)
141                 ret = ps->memStore->crls.addContext(ps->memStore, crl, NULL,
142                  ppStoreContext);
143         }
144     }
145     /* dirty trick: replace the returned context's hCertStore with
146      * store.
147      */
148     if (ret && ppStoreContext)
149         (*(PCRL_CONTEXT *)ppStoreContext)->hCertStore = store;
150     return ret;
151 }
152
153 static void *CRYPT_ProvEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
154 {
155     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
156     void *ret;
157
158     ret = ps->memStore->crls.enumContext(ps->memStore, pPrev);
159     if (ret)
160     {
161         /* same dirty trick: replace the returned context's hCertStore with
162          * store.
163          */
164         ((PCRL_CONTEXT)ret)->hCertStore = store;
165     }
166     return ret;
167 }
168
169 static BOOL CRYPT_ProvDeleteCRL(PWINECRYPT_CERTSTORE store, void *crl)
170 {
171     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
172     BOOL ret = TRUE;
173
174     TRACE("(%p, %p)\n", store, crl);
175
176     if (ps->provDeleteCrl)
177         ret = ps->provDeleteCrl(ps->hStoreProv, crl, 0);
178     if (ret)
179         ret = ps->memStore->crls.deleteContext(ps->memStore, crl);
180     return ret;
181 }
182
183 static BOOL CRYPT_ProvAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
184  void *toReplace, const void **ppStoreContext)
185 {
186     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
187     BOOL ret;
188
189     TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
190
191     if (toReplace)
192         ret = ps->memStore->ctls.addContext(ps->memStore, ctl, toReplace,
193          ppStoreContext);
194     else
195     {
196         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
197         {
198             SetLastError(ERROR_ACCESS_DENIED);
199             ret = FALSE;
200         }
201         else
202         {
203             ret = TRUE;
204             if (ps->provWriteCtl)
205                 ret = ps->provWriteCtl(ps->hStoreProv, ctl,
206                  CERT_STORE_PROV_WRITE_ADD_FLAG);
207             if (ret)
208                 ret = ps->memStore->ctls.addContext(ps->memStore, ctl, NULL,
209                  ppStoreContext);
210         }
211     }
212     /* dirty trick: replace the returned context's hCertStore with
213      * store.
214      */
215     if (ret && ppStoreContext)
216         (*(PCTL_CONTEXT *)ppStoreContext)->hCertStore = store;
217     return ret;
218 }
219
220 static void *CRYPT_ProvEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
221 {
222     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
223     void *ret;
224
225     ret = ps->memStore->ctls.enumContext(ps->memStore, pPrev);
226     if (ret)
227     {
228         /* same dirty trick: replace the returned context's hCertStore with
229          * store.
230          */
231         ((PCTL_CONTEXT)ret)->hCertStore = store;
232     }
233     return ret;
234 }
235
236 static BOOL CRYPT_ProvDeleteCTL(PWINECRYPT_CERTSTORE store, void *ctl)
237 {
238     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
239     BOOL ret = TRUE;
240
241     TRACE("(%p, %p)\n", store, ctl);
242
243     if (ps->provDeleteCtl)
244         ret = ps->provDeleteCtl(ps->hStoreProv, ctl, 0);
245     if (ret)
246         ret = ps->memStore->ctls.deleteContext(ps->memStore, ctl);
247     return ret;
248 }
249
250 static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
251  DWORD dwCtrlType, void const *pvCtrlPara)
252 {
253     PWINE_PROVIDERSTORE store = hCertStore;
254     BOOL ret = TRUE;
255
256     TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
257      pvCtrlPara);
258
259     if (store->provControl)
260         ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType,
261          pvCtrlPara);
262     return ret;
263 }
264
265 PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
266  PWINECRYPT_CERTSTORE memStore, const CERT_STORE_PROV_INFO *pProvInfo)
267 {
268     PWINE_PROVIDERSTORE ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
269
270     if (ret)
271     {
272         CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider);
273         ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
274         if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
275         {
276             CertCloseStore(memStore, 0);
277             ret->memStore = NULL;
278         }
279         else
280             ret->memStore = memStore;
281         ret->hStoreProv = pProvInfo->hStoreProv;
282         ret->hdr.closeStore = CRYPT_ProvCloseStore;
283         ret->hdr.certs.addContext = CRYPT_ProvAddCert;
284         ret->hdr.certs.enumContext = CRYPT_ProvEnumCert;
285         ret->hdr.certs.deleteContext = CRYPT_ProvDeleteCert;
286         ret->hdr.crls.addContext = CRYPT_ProvAddCRL;
287         ret->hdr.crls.enumContext = CRYPT_ProvEnumCRL;
288         ret->hdr.crls.deleteContext = CRYPT_ProvDeleteCRL;
289         ret->hdr.ctls.addContext = CRYPT_ProvAddCTL;
290         ret->hdr.ctls.enumContext = CRYPT_ProvEnumCTL;
291         ret->hdr.ctls.deleteContext = CRYPT_ProvDeleteCTL;
292         ret->hdr.control = CRYPT_ProvControl;
293         if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
294             ret->provCloseStore =
295              pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
296         else
297             ret->provCloseStore = NULL;
298         if (pProvInfo->cStoreProvFunc >
299          CERT_STORE_PROV_WRITE_CERT_FUNC)
300             ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[
301              CERT_STORE_PROV_WRITE_CERT_FUNC];
302         else
303             ret->provWriteCert = NULL;
304         if (pProvInfo->cStoreProvFunc >
305          CERT_STORE_PROV_DELETE_CERT_FUNC)
306             ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[
307              CERT_STORE_PROV_DELETE_CERT_FUNC];
308         else
309             ret->provDeleteCert = NULL;
310         if (pProvInfo->cStoreProvFunc >
311          CERT_STORE_PROV_WRITE_CRL_FUNC)
312             ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[
313              CERT_STORE_PROV_WRITE_CRL_FUNC];
314         else
315             ret->provWriteCrl = NULL;
316         if (pProvInfo->cStoreProvFunc >
317          CERT_STORE_PROV_DELETE_CRL_FUNC)
318             ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
319              CERT_STORE_PROV_DELETE_CRL_FUNC];
320         else
321             ret->provDeleteCrl = NULL;
322         if (pProvInfo->cStoreProvFunc >
323          CERT_STORE_PROV_WRITE_CTL_FUNC)
324             ret->provWriteCtl = pProvInfo->rgpvStoreProvFunc[
325              CERT_STORE_PROV_WRITE_CTL_FUNC];
326         else
327             ret->provWriteCtl = NULL;
328         if (pProvInfo->cStoreProvFunc >
329          CERT_STORE_PROV_DELETE_CTL_FUNC)
330             ret->provDeleteCtl = pProvInfo->rgpvStoreProvFunc[
331              CERT_STORE_PROV_DELETE_CTL_FUNC];
332         else
333             ret->provDeleteCtl = NULL;
334         if (pProvInfo->cStoreProvFunc >
335          CERT_STORE_PROV_CONTROL_FUNC)
336             ret->provControl = pProvInfo->rgpvStoreProvFunc[
337              CERT_STORE_PROV_CONTROL_FUNC];
338         else
339             ret->provControl = NULL;
340     }
341     return (PWINECRYPT_CERTSTORE)ret;
342 }
343
344 PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
345  DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
346 {
347     static HCRYPTOIDFUNCSET set = NULL;
348     PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
349     HCRYPTOIDFUNCADDR hFunc;
350     PWINECRYPT_CERTSTORE ret = NULL;
351
352     if (!set)
353         set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
354     CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0,
355      (void **)&provOpenFunc, &hFunc);
356     if (provOpenFunc)
357     {
358         CERT_STORE_PROV_INFO provInfo = { 0 };
359
360         provInfo.cbSize = sizeof(provInfo);
361         if (dwFlags & CERT_STORE_DELETE_FLAG)
362             provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
363              dwFlags, pvPara, NULL, &provInfo);
364         else
365         {
366             HCERTSTORE memStore;
367
368             memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
369              CERT_STORE_CREATE_NEW_FLAG, NULL);
370             if (memStore)
371             {
372                 if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
373                  dwFlags, pvPara, memStore, &provInfo))
374                     ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
375                 else
376                     CertCloseStore(memStore, 0);
377             }
378         }
379         CryptFreeOIDFunctionAddress(hFunc, 0);
380     }
381     else
382         SetLastError(ERROR_FILE_NOT_FOUND);
383     return ret;
384 }