wintrust: Use path in WIN_TRUST_SUBJECT_FILE structure rather than assuming a path...
[wine] / dlls / 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 #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_CONTROL     provControl;
40 } WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
41
42 static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
43 {
44     PWINE_PROVIDERSTORE store = (PWINE_PROVIDERSTORE)hCertStore;
45
46     TRACE("(%p, %08x)\n", store, dwFlags);
47
48     if (store->provCloseStore)
49         store->provCloseStore(store->hStoreProv, dwFlags);
50     if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
51         CertCloseStore(store->memStore, dwFlags);
52     CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
53 }
54
55 static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, void *cert,
56  void *toReplace, const void **ppStoreContext)
57 {
58     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
59     BOOL ret;
60
61     TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
62
63     if (toReplace)
64         ret = ps->memStore->certs.addContext(ps->memStore, cert, toReplace,
65          ppStoreContext);
66     else
67     {
68         ret = TRUE;
69         if (ps->provWriteCert)
70             ret = ps->provWriteCert(ps->hStoreProv, (PCCERT_CONTEXT)cert,
71              CERT_STORE_PROV_WRITE_ADD_FLAG);
72         if (ret)
73             ret = ps->memStore->certs.addContext(ps->memStore, cert, NULL,
74              ppStoreContext);
75     }
76     /* dirty trick: replace the returned context's hCertStore with
77      * store.
78      */
79     if (ppStoreContext)
80         (*(PCERT_CONTEXT *)ppStoreContext)->hCertStore = store;
81     return ret;
82 }
83
84 static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
85 {
86     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
87     void *ret;
88
89     ret = ps->memStore->certs.enumContext(ps->memStore, pPrev);
90     if (ret)
91     {
92         /* same dirty trick: replace the returned context's hCertStore with
93          * store.
94          */
95         ((PCERT_CONTEXT)ret)->hCertStore = store;
96     }
97     return ret;
98 }
99
100 static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store, void *cert)
101 {
102     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
103     BOOL ret = TRUE;
104
105     TRACE("(%p, %p)\n", store, cert);
106
107     if (ps->provDeleteCert)
108         ret = ps->provDeleteCert(ps->hStoreProv, cert, 0);
109     if (ret)
110         ret = ps->memStore->certs.deleteContext(ps->memStore, cert);
111     return ret;
112 }
113
114 static BOOL CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
115  void *toReplace, const void **ppStoreContext)
116 {
117     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
118     BOOL ret;
119
120     TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
121
122     if (toReplace)
123         ret = ps->memStore->crls.addContext(ps->memStore, crl, toReplace,
124          ppStoreContext);
125     else
126     {
127         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
128         {
129             SetLastError(ERROR_ACCESS_DENIED);
130             ret = FALSE;
131         }
132         else
133         {
134             ret = TRUE;
135             if (ps->provWriteCrl)
136                 ret = ps->provWriteCrl(ps->hStoreProv, (PCCRL_CONTEXT)crl,
137                  CERT_STORE_PROV_WRITE_ADD_FLAG);
138             if (ret)
139                 ret = ps->memStore->crls.addContext(ps->memStore, crl, NULL,
140                  ppStoreContext);
141         }
142     }
143     /* dirty trick: replace the returned context's hCertStore with
144      * store.
145      */
146     if (ppStoreContext)
147         (*(PCRL_CONTEXT *)ppStoreContext)->hCertStore = store;
148     return ret;
149 }
150
151 static void *CRYPT_ProvEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
152 {
153     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
154     void *ret;
155
156     ret = ps->memStore->crls.enumContext(ps->memStore, pPrev);
157     if (ret)
158     {
159         /* same dirty trick: replace the returned context's hCertStore with
160          * store.
161          */
162         ((PCRL_CONTEXT)ret)->hCertStore = store;
163     }
164     return ret;
165 }
166
167 static BOOL CRYPT_ProvDeleteCRL(PWINECRYPT_CERTSTORE store, void *crl)
168 {
169     PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
170     BOOL ret = TRUE;
171
172     TRACE("(%p, %p)\n", store, crl);
173
174     if (ps->provDeleteCrl)
175         ret = ps->provDeleteCrl(ps->hStoreProv, crl, 0);
176     if (ret)
177         ret = ps->memStore->crls.deleteContext(ps->memStore, crl);
178     return ret;
179 }
180
181 static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
182  DWORD dwCtrlType, void const *pvCtrlPara)
183 {
184     PWINE_PROVIDERSTORE store = (PWINE_PROVIDERSTORE)hCertStore;
185     BOOL ret = TRUE;
186
187     TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
188      pvCtrlPara);
189
190     if (store->provControl)
191         ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType,
192          pvCtrlPara);
193     return ret;
194 }
195
196 PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
197  PWINECRYPT_CERTSTORE memStore, const CERT_STORE_PROV_INFO *pProvInfo)
198 {
199     PWINE_PROVIDERSTORE ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
200
201     if (ret)
202     {
203         CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider);
204         ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
205         if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
206         {
207             CertCloseStore(memStore, 0);
208             ret->memStore = NULL;
209         }
210         else
211             ret->memStore = memStore;
212         ret->hStoreProv = pProvInfo->hStoreProv;
213         ret->hdr.closeStore = CRYPT_ProvCloseStore;
214         ret->hdr.certs.addContext = CRYPT_ProvAddCert;
215         ret->hdr.certs.enumContext = CRYPT_ProvEnumCert;
216         ret->hdr.certs.deleteContext = CRYPT_ProvDeleteCert;
217         ret->hdr.crls.addContext = CRYPT_ProvAddCRL;
218         ret->hdr.crls.enumContext = CRYPT_ProvEnumCRL;
219         ret->hdr.crls.deleteContext = CRYPT_ProvDeleteCRL;
220         ret->hdr.control = CRYPT_ProvControl;
221         if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
222             ret->provCloseStore =
223              pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
224         else
225             ret->provCloseStore = NULL;
226         if (pProvInfo->cStoreProvFunc >
227          CERT_STORE_PROV_WRITE_CERT_FUNC)
228             ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[
229              CERT_STORE_PROV_WRITE_CERT_FUNC];
230         else
231             ret->provWriteCert = NULL;
232         if (pProvInfo->cStoreProvFunc >
233          CERT_STORE_PROV_DELETE_CERT_FUNC)
234             ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[
235              CERT_STORE_PROV_DELETE_CERT_FUNC];
236         else
237             ret->provDeleteCert = NULL;
238         if (pProvInfo->cStoreProvFunc >
239          CERT_STORE_PROV_WRITE_CRL_FUNC)
240             ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[
241              CERT_STORE_PROV_WRITE_CRL_FUNC];
242         else
243             ret->provWriteCert = NULL;
244         if (pProvInfo->cStoreProvFunc >
245          CERT_STORE_PROV_DELETE_CRL_FUNC)
246             ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
247              CERT_STORE_PROV_DELETE_CRL_FUNC];
248         else
249             ret->provDeleteCert = NULL;
250         if (pProvInfo->cStoreProvFunc >
251          CERT_STORE_PROV_CONTROL_FUNC)
252             ret->provControl = pProvInfo->rgpvStoreProvFunc[
253              CERT_STORE_PROV_CONTROL_FUNC];
254         else
255             ret->provControl = NULL;
256     }
257     return (PWINECRYPT_CERTSTORE)ret;
258 }
259
260 PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
261  DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
262 {
263     static HCRYPTOIDFUNCSET set = NULL;
264     PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
265     HCRYPTOIDFUNCADDR hFunc;
266     PWINECRYPT_CERTSTORE ret = NULL;
267
268     if (!set)
269         set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
270     CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0,
271      (void **)&provOpenFunc, &hFunc);
272     if (provOpenFunc)
273     {
274         CERT_STORE_PROV_INFO provInfo = { 0 };
275
276         provInfo.cbSize = sizeof(provInfo);
277         if (dwFlags & CERT_STORE_DELETE_FLAG)
278             provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
279              dwFlags, pvPara, NULL, &provInfo);
280         else
281         {
282             HCERTSTORE memStore;
283
284             memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
285              CERT_STORE_CREATE_NEW_FLAG, NULL);
286             if (memStore)
287             {
288                 if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
289                  dwFlags, pvPara, memStore, &provInfo))
290                     ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
291                 else
292                     CertCloseStore(memStore, 0);
293             }
294         }
295         CryptFreeOIDFunctionAddress(hFunc, 0);
296     }
297     else
298         SetLastError(ERROR_FILE_NOT_FOUND);
299     return ret;
300 }