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
ProvStore_addref(WINECRYPT_CERTSTORE * store)46 static void ProvStore_addref(WINECRYPT_CERTSTORE *store)
47 {
48 LONG ref = InterlockedIncrement(&store->ref);
49 TRACE("ref = %d\n", ref);
50 }
51
ProvStore_release(WINECRYPT_CERTSTORE * cert_store,DWORD flags)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
ProvStore_releaseContext(WINECRYPT_CERTSTORE * store,context_t * context)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
ProvStore_addCert(WINECRYPT_CERTSTORE * store,context_t * cert,context_t * toReplace,context_t ** ppStoreContext,BOOL use_link)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
ProvStore_enumCert(WINECRYPT_CERTSTORE * store,context_t * prev)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
ProvStore_deleteCert(WINECRYPT_CERTSTORE * store,context_t * context)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
ProvStore_addCRL(WINECRYPT_CERTSTORE * store,context_t * crl,context_t * toReplace,context_t ** ppStoreContext,BOOL use_link)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
ProvStore_enumCRL(WINECRYPT_CERTSTORE * store,context_t * prev)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
ProvStore_deleteCRL(WINECRYPT_CERTSTORE * store,context_t * crl)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
ProvStore_addCTL(WINECRYPT_CERTSTORE * store,context_t * ctl,context_t * toReplace,context_t ** ppStoreContext,BOOL use_link)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
ProvStore_enumCTL(WINECRYPT_CERTSTORE * store,context_t * prev)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
ProvStore_deleteCTL(WINECRYPT_CERTSTORE * store,context_t * ctl)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
ProvStore_control(WINECRYPT_CERTSTORE * cert_store,DWORD dwFlags,DWORD dwCtrlType,void const * pvCtrlPara)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
CRYPT_ProvCreateStore(DWORD dwFlags,WINECRYPT_CERTSTORE * memStore,const CERT_STORE_PROV_INFO * pProvInfo)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
CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,DWORD dwEncodingType,HCRYPTPROV hCryptProv,DWORD dwFlags,const void * pvPara)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