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

Last change on this file since 22021 was 22020, checked in by dmik, 13 years ago

Disable debug fields of RTL_CRITICAL_SECTION_DEBUG.

Odin uses the DebugInfo ptr in CRITICAL_SECTION for its own purposes
which are incompatible with NT. For this reason any NT-style usage must
be disabled.

This in particular fixes debug assertions and crashes in CRYPT32.DLL (due to
misinterpretation of the structure fields) which happened e.g. during playback of
some Flash content.

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