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 "winnls.h"
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
25 #include "crypt32_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28
29 typedef struct _WINE_FILESTOREINFO
30 {
31 DWORD dwOpenFlags;
32 HCERTSTORE memStore;
33 HANDLE file;
34 DWORD type;
35 BOOL dirty;
36 } WINE_FILESTOREINFO, *PWINE_FILESTOREINFO;
37
38 static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
39 {
40 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
41
42 TRACE("(%p, %08x)\n", store, dwFlags);
43 if (store->dirty)
44 CertSaveStore(store->memStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
45 store->type, CERT_STORE_SAVE_TO_FILE, store->file, 0);
46 CertCloseStore(store->memStore, dwFlags);
47 CloseHandle(store->file);
48 CryptMemFree(store);
49 }
50
51 static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore,
52 PCCERT_CONTEXT cert, DWORD dwFlags)
53 {
54 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
55
56 TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
57 store->dirty = TRUE;
58 return TRUE;
59 }
60
61 static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore,
62 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
63 {
64 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
65
66 TRACE("(%p, %p, %08x)\n", hCertStore, pCertContext, dwFlags);
67 store->dirty = TRUE;
68 return TRUE;
69 }
70
71 static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore,
72 PCCRL_CONTEXT crl, DWORD dwFlags)
73 {
74 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
75
76 TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
77 store->dirty = TRUE;
78 return TRUE;
79 }
80
81 static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
82 PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
83 {
84 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
85
86 TRACE("(%p, %p, %08x)\n", hCertStore, pCrlContext, dwFlags);
87 store->dirty = TRUE;
88 return TRUE;
89 }
90
91 static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob)
92 {
93 BOOL ret = TRUE;
94
95 blob->cbData = GetFileSize(file, NULL);
96 if (blob->cbData)
97 {
98 blob->pbData = CryptMemAlloc(blob->cbData);
99 if (blob->pbData)
100 {
101 DWORD read;
102
103 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
104 }
105 }
106 return ret;
107 }
108
109 static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
110 DWORD dwCtrlType, void const *pvCtrlPara)
111 {
112 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
113 BOOL ret;
114
115 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
116 pvCtrlPara);
117
118 switch (dwCtrlType)
119 {
120 case CERT_STORE_CTRL_RESYNC:
121 store->dirty = FALSE;
122 if (store->type == CERT_STORE_SAVE_AS_STORE)
123 {
124 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
125 CERT_STORE_CREATE_NEW_FLAG, NULL);
126
127 /* FIXME: if I could translate a handle to a path, I could use
128 * CryptQueryObject instead, but there's no API to do so yet.
129 */
130 ret = CRYPT_ReadSerializedStoreFromFile(store->file, memStore);
131 if (ret)
132 I_CertUpdateStore(store->memStore, memStore, 0, 0);
133 CertCloseStore(memStore, 0);
134 }
135 else if (store->type == CERT_STORE_SAVE_AS_PKCS7)
136 {
137 CERT_BLOB blob = { 0, NULL };
138
139 ret = CRYPT_ReadBlobFromFile(store->file, &blob);
140 if (ret)
141 {
142 HCERTSTORE messageStore;
143
144 ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
145 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
146 CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
147 &messageStore, NULL, NULL);
148 I_CertUpdateStore(store->memStore, messageStore, 0, 0);
149 CertCloseStore(messageStore, 0);
150 CryptMemFree(blob.pbData);
151 }
152 }
153 else
154 {
155 WARN("unknown type %d\n", store->type);
156 ret = FALSE;
157 }
158 break;
159 case CERT_STORE_CTRL_COMMIT:
160 if (!(store->dwOpenFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
161 {
162 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
163 ret = FALSE;
164 }
165 else if (store->dirty)
166 ret = CertSaveStore(store->memStore,
167 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
168 store->type, CERT_STORE_SAVE_TO_FILE, store->file, 0);
169 else
170 ret = TRUE;
171 break;
172 default:
173 FIXME("%d: stub\n", dwCtrlType);
174 ret = FALSE;
175 }
176 return ret;
177 }
178
179 static void *fileProvFuncs[] = {
180 CRYPT_FileCloseStore,
181 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
182 CRYPT_FileWriteCert,
183 CRYPT_FileDeleteCert,
184 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
185 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
186 CRYPT_FileWriteCRL,
187 CRYPT_FileDeleteCRL,
188 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
189 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
190 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
191 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
192 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
193 CRYPT_FileControl,
194 };
195
196 static PWINECRYPT_CERTSTORE CRYPT_CreateFileStore(DWORD dwFlags,
197 HCERTSTORE memStore, HANDLE file, DWORD type)
198 {
199 PWINECRYPT_CERTSTORE store = NULL;
200 PWINE_FILESTOREINFO info = CryptMemAlloc(sizeof(WINE_FILESTOREINFO));
201
202 if (info)
203 {
204 CERT_STORE_PROV_INFO provInfo = { 0 };
205
206 info->dwOpenFlags = dwFlags;
207 info->memStore = memStore;
208 info->file = file;
209 info->type = type;
210 info->dirty = FALSE;
211 provInfo.cbSize = sizeof(provInfo);
212 provInfo.cStoreProvFunc = sizeof(fileProvFuncs) /
213 sizeof(fileProvFuncs[0]);
214 provInfo.rgpvStoreProvFunc = fileProvFuncs;
215 provInfo.hStoreProv = info;
216 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
217 }
218 return store;
219 }
220
221 PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
222 const void *pvPara)
223 {
224 PWINECRYPT_CERTSTORE store = NULL;
225 HANDLE file = (HANDLE)pvPara;
226
227 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
228
229 if (!pvPara)
230 {
231 SetLastError(ERROR_INVALID_HANDLE);
232 return NULL;
233 }
234 if (dwFlags & CERT_STORE_DELETE_FLAG)
235 {
236 SetLastError(E_INVALIDARG);
237 return NULL;
238 }
239 if ((dwFlags & CERT_STORE_READONLY_FLAG) &&
240 (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
241 {
242 SetLastError(E_INVALIDARG);
243 return NULL;
244 }
245
246 if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara,
247 GetCurrentProcess(), &file, dwFlags & CERT_STORE_READONLY_FLAG ?
248 GENERIC_READ : GENERIC_READ | GENERIC_WRITE, TRUE, 0))
249 {
250 HCERTSTORE memStore;
251
252 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
253 CERT_STORE_CREATE_NEW_FLAG, NULL);
254 if (memStore)
255 {
256 if (CRYPT_ReadSerializedStoreFromFile(file, memStore))
257 {
258 store = CRYPT_CreateFileStore(dwFlags, memStore, file,
259 CERT_STORE_SAVE_AS_STORE);
260 /* File store doesn't need crypto provider, so close it */
261 if (hCryptProv &&
262 !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
263 CryptReleaseContext(hCryptProv, 0);
264 }
265 }
266 }
267 TRACE("returning %p\n", store);
268 return store;
269 }
270
271 PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
272 DWORD dwFlags, const void *pvPara)
273 {
274 HCERTSTORE store = 0;
275 LPCWSTR fileName = (LPCWSTR)pvPara;
276 DWORD access, create;
277 HANDLE file;
278
279 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_w(fileName));
280
281 if (!fileName)
282 {
283 SetLastError(ERROR_PATH_NOT_FOUND);
284 return NULL;
285 }
286 if ((dwFlags & CERT_STORE_READONLY_FLAG) &&
287 (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
288 {
289 SetLastError(E_INVALIDARG);
290 return NULL;
291 }
292
293 access = GENERIC_READ;
294 if (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG)
295 access |= GENERIC_WRITE;
296 if (dwFlags & CERT_STORE_CREATE_NEW_FLAG)
297 create = CREATE_NEW;
298 else if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
299 create = OPEN_EXISTING;
300 else
301 create = OPEN_ALWAYS;
302 file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL, create,
303 FILE_ATTRIBUTE_NORMAL, NULL);
304 if (file != INVALID_HANDLE_VALUE)
305 {
306 HCERTSTORE memStore = NULL;
307 DWORD size = GetFileSize(file, NULL), type = 0;
308
309 /* If the file isn't empty, try to get the type from the file itself */
310 if (size)
311 {
312 DWORD contentType;
313 BOOL ret;
314
315 /* Close the file so CryptQueryObject can succeed.. */
316 CloseHandle(file);
317 ret = CryptQueryObject(CERT_QUERY_OBJECT_FILE, fileName,
318 CERT_QUERY_CONTENT_FLAG_CERT |
319 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
320 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
321 CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, &contentType, NULL,
322 &memStore, NULL, NULL);
323 if (ret)
324 {
325 if (contentType == CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
326 type = CERT_STORE_SAVE_AS_PKCS7;
327 else
328 type = CERT_STORE_SAVE_AS_STORE;
329 /* and reopen the file. */
330 file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL,
331 create, FILE_ATTRIBUTE_NORMAL, NULL);
332 }
333 }
334 else
335 {
336 static const WCHAR spc[] = { 's','p','c',0 };
337 static const WCHAR p7c[] = { 'p','7','c',0 };
338 LPCWSTR ext = strrchrW(fileName, '.');
339
340 if (ext)
341 {
342 ext++;
343 if (!lstrcmpiW(ext, spc) || !lstrcmpiW(ext, p7c))
344 type = CERT_STORE_SAVE_AS_PKCS7;
345 }
346 if (!type)
347 type = CERT_STORE_SAVE_AS_STORE;
348 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
349 CERT_STORE_CREATE_NEW_FLAG, NULL);
350 }
351 if (memStore)
352 {
353 store = CRYPT_CreateFileStore(dwFlags, memStore, file, type);
354 /* File store doesn't need crypto provider, so close it */
355 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
356 CryptReleaseContext(hCryptProv, 0);
357 }
358 }
359 return (PWINECRYPT_CERTSTORE)store;
360 }
361
362 PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
363 DWORD dwFlags, const void *pvPara)
364 {
365 int len;
366 PWINECRYPT_CERTSTORE ret = NULL;
367
368 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
369 debugstr_a((LPCSTR)pvPara));
370
371 if (!pvPara)
372 {
373 SetLastError(ERROR_FILE_NOT_FOUND);
374 return NULL;
375 }
376 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
377 if (len)
378 {
379 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
380
381 if (storeName)
382 {
383 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
384 ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName);
385 CryptMemFree(storeName);
386 }
387 }
388 return ret;
389 }
390
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.