xref: /reactos/dll/win32/crypt32/provstore.c (revision 40462c92)
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 
19 #include <stdarg.h>
20 #include <assert.h>
21 
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wincrypt.h"
25 #include "wine/debug.h"
26 #include "crypt32_private.h"
27 
28 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
29 
30 typedef struct _WINE_PROVIDERSTORE
31 {
32     WINECRYPT_CERTSTORE             hdr;
33     DWORD                           dwStoreProvFlags;
34     WINECRYPT_CERTSTORE            *memStore;
35     HCERTSTOREPROV                  hStoreProv;
36     PFN_CERT_STORE_PROV_CLOSE       provCloseStore;
37     PFN_CERT_STORE_PROV_WRITE_CERT  provWriteCert;
38     PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert;
39     PFN_CERT_STORE_PROV_WRITE_CRL   provWriteCrl;
40     PFN_CERT_STORE_PROV_DELETE_CRL  provDeleteCrl;
41     PFN_CERT_STORE_PROV_WRITE_CTL   provWriteCtl;
42     PFN_CERT_STORE_PROV_DELETE_CTL  provDeleteCtl;
43     PFN_CERT_STORE_PROV_CONTROL     provControl;
44 } WINE_PROVIDERSTORE;
45 
46 static void ProvStore_addref(WINECRYPT_CERTSTORE *store)
47 {
48     LONG ref = InterlockedIncrement(&store->ref);
49     TRACE("ref = %d\n", ref);
50 }
51 
52 static DWORD ProvStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
53 {
54     WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store;
55     LONG ref;
56 
57     if(flags)
58         FIXME("Unimplemented flags %x\n", flags);
59 
60     ref = InterlockedDecrement(&store->hdr.ref);
61     TRACE("(%p) ref=%d\n", store, ref);
62 
63     if(ref)
64         return ERROR_SUCCESS;
65 
66     if (store->provCloseStore)
67         store->provCloseStore(store->hStoreProv, flags);
68     if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
69         store->memStore->vtbl->release(store->memStore, flags);
70     CRYPT_FreeStore(&store->hdr);
71     return ERROR_SUCCESS;
72 }
73 
74 static void ProvStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
75 {
76     /* As long as we don't have contexts properly stored (and hack around hCertStore
77        in add* and enum* functions), this function should never be called. */
78     assert(0);
79 }
80 
81 static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
82  context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
83 {
84     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
85     BOOL ret;
86 
87     TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
88 
89     if (toReplace)
90         ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, toReplace,
91          ppStoreContext, TRUE);
92     else
93     {
94         ret = TRUE;
95         if (ps->provWriteCert)
96             ret = ps->provWriteCert(ps->hStoreProv, context_ptr(cert), CERT_STORE_PROV_WRITE_ADD_FLAG);
97         if (ret)
98             ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, NULL,
99              ppStoreContext, TRUE);
100     }
101     /* dirty trick: replace the returned context's hCertStore with
102      * store.
103      */
104     if (ret && ppStoreContext)
105         (*(cert_t**)ppStoreContext)->ctx.hCertStore = store;
106     return ret;
107 }
108 
109 static context_t *ProvStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
110 {
111     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
112     cert_t *ret;
113 
114     ret = (cert_t*)ps->memStore->vtbl->certs.enumContext(ps->memStore, prev);
115     if (!ret)
116         return NULL;
117 
118     /* same dirty trick: replace the returned context's hCertStore with
119      * store.
120      */
121     ret->ctx.hCertStore = store;
122     return &ret->base;
123 }
124 
125 static BOOL ProvStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
126 {
127     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
128     BOOL ret = TRUE;
129 
130     TRACE("(%p, %p)\n", store, context);
131 
132     if (ps->provDeleteCert)
133         ret = ps->provDeleteCert(ps->hStoreProv, context_ptr(context), 0);
134     if (ret)
135         ret = ps->memStore->vtbl->certs.delete(ps->memStore, context);
136     return ret;
137 }
138 
139 static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
140  context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
141 {
142     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
143     BOOL ret;
144 
145     TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
146 
147     if (toReplace)
148         ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, toReplace,
149          ppStoreContext, TRUE);
150     else
151     {
152         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
153         {
154             SetLastError(ERROR_ACCESS_DENIED);
155             ret = FALSE;
156         }
157         else
158         {
159             ret = TRUE;
160             if (ps->provWriteCrl)
161                 ret = ps->provWriteCrl(ps->hStoreProv, context_ptr(crl),
162                  CERT_STORE_PROV_WRITE_ADD_FLAG);
163             if (ret)
164                 ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, NULL,
165                  ppStoreContext, TRUE);
166         }
167     }
168     /* dirty trick: replace the returned context's hCertStore with
169      * store.
170      */
171     if (ret && ppStoreContext)
172         (*(crl_t**)ppStoreContext)->ctx.hCertStore = store;
173     return ret;
174 }
175 
176 static context_t *ProvStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
177 {
178     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
179     crl_t *ret;
180 
181     ret = (crl_t*)ps->memStore->vtbl->crls.enumContext(ps->memStore, prev);
182     if (!ret)
183         return NULL;
184 
185     /* same dirty trick: replace the returned context's hCertStore with
186      * store.
187      */
188     ret->ctx.hCertStore = store;
189     return &ret->base;
190 }
191 
192 static BOOL ProvStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *crl)
193 {
194     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
195     BOOL ret = TRUE;
196 
197     TRACE("(%p, %p)\n", store, crl);
198 
199     if (ps->provDeleteCrl)
200         ret = ps->provDeleteCrl(ps->hStoreProv, context_ptr(crl), 0);
201     if (ret)
202         ret = ps->memStore->vtbl->crls.delete(ps->memStore, crl);
203     return ret;
204 }
205 
206 static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
207  context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
208 {
209     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
210     BOOL ret;
211 
212     TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
213 
214     if (toReplace)
215         ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, toReplace,
216          ppStoreContext, TRUE);
217     else
218     {
219         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
220         {
221             SetLastError(ERROR_ACCESS_DENIED);
222             ret = FALSE;
223         }
224         else
225         {
226             ret = TRUE;
227             if (ps->provWriteCtl)
228                 ret = ps->provWriteCtl(ps->hStoreProv, context_ptr(ctl),
229                  CERT_STORE_PROV_WRITE_ADD_FLAG);
230             if (ret)
231                 ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, NULL,
232                  ppStoreContext, TRUE);
233         }
234     }
235     /* dirty trick: replace the returned context's hCertStore with
236      * store.
237      */
238     if (ret && ppStoreContext)
239         (*(ctl_t**)ppStoreContext)->ctx.hCertStore = store;
240     return ret;
241 }
242 
243 static context_t *ProvStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
244 {
245     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
246     ctl_t *ret;
247 
248     ret = (ctl_t*)ps->memStore->vtbl->ctls.enumContext(ps->memStore, prev);
249     if (!ret)
250         return NULL;
251 
252     /* same dirty trick: replace the returned context's hCertStore with
253      * store.
254      */
255     ret->ctx.hCertStore = store;
256     return &ret->base;
257 }
258 
259 static BOOL ProvStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *ctl)
260 {
261     WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
262     BOOL ret = TRUE;
263 
264     TRACE("(%p, %p)\n", store, ctl);
265 
266     if (ps->provDeleteCtl)
267         ret = ps->provDeleteCtl(ps->hStoreProv, context_ptr(ctl), 0);
268     if (ret)
269         ret = ps->memStore->vtbl->ctls.delete(ps->memStore, ctl);
270     return ret;
271 }
272 
273 static BOOL ProvStore_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara)
274 {
275     WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store;
276     BOOL ret = TRUE;
277 
278     TRACE("(%p, %08x, %d, %p)\n", store, dwFlags, dwCtrlType,
279      pvCtrlPara);
280 
281     if (store->provControl)
282         ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType,
283          pvCtrlPara);
284     return ret;
285 }
286 
287 static const store_vtbl_t ProvStoreVtbl = {
288     ProvStore_addref,
289     ProvStore_release,
290     ProvStore_releaseContext,
291     ProvStore_control,
292     {
293         ProvStore_addCert,
294         ProvStore_enumCert,
295         ProvStore_deleteCert
296     }, {
297         ProvStore_addCRL,
298         ProvStore_enumCRL,
299         ProvStore_deleteCRL
300     }, {
301         ProvStore_addCTL,
302         ProvStore_enumCTL,
303         ProvStore_deleteCTL
304     }
305 };
306 
307 WINECRYPT_CERTSTORE *CRYPT_ProvCreateStore(DWORD dwFlags,
308  WINECRYPT_CERTSTORE *memStore, const CERT_STORE_PROV_INFO *pProvInfo)
309 {
310     WINE_PROVIDERSTORE *ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
311 
312     if (ret)
313     {
314         CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider, &ProvStoreVtbl);
315         ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
316         if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
317         {
318             CertCloseStore(memStore, 0);
319             ret->memStore = NULL;
320         }
321         else
322             ret->memStore = memStore;
323         ret->hStoreProv = pProvInfo->hStoreProv;
324         if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
325             ret->provCloseStore =
326              pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
327         else
328             ret->provCloseStore = NULL;
329         if (pProvInfo->cStoreProvFunc >
330          CERT_STORE_PROV_WRITE_CERT_FUNC)
331             ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[
332              CERT_STORE_PROV_WRITE_CERT_FUNC];
333         else
334             ret->provWriteCert = NULL;
335         if (pProvInfo->cStoreProvFunc >
336          CERT_STORE_PROV_DELETE_CERT_FUNC)
337             ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[
338              CERT_STORE_PROV_DELETE_CERT_FUNC];
339         else
340             ret->provDeleteCert = NULL;
341         if (pProvInfo->cStoreProvFunc >
342          CERT_STORE_PROV_WRITE_CRL_FUNC)
343             ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[
344              CERT_STORE_PROV_WRITE_CRL_FUNC];
345         else
346             ret->provWriteCrl = NULL;
347         if (pProvInfo->cStoreProvFunc >
348          CERT_STORE_PROV_DELETE_CRL_FUNC)
349             ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
350              CERT_STORE_PROV_DELETE_CRL_FUNC];
351         else
352             ret->provDeleteCrl = NULL;
353         if (pProvInfo->cStoreProvFunc >
354          CERT_STORE_PROV_WRITE_CTL_FUNC)
355             ret->provWriteCtl = pProvInfo->rgpvStoreProvFunc[
356              CERT_STORE_PROV_WRITE_CTL_FUNC];
357         else
358             ret->provWriteCtl = NULL;
359         if (pProvInfo->cStoreProvFunc >
360          CERT_STORE_PROV_DELETE_CTL_FUNC)
361             ret->provDeleteCtl = pProvInfo->rgpvStoreProvFunc[
362              CERT_STORE_PROV_DELETE_CTL_FUNC];
363         else
364             ret->provDeleteCtl = NULL;
365         if (pProvInfo->cStoreProvFunc >
366          CERT_STORE_PROV_CONTROL_FUNC)
367             ret->provControl = pProvInfo->rgpvStoreProvFunc[
368              CERT_STORE_PROV_CONTROL_FUNC];
369         else
370             ret->provControl = NULL;
371     }
372     return (WINECRYPT_CERTSTORE*)ret;
373 }
374 
375 WINECRYPT_CERTSTORE *CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
376  DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
377 {
378     static HCRYPTOIDFUNCSET set = NULL;
379     PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
380     HCRYPTOIDFUNCADDR hFunc;
381     WINECRYPT_CERTSTORE *ret = NULL;
382 
383     if (!set)
384         set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
385     CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0,
386      (void **)&provOpenFunc, &hFunc);
387     if (provOpenFunc)
388     {
389         CERT_STORE_PROV_INFO provInfo = { 0 };
390 
391         provInfo.cbSize = sizeof(provInfo);
392         if (dwFlags & CERT_STORE_DELETE_FLAG)
393             provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
394              dwFlags, pvPara, NULL, &provInfo);
395         else
396         {
397             HCERTSTORE memStore;
398 
399             memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
400              CERT_STORE_CREATE_NEW_FLAG, NULL);
401             if (memStore)
402             {
403                 if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
404                  dwFlags, pvPara, memStore, &provInfo))
405                     ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
406                 else
407                     CertCloseStore(memStore, 0);
408             }
409         }
410         CryptFreeOIDFunctionAddress(hFunc, 0);
411     }
412     else
413         SetLastError(ERROR_FILE_NOT_FOUND);
414     return ret;
415 }
416