crypt32: Add support for CRLs.
This commit is contained in:
parent
3be75cebe8
commit
c4f2bcf3d1
|
@ -9,6 +9,7 @@ IMPORTS = user32 advapi32 kernel32 ntdll
|
|||
|
||||
C_SRCS = \
|
||||
cert.c \
|
||||
crl.c \
|
||||
context.c \
|
||||
decode.c \
|
||||
encode.c \
|
||||
|
|
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* Copyright 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wincrypt.h"
|
||||
#include "wine/debug.h"
|
||||
#include "crypt32_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
|
||||
const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
|
||||
{
|
||||
PCRL_CONTEXT crl = NULL;
|
||||
BOOL ret;
|
||||
PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
|
||||
PCRL_INFO crlInfo = NULL;
|
||||
DWORD size = 0;
|
||||
|
||||
TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCrlEncoded,
|
||||
cbCrlEncoded);
|
||||
|
||||
if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
|
||||
{
|
||||
SetLastError(E_INVALIDARG);
|
||||
return NULL;
|
||||
}
|
||||
/* First try to decode it as a signed crl. */
|
||||
ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT, pbCrlEncoded,
|
||||
cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&signedCrl, &size);
|
||||
if (ret)
|
||||
{
|
||||
size = 0;
|
||||
ret = CryptDecodeObjectEx(dwCertEncodingType,
|
||||
X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
|
||||
signedCrl->ToBeSigned.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&crlInfo, &size);
|
||||
LocalFree(signedCrl);
|
||||
}
|
||||
/* Failing that, try it as an unsigned crl */
|
||||
if (!ret)
|
||||
{
|
||||
size = 0;
|
||||
ret = CryptDecodeObjectEx(dwCertEncodingType,
|
||||
X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded,
|
||||
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
|
||||
(BYTE *)&crlInfo, &size);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
BYTE *data = NULL;
|
||||
|
||||
crl = (PCRL_CONTEXT)Context_CreateDataContext(sizeof(CRL_CONTEXT));
|
||||
if (!crl)
|
||||
goto end;
|
||||
data = CryptMemAlloc(cbCrlEncoded);
|
||||
if (!data)
|
||||
{
|
||||
CryptMemFree(crl);
|
||||
crl = NULL;
|
||||
goto end;
|
||||
}
|
||||
memcpy(data, pbCrlEncoded, cbCrlEncoded);
|
||||
crl->dwCertEncodingType = dwCertEncodingType;
|
||||
crl->pbCrlEncoded = data;
|
||||
crl->cbCrlEncoded = cbCrlEncoded;
|
||||
crl->pCrlInfo = crlInfo;
|
||||
crl->hCertStore = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
return (PCCRL_CONTEXT)crl;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
|
||||
DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
|
||||
DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
|
||||
{
|
||||
PCCRL_CONTEXT crl = CertCreateCRLContext(dwCertEncodingType,
|
||||
pbCrlEncoded, cbCrlEncoded);
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore, dwCertEncodingType,
|
||||
pbCrlEncoded, cbCrlEncoded, dwAddDisposition, ppCrlContext);
|
||||
|
||||
if (crl)
|
||||
{
|
||||
ret = CertAddCRLContextToStore(hCertStore, crl, dwAddDisposition,
|
||||
ppCrlContext);
|
||||
CertFreeCRLContext(crl);
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef BOOL (*CrlCompareFunc)(PCCRL_CONTEXT pCrlContext, DWORD dwType,
|
||||
DWORD dwFlags, const void *pvPara);
|
||||
|
||||
static BOOL compare_crl_any(PCCRL_CONTEXT pCrlContext, DWORD dwType,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
if (pvPara)
|
||||
{
|
||||
PCCERT_CONTEXT issuer = (PCCERT_CONTEXT)pvPara;
|
||||
|
||||
ret = CertCompareCertificateName(issuer->dwCertEncodingType,
|
||||
&issuer->pCertInfo->Issuer, &pCrlContext->pCrlInfo->Issuer);
|
||||
}
|
||||
else
|
||||
ret = TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL compare_crl_existing(PCCRL_CONTEXT pCrlContext, DWORD dwType,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
if (pvPara)
|
||||
{
|
||||
PCCRL_CONTEXT crl = (PCCRL_CONTEXT)pvPara;
|
||||
|
||||
ret = CertCompareCertificateName(pCrlContext->dwCertEncodingType,
|
||||
&pCrlContext->pCrlInfo->Issuer, &crl->pCrlInfo->Issuer);
|
||||
}
|
||||
else
|
||||
ret = TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertFindCRLInStore(HCERTSTORE hCertStore,
|
||||
DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
|
||||
const void *pvFindPara, PCCRL_CONTEXT pPrevCrlContext)
|
||||
{
|
||||
PCCRL_CONTEXT ret;
|
||||
CrlCompareFunc compare;
|
||||
|
||||
TRACE("(%p, %ld, %ld, %ld, %p, %p)\n", hCertStore, dwCertEncodingType,
|
||||
dwFindFlags, dwFindType, pvFindPara, pPrevCrlContext);
|
||||
|
||||
switch (dwFindType)
|
||||
{
|
||||
case CRL_FIND_ANY:
|
||||
compare = compare_crl_any;
|
||||
break;
|
||||
case CRL_FIND_ISSUED_BY:
|
||||
compare = compare_crl_issued_by;
|
||||
break;
|
||||
case CRL_FIND_EXISTING:
|
||||
compare = compare_crl_existing;
|
||||
break;
|
||||
default:
|
||||
FIXME("find type %08lx unimplemented\n", dwFindType);
|
||||
compare = NULL;
|
||||
}
|
||||
|
||||
if (compare)
|
||||
{
|
||||
BOOL matches = FALSE;
|
||||
|
||||
ret = pPrevCrlContext;
|
||||
do {
|
||||
ret = CertEnumCRLsInStore(hCertStore, ret);
|
||||
if (ret)
|
||||
matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
|
||||
} while (ret != NULL && !matches);
|
||||
if (!ret)
|
||||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
|
||||
{
|
||||
TRACE("(%p)\n", pCrlContext);
|
||||
Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
|
||||
return pCrlContext;
|
||||
}
|
||||
|
||||
static void CrlDataContext_Free(void *context)
|
||||
{
|
||||
PCRL_CONTEXT crlContext = (PCRL_CONTEXT)context;
|
||||
|
||||
CryptMemFree(crlContext->pbCrlEncoded);
|
||||
LocalFree(crlContext->pCrlInfo);
|
||||
}
|
||||
|
||||
BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
|
||||
{
|
||||
TRACE("(%p)\n", pCrlContext);
|
||||
|
||||
if (pCrlContext)
|
||||
Context_Release((void *)pCrlContext, sizeof(CRL_CONTEXT),
|
||||
CrlDataContext_Free);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WINAPI CertEnumCRLContextProperties(PCCRL_CONTEXT pCRLContext,
|
||||
DWORD dwPropId)
|
||||
{
|
||||
PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
|
||||
(void *)pCRLContext, sizeof(CRL_CONTEXT));
|
||||
DWORD ret;
|
||||
|
||||
TRACE("(%p, %ld)\n", pCRLContext, dwPropId);
|
||||
|
||||
if (properties)
|
||||
ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
|
||||
else
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRLContext_SetProperty(void *context, DWORD dwPropId,
|
||||
DWORD dwFlags, const void *pvData);
|
||||
|
||||
static BOOL CRLContext_GetHashProp(void *context, DWORD dwPropId,
|
||||
ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
|
||||
DWORD *pcbData)
|
||||
{
|
||||
BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
|
||||
pcbData);
|
||||
if (ret)
|
||||
{
|
||||
CRYPT_DATA_BLOB blob = { *pcbData, pvData };
|
||||
|
||||
ret = CRLContext_SetProperty(context, dwPropId, 0, &blob);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRLContext_GetProperty(void *context, DWORD dwPropId,
|
||||
void *pvData, DWORD *pcbData)
|
||||
{
|
||||
PCCRL_CONTEXT pCRLContext = (PCCRL_CONTEXT)context;
|
||||
PCONTEXT_PROPERTY_LIST properties =
|
||||
Context_GetProperties(context, sizeof(CRL_CONTEXT));
|
||||
BOOL ret;
|
||||
CRYPT_DATA_BLOB blob;
|
||||
|
||||
TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
|
||||
|
||||
if (properties)
|
||||
ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
|
||||
else
|
||||
ret = FALSE;
|
||||
if (ret)
|
||||
{
|
||||
if (!pvData)
|
||||
{
|
||||
*pcbData = blob.cbData;
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (*pcbData < blob.cbData)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbData = blob.cbData;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pvData, blob.pbData, blob.cbData);
|
||||
*pcbData = blob.cbData;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Implicit properties */
|
||||
switch (dwPropId)
|
||||
{
|
||||
case CERT_SHA1_HASH_PROP_ID:
|
||||
ret = CRLContext_GetHashProp(context, dwPropId, CALG_SHA1,
|
||||
pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, pvData,
|
||||
pcbData);
|
||||
break;
|
||||
case CERT_MD5_HASH_PROP_ID:
|
||||
ret = CRLContext_GetHashProp(context, dwPropId, CALG_MD5,
|
||||
pCRLContext->pbCrlEncoded, pCRLContext->cbCrlEncoded, pvData,
|
||||
pcbData);
|
||||
break;
|
||||
default:
|
||||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
|
||||
DWORD dwPropId, void *pvData, DWORD *pcbData)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %ld, %p, %p)\n", pCRLContext, dwPropId, pvData, pcbData);
|
||||
|
||||
switch (dwPropId)
|
||||
{
|
||||
case 0:
|
||||
case CERT_CERT_PROP_ID:
|
||||
case CERT_CRL_PROP_ID:
|
||||
case CERT_CTL_PROP_ID:
|
||||
SetLastError(E_INVALIDARG);
|
||||
ret = FALSE;
|
||||
break;
|
||||
case CERT_ACCESS_STATE_PROP_ID:
|
||||
if (!pvData)
|
||||
{
|
||||
*pcbData = sizeof(DWORD);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (*pcbData < sizeof(DWORD))
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
*pcbData = sizeof(DWORD);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(DWORD *)pvData =
|
||||
CertStore_GetAccessState(pCRLContext->hCertStore);
|
||||
ret = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = CRLContext_GetProperty((void *)pCRLContext, dwPropId, pvData,
|
||||
pcbData);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRLContext_SetProperty(void *context, DWORD dwPropId,
|
||||
DWORD dwFlags, const void *pvData)
|
||||
{
|
||||
PCONTEXT_PROPERTY_LIST properties =
|
||||
Context_GetProperties(context, sizeof(CERT_CONTEXT));
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData);
|
||||
|
||||
if (!properties)
|
||||
ret = FALSE;
|
||||
else if (!pvData)
|
||||
{
|
||||
ContextPropertyList_RemoveProperty(properties, dwPropId);
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dwPropId)
|
||||
{
|
||||
case CERT_AUTO_ENROLL_PROP_ID:
|
||||
case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
|
||||
case CERT_DESCRIPTION_PROP_ID:
|
||||
case CERT_FRIENDLY_NAME_PROP_ID:
|
||||
case CERT_HASH_PROP_ID:
|
||||
case CERT_KEY_IDENTIFIER_PROP_ID:
|
||||
case CERT_MD5_HASH_PROP_ID:
|
||||
case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
|
||||
case CERT_PUBKEY_ALG_PARA_PROP_ID:
|
||||
case CERT_PVK_FILE_PROP_ID:
|
||||
case CERT_SIGNATURE_HASH_PROP_ID:
|
||||
case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
|
||||
case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
|
||||
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
|
||||
case CERT_ENROLLMENT_PROP_ID:
|
||||
case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
|
||||
case CERT_RENEWAL_PROP_ID:
|
||||
{
|
||||
PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
|
||||
|
||||
ret = ContextPropertyList_SetProperty(properties, dwPropId,
|
||||
blob->pbData, blob->cbData);
|
||||
break;
|
||||
}
|
||||
case CERT_DATE_STAMP_PROP_ID:
|
||||
ret = ContextPropertyList_SetProperty(properties, dwPropId,
|
||||
(LPBYTE)pvData, sizeof(FILETIME));
|
||||
break;
|
||||
default:
|
||||
FIXME("%ld: stub\n", dwPropId);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
|
||||
DWORD dwPropId, DWORD dwFlags, const void *pvData)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %ld, %08lx, %p)\n", pCRLContext, dwPropId, dwFlags, pvData);
|
||||
|
||||
/* Handle special cases for "read-only"/invalid prop IDs. Windows just
|
||||
* crashes on most of these, I'll be safer.
|
||||
*/
|
||||
switch (dwPropId)
|
||||
{
|
||||
case 0:
|
||||
case CERT_ACCESS_STATE_PROP_ID:
|
||||
case CERT_CERT_PROP_ID:
|
||||
case CERT_CRL_PROP_ID:
|
||||
case CERT_CTL_PROP_ID:
|
||||
SetLastError(E_INVALIDARG);
|
||||
return FALSE;
|
||||
}
|
||||
ret = CRLContext_SetProperty((void *)pCRLContext, dwPropId, dwFlags,
|
||||
pvData);
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
|
@ -28,13 +28,14 @@
|
|||
@ stdcall CertDuplicateCTLContext(ptr)
|
||||
@ stdcall CertDuplicateCertificateContext(ptr)
|
||||
@ stdcall CertDuplicateStore(ptr)
|
||||
@ stub CertEnumCRLContextProperties
|
||||
@ stdcall CertEnumCRLContextProperties(ptr long)
|
||||
@ stdcall CertEnumCRLsInStore(ptr ptr)
|
||||
@ stub CertEnumCTLContextProperties
|
||||
@ stdcall CertEnumCTLsInStore(ptr ptr)
|
||||
@ stdcall CertEnumCertificateContextProperties(ptr long)
|
||||
@ stdcall CertEnumCertificatesInStore(long ptr)
|
||||
@ stdcall CertFindAttribute(str long ptr)
|
||||
@ stdcall CertFindCRLInStore(long long long long ptr ptr)
|
||||
@ stub CertFindCTLInStore
|
||||
@ stdcall CertFindCertificateInStore(long long long long ptr ptr)
|
||||
@ stdcall CertFindExtension(str long ptr)
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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.)
|
||||
|
@ -134,6 +131,7 @@ typedef struct WINE_CRYPTCERTSTORE
|
|||
CertStoreType type;
|
||||
PFN_CERT_STORE_PROV_CLOSE closeStore;
|
||||
CONTEXT_STORE certs;
|
||||
CONTEXT_STORE crls;
|
||||
PFN_CERT_STORE_PROV_CONTROL control; /* optional */
|
||||
} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
|
||||
|
||||
|
@ -141,6 +139,7 @@ typedef struct _WINE_MEMSTORE
|
|||
{
|
||||
WINECRYPT_CERTSTORE hdr;
|
||||
struct ContextList *certs;
|
||||
struct ContextList *crls;
|
||||
} WINE_MEMSTORE, *PWINE_MEMSTORE;
|
||||
|
||||
typedef struct _WINE_HASH_TO_DELETE
|
||||
|
@ -158,6 +157,7 @@ typedef struct _WINE_REGSTOREINFO
|
|||
BOOL dirty;
|
||||
CRITICAL_SECTION cs;
|
||||
struct list certsToDelete;
|
||||
struct list crlsToDelete;
|
||||
} WINE_REGSTOREINFO, *PWINE_REGSTOREINFO;
|
||||
|
||||
typedef struct _WINE_STORE_LIST_ENTRY
|
||||
|
@ -184,6 +184,8 @@ typedef struct _WINE_PROVIDERSTORE
|
|||
PFN_CERT_STORE_PROV_CLOSE provCloseStore;
|
||||
PFN_CERT_STORE_PROV_WRITE_CERT provWriteCert;
|
||||
PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert;
|
||||
PFN_CERT_STORE_PROV_WRITE_CRL provWriteCrl;
|
||||
PFN_CERT_STORE_PROV_DELETE_CRL provDeleteCrl;
|
||||
PFN_CERT_STORE_PROV_CONTROL provControl;
|
||||
} WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
|
||||
|
||||
|
@ -244,9 +246,52 @@ static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
|
||||
void *toReplace, const void **ppStoreContext)
|
||||
{
|
||||
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
|
||||
PCRL_CONTEXT context;
|
||||
|
||||
TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
|
||||
|
||||
context = (PCRL_CONTEXT)ContextList_Add(ms->crls, crl, toReplace);
|
||||
if (context)
|
||||
{
|
||||
context->hCertStore = store;
|
||||
if (ppStoreContext)
|
||||
*ppStoreContext =
|
||||
CertDuplicateCRLContext(context);
|
||||
}
|
||||
return context ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
|
||||
{
|
||||
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
|
||||
void *ret;
|
||||
|
||||
TRACE("(%p, %p)\n", store, pPrev);
|
||||
|
||||
ret = ContextList_Enum(ms->crls, pPrev);
|
||||
if (!ret)
|
||||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
|
||||
TRACE("returning %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
|
||||
{
|
||||
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
|
||||
|
||||
ContextList_Delete(ms->crls, pCrlContext);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void CRYPT_MemEmptyStore(PWINE_MEMSTORE store)
|
||||
{
|
||||
ContextList_Empty(store->certs);
|
||||
ContextList_Empty(store->crls);
|
||||
}
|
||||
|
||||
static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
|
||||
|
@ -258,6 +303,7 @@ static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
|
|||
FIXME("Unimplemented flags: %08lx\n", dwFlags);
|
||||
|
||||
ContextList_Free(store->certs);
|
||||
ContextList_Free(store->crls);
|
||||
CryptMemFree(store);
|
||||
}
|
||||
|
||||
|
@ -284,9 +330,14 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
|
|||
store->hdr.certs.addContext = CRYPT_MemAddCert;
|
||||
store->hdr.certs.enumContext = CRYPT_MemEnumCert;
|
||||
store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
|
||||
store->hdr.crls.addContext = CRYPT_MemAddCrl;
|
||||
store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
|
||||
store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
|
||||
store->hdr.control = NULL;
|
||||
store->certs = ContextList_Create(pCertInterface,
|
||||
sizeof(CERT_CONTEXT));
|
||||
store->crls = ContextList_Create(pCRLInterface,
|
||||
sizeof(CRL_CONTEXT));
|
||||
}
|
||||
}
|
||||
return (PWINECRYPT_CERTSTORE)store;
|
||||
|
@ -375,31 +426,6 @@ static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert,
|
||||
void *toReplace, const void **ppStoreContext)
|
||||
{
|
||||
BOOL ret;
|
||||
void *childContext = NULL;
|
||||
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
|
||||
|
||||
ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs),
|
||||
cert, toReplace, sizeof(CERT_CONTEXT), &childContext);
|
||||
if (ppStoreContext && childContext)
|
||||
{
|
||||
PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
|
||||
Context_GetExtra(childContext, sizeof(CERT_CONTEXT));
|
||||
PCERT_CONTEXT context =
|
||||
CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
|
||||
sizeof(CERT_CONTEXT), TRUE);
|
||||
|
||||
if (context)
|
||||
context->hCertStore = store;
|
||||
*ppStoreContext = context;
|
||||
}
|
||||
CertFreeCertificateContext((PCCERT_CONTEXT)childContext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Advances a collection enumeration by one context, if possible, where
|
||||
* advancing means:
|
||||
* - calling the current store's enumeration function once, and returning
|
||||
|
@ -452,6 +478,31 @@ static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert,
|
||||
void *toReplace, const void **ppStoreContext)
|
||||
{
|
||||
BOOL ret;
|
||||
void *childContext = NULL;
|
||||
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
|
||||
|
||||
ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs),
|
||||
cert, toReplace, sizeof(CERT_CONTEXT), &childContext);
|
||||
if (ppStoreContext && childContext)
|
||||
{
|
||||
PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
|
||||
Context_GetExtra(childContext, sizeof(CERT_CONTEXT));
|
||||
PCERT_CONTEXT context =
|
||||
CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
|
||||
sizeof(CERT_CONTEXT), TRUE);
|
||||
|
||||
if (context)
|
||||
context->hCertStore = store;
|
||||
*ppStoreContext = context;
|
||||
}
|
||||
CertFreeCertificateContext((PCCERT_CONTEXT)childContext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
|
||||
{
|
||||
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
|
||||
|
@ -506,6 +557,85 @@ static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
|
||||
void *toReplace, const void **ppStoreContext)
|
||||
{
|
||||
BOOL ret;
|
||||
void *childContext = NULL;
|
||||
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
|
||||
|
||||
ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, crls),
|
||||
crl, toReplace, sizeof(CRL_CONTEXT), &childContext);
|
||||
if (ppStoreContext && childContext)
|
||||
{
|
||||
PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
|
||||
Context_GetExtra(childContext, sizeof(CRL_CONTEXT));
|
||||
PCRL_CONTEXT context =
|
||||
CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
|
||||
sizeof(CRL_CONTEXT), TRUE);
|
||||
|
||||
if (context)
|
||||
context->hCertStore = store;
|
||||
*ppStoreContext = context;
|
||||
}
|
||||
CertFreeCRLContext((PCCRL_CONTEXT)childContext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
|
||||
{
|
||||
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
|
||||
void *ret;
|
||||
|
||||
TRACE("(%p, %p)\n", store, pPrev);
|
||||
|
||||
EnterCriticalSection(&cs->cs);
|
||||
if (pPrev)
|
||||
{
|
||||
PWINE_STORE_LIST_ENTRY storeEntry =
|
||||
*(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
|
||||
sizeof(CERT_CONTEXT));
|
||||
|
||||
ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
|
||||
offsetof(WINECRYPT_CERTSTORE, crls), pCRLInterface, pPrev,
|
||||
sizeof(CRL_CONTEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!list_empty(&cs->stores))
|
||||
{
|
||||
PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
|
||||
WINE_STORE_LIST_ENTRY, entry);
|
||||
|
||||
ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
|
||||
offsetof(WINECRYPT_CERTSTORE, crls), pCRLInterface, NULL,
|
||||
sizeof(CRL_CONTEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&cs->cs);
|
||||
if (ret)
|
||||
((PCRL_CONTEXT)ret)->hCertStore = store;
|
||||
TRACE("returning %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store,
|
||||
void *pCrlContext)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %p)\n", store, pCrlContext);
|
||||
|
||||
ret = CertDeleteCRLFromStore((PCCRL_CONTEXT)
|
||||
Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
|
@ -528,6 +658,9 @@ static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
|
|||
store->hdr.certs.addContext = CRYPT_CollectionAddCert;
|
||||
store->hdr.certs.enumContext = CRYPT_CollectionEnumCert;
|
||||
store->hdr.certs.deleteContext = CRYPT_CollectionDeleteCert;
|
||||
store->hdr.crls.addContext = CRYPT_CollectionAddCRL;
|
||||
store->hdr.crls.enumContext = CRYPT_CollectionEnumCRL;
|
||||
store->hdr.crls.deleteContext = CRYPT_CollectionDeleteCRL;
|
||||
InitializeCriticalSection(&store->cs);
|
||||
list_init(&store->stores);
|
||||
}
|
||||
|
@ -601,8 +734,7 @@ static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store,
|
||||
void *cert)
|
||||
static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store, void *cert)
|
||||
{
|
||||
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
|
||||
BOOL ret = TRUE;
|
||||
|
@ -616,6 +748,73 @@ static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
|
||||
void *toReplace, const void **ppStoreContext)
|
||||
{
|
||||
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
|
||||
|
||||
if (toReplace)
|
||||
ret = ps->memStore->crls.addContext(ps->memStore, crl, toReplace,
|
||||
(const void **)ppStoreContext);
|
||||
else
|
||||
{
|
||||
if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = TRUE;
|
||||
if (ps->provWriteCrl)
|
||||
ret = ps->provWriteCrl(ps->hStoreProv, (PCCRL_CONTEXT)crl,
|
||||
CERT_STORE_PROV_WRITE_ADD_FLAG);
|
||||
if (ret)
|
||||
ret = ps->memStore->crls.addContext(ps->memStore, crl, NULL,
|
||||
(const void **)ppStoreContext);
|
||||
}
|
||||
}
|
||||
/* dirty trick: replace the returned context's hCertStore with
|
||||
* store.
|
||||
*/
|
||||
if (ppStoreContext)
|
||||
(*(PCRL_CONTEXT *)ppStoreContext)->hCertStore = store;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *CRYPT_ProvEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
|
||||
{
|
||||
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
|
||||
void *ret;
|
||||
|
||||
ret = ps->memStore->crls.enumContext(ps->memStore, pPrev);
|
||||
if (ret)
|
||||
{
|
||||
/* same dirty trick: replace the returned context's hCertStore with
|
||||
* store.
|
||||
*/
|
||||
((PCERT_CONTEXT)ret)->hCertStore = store;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_ProvDeleteCRL(PWINECRYPT_CERTSTORE store, void *crl)
|
||||
{
|
||||
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
TRACE("(%p, %p)\n", store, crl);
|
||||
|
||||
if (ps->provDeleteCrl)
|
||||
ret = ps->provDeleteCrl(ps->hStoreProv, crl, 0);
|
||||
if (ret)
|
||||
ret = ps->memStore->crls.deleteContext(ps->memStore, crl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
|
||||
DWORD dwCtrlType, void const *pvCtrlPara)
|
||||
{
|
||||
|
@ -654,6 +853,9 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv,
|
|||
ret->hdr.certs.addContext = CRYPT_ProvAddCert;
|
||||
ret->hdr.certs.enumContext = CRYPT_ProvEnumCert;
|
||||
ret->hdr.certs.deleteContext = CRYPT_ProvDeleteCert;
|
||||
ret->hdr.crls.addContext = CRYPT_ProvAddCRL;
|
||||
ret->hdr.crls.enumContext = CRYPT_ProvEnumCRL;
|
||||
ret->hdr.crls.deleteContext = CRYPT_ProvDeleteCRL;
|
||||
ret->hdr.control = CRYPT_ProvControl;
|
||||
if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
|
||||
ret->provCloseStore =
|
||||
|
@ -672,6 +874,18 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv,
|
|||
CERT_STORE_PROV_DELETE_CERT_FUNC];
|
||||
else
|
||||
ret->provDeleteCert = NULL;
|
||||
if (pProvInfo->cStoreProvFunc >
|
||||
CERT_STORE_PROV_WRITE_CRL_FUNC)
|
||||
ret->provWriteCrl = pProvInfo->rgpvStoreProvFunc[
|
||||
CERT_STORE_PROV_WRITE_CRL_FUNC];
|
||||
else
|
||||
ret->provWriteCert = NULL;
|
||||
if (pProvInfo->cStoreProvFunc >
|
||||
CERT_STORE_PROV_DELETE_CRL_FUNC)
|
||||
ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
|
||||
CERT_STORE_PROV_DELETE_CRL_FUNC];
|
||||
else
|
||||
ret->provDeleteCert = NULL;
|
||||
if (pProvInfo->cStoreProvFunc >
|
||||
CERT_STORE_PROV_CONTROL_FUNC)
|
||||
ret->provControl = pProvInfo->rgpvStoreProvFunc[
|
||||
|
@ -930,7 +1144,8 @@ static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store)
|
|||
static const WCHAR *subKeys[] = { CertsW, CRLsW, CTLsW };
|
||||
static const WINE_CONTEXT_INTERFACE *interfaces[] = { &gCertInterface,
|
||||
&gCRLInterface, &gCTLInterface };
|
||||
struct list *listToDelete[] = { &store->certsToDelete, NULL, NULL };
|
||||
struct list *listToDelete[] = { &store->certsToDelete, &store->crlsToDelete,
|
||||
NULL };
|
||||
BOOL ret = TRUE;
|
||||
DWORD i;
|
||||
|
||||
|
@ -1071,6 +1286,68 @@ static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_RegWriteCRL(HCERTSTORE hCertStore,
|
||||
PCCRL_CONTEXT crl, DWORD dwFlags)
|
||||
{
|
||||
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %p, %ld)\n", hCertStore, crl, dwFlags);
|
||||
|
||||
if (dwFlags & CERT_STORE_PROV_WRITE_ADD_FLAG)
|
||||
{
|
||||
store->dirty = TRUE;
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_RegDeleteCRL(HCERTSTORE hCertStore,
|
||||
PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
|
||||
{
|
||||
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, %p, %08lx)\n", store, pCrlContext, dwFlags);
|
||||
|
||||
if (store->dwOpenFlags & CERT_STORE_READONLY_FLAG)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PWINE_HASH_TO_DELETE toDelete =
|
||||
CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE));
|
||||
|
||||
if (toDelete)
|
||||
{
|
||||
DWORD size = sizeof(toDelete->hash);
|
||||
|
||||
ret = CertGetCRLContextProperty(pCrlContext, CERT_HASH_PROP_ID,
|
||||
toDelete->hash, &size);
|
||||
if (ret)
|
||||
{
|
||||
EnterCriticalSection(&store->cs);
|
||||
list_add_tail(&store->crlsToDelete, &toDelete->entry);
|
||||
LeaveCriticalSection(&store->cs);
|
||||
}
|
||||
else
|
||||
{
|
||||
CryptMemFree(toDelete);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = FALSE;
|
||||
if (ret)
|
||||
store->dirty = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags,
|
||||
DWORD dwCtrlType, void const *pvCtrlPara)
|
||||
{
|
||||
|
@ -1159,8 +1436,8 @@ static void *regProvFuncs[] = {
|
|||
CRYPT_RegDeleteCert,
|
||||
NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
|
||||
NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
|
||||
NULL, /* CERT_STORE_PROV_WRITE_CRL_FUNC */
|
||||
NULL, /* CERT_STORE_PROV_DELETE_CRL_FUNC */
|
||||
CRYPT_RegWriteCRL,
|
||||
CRYPT_RegDeleteCRL,
|
||||
NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
|
||||
NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
|
||||
NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
|
||||
|
@ -1215,6 +1492,7 @@ static WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv,
|
|||
regInfo->key = key;
|
||||
InitializeCriticalSection(®Info->cs);
|
||||
list_init(®Info->certsToDelete);
|
||||
list_init(®Info->crlsToDelete);
|
||||
CRYPT_RegReadFromReg(regInfo);
|
||||
regInfo->dirty = FALSE;
|
||||
provInfo.cbSize = sizeof(provInfo);
|
||||
|
@ -1563,35 +1841,6 @@ BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType,
|
||||
const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
|
||||
{
|
||||
PCRL_CONTEXT pcrl;
|
||||
BYTE* data;
|
||||
|
||||
TRACE("%08lx %p %08lx\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded);
|
||||
|
||||
/* FIXME: semi-stub, need to use CryptDecodeObjectEx to decode the CRL. */
|
||||
pcrl = CryptMemAlloc( sizeof (CRL_CONTEXT) );
|
||||
if( !pcrl )
|
||||
return NULL;
|
||||
|
||||
data = CryptMemAlloc( cbCrlEncoded );
|
||||
if( !data )
|
||||
{
|
||||
CryptMemFree( pcrl );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcrl->dwCertEncodingType = dwCertEncodingType;
|
||||
pcrl->pbCrlEncoded = data;
|
||||
pcrl->cbCrlEncoded = cbCrlEncoded;
|
||||
pcrl->pCrlInfo = NULL;
|
||||
pcrl->hCertStore = 0;
|
||||
|
||||
return pcrl;
|
||||
}
|
||||
|
||||
DWORD CertStore_GetAccessState(HCERTSTORE hCertStore)
|
||||
{
|
||||
DWORD state = 0;
|
||||
|
@ -1740,49 +1989,144 @@ BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
|
|||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
|
||||
DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
|
||||
DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
|
||||
static void CrlContext_CopyProperties(PCCRL_CONTEXT to, PCCRL_CONTEXT from)
|
||||
{
|
||||
FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore,
|
||||
dwCertEncodingType, pbCrlEncoded, cbCrlEncoded, dwAddDisposition,
|
||||
ppCrlContext);
|
||||
return FALSE;
|
||||
PCONTEXT_PROPERTY_LIST toProperties, fromProperties;
|
||||
|
||||
toProperties = Context_GetProperties((void *)to, sizeof(CRL_CONTEXT));
|
||||
fromProperties = Context_GetProperties((void *)from, sizeof(CRL_CONTEXT));
|
||||
ContextPropertyList_Copy(toProperties, fromProperties);
|
||||
}
|
||||
|
||||
BOOL WINAPI CertAddCRLContextToStore( HCERTSTORE hCertStore,
|
||||
PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
|
||||
PCCRL_CONTEXT* ppStoreContext )
|
||||
BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
|
||||
PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
|
||||
PCCRL_CONTEXT* ppStoreContext)
|
||||
{
|
||||
FIXME("%p %p %08lx %p\n", hCertStore, pCrlContext,
|
||||
dwAddDisposition, ppStoreContext);
|
||||
return TRUE;
|
||||
}
|
||||
PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
|
||||
BOOL ret = TRUE;
|
||||
PCCRL_CONTEXT toAdd = NULL, existing = NULL;
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
|
||||
{
|
||||
FIXME("(%p): stub\n", pCrlContext);
|
||||
return pCrlContext;
|
||||
}
|
||||
TRACE("(%p, %p, %08lx, %p)\n", hCertStore, pCrlContext,
|
||||
dwAddDisposition, ppStoreContext);
|
||||
|
||||
BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
|
||||
{
|
||||
FIXME("%p\n", pCrlContext );
|
||||
/* Weird case to pass a test */
|
||||
if (dwAddDisposition == 0)
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
return FALSE;
|
||||
}
|
||||
if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
|
||||
{
|
||||
existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
|
||||
pCrlContext, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
switch (dwAddDisposition)
|
||||
{
|
||||
case CERT_STORE_ADD_ALWAYS:
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
break;
|
||||
case CERT_STORE_ADD_NEW:
|
||||
if (existing)
|
||||
{
|
||||
TRACE("found matching CRL, not adding\n");
|
||||
SetLastError(CRYPT_E_EXISTS);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
break;
|
||||
case CERT_STORE_ADD_NEWER:
|
||||
if (existing)
|
||||
{
|
||||
LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
|
||||
&pCrlContext->pCrlInfo->ThisUpdate);
|
||||
|
||||
if (newer < 0)
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
else
|
||||
{
|
||||
TRACE("existing CRL is newer, not adding\n");
|
||||
SetLastError(CRYPT_E_EXISTS);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
break;
|
||||
case CERT_STORE_ADD_REPLACE_EXISTING:
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
break;
|
||||
case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
|
||||
toAdd = CertDuplicateCRLContext(pCrlContext);
|
||||
if (existing)
|
||||
CrlContext_CopyProperties(toAdd, existing);
|
||||
break;
|
||||
case CERT_STORE_ADD_USE_EXISTING:
|
||||
if (existing)
|
||||
CrlContext_CopyProperties(existing, pCrlContext);
|
||||
break;
|
||||
default:
|
||||
FIXME("Unimplemented add disposition %ld\n", dwAddDisposition);
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
if (toAdd)
|
||||
{
|
||||
if (store)
|
||||
ret = store->crls.addContext(store, (void *)toAdd,
|
||||
(void *)existing, (const void **)ppStoreContext);
|
||||
else if (ppStoreContext)
|
||||
*ppStoreContext = CertDuplicateCRLContext(toAdd);
|
||||
CertFreeCRLContext(toAdd);
|
||||
}
|
||||
CertFreeCRLContext(existing);
|
||||
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
|
||||
{
|
||||
FIXME("(%p): stub\n", pCrlContext);
|
||||
return TRUE;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p)\n", pCrlContext);
|
||||
|
||||
if (!pCrlContext)
|
||||
ret = TRUE;
|
||||
else if (!pCrlContext->hCertStore)
|
||||
{
|
||||
ret = TRUE;
|
||||
CertFreeCRLContext(pCrlContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
PWINECRYPT_CERTSTORE hcs =
|
||||
(PWINECRYPT_CERTSTORE)pCrlContext->hCertStore;
|
||||
|
||||
if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
|
||||
ret = FALSE;
|
||||
else
|
||||
ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
|
||||
CertFreeCRLContext(pCrlContext);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
|
||||
PCCRL_CONTEXT pPrev)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", hCertStore, pPrev);
|
||||
return NULL;
|
||||
WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
|
||||
PCCRL_CONTEXT ret;
|
||||
|
||||
TRACE("(%p, %p)\n", hCertStore, pPrev);
|
||||
if (!hCertStore)
|
||||
ret = NULL;
|
||||
else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
|
||||
|
@ -1896,21 +2240,6 @@ BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
|
|||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
|
||||
DWORD dwPropId, void *pvData, DWORD *pcbData)
|
||||
{
|
||||
FIXME("(%p, %ld, %p, %p): stub\n", pCRLContext, dwPropId, pvData, pcbData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
|
||||
DWORD dwPropId, DWORD dwFlags, const void *pvData)
|
||||
{
|
||||
FIXME("(%p, %ld, %08lx, %p): stub\n", pCRLContext, dwPropId, dwFlags,
|
||||
pvData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
|
||||
DWORD dwPropId, void *pvData, DWORD *pcbData)
|
||||
{
|
||||
|
|
|
@ -1884,6 +1884,312 @@ static void testAddSerialized(void)
|
|||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static const BYTE CRL[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
|
||||
0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
|
||||
0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
|
||||
0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5a };
|
||||
static const BYTE newerCRL[] = { 0x30, 0x2a, 0x30, 0x02, 0x06, 0x00, 0x30,
|
||||
0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
|
||||
0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x17, 0x0d, 0x30, 0x36,
|
||||
0x30, 0x35, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
|
||||
|
||||
static void testCreateCRL(void)
|
||||
{
|
||||
PCCRL_CONTEXT context;
|
||||
|
||||
context = CertCreateCRLContext(0, NULL, 0);
|
||||
ok(!context && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, NULL, 0);
|
||||
ok(!context && GetLastError() == CRYPT_E_ASN1_EOD,
|
||||
"Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
|
||||
ok(!context && GetLastError() == CRYPT_E_ASN1_CORRUPT,
|
||||
"Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL) - 1);
|
||||
ok(!context && (GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == CRYPT_E_ASN1_CORRUPT),
|
||||
"Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
|
||||
GetLastError());
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL));
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, CRL, sizeof(CRL));
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
}
|
||||
|
||||
static void testAddCRL(void)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCRL_CONTEXT context;
|
||||
BOOL ret;
|
||||
|
||||
if (!store) return;
|
||||
|
||||
/* Bad CRL encoding type */
|
||||
ret = CertAddEncodedCRLToStore(0, 0, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL), 0,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
|
||||
/* No CRL */
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
|
||||
"Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
|
||||
"Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
|
||||
|
||||
/* Weird--bad add disposition leads to an access violation in Windows. */
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
|
||||
"Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
|
||||
"Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
|
||||
|
||||
/* Weird--can add a CRL to the NULL store (does this have special meaning?)
|
||||
*/
|
||||
context = NULL;
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* Normal cases: a "signed" CRL is okay.. */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
/* and an unsigned one is too. */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, CRL, sizeof(CRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
|
||||
sizeof(newerCRL), CERT_STORE_ADD_NEW, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_EXISTS,
|
||||
"Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
|
||||
|
||||
/* This should replace (one of) the existing CRL(s). */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
|
||||
sizeof(newerCRL), CERT_STORE_ADD_NEWER, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void testFindCRL(void)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCRL_CONTEXT context;
|
||||
PCCERT_CONTEXT cert;
|
||||
BOOL ret;
|
||||
|
||||
if (!store) return;
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
|
||||
|
||||
/* Crashes
|
||||
context = CertFindCRLInStore(NULL, 0, 0, 0, NULL, NULL);
|
||||
*/
|
||||
|
||||
/* Find any context */
|
||||
context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
/* Bogus flags are ignored */
|
||||
context = CertFindCRLInStore(store, 0, 1234, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
/* CRL encoding type is ignored too */
|
||||
context = CertFindCRLInStore(store, 1234, 0, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* This appears to match any cert */
|
||||
context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* Try to match an issuer that isn't in the store */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
|
||||
sizeof(bigCert2));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
|
||||
GetLastError());
|
||||
context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
|
||||
ok(context == NULL, "Expected no matching context\n");
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
/* Match an issuer that is in the store */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
|
||||
GetLastError());
|
||||
context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void checkCRLHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
|
||||
PCCRL_CONTEXT context, DWORD propID)
|
||||
{
|
||||
BYTE hash[20] = { 0 }, hashProperty[20];
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
|
||||
memset(hash, 0, sizeof(hash));
|
||||
memset(hashProperty, 0, sizeof(hashProperty));
|
||||
size = sizeof(hash);
|
||||
ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
|
||||
ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
|
||||
ret = CertGetCRLContextProperty(context, propID, hashProperty, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
|
||||
ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
|
||||
propID);
|
||||
}
|
||||
|
||||
static void testCRLProperties(void)
|
||||
{
|
||||
PCCRL_CONTEXT context = CertCreateCRLContext(X509_ASN_ENCODING,
|
||||
CRL, sizeof(CRL));
|
||||
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
|
||||
if (context)
|
||||
{
|
||||
DWORD propID, numProps, access, size;
|
||||
BOOL ret;
|
||||
BYTE hash[20] = { 0 }, hashProperty[20];
|
||||
CRYPT_DATA_BLOB blob;
|
||||
|
||||
/* This crashes
|
||||
propID = CertEnumCRLContextProperties(NULL, 0);
|
||||
*/
|
||||
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCRLContextProperties(context, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
|
||||
|
||||
/* Tests with a NULL cert context. Prop ID 0 fails.. */
|
||||
ret = CertSetCRLContextProperty(NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
/* while this just crashes.
|
||||
ret = CertSetCRLContextProperty(NULL, CERT_KEY_PROV_HANDLE_PROP_ID, 0,
|
||||
NULL);
|
||||
*/
|
||||
|
||||
ret = CertSetCRLContextProperty(context, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08lx\n", GetLastError());
|
||||
/* Can't set the cert property directly, this crashes.
|
||||
ret = CertSetCRLContextProperty(context, CERT_CRL_PROP_ID, 0, CRL);
|
||||
*/
|
||||
|
||||
/* These all crash.
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
|
||||
NULL);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, NULL, NULL);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
|
||||
hashProperty, NULL);
|
||||
*/
|
||||
/* A missing prop */
|
||||
size = 0;
|
||||
ret = CertGetCRLContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
|
||||
NULL, &size);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
|
||||
/* And, an implicit property */
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
|
||||
NULL, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
|
||||
&access, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
|
||||
ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
|
||||
"Didn't expect a persisted crl\n");
|
||||
/* Trying to set this "read only" property crashes.
|
||||
access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
|
||||
ret = CertSetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
|
||||
&access);
|
||||
*/
|
||||
|
||||
/* Can I set the hash to an invalid hash? */
|
||||
blob.pbData = hash;
|
||||
blob.cbData = sizeof(hash);
|
||||
ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, &blob);
|
||||
ok(ret, "CertSetCRLContextProperty failed: %08lx\n",
|
||||
GetLastError());
|
||||
size = sizeof(hashProperty);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
|
||||
hashProperty, &size);
|
||||
ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
|
||||
/* Delete the (bogus) hash, and get the real one */
|
||||
ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, NULL);
|
||||
ok(ret, "CertSetCRLContextProperty failed: %08lx\n", GetLastError());
|
||||
checkCRLHash(CRL, sizeof(CRL), CALG_SHA1, context, CERT_HASH_PROP_ID);
|
||||
|
||||
/* Now that the hash property is set, we should get one property when
|
||||
* enumerating.
|
||||
*/
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCRLContextProperties(context, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
|
||||
|
||||
/* Check a few other implicit properties */
|
||||
checkCRLHash(CRL, sizeof(CRL), CALG_MD5, context,
|
||||
CERT_MD5_HASH_PROP_ID);
|
||||
|
||||
CertFreeCRLContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(store)
|
||||
{
|
||||
testAddCert();
|
||||
|
@ -1892,6 +2198,10 @@ START_TEST(store)
|
|||
testGetSubjectCert();
|
||||
testGetIssuerCert();
|
||||
|
||||
testCreateCRL();
|
||||
testAddCRL();
|
||||
testFindCRL();
|
||||
|
||||
/* various combinations of CertOpenStore */
|
||||
testMemStore();
|
||||
testCollectionStore();
|
||||
|
@ -1902,5 +2212,6 @@ START_TEST(store)
|
|||
testCertOpenSystemStore();
|
||||
|
||||
testCertProperties();
|
||||
testCRLProperties();
|
||||
testAddSerialized();
|
||||
}
|
||||
|
|
|
@ -1939,6 +1939,22 @@ static const WCHAR CERT_PHYSICAL_STORE_AUTH_ROOT_NAME[] =
|
|||
#define CERT_FIND_VALID_ENHKEY_USAGE_FLAG 0x20
|
||||
#define CERT_FIND_VALID_CTL_USAGE_FLAG 0x20
|
||||
|
||||
#define CRL_FIND_ANY 0
|
||||
#define CRL_FIND_ISSUED_BY 1
|
||||
#define CRL_FIND_EXISTING 2
|
||||
#define CRL_FIND_ISSUED_FOR 3
|
||||
|
||||
#define CRL_FIND_ISSUED_BY_AKI_FLAG 0x1
|
||||
#define CRL_FIND_ISSUED_BY_SIGNATURE_FLAG 0x2
|
||||
#define CRL_FIND_ISSUED_BY_DELTA_FLAG 0x4
|
||||
#define CRL_FIND_ISSUED_BY_BASE_FLAG 0x8
|
||||
|
||||
typedef struct _CRL_FIND_ISSUED_FOR_PARA
|
||||
{
|
||||
PCCERT_CONTEXT pSubjectCert;
|
||||
PCCERT_CONTEXT pIssuerCert;
|
||||
} CRL_FIND_ISSUED_FOR_PARA, *PCRL_FIND_ISSUED_FOR_PARA;
|
||||
|
||||
/* PFN_CERT_STORE_PROV_WRITE_CERT dwFlags values */
|
||||
#define CERT_STORE_PROV_WRITE_ADD_FLAG 0x1
|
||||
|
||||
|
|
Loading…
Reference in New Issue