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 = (PWINE_PROVIDERSTORE)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, (PCCERT_CONTEXT)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, (PCCRL_CONTEXT)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, (PCCTL_CONTEXT)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 = (PWINE_PROVIDERSTORE)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 = (PFN_CERT_STORE_PROV_CLOSE)
|
---|
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 = (PFN_CERT_STORE_PROV_WRITE_CERT)
|
---|
301 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_DELETE_CERT)
|
---|
307 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_WRITE_CRL)
|
---|
313 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_DELETE_CRL)
|
---|
319 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_WRITE_CTL)
|
---|
325 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_DELETE_CTL)
|
---|
331 | pProvInfo->rgpvStoreProvFunc[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 = (PFN_CERT_STORE_PROV_CONTROL)
|
---|
337 | pProvInfo->rgpvStoreProvFunc[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 | }
|
---|