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