crypt32: Don't use links to certs in memory store.

This commit is contained in:
Jacek Caban 2013-10-17 11:06:44 +02:00 committed by Alexandre Julliard
parent 4e14c45b8b
commit 2601f58acb
8 changed files with 140 additions and 107 deletions

View File

@ -109,6 +109,8 @@ BOOL WINAPI CertAddEncodedCertificateToSystemStoreW(LPCWSTR pszCertStoreName,
return ret;
}
static const context_vtbl_t cert_vtbl;
static void Cert_free(context_t *context)
{
cert_t *cert = (cert_t*)context;
@ -117,13 +119,41 @@ static void Cert_free(context_t *context)
LocalFree(cert->ctx.pCertInfo);
}
static context_t *Cert_clone(context_t *context, WINECRYPT_CERTSTORE *store)
static context_t *Cert_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
{
cert_t *cert;
if(use_link) {
cert = (cert_t*)Context_CreateLinkContext(sizeof(CERT_CONTEXT), context);
if(!cert)
return NULL;
}else {
const cert_t *cloned = (const cert_t*)context;
void *new_context;
DWORD size = 0;
BOOL res;
new_context = Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl);
if(!new_context)
return NULL;
cert = cert_from_ptr(new_context);
Context_CopyProperties(&cert->ctx, &cloned->ctx);
cert->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType;
cert->ctx.pbCertEncoded = CryptMemAlloc(cloned->ctx.cbCertEncoded);
memcpy(cert->ctx.pbCertEncoded, cloned->ctx.pbCertEncoded, cloned->ctx.cbCertEncoded);
cert->ctx.cbCertEncoded = cloned->ctx.cbCertEncoded;
/* FIXME: We don't need to decode the object here, we could just clone cert info. */
res = CryptDecodeObjectEx(cert->ctx.dwCertEncodingType, X509_CERT_TO_BE_SIGNED,
cert->ctx.pbCertEncoded, cert->ctx.cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
&cert->ctx.pCertInfo, &size);
if(!res) {
CertFreeCertificateContext(&cert->ctx);
return NULL;
}
}
cert->ctx.hCertStore = store;
return &cert->base;
@ -134,18 +164,14 @@ static const context_vtbl_t cert_vtbl = {
Cert_clone
};
BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppStoreContext)
BOOL WINAPI add_cert_to_store(WINECRYPT_CERTSTORE *store, const CERT_CONTEXT *cert,
DWORD add_disposition, BOOL use_link, PCCERT_CONTEXT *ret_context)
{
WINECRYPT_CERTSTORE *store = hCertStore;
BOOL ret = TRUE;
PCCERT_CONTEXT toAdd = NULL, existing = NULL;
const CERT_CONTEXT *existing = NULL;
BOOL ret = TRUE, inherit_props = FALSE;
CERT_CONTEXT *new_context = NULL;
TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
dwAddDisposition, ppStoreContext);
switch (dwAddDisposition)
switch (add_disposition)
{
case CERT_STORE_ADD_ALWAYS:
break;
@ -159,109 +185,110 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
BYTE hashToAdd[20];
DWORD size = sizeof(hashToAdd);
ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
hashToAdd, &size);
if (ret)
{
CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
existing = CertFindCertificateInStore(hCertStore,
pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
NULL);
existing = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0,
CERT_FIND_SHA1_HASH, &blob, NULL);
}
break;
}
default:
FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
FIXME("Unimplemented add disposition %d\n", add_disposition);
SetLastError(E_INVALIDARG);
ret = FALSE;
return FALSE;
}
switch (dwAddDisposition)
switch (add_disposition)
{
case CERT_STORE_ADD_ALWAYS:
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
case CERT_STORE_ADD_NEW:
if (existing)
{
TRACE("found matching certificate, not adding\n");
SetLastError(CRYPT_E_EXISTS);
ret = FALSE;
return FALSE;
}
else
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
case CERT_STORE_ADD_REPLACE_EXISTING:
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
toAdd = CertDuplicateCertificateContext(pCertContext);
if (use_link)
FIXME("CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: semi-stub for links\n");
if (existing)
Context_CopyProperties(toAdd, existing);
inherit_props = TRUE;
break;
case CERT_STORE_ADD_USE_EXISTING:
if(use_link)
FIXME("CERT_STORE_ADD_USE_EXISTING: semi-stub for links\n");
if (existing)
{
Context_CopyProperties(existing, pCertContext);
if (ppStoreContext)
*ppStoreContext = CertDuplicateCertificateContext(existing);
Context_CopyProperties(existing, cert);
if (ret_context)
*ret_context = CertDuplicateCertificateContext(existing);
return TRUE;
}
else
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
case CERT_STORE_ADD_NEWER:
if (existing)
{
if (CompareFileTime(&existing->pCertInfo->NotBefore,
&pCertContext->pCertInfo->NotBefore) >= 0)
if (existing && CompareFileTime(&existing->pCertInfo->NotBefore, &cert->pCertInfo->NotBefore) >= 0)
{
TRACE("existing certificate is newer, not adding\n");
SetLastError(CRYPT_E_EXISTS);
ret = FALSE;
return FALSE;
}
else
toAdd = CertDuplicateCertificateContext(pCertContext);
}
else
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
if (existing)
{
if (CompareFileTime(&existing->pCertInfo->NotBefore,
&pCertContext->pCertInfo->NotBefore) >= 0)
if (CompareFileTime(&existing->pCertInfo->NotBefore, &cert->pCertInfo->NotBefore) >= 0)
{
TRACE("existing certificate is newer, not adding\n");
SetLastError(CRYPT_E_EXISTS);
ret = FALSE;
return FALSE;
}
else
{
toAdd = CertDuplicateCertificateContext(pCertContext);
Context_CopyProperties(toAdd, existing);
inherit_props = TRUE;
}
}
else
toAdd = CertDuplicateCertificateContext(pCertContext);
break;
}
if (toAdd)
{
if (store)
ret = store->vtbl->certs.addContext(store, (void *)toAdd,
(void *)existing, (const void **)ppStoreContext);
else if (ppStoreContext)
*ppStoreContext = CertDuplicateCertificateContext(toAdd);
CertFreeCertificateContext(toAdd);
/* FIXME: We have tests that this works, but what should we really do in this case? */
if(!store) {
if(ret_context)
*ret_context = CertDuplicateCertificateContext(cert);
return TRUE;
}
CertFreeCertificateContext(existing);
ret = store->vtbl->certs.addContext(store, (void*)cert, (void*)existing,
(ret_context || inherit_props) ? (const void **)&new_context : NULL, use_link);
if(!ret)
return FALSE;
if(inherit_props)
Context_CopyProperties(new_context, existing);
if(ret_context)
*ret_context = CertDuplicateCertificateContext(new_context);
else if(new_context)
CertFreeCertificateContext(new_context);
TRACE("returning %d\n", ret);
return ret;
}
BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext,
DWORD dwAddDisposition, PCCERT_CONTEXT *ppStoreContext)
{
WINECRYPT_CERTSTORE *store = hCertStore;
TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext, dwAddDisposition, ppStoreContext);
return add_cert_to_store(store, pCertContext, dwAddDisposition, FALSE, ppStoreContext);
}
BOOL WINAPI CertAddCertificateLinkToStore(HCERTSTORE hCertStore,
PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppCertContext)
@ -279,8 +306,7 @@ BOOL WINAPI CertAddCertificateLinkToStore(HCERTSTORE hCertStore,
SetLastError(E_INVALIDARG);
return FALSE;
}
return CertAddCertificateContextToStore(hCertStore, pCertContext,
dwAddDisposition, ppCertContext);
return add_cert_to_store(hCertStore, pCertContext, dwAddDisposition, TRUE, ppCertContext);
}
PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,

