store.c
来自「一个类似windows」· C语言 代码 · 共 1,949 行 · 第 1/5 页
C
1,949 行
/*
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2004-2006 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME:
* - As you can see in the stubs below, support for CRLs and CTLs is missing.
* Mostly this should be copy-paste work, and some code (e.g. extended
* properties) could be shared between them.
* - The concept of physical stores and locations isn't implemented. (This
* doesn't mean registry stores et al aren't implemented. See the PSDK for
* registering and enumerating physical stores and locations.)
* - Many flags, options and whatnot are unimplemented.
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "winuser.h"
#include "wincrypt.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "excpt.h"
#include "wine/exception.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
#define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
/* Some typedefs that make it easier to abstract which type of context we're
* working with.
*/
typedef const void *(WINAPI *CreateContextFunc)(DWORD dwCertEncodingType,
const BYTE *pbCertEncoded, DWORD cbCertEncoded);
typedef BOOL (WINAPI *AddContextToStoreFunc)(HCERTSTORE hCertStore,
const void *context, DWORD dwAddDisposition, const void **ppStoreContext);
typedef BOOL (WINAPI *AddEncodedContextToStoreFunc)(HCERTSTORE hCertStore,
DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwAddDisposition, const void **ppContext);
typedef const void *(WINAPI *EnumContextsInStoreFunc)(HCERTSTORE hCertStore,
const void *pPrevContext);
typedef BOOL (WINAPI *GetContextPropertyFunc)(const void *context,
DWORD dwPropID, void *pvData, DWORD *pcbData);
typedef BOOL (WINAPI *SetContextPropertyFunc)(const void *context,
DWORD dwPropID, DWORD dwFlags, const void *pvData);
typedef BOOL (WINAPI *SerializeElementFunc)(const void *context, DWORD dwFlags,
BYTE *pbElement, DWORD *pcbElement);
typedef BOOL (WINAPI *FreeContextFunc)(const void *context);
typedef BOOL (WINAPI *DeleteContextFunc)(const void *context);
/* An abstract context (certificate, CRL, or CTL) interface */
typedef struct _WINE_CONTEXT_INTERFACE
{
CreateContextFunc create;
AddContextToStoreFunc addContextToStore;
AddEncodedContextToStoreFunc addEncodedToStore;
EnumContextsInStoreFunc enumContextsInStore;
GetContextPropertyFunc getProp;
SetContextPropertyFunc setProp;
SerializeElementFunc serialize;
FreeContextFunc free;
DeleteContextFunc deleteFromStore;
} WINE_CONTEXT_INTERFACE, *PWINE_CONTEXT_INTERFACE;
static const WINE_CONTEXT_INTERFACE gCertInterface = {
(CreateContextFunc)CertCreateCertificateContext,
(AddContextToStoreFunc)CertAddCertificateContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
(EnumContextsInStoreFunc)CertEnumCertificatesInStore,
(GetContextPropertyFunc)CertGetCertificateContextProperty,
(SetContextPropertyFunc)CertSetCertificateContextProperty,
(SerializeElementFunc)CertSerializeCertificateStoreElement,
(FreeContextFunc)CertFreeCertificateContext,
(DeleteContextFunc)CertDeleteCertificateFromStore,
};
static const WINE_CONTEXT_INTERFACE gCRLInterface = {
(CreateContextFunc)CertCreateCRLContext,
(AddContextToStoreFunc)CertAddCRLContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
(EnumContextsInStoreFunc)CertEnumCRLsInStore,
(GetContextPropertyFunc)CertGetCRLContextProperty,
(SetContextPropertyFunc)CertSetCRLContextProperty,
(SerializeElementFunc)CertSerializeCRLStoreElement,
(FreeContextFunc)CertFreeCRLContext,
(DeleteContextFunc)CertDeleteCRLFromStore,
};
static const WINE_CONTEXT_INTERFACE gCTLInterface = {
(CreateContextFunc)CertCreateCTLContext,
(AddContextToStoreFunc)CertAddCTLContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
(EnumContextsInStoreFunc)CertEnumCTLsInStore,
(GetContextPropertyFunc)CertGetCTLContextProperty,
(SetContextPropertyFunc)CertSetCTLContextProperty,
(SerializeElementFunc)CertSerializeCTLStoreElement,
(FreeContextFunc)CertFreeCTLContext,
(DeleteContextFunc)CertDeleteCTLFromStore,
};
struct WINE_CRYPTCERTSTORE;
typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara);
struct _WINE_CERT_CONTEXT;
/* Called to enumerate the next certificate in a store. */
typedef struct _WINE_CERT_CONTEXT * (*EnumCertFunc)
(struct WINE_CRYPTCERTSTORE *store, struct _WINE_CERT_CONTEXT *pPrev);
/* Called to add a new certificate context to a store. If ppStoreContext is
* not NULL, the added context should be returned in *ppStoreContext.
*/
typedef BOOL (*AddCertFunc)(struct WINE_CRYPTCERTSTORE *store,
struct _WINE_CERT_CONTEXT *context, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppStoreContext);
typedef enum _CertStoreType {
StoreTypeMem,
StoreTypeCollection,
StoreTypeProvider,
} CertStoreType;
/* A cert store is polymorphic through the use of function pointers. A type
* is still needed to distinguish collection stores from other types.
* On the function pointers:
* - closeStore is called when the store's ref count becomes 0
* - control is optional, but should be implemented by any store that supports
* persistence
*/
typedef struct WINE_CRYPTCERTSTORE
{
DWORD dwMagic;
LONG ref;
DWORD dwOpenFlags;
HCRYPTPROV cryptProv;
CertStoreType type;
PFN_CERT_STORE_PROV_CLOSE closeStore;
AddCertFunc addCert;
EnumCertFunc enumCert;
PFN_CERT_STORE_PROV_DELETE_CERT deleteCert;
PFN_CERT_STORE_PROV_CONTROL control; /* optional */
} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
typedef enum _ContextType {
ContextTypeData,
ContextTypeLink,
} ContextType;
/* A certificate context. This is the base type, and the two real types
* (data and link) derive from it. Each one can be cast to a PCCERT_CONTEXT.
*/
typedef struct _WINE_CERT_CONTEXT
{
CERT_CONTEXT cert;
LONG ref;
ContextType type;
} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
typedef const struct _WINE_CERT_CONTEXT PCWINE_CERT_CONTEXT;
typedef struct _WINE_CERT_CONTEXT_DATA
{
CERT_CONTEXT cert;
LONG ref;
ContextType type; /* always ContextTypeData */
PCONTEXT_PROPERTY_LIST properties;
} WINE_CERT_CONTEXT_DATA, *PWINE_CERT_CONTEXT_DATA;
typedef const struct _WINE_CERT_CONTEXT_DATA PCWINE_CERT_CONTEXT_DATA;
typedef struct _WINE_CERT_CONTEXT_LINK
{
CERT_CONTEXT cert;
LONG ref;
ContextType type; /* always ContextTypeLink */
PWINE_CERT_CONTEXT linked;
} WINE_CERT_CONTEXT_LINK, *PWINE_CERT_CONTEXT_LINK;
typedef const struct _WINE_CERT_CONTEXT_LINK PCWINE_CERT_CONTEXT_LINK;
/* A mem store has a list of these. They're also returned by the mem store
* during enumeration.
*/
typedef struct _WINE_CERT_LIST_ENTRY
{
WINE_CERT_CONTEXT_LINK cert;
struct list entry;
} WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY;
typedef struct _WINE_MEMSTORE
{
WINECRYPT_CERTSTORE hdr;
CRITICAL_SECTION cs;
struct list certs;
} WINE_MEMSTORE, *PWINE_MEMSTORE;
typedef struct _WINE_HASH_TO_DELETE
{
BYTE hash[20];
struct list entry;
} WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE;
typedef struct _WINE_REGSTOREINFO
{
DWORD dwOpenFlags;
HCRYPTPROV cryptProv;
PWINECRYPT_CERTSTORE memStore;
HKEY key;
BOOL dirty;
CRITICAL_SECTION cs;
struct list certsToDelete;
} WINE_REGSTOREINFO, *PWINE_REGSTOREINFO;
typedef struct _WINE_STORE_LIST_ENTRY
{
PWINECRYPT_CERTSTORE store;
DWORD dwUpdateFlags;
DWORD dwPriority;
struct list entry;
} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY;
/* Returned by a collection store during enumeration.
* Note: relies on the list entry being valid after use, which a number of
* conditions might make untrue (reentrancy, closing a collection store before
* continuing an enumeration on it, ...). The tests seem to indicate this
* sort of unsafety is okay, since Windows isn't well-behaved in these
* scenarios either.
*/
typedef struct _WINE_COLLECTION_CERT_CONTEXT
{
WINE_CERT_CONTEXT_LINK cert;
PWINE_STORE_LIST_ENTRY storeEntry;
} WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT;
typedef struct _WINE_COLLECTIONSTORE
{
WINECRYPT_CERTSTORE hdr;
CRITICAL_SECTION cs;
struct list stores;
} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE;
typedef struct _WINE_PROVIDERSTORE
{
WINECRYPT_CERTSTORE hdr;
DWORD dwStoreProvFlags;
PWINECRYPT_CERTSTORE memStore;
HCERTSTOREPROV hStoreProv;
PFN_CERT_STORE_PROV_CLOSE provCloseStore;
PFN_CERT_STORE_PROV_WRITE_CERT provWriteCert;
PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert;
PFN_CERT_STORE_PROV_CONTROL provControl;
} WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
/* Internal version of CertGetCertificateContextProperty that gets properties
* directly from the context (or the context it's linked to, depending on its
* type.) Doesn't handle special-case properties, since they are handled by
* CertGetCertificateContextProperty, and are particular to the store in which
* the property exists (which is separate from the context.)
*/
static BOOL WINAPI CRYPT_GetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData);
/* Internal version of CertSetCertificateContextProperty that sets properties
* directly on the context (or the context it's linked to, depending on its
* type.) Doesn't handle special cases, since they're handled by
* CertSetCertificateContextProperty anyway.
*/
static BOOL WINAPI CRYPT_SetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags,
const void *pvData);
static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
DWORD dwFlags, CertStoreType type)
{
store->ref = 1;
store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
store->type = type;
if (!hCryptProv)
{
hCryptProv = CRYPT_GetDefaultProvider();
dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
}
store->cryptProv = hCryptProv;
store->dwOpenFlags = dwFlags;
}
/* Initializes the reference ref to point to context, and increments context's
* reference count. Also sets the hCertStore member of the reference to store.
*/
static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_LINK ref,
PWINE_CERT_CONTEXT context, HCERTSTORE store)
{
TRACE("(%p, %p)\n", ref, context);
memcpy(&ref->cert, context, sizeof(ref->cert));
ref->ref = 1;
ref->type = ContextTypeLink;
ref->linked = context;
InterlockedIncrement(&context->ref);
TRACE("%p's ref count is %ld\n", context, context->ref);
ref->cert.hCertStore = store;
}
static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store,
PWINE_CERT_CONTEXT cert, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppStoreContext)
{
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
BOOL add = FALSE, ret;
PCCERT_CONTEXT existing = NULL;
TRACE("(%p, %p, %ld, %p)\n", store, cert, dwAddDisposition, ppStoreContext);
if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
{
BYTE hashToAdd[20];
DWORD size = sizeof(hashToAdd);
ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)cert,
CERT_HASH_PROP_ID, hashToAdd, &size);
if (ret)
{
CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
existing = CertFindCertificateInStore(store,
cert->cert.dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
NULL);
}
}
switch (dwAddDisposition)
{
case CERT_STORE_ADD_ALWAYS:
add = TRUE;
break;
case CERT_STORE_ADD_NEW:
{
if (existing)
{
TRACE("found matching certificate, not adding\n");
SetLastError(CRYPT_E_EXISTS);
add = FALSE;
}
else
add = TRUE;
break;
}
case CERT_STORE_ADD_REPLACE_EXISTING:
{
add = TRUE;
if (existing)
{
TRACE("found matching certificate, replacing\n");
CertDeleteCertificateFromStore(existing);
}
break;
}
default:
FIXME("Unimplemented add disposition %ld\n", dwAddDisposition);
add = FALSE;
}
if (existing)
CertFreeCertificateContext(existing);
if (add)
{
PWINE_CERT_LIST_ENTRY entry = CryptMemAlloc(
sizeof(WINE_CERT_LIST_ENTRY));
if (entry)
{
TRACE("adding %p\n", entry);
CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)cert, store);
EnterCriticalSection(&ms->cs);
list_add_tail(&ms->certs, &entry->entry);
LeaveCriticalSection(&ms->cs);
if (ppStoreContext)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?