source: trunk/src/crypt32/filestore.c@ 22012

Last change on this file since 22012 was 21354, checked in by rlwalsh, 16 years ago

eliminate VACPP warning & info msgs - see Ticket #1

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