View File

@ -76,7 +76,7 @@ static void *CRYPT_CollectionCreateContextFromChild(WINE_COLLECTIONSTORE *store,
{
context_t *ret;
ret = child->vtbl->clone(child, &store->hdr);
ret = child->vtbl->clone(child, &store->hdr, TRUE);
if (!ret)
return NULL;
@ -105,7 +105,7 @@ static BOOL CRYPT_CollectionAddContext(WINE_COLLECTIONSTORE *store,
contextFuncs = (CONTEXT_FUNCS*)((LPBYTE)storeEntry->store->vtbl +
contextFuncsOffset);
ret = contextFuncs->addContext(storeEntry->store, context,
context_ptr(existingLinked), (const void **)&childContext);
context_ptr(existingLinked), (const void **)&childContext, TRUE);
}
else
{
@ -122,7 +122,7 @@ static BOOL CRYPT_CollectionAddContext(WINE_COLLECTIONSTORE *store,
storeEntry = entry;
ret = contextFuncs->addContext(entry->store, context, NULL,
(const void **)&childContext);
(const void **)&childContext, TRUE);
break;
}
}
@ -201,7 +201,7 @@ static void *CRYPT_CollectionAdvanceEnum(WINE_COLLECTIONSTORE *store,
}
static BOOL Collection_addCert(WINECRYPT_CERTSTORE *store, void *cert,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
BOOL ret;
void *childContext = NULL;
@ -274,7 +274,7 @@ static BOOL Collection_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context
}
static BOOL Collection_addCRL(WINECRYPT_CERTSTORE *store, void *crl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
BOOL ret;
void *childContext = NULL;
@ -345,7 +345,7 @@ static BOOL Collection_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
}
static BOOL Collection_addCTL(WINECRYPT_CERTSTORE *store, void *ctl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
BOOL ret;
void *childContext = NULL;

View File

@ -162,13 +162,13 @@ struct ContextList *ContextList_Create(
return list;
}
void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace, struct WINE_CRYPTCERTSTORE *store)
void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace, struct WINE_CRYPTCERTSTORE *store, BOOL use_link)
{
context_t *context;
TRACE("(%p, %p, %p)\n", list, toLink, toReplace);
context = context_from_ptr(toLink)->vtbl->clone(BASE_CONTEXT_FROM_CONTEXT(toLink), store);
context = context_from_ptr(toLink)->vtbl->clone(BASE_CONTEXT_FROM_CONTEXT(toLink), store, use_link);
if (context)
{
TRACE("adding %p\n", context);

View File

@ -37,10 +37,15 @@ static void CRL_free(context_t *context)
LocalFree(crl->ctx.pCrlInfo);
}
static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store)
static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
{
crl_t *crl;
if(!use_link) {
FIXME("Only links supported\n");
return NULL;
}
crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context);
if(!crl)
return NULL;

