crypt32: Move context properties to a separate file.

This commit is contained in:
Juan Lang 2006-03-09 19:06:42 -08:00 committed by Alexandre Julliard
parent 2eca872675
commit 91b80fc8e2
4 changed files with 279 additions and 206 deletions

View file

@ -11,6 +11,7 @@ C_SRCS = \
cert.c \
encode.c \
oid.c \
proplist.c \
protectdata.c \
serialize.c \
store.c \

View file

@ -41,4 +41,31 @@ void crypt_oid_free(void);
const void *CRYPT_ReadSerializedElement(const BYTE *pbElement,
DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
/**
* Context property list functions
*/
struct _CONTEXT_PROPERTY_LIST;
typedef struct _CONTEXT_PROPERTY_LIST *PCONTEXT_PROPERTY_LIST;
PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void);
/* Searches for the property with ID id in the context. Returns TRUE if found,
* and copies the property's length and a pointer to its data to blob.
* Otherwise returns FALSE.
*/
BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
PCRYPT_DATA_BLOB blob);
BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
const BYTE *pbData, size_t cbData);
void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id);
DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id);
void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
PCONTEXT_PROPERTY_LIST from);
void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list);
#endif

215
dlls/crypt32/proplist.c Normal file
View file

@ -0,0 +1,215 @@
/*
* 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
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
typedef struct _CONTEXT_PROPERTY_LIST
{
CRITICAL_SECTION cs;
struct list properties;
} CONTEXT_PROPERTY_LIST;
typedef struct _CONTEXT_PROPERTY
{
DWORD propID;
DWORD cbData;
LPBYTE pbData;
struct list entry;
} CONTEXT_PROPERTY, *PCONTEXT_PROPERTY;
PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void)
{
PCONTEXT_PROPERTY_LIST list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
if (list)
{
InitializeCriticalSection(&list->cs);
list_init(&list->properties);
}
return list;
}
void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list)
{
PCONTEXT_PROPERTY prop, next;
LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
entry)
{
list_remove(&prop->entry);
CryptMemFree(prop->pbData);
CryptMemFree(prop);
}
DeleteCriticalSection(&list->cs);
CryptMemFree(list);
}
BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
PCRYPT_DATA_BLOB blob)
{
PCONTEXT_PROPERTY prop;
BOOL ret = FALSE;
TRACE("(%p, %ld, %p)\n", list, id, blob);
EnterCriticalSection(&list->cs);
LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
{
if (prop->propID == id)
{
blob->cbData = prop->cbData;
blob->pbData = prop->pbData;
ret = TRUE;
break;
}
}
LeaveCriticalSection(&list->cs);
return ret;
}
BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
const BYTE *pbData, size_t cbData)
{
LPBYTE data;
BOOL ret = FALSE;
if (cbData)
{
data = CryptMemAlloc(cbData);
if (data)
memcpy(data, pbData, cbData);
}
else
data = NULL;
if (!cbData || data)
{
PCONTEXT_PROPERTY prop;
BOOL found = FALSE;
EnterCriticalSection(&list->cs);
LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
{
if (prop->propID == id)
{
found = TRUE;
break;
}
}
if (found)
{
CryptMemFree(prop->pbData);
prop->cbData = cbData;
prop->pbData = data;
ret = TRUE;
}
else
{
prop = CryptMemAlloc(sizeof(CONTEXT_PROPERTY));
if (prop)
{
prop->propID = id;
prop->cbData = cbData;
list_init(&prop->entry);
prop->pbData = data;
list_add_tail(&list->properties, &prop->entry);
ret = TRUE;
}
else
CryptMemFree(data);
}
LeaveCriticalSection(&list->cs);
}
return ret;
}
void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id)
{
PCONTEXT_PROPERTY prop, next;
EnterCriticalSection(&list->cs);
LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
entry)
{
if (prop->propID == id)
{
list_remove(&prop->entry);
CryptMemFree(prop->pbData);
CryptMemFree(prop);
}
}
LeaveCriticalSection(&list->cs);
}
/* Since the properties are stored in a list, this is a tad inefficient
* (O(n^2)) since I have to find the previous position every time.
*/
DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id)
{
DWORD ret;
EnterCriticalSection(&list->cs);
if (id)
{
PCONTEXT_PROPERTY cursor = NULL;
LIST_FOR_EACH_ENTRY(cursor, &list->properties, CONTEXT_PROPERTY, entry)
{
if (cursor->propID == id)
break;
}
if (cursor)
{
if (cursor->entry.next != &list->properties)
ret = LIST_ENTRY(cursor->entry.next, CONTEXT_PROPERTY,
entry)->propID;
else
ret = 0;
}
else
ret = 0;
}
else if (!list_empty(&list->properties))
ret = LIST_ENTRY(list->properties.next, CONTEXT_PROPERTY,
entry)->propID;
else
ret = 0;
LeaveCriticalSection(&list->cs);
return ret;
}
void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
PCONTEXT_PROPERTY_LIST from)
{
PCONTEXT_PROPERTY prop;
EnterCriticalSection(&from->cs);
LIST_FOR_EACH_ENTRY(prop, &from->properties, CONTEXT_PROPERTY, entry)
{
ContextPropertyList_SetProperty(to, prop->propID, prop->pbData,
prop->cbData);
}
LeaveCriticalSection(&from->cs);
}

