* Sync up to trunk head (r64921).
[reactos.git] / dll / win32 / 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
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 }