source: trunk/src/crypt32/collectionstore.c@ 21388

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

eliminate VACPP warning & info msgs - see Ticket #1

File size: 17.9 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 <string.h>
20#include "windef.h"
21#include "winbase.h"
22#include "winbase.h"
23#include "winerror.h"
24#include "wincrypt.h"
25#include "wine/debug.h"
26#include "wine/list.h"
27#include "crypt32_private.h"
28#include "winnt.h"
29
30ODINDEBUGCHANNEL(crypt);
31
32
33typedef struct _WINE_STORE_LIST_ENTRY
34{
35 PWINECRYPT_CERTSTORE store;
36 DWORD dwUpdateFlags;
37 DWORD dwPriority;
38 struct list entry;
39} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY;
40
41typedef struct _WINE_COLLECTIONSTORE
42{
43 WINECRYPT_CERTSTORE hdr;
44 /*CRITICAL_SECTION*/RTL_CRITICAL_SECTION cs;
45 struct list stores;
46} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE;
47
48static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags)
49{
50 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
51 PWINE_STORE_LIST_ENTRY entry, next;
52
53 TRACE("(%p, %08x)\n", store, dwFlags);
54
55 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY,
56 entry)
57 {
58 TRACE("closing %p\n", entry);
59 CertCloseStore((HCERTSTORE)entry->store, dwFlags);
60 CryptMemFree(entry);
61 }
62 cs->cs.DebugInfo->Spare[0] = 0;
63 DeleteCriticalSection((CRITICAL_SECTION*)&cs->cs);
64 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
65}
66
67static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store,
68 PWINE_STORE_LIST_ENTRY storeEntry, void *child, size_t contextSize,
69 BOOL addRef)
70{
71 void *ret = Context_CreateLinkContext(contextSize, child,
72 sizeof(PWINE_STORE_LIST_ENTRY), addRef);
73
74 if (ret)
75 *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(ret, contextSize)
76 = storeEntry;
77
78 return ret;
79}
80
81static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store,
82 unsigned int contextFuncsOffset, void *context, void *toReplace, unsigned int contextSize,
83 void **pChildContext)
84{
85 BOOL ret;
86 void *childContext = NULL;
87 PWINE_STORE_LIST_ENTRY storeEntry = NULL;
88
89 TRACE("(%p, %d, %p, %p, %d)\n", store, contextFuncsOffset, context,
90 toReplace, contextSize);
91
92 ret = FALSE;
93 if (toReplace)
94 {
95 void *existingLinked = Context_GetLinkedContext(toReplace, contextSize);
96 PCONTEXT_FUNCS contextFuncs;
97
98 storeEntry = *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(toReplace,
99 contextSize);
100 contextFuncs = (PCONTEXT_FUNCS)((LPBYTE)storeEntry->store +
101 contextFuncsOffset);
102 ret = contextFuncs->addContext(storeEntry->store, context,
103 existingLinked, childContext);
104 }
105 else
106 {
107 PWINE_STORE_LIST_ENTRY entry, next;
108
109 EnterCriticalSection((CRITICAL_SECTION*)&store->cs);
110 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores,
111 WINE_STORE_LIST_ENTRY, entry)
112 {
113 if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG)
114 {
115 PCONTEXT_FUNCS contextFuncs = (PCONTEXT_FUNCS)(
116 (LPBYTE)entry->store + contextFuncsOffset);
117
118 storeEntry = entry;
119 ret = contextFuncs->addContext(entry->store, context, NULL,
120 (const void **)&childContext);
121 break;
122 }
123 }
124 LeaveCriticalSection((CRITICAL_SECTION*)&store->cs);
125 if (!storeEntry)
126 SetLastError(E_ACCESSDENIED);
127 }
128 *pChildContext = childContext;
129 return ret;
130}
131
132/* Advances a collection enumeration by one context, if possible, where
133 * advancing means:
134 * - calling the current store's enumeration function once, and returning
135 * the enumerated context if one is returned
136 * - moving to the next store if the current store has no more items, and
137 * recursively calling itself to get the next item.
138 * Returns NULL if the collection contains no more items or on error.
139 * Assumes the collection store's lock is held.
140 */
141static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store,
142 PWINE_STORE_LIST_ENTRY storeEntry, PCONTEXT_FUNCS contextFuncs,
143 PCWINE_CONTEXT_INTERFACE contextInterface, void *pPrev, size_t contextSize)
144{
145 void *ret, *child;
146 struct list *storeNext = list_next(&store->stores, &storeEntry->entry);
147
148 TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
149
150 if (pPrev)
151 {
152 /* Ref-counting funny business: "duplicate" (addref) the child, because
153 * the free(pPrev) below can cause the ref count to become negative.
154 */
155 child = Context_GetLinkedContext(pPrev, contextSize);
156 contextInterface->duplicate(child);
157 child = contextFuncs->enumContext(storeEntry->store, child);
158 contextInterface->confree(pPrev);
159 pPrev = NULL;
160 }
161 else
162 child = contextFuncs->enumContext(storeEntry->store, NULL);
163 if (child)
164 ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child,
165 contextSize, FALSE);
166 else
167 {
168 if (storeNext)
169 {
170 /* We always want the same function pointers (from certs, crls)
171 * in the next store, so use the same offset into the next store.
172 */
173 size_t offset = (LPBYTE)contextFuncs - (LPBYTE)storeEntry->store;
174 PWINE_STORE_LIST_ENTRY storeNextEntry =
175 LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry);
176 PCONTEXT_FUNCS storeNextContexts =
177 (PCONTEXT_FUNCS)((LPBYTE)storeNextEntry->store + offset);
178
179 ret = CRYPT_CollectionAdvanceEnum(store, storeNextEntry,
180 storeNextContexts, contextInterface, NULL, contextSize);
181 }
182 else
183 {
184 SetLastError(CRYPT_E_NOT_FOUND);
185 ret = NULL;
186 }
187 }
188 TRACE("returning %p\n", ret);
189 return ret;
190}
191
192static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert,
193 void *toReplace, const void **ppStoreContext)
194{
195 BOOL ret;
196 void *childContext = NULL;
197 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
198
199 ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs),
200 cert, toReplace, sizeof(CERT_CONTEXT), &childContext);
201 if (ppStoreContext && childContext)
202 {
203 PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
204 Context_GetExtra(childContext, sizeof(CERT_CONTEXT));
205 PCERT_CONTEXT context =
206 CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
207 sizeof(CERT_CONTEXT), TRUE);
208
209 if (context)
210 context->hCertStore = store;
211 *ppStoreContext = context;
212 }
213 CertFreeCertificateContext((PCCERT_CONTEXT)childContext);
214 return ret;
215}
216
217static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
218{
219 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
220 void *ret;
221
222 TRACE("(%p, %p)\n", store, pPrev);
223
224 EnterCriticalSection((CRITICAL_SECTION*)&cs->cs);
225 if (pPrev)
226 {
227 PWINE_STORE_LIST_ENTRY storeEntry =
228 *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
229 sizeof(CERT_CONTEXT));
230
231 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
232 &storeEntry->store->certs, pCertInterface, pPrev,
233 sizeof(CERT_CONTEXT));
234 }
235 else
236 {
237 if (!list_empty(&cs->stores))
238 {
239 PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
240 WINE_STORE_LIST_ENTRY, entry);
241
242 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
243 &storeEntry->store->certs, pCertInterface, NULL,
244 sizeof(CERT_CONTEXT));
245 }
246 else
247 {
248 SetLastError(CRYPT_E_NOT_FOUND);
249 ret = NULL;
250 }
251 }
252 LeaveCriticalSection((CRITICAL_SECTION*)&cs->cs);
253 if (ret)
254 ((PCERT_CONTEXT)ret)->hCertStore = store;
255 TRACE("returning %p\n", ret);
256 return ret;
257}
258
259static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store,
260 void *pCertContext)
261{
262 BOOL ret;
263
264 TRACE("(%p, %p)\n", store, pCertContext);
265
266 ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT)
267 Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT)));
268 return ret;
269}
270
271static BOOL CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
272 void *toReplace, const void **ppStoreContext)
273{
274 BOOL ret;
275 void *childContext = NULL;
276 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
277
278 ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, crls),
279 crl, toReplace, sizeof(CRL_CONTEXT), &childContext);
280 if (ppStoreContext && childContext)
281 {
282 PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
283 Context_GetExtra(childContext, sizeof(CRL_CONTEXT));
284 PCRL_CONTEXT context =
285 CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
286 sizeof(CRL_CONTEXT), TRUE);
287
288 if (context)
289 context->hCertStore = store;
290 *ppStoreContext = context;
291 }
292 CertFreeCRLContext((PCCRL_CONTEXT)childContext);
293 return ret;
294}
295
296static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
297{
298 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
299 void *ret;
300
301 TRACE("(%p, %p)\n", store, pPrev);
302
303 EnterCriticalSection((CRITICAL_SECTION*)&cs->cs);
304 if (pPrev)
305 {
306 PWINE_STORE_LIST_ENTRY storeEntry =
307 *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
308 sizeof(CRL_CONTEXT));
309
310 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
311 &storeEntry->store->crls, pCRLInterface, pPrev, sizeof(CRL_CONTEXT));
312 }
313 else
314 {
315 if (!list_empty(&cs->stores))
316 {
317 PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
318 WINE_STORE_LIST_ENTRY, entry);
319
320 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
321 &storeEntry->store->crls, pCRLInterface, NULL,
322 sizeof(CRL_CONTEXT));
323 }
324 else
325 {
326 SetLastError(CRYPT_E_NOT_FOUND);
327 ret = NULL;
328 }
329 }
330 LeaveCriticalSection((CRITICAL_SECTION*)&cs->cs);
331 if (ret)
332 ((PCRL_CONTEXT)ret)->hCertStore = store;
333 TRACE("returning %p\n", ret);
334 return ret;
335}
336
337static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store,
338 void *pCrlContext)
339{
340 BOOL ret;
341
342 TRACE("(%p, %p)\n", store, pCrlContext);
343
344 ret = CertDeleteCRLFromStore((PCCRL_CONTEXT)
345 Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT)));
346 return ret;
347}
348
349static BOOL CRYPT_CollectionAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
350 void *toReplace, const void **ppStoreContext)
351{
352 BOOL ret;
353 void *childContext = NULL;
354 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
355
356 ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, ctls),
357 ctl, toReplace, sizeof(CTL_CONTEXT), &childContext);
358 if (ppStoreContext && childContext)
359 {
360 PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
361 Context_GetExtra(childContext, sizeof(CTL_CONTEXT));
362 PCTL_CONTEXT context =
363 CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
364 sizeof(CTL_CONTEXT), TRUE);
365
366 if (context)
367 context->hCertStore = store;
368 *ppStoreContext = context;
369 }
370 CertFreeCTLContext((PCCTL_CONTEXT)childContext);
371 return ret;
372}
373
374static void *CRYPT_CollectionEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
375{
376 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
377 void *ret;
378
379 TRACE("(%p, %p)\n", store, pPrev);
380
381 EnterCriticalSection((CRITICAL_SECTION*)&cs->cs);
382 if (pPrev)
383 {
384 PWINE_STORE_LIST_ENTRY storeEntry =
385 *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
386 sizeof(CTL_CONTEXT));
387
388 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
389 &storeEntry->store->ctls, pCTLInterface, pPrev, sizeof(CTL_CONTEXT));
390 }
391 else
392 {
393 if (!list_empty(&cs->stores))
394 {
395 PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
396 WINE_STORE_LIST_ENTRY, entry);
397
398 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
399 &storeEntry->store->ctls, pCTLInterface, NULL,
400 sizeof(CTL_CONTEXT));
401 }
402 else
403 {
404 SetLastError(CRYPT_E_NOT_FOUND);
405 ret = NULL;
406 }
407 }
408 LeaveCriticalSection((CRITICAL_SECTION*)&cs->cs);
409 if (ret)
410 ((PCTL_CONTEXT)ret)->hCertStore = store;
411 TRACE("returning %p\n", ret);
412 return ret;
413}
414
415static BOOL CRYPT_CollectionDeleteCTL(PWINECRYPT_CERTSTORE store,
416 void *pCtlContext)
417{
418 BOOL ret;
419
420 TRACE("(%p, %p)\n", store, pCtlContext);
421
422 ret = CertDeleteCTLFromStore((PCCTL_CONTEXT)
423 Context_GetLinkedContext(pCtlContext, sizeof(CTL_CONTEXT)));
424 return ret;
425}
426
427PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
428 DWORD dwFlags, const void *pvPara)
429{
430 PWINE_COLLECTIONSTORE store;
431
432 if (dwFlags & CERT_STORE_DELETE_FLAG)
433 {
434 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
435 store = NULL;
436 }
437 else
438 {
439 store = CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE));
440 if (store)
441 {
442 memset(store, 0, sizeof(WINE_COLLECTIONSTORE));
443 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeCollection);
444 store->hdr.closeStore = CRYPT_CollectionCloseStore;
445 store->hdr.certs.addContext = CRYPT_CollectionAddCert;
446 store->hdr.certs.enumContext = CRYPT_CollectionEnumCert;
447 store->hdr.certs.deleteContext = CRYPT_CollectionDeleteCert;
448 store->hdr.crls.addContext = CRYPT_CollectionAddCRL;
449 store->hdr.crls.enumContext = CRYPT_CollectionEnumCRL;
450 store->hdr.crls.deleteContext = CRYPT_CollectionDeleteCRL;
451 store->hdr.ctls.addContext = CRYPT_CollectionAddCTL;
452 store->hdr.ctls.enumContext = CRYPT_CollectionEnumCTL;
453 store->hdr.ctls.deleteContext = CRYPT_CollectionDeleteCTL;
454 InitializeCriticalSection((CRITICAL_SECTION*)&store->cs);
455 store->cs.DebugInfo->Spare[0] = (DWORD)(DWORD_PTR)(__FILE__ ": PWINE_COLLECTIONSTORE->cs");
456 list_init(&store->stores);
457 }
458 }
459 return (PWINECRYPT_CERTSTORE)store;
460}
461
462BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
463 HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
464{
465 PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore;
466 WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore;
467 PWINE_STORE_LIST_ENTRY entry;
468 BOOL ret;
469
470 TRACE("(%p, %p, %08x, %d)\n", hCollectionStore, hSiblingStore,
471 dwUpdateFlags, dwPriority);
472
473 if (!collection || !sibling)
474 return TRUE;
475 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
476 {
477 SetLastError(E_INVALIDARG);
478 return FALSE;
479 }
480 if (collection->hdr.type != StoreTypeCollection)
481 {
482 SetLastError(E_INVALIDARG);
483 return FALSE;
484 }
485 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
486 {
487 SetLastError(E_INVALIDARG);
488 return FALSE;
489 }
490
491 entry = CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY));
492 if (entry)
493 {
494 InterlockedIncrement(&sibling->ref);
495 TRACE("sibling %p's ref count is %d\n", sibling, sibling->ref);
496 entry->store = sibling;
497 entry->dwUpdateFlags = dwUpdateFlags;
498 entry->dwPriority = dwPriority;
499 list_init(&entry->entry);
500 TRACE("%p: adding %p, priority %d\n", collection, entry, dwPriority);
501 EnterCriticalSection((CRITICAL_SECTION*)&collection->cs);
502 if (dwPriority)
503 {
504 PWINE_STORE_LIST_ENTRY cursor;
505 BOOL added = FALSE;
506
507 LIST_FOR_EACH_ENTRY(cursor, &collection->stores,
508 WINE_STORE_LIST_ENTRY, entry)
509 {
510 if (cursor->dwPriority < dwPriority)
511 {
512 list_add_before(&cursor->entry, &entry->entry);
513 added = TRUE;
514 break;
515 }
516 }
517 if (!added)
518 list_add_tail(&collection->stores, &entry->entry);
519 }
520 else
521 list_add_tail(&collection->stores, &entry->entry);
522 LeaveCriticalSection((CRITICAL_SECTION*)&collection->cs);
523 ret = TRUE;
524 }
525 else
526 ret = FALSE;
527 return ret;
528}
529
530void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore,
531 HCERTSTORE hSiblingStore)
532{
533 PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore;
534 WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore;
535 PWINE_STORE_LIST_ENTRY store, next;
536
537 TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore);
538
539 if (!collection || !sibling)
540 return;
541 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
542 {
543 SetLastError(E_INVALIDARG);
544 return;
545 }
546 if (collection->hdr.type != StoreTypeCollection)
547 return;
548 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
549 {
550 SetLastError(E_INVALIDARG);
551 return;
552 }
553 EnterCriticalSection((CRITICAL_SECTION*)&collection->cs);
554 LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores,
555 WINE_STORE_LIST_ENTRY, entry)
556 {
557 if (store->store == sibling)
558 {
559 list_remove(&store->entry);
560 CertCloseStore(store->store, 0);
561 CryptMemFree(store);
562 break;
563 }
564 }
565 LeaveCriticalSection((CRITICAL_SECTION*)&collection->cs);
566}
Note: See TracBrowser for help on using the repository browser.