View file

@ -182,27 +182,19 @@ typedef struct WINE_CRYPTCERTSTORE
*/
typedef struct _WINE_CERT_CONTEXT
{
CERT_CONTEXT cert;
LONG ref;
CRITICAL_SECTION cs;
struct list extendedProperties;
CERT_CONTEXT cert;
LONG ref;
PCONTEXT_PROPERTY_LIST properties;
} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
typedef const struct _WINE_CERT_CONTEXT PCWINE_CERT_CONTEXT;
typedef struct _WINE_CERT_CONTEXT_REF
{
CERT_CONTEXT cert;
LONG ref;
WINE_CERT_CONTEXT *context;
PWINE_CERT_CONTEXT context;
} WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF;
/* Stores an extended property in a cert. */
typedef struct _WINE_CERT_PROPERTY
{
DWORD propID;
DWORD cbData;
LPBYTE pbData;
struct list entry;
} WINE_CERT_PROPERTY, *PWINE_CERT_PROPERTY;
typedef const struct _WINE_CERT_CONTEXT_REF PCWINE_CERT_CONTEXT_REF;
/* A mem store has a list of these. They're also returned by the mem store
* during enumeration.
@ -554,7 +546,6 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
store->hdr.addCert = CRYPT_MemAddCert;
store->hdr.enumCert = CRYPT_MemEnumCert;
store->hdr.deleteCert = CRYPT_MemDeleteCert;
store->hdr.freeCert = NULL;
store->hdr.control = NULL;
InitializeCriticalSection(&store->cs);
list_init(&store->certs);
@ -1905,8 +1896,7 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
cert->cert.pCertInfo = certInfo;
cert->cert.hCertStore = 0;
cert->ref = 0;
InitializeCriticalSection(&cert->cs);
list_init(&cert->extendedProperties);
cert->properties = ContextPropertyList_Create();
}
end:
@ -1915,18 +1905,9 @@ end:
static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context)
{
PWINE_CERT_PROPERTY prop, next;
CryptMemFree(context->cert.pbCertEncoded);
LocalFree(context->cert.pCertInfo);
DeleteCriticalSection(&context->cs);
LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
WINE_CERT_PROPERTY, entry)
{
list_remove(&prop->entry);
CryptMemFree(prop->pbData);
CryptMemFree(prop);
}
ContextPropertyList_Free(context->properties);
CryptMemFree(context);
}
@ -1946,46 +1927,14 @@ PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
return (PCCERT_CONTEXT)ret;
}
/* Since the properties are stored in a list, this is a tad inefficient
* (O(n^2)) since I have to find the previous position every time.
*/
DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
DWORD dwPropId)
{
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
DWORD ret;
TRACE("(%p, %ld)\n", pCertContext, dwPropId);
EnterCriticalSection(&ref->context->cs);
if (dwPropId)
{
PWINE_CERT_PROPERTY cursor = NULL;
LIST_FOR_EACH_ENTRY(cursor, &ref->context->extendedProperties,
WINE_CERT_PROPERTY, entry)
{
if (cursor->propID == dwPropId)
break;
}
if (cursor)
{
if (cursor->entry.next != &ref->context->extendedProperties)
ret = LIST_ENTRY(cursor->entry.next, WINE_CERT_PROPERTY,
entry)->propID;
else
ret = 0;
}
else
ret = 0;
}
else if (!list_empty(&ref->context->extendedProperties))
ret = LIST_ENTRY(ref->context->extendedProperties.next,
WINE_CERT_PROPERTY, entry)->propID;
else
ret = 0;
LeaveCriticalSection(&ref->context->cs);
return ret;
return ContextPropertyList_EnumPropIDs(ref->context->properties, dwPropId);
}
static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
@ -2007,40 +1956,33 @@ static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
static BOOL WINAPI CRYPT_GetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
{
PWINE_CERT_PROPERTY prop;
BOOL ret, found;
BOOL ret;
CRYPT_DATA_BLOB blob;
TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
EnterCriticalSection(&context->cs);
ret = FALSE;
found = FALSE;
LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
WINE_CERT_PROPERTY, entry)
ret = ContextPropertyList_FindProperty(context->properties, dwPropId,
&blob);
if (ret)
{
if (prop->propID == dwPropId)
if (!pvData)
{
if (!pvData)
{
*pcbData = prop->cbData;
ret = TRUE;
}
else if (*pcbData < prop->cbData)
{
SetLastError(ERROR_MORE_DATA);
*pcbData = prop->cbData;
}
else
{
memcpy(pvData, prop->pbData, prop->cbData);
*pcbData = prop->cbData;
ret = TRUE;
}
found = TRUE;
break;
*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;
}
}
if (!found)
else
{
/* Implicit properties */
switch (dwPropId)
@ -2076,7 +2018,6 @@ static BOOL WINAPI CRYPT_GetCertificateContextProperty(
SetLastError(CRYPT_E_NOT_FOUND);
}
}
LeaveCriticalSection(&context->cs);
TRACE("returning %d\n", ret);
return ret;
}
@ -2134,65 +2075,6 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
return ret;
}
/* Copies cbData bytes from pbData to the context's property with ID
* dwPropId.
*/
static BOOL CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context,
DWORD dwPropId, const BYTE *pbData, size_t cbData)
{
BOOL ret = FALSE;
LPBYTE data;
if (cbData)
{
data = CryptMemAlloc(cbData);
if (data)
memcpy(data, pbData, cbData);
}
else
data = NULL;
if (!cbData || data)
{
PWINE_CERT_PROPERTY prop;
BOOL found = FALSE;
EnterCriticalSection(&context->cs);
LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
WINE_CERT_PROPERTY, entry)
{
if (prop->propID == dwPropId)
{
found = TRUE;
break;
}
}
if (found)
{
CryptMemFree(prop->pbData);
prop->cbData = cbData;
prop->pbData = data;
ret = TRUE;
}
else
{
prop = CryptMemAlloc(sizeof(WINE_CERT_PROPERTY));
if (prop)
{
prop->propID = dwPropId;
prop->cbData = cbData;
list_init(&prop->entry);
prop->pbData = data;
list_add_tail(&context->extendedProperties, &prop->entry);
ret = TRUE;
}
else
CryptMemFree(data);
}
LeaveCriticalSection(&context->cs);
}
return ret;
}
static BOOL WINAPI CRYPT_SetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData)
{
@ -2202,20 +2084,7 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
if (!pvData)
{
PWINE_CERT_PROPERTY prop, next;
EnterCriticalSection(&context->cs);
LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
WINE_CERT_PROPERTY, entry)
{
if (prop->propID == dwPropId)
{
list_remove(&prop->entry);
CryptMemFree(prop->pbData);
CryptMemFree(prop);
}
}
LeaveCriticalSection(&context->cs);
ContextPropertyList_RemoveProperty(context->properties, dwPropId);
ret = TRUE;
}
else
@ -2242,12 +2111,12 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
{
PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
ret = ContextPropertyList_SetProperty(context->properties, dwPropId,
blob->pbData, blob->cbData);
break;
}
case CERT_DATE_STAMP_PROP_ID:
ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
ret = ContextPropertyList_SetProperty(context->properties, dwPropId,
pvData, sizeof(FILETIME));
break;
default:
@ -2319,51 +2188,12 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
return FALSE;
}
cert = CRYPT_CreateCertificateContext(ref->context->cert.dwCertEncodingType,
ref->context->cert.pbCertEncoded, ref->context->cert.cbCertEncoded);
cert = CRYPT_CreateCertificateContext(ref->cert.dwCertEncodingType,
ref->cert.pbCertEncoded, ref->cert.cbCertEncoded);
if (cert)
{
DWORD prop = 0, bufSize = 0;
LPBYTE buf = NULL;
ret = TRUE;
EnterCriticalSection(&ref->context->cs);
do {
prop = CertEnumCertificateContextProperties((PCCERT_CONTEXT)ref,
prop);
if (prop)
{
DWORD propSize = 0;
ret = CertGetCertificateContextProperty(pCertContext, prop,
NULL, &propSize);
if (ret)
{
if (bufSize < propSize)
{
if (buf)
buf = CryptMemRealloc(buf, propSize);
else
buf = CryptMemAlloc(propSize);
bufSize = propSize;
}
if (buf)
{
ret = CertGetCertificateContextProperty(pCertContext,
prop, buf, &propSize);
if (ret)
ret = CRYPT_SaveCertificateContextProperty(cert,
prop, buf, bufSize);
}
else
ret = FALSE;
}
}
} while (ret && prop != 0);
CryptMemFree(buf);
LeaveCriticalSection(&ref->context->cs);
if (ret)
ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext);
ContextPropertyList_Copy(cert->properties, ref->context->properties);
ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext);
if (!ret)
CRYPT_FreeCert(cert);
}