View File

@ -168,7 +168,7 @@ typedef struct _context_t context_t;
typedef struct {
void (*free)(context_t*);
struct _context_t *(*clone)(context_t*,struct WINE_CRYPTCERTSTORE*);
struct _context_t *(*clone)(context_t*,struct WINE_CRYPTCERTSTORE*,BOOL);
} context_vtbl_t;
typedef struct _context_t {
@ -267,18 +267,15 @@ typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
/* Called to enumerate the next context in a store. */
typedef void * (*EnumFunc)(struct WINE_CRYPTCERTSTORE *store, void *pPrev);
/* Called to add a context to a store. If toReplace is not NULL,
typedef struct _CONTEXT_FUNCS
{
/* Called to add a context to a store. If toReplace is not NULL,
* context replaces toReplace in the store, and access checks should not be
* performed. Otherwise context is a new context, and it should only be
* added if the store allows it. If ppStoreContext is not NULL, the added
* context should be returned in *ppStoreContext.
*/
typedef BOOL (*AddFunc)(struct WINE_CRYPTCERTSTORE *store, void *context,
void *toReplace, const void **ppStoreContext);
typedef struct _CONTEXT_FUNCS
{
AddFunc addContext;
BOOL (*addContext)(struct WINE_CRYPTCERTSTORE*,void*,void*,const void**,BOOL);
EnumFunc enumContext;
BOOL (*delete)(struct WINE_CRYPTCERTSTORE*,context_t*);
} CONTEXT_FUNCS;
@ -452,7 +449,8 @@ struct ContextList;
struct ContextList *ContextList_Create(
const WINE_CONTEXT_INTERFACE *contextInterface, size_t contextSize) DECLSPEC_HIDDEN;
void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace, struct WINE_CRYPTCERTSTORE *store) DECLSPEC_HIDDEN;
void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace,
struct WINE_CRYPTCERTSTORE *store, BOOL use_link) DECLSPEC_HIDDEN;
void *ContextList_Enum(struct ContextList *list, void *pPrev) DECLSPEC_HIDDEN;

View File

@ -39,10 +39,15 @@ static void CTL_free(context_t *context)
LocalFree(ctl->ctx.pCtlInfo);
}
static context_t *CTL_clone(context_t *context, WINECRYPT_CERTSTORE *store)
static context_t *CTL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
{
ctl_t *ctl;
if(!use_link) {
FIXME("Only links supported\n");
return NULL;
}
ctl = (ctl_t*)Context_CreateLinkContext(sizeof(CTL_CONTEXT), context);
if(!ctl)
return NULL;
@ -154,7 +159,7 @@ BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
{
if (store)
ret = store->vtbl->ctls.addContext(store, (void *)toAdd,
(void *)existing, (const void **)ppStoreContext);
(void *)existing, (const void **)ppStoreContext, TRUE);
else if (ppStoreContext)
*ppStoreContext = CertDuplicateCTLContext(toAdd);
CertFreeCTLContext(toAdd);

View File

@ -69,7 +69,7 @@ static DWORD ProvStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
}
static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, void *cert,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
BOOL ret;
@ -78,7 +78,7 @@ static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, void *cert,
if (toReplace)
ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, toReplace,
ppStoreContext);
ppStoreContext, TRUE);
else
{
ret = TRUE;
@ -87,7 +87,7 @@ static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, void *cert,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, NULL,
ppStoreContext);
ppStoreContext, TRUE);
}
/* dirty trick: replace the returned context's hCertStore with
* store.
@ -128,7 +128,7 @@ static BOOL ProvStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
}
static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, void *crl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
BOOL ret;
@ -137,7 +137,7 @@ static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, void *crl,
if (toReplace)
ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, toReplace,
ppStoreContext);
ppStoreContext, TRUE);
else
{
if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
@ -153,7 +153,7 @@ static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, void *crl,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, NULL,
ppStoreContext);
ppStoreContext, TRUE);
}
}
/* dirty trick: replace the returned context's hCertStore with
@ -195,7 +195,7 @@ static BOOL ProvStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *crl)
}
static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, void *ctl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
BOOL ret;
@ -204,7 +204,7 @@ static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, void *ctl,
if (toReplace)
ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, toReplace,
ppStoreContext);
ppStoreContext, TRUE);
else
{
if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
@ -220,7 +220,7 @@ static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, void *ctl,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, NULL,
ppStoreContext);
ppStoreContext, TRUE);
}
}
/* dirty trick: replace the returned context's hCertStore with

View File

@ -143,14 +143,14 @@ BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
}
static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, void *cert,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
PCERT_CONTEXT context;
TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
context = ContextList_Add(ms->certs, cert, toReplace, store);
context = ContextList_Add(ms->certs, cert, toReplace, store, use_link);
if (!context)
return FALSE;
@ -185,14 +185,14 @@ static BOOL MemStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
}
static BOOL MemStore_addCRL(WINECRYPT_CERTSTORE *store, void *crl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
PCRL_CONTEXT context;
TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
context = ContextList_Add(ms->crls, crl, toReplace, store);
context = ContextList_Add(ms->crls, crl, toReplace, store, use_link);
if (!context)
return FALSE;
@ -227,14 +227,14 @@ static BOOL MemStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
}
static BOOL MemStore_addCTL(WINECRYPT_CERTSTORE *store, void *ctl,
void *toReplace, const void **ppStoreContext)
void *toReplace, const void **ppStoreContext, BOOL use_link)
{
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
PCTL_CONTEXT context;
TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
context = ContextList_Add(ms->ctls, ctl, toReplace, store);
context = ContextList_Add(ms->ctls, ctl, toReplace, store, use_link);
if (!context)
return FALSE;
@ -1022,8 +1022,7 @@ BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
if (toAdd)
{
if (store)
ret = store->vtbl->crls.addContext(store, (void *)toAdd,
(void *)existing, (const void **)ppStoreContext);
ret = store->vtbl->crls.addContext(store, (void*)toAdd, (void*)existing, (const void **)ppStoreContext, TRUE);
else if (ppStoreContext)
*ppStoreContext = CertDuplicateCRLContext(toAdd);
CertFreeCRLContext(toAdd);
@ -1356,7 +1355,7 @@ static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
}
static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, void *context,
void *replace, const void **ret_context)
void *replace, const void **ret_context, BOOL use_link)
{
TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);