blob: 795c8e1114b38f27512f9d400fc757d23730ce54 [file] [log] [blame]
/*
* Copyright 2004-2007 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 <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 _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_WRITE_CRL provWriteCrl;
PFN_CERT_STORE_PROV_DELETE_CRL provDeleteCrl;
PFN_CERT_STORE_PROV_WRITE_CTL provWriteCtl;
PFN_CERT_STORE_PROV_DELETE_CTL provDeleteCtl;
PFN_CERT_STORE_PROV_CONTROL provControl;
} WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
{
PWINE_PROVIDERSTORE store = hCertStore;
TRACE("(%p, %08x)\n", store, dwFlags);
if (store->provCloseStore)
store->provCloseStore(store->hStoreProv, dwFlags);
if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
CertCloseStore(store->memStore, dwFlags);
CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
}
static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, void *cert,
void *toReplace, const void **ppStoreContext)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
BOOL ret;
TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
if (toReplace)
ret = ps->memStore->certs.addContext(ps->memStore, cert, toReplace,
ppStoreContext);
else
{
ret = TRUE;
if (ps->provWriteCert)
ret = ps->provWriteCert(ps->hStoreProv, cert,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->certs.addContext(ps->memStore, cert, NULL,
ppStoreContext);
}
/* dirty trick: replace the returned context's hCertStore with
* store.
*/
if (ret && ppStoreContext)
(*(PCERT_CONTEXT *)ppStoreContext)->hCertStore = store;
return ret;
}
static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
void *ret;
ret = ps->memStore->certs.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_ProvDeleteCert(PWINECRYPT_CERTSTORE store, void *cert)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
BOOL ret = TRUE;
TRACE("(%p, %p)\n", store, cert);
if (ps->provDeleteCert)
ret = ps->provDeleteCert(ps->hStoreProv, cert, 0);
if (ret)
ret = ps->memStore->certs.deleteContext(ps->memStore, cert);
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,
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, crl,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->crls.addContext(ps->memStore, crl, NULL,
ppStoreContext);
}
}
/* dirty trick: replace the returned context's hCertStore with
* store.
*/
if (ret && 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.
*/
((PCRL_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 CRYPT_ProvAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
void *toReplace, const void **ppStoreContext)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
BOOL ret;
TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
if (toReplace)
ret = ps->memStore->ctls.addContext(ps->memStore, ctl, toReplace,
ppStoreContext);
else
{
if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
{
SetLastError(ERROR_ACCESS_DENIED);
ret = FALSE;
}
else
{
ret = TRUE;
if (ps->provWriteCtl)
ret = ps->provWriteCtl(ps->hStoreProv, ctl,
CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret)
ret = ps->memStore->ctls.addContext(ps->memStore, ctl, NULL,
ppStoreContext);
}
}
/* dirty trick: replace the returned context's hCertStore with
* store.
*/
if (ret && ppStoreContext)
(*(PCTL_CONTEXT *)ppStoreContext)->hCertStore = store;
return ret;
}
static void *CRYPT_ProvEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
void *ret;
ret = ps->memStore->ctls.enumContext(ps->memStore, pPrev);
if (ret)
{
/* same dirty trick: replace the returned context's hCertStore with
* store.
*/
((PCTL_CONTEXT)ret)->hCertStore = store;
}
return ret;
}
static BOOL CRYPT_ProvDeleteCTL(PWINECRYPT_CERTSTORE store, void *ctl)
{
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
BOOL ret = TRUE;
TRACE("(%p, %p)\n", store, ctl);
if (ps->provDeleteCtl)
ret = ps->provDeleteCtl(ps->hStoreProv, ctl, 0);
if (ret)
ret = ps->memStore->ctls.deleteContext(ps->memStore, ctl);
return ret;
}
static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
DWORD dwCtrlType, void const *pvCtrlPara)
{
PWINE_PROVIDERSTORE store = hCertStore;
BOOL ret = TRUE;
TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
pvCtrlPara);
if (store->provControl)
ret = store->provControl(store->hStoreProv, dwFlags, dwCtrlType,
pvCtrlPara);
return ret;
}
PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
PWINECRYPT_CERTSTORE memStore, const CERT_STORE_PROV_INFO *pProvInfo)
{
PWINE_PROVIDERSTORE ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
if (ret)
{
CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider);
ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
{
CertCloseStore(memStore, 0);
ret->memStore = NULL;
}
else
ret->memStore = memStore;
ret->hStoreProv = pProvInfo->hStoreProv;
ret->hdr.closeStore = CRYPT_ProvCloseStore;
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.ctls.addContext = CRYPT_ProvAddCTL;
ret->hdr.ctls.enumContext = CRYPT_ProvEnumCTL;
ret->hdr.ctls.deleteContext = CRYPT_ProvDeleteCTL;
ret->hdr.control = CRYPT_ProvControl;
if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
ret->provCloseStore =
pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
else
ret->provCloseStore = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_WRITE_CERT_FUNC)
ret->provWriteCert = pProvInfo->rgpvStoreProvFunc[
CERT_STORE_PROV_WRITE_CERT_FUNC];
else
ret->provWriteCert = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_DELETE_CERT_FUNC)
ret->provDeleteCert = pProvInfo->rgpvStoreProvFunc[
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->provWriteCrl = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_DELETE_CRL_FUNC)
ret->provDeleteCrl = pProvInfo->rgpvStoreProvFunc[
CERT_STORE_PROV_DELETE_CRL_FUNC];
else
ret->provDeleteCrl = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_WRITE_CTL_FUNC)
ret->provWriteCtl = pProvInfo->rgpvStoreProvFunc[
CERT_STORE_PROV_WRITE_CTL_FUNC];
else
ret->provWriteCtl = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_DELETE_CTL_FUNC)
ret->provDeleteCtl = pProvInfo->rgpvStoreProvFunc[
CERT_STORE_PROV_DELETE_CTL_FUNC];
else
ret->provDeleteCtl = NULL;
if (pProvInfo->cStoreProvFunc >
CERT_STORE_PROV_CONTROL_FUNC)
ret->provControl = pProvInfo->rgpvStoreProvFunc[
CERT_STORE_PROV_CONTROL_FUNC];
else
ret->provControl = NULL;
}
return (PWINECRYPT_CERTSTORE)ret;
}
PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
{
static HCRYPTOIDFUNCSET set = NULL;
PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
HCRYPTOIDFUNCADDR hFunc;
PWINECRYPT_CERTSTORE ret = NULL;
if (!set)
set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
CryptGetOIDFunctionAddress(set, dwEncodingType, lpszStoreProvider, 0,
(void **)&provOpenFunc, &hFunc);
if (provOpenFunc)
{
CERT_STORE_PROV_INFO provInfo = { 0 };
provInfo.cbSize = sizeof(provInfo);
if (dwFlags & CERT_STORE_DELETE_FLAG)
provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
dwFlags, pvPara, NULL, &provInfo);
else
{
HCERTSTORE memStore;
memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
if (memStore)
{
if (provOpenFunc(lpszStoreProvider, dwEncodingType, hCryptProv,
dwFlags, pvPara, memStore, &provInfo))
ret = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
else
CertCloseStore(memStore, 0);
}
}
CryptFreeOIDFunctionAddress(hFunc, 0);
}
else
SetLastError(ERROR_FILE_NOT_FOUND);
return ret;
}