/* * 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 #include "windef.h" #include "winbase.h" #include "wincrypt.h" #include "winnls.h" #include "wine/debug.h" #include "crypt32_private.h" WINE_DEFAULT_DEBUG_CHANNEL(crypt); typedef struct _WINE_FILESTOREINFO { DWORD dwOpenFlags; HCERTSTORE memStore; HANDLE file; BOOL dirty; } WINE_FILESTOREINFO, *PWINE_FILESTOREINFO; static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; TRACE("(%p, %08x)\n", store, dwFlags); if (store->dirty) CRYPT_WriteSerializedFile(store->file, store->memStore); CertCloseStore(store->memStore, dwFlags); CloseHandle(store->file); CryptMemFree(store); } static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore, PCCERT_CONTEXT cert, DWORD dwFlags) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags); store->dirty = TRUE; return TRUE; } static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext, DWORD dwFlags) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; TRACE("(%p, %p, %08x)\n", hCertStore, pCertContext, dwFlags); store->dirty = TRUE; return TRUE; } static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore, PCCRL_CONTEXT crl, DWORD dwFlags) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags); store->dirty = TRUE; return TRUE; } static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore, PCCRL_CONTEXT pCrlContext, DWORD dwFlags) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; TRACE("(%p, %p, %08x)\n", hCertStore, pCrlContext, dwFlags); store->dirty = TRUE; return TRUE; } static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara) { PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore; BOOL ret; TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType, pvCtrlPara); switch (dwCtrlType) { case CERT_STORE_CTRL_RESYNC: CRYPT_EmptyStore(store->memStore); CRYPT_ReadSerializedFile(store->file, store); ret = TRUE; break; case CERT_STORE_CTRL_COMMIT: if (!(store->dwOpenFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG)) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); ret = FALSE; } else if (store->dirty) ret = CRYPT_WriteSerializedFile(store->file, store->memStore); else ret = TRUE; break; default: FIXME("%d: stub\n", dwCtrlType); ret = FALSE; } return ret; } static void *fileProvFuncs[] = { CRYPT_FileCloseStore, NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */ CRYPT_FileWriteCert, CRYPT_FileDeleteCert, NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */ NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */ CRYPT_FileWriteCRL, CRYPT_FileDeleteCRL, NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */ NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */ NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */ NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */ NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */ CRYPT_FileControl, }; PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { PWINECRYPT_CERTSTORE store = NULL; HANDLE file = (HANDLE)pvPara; TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); if (!pvPara) { SetLastError(ERROR_INVALID_HANDLE); return NULL; } if (dwFlags & CERT_STORE_DELETE_FLAG) { SetLastError(E_INVALIDARG); return NULL; } if ((dwFlags & CERT_STORE_READONLY_FLAG) && (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG)) { SetLastError(E_INVALIDARG); return NULL; } if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara, GetCurrentProcess(), &file, dwFlags & CERT_STORE_READONLY_FLAG ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, TRUE, 0)) { PWINECRYPT_CERTSTORE memStore; memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); if (memStore) { if (CRYPT_ReadSerializedFile(file, memStore)) { PWINE_FILESTOREINFO info = CryptMemAlloc( sizeof(WINE_FILESTOREINFO)); if (info) { CERT_STORE_PROV_INFO provInfo = { 0 }; info->dwOpenFlags = dwFlags; info->memStore = memStore; info->file = file; info->dirty = FALSE; provInfo.cbSize = sizeof(provInfo); provInfo.cStoreProvFunc = sizeof(fileProvFuncs) / sizeof(fileProvFuncs[0]); provInfo.rgpvStoreProvFunc = fileProvFuncs; provInfo.hStoreProv = info; store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); /* File store doesn't need crypto provider, so close it */ if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) CryptReleaseContext(hCryptProv, 0); } } } } TRACE("returning %p\n", store); return store; } PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { HCERTSTORE store = 0; LPCWSTR fileName = (LPCWSTR)pvPara; DWORD access, create; HANDLE file; TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_w(fileName)); if (!fileName) { SetLastError(ERROR_PATH_NOT_FOUND); return NULL; } access = GENERIC_READ; if (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG) access |= GENERIC_WRITE; if (dwFlags & CERT_STORE_CREATE_NEW_FLAG) create = CREATE_NEW; else if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG) create = OPEN_EXISTING; else create = OPEN_ALWAYS; file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); if (file != INVALID_HANDLE_VALUE) { /* FIXME: need to check whether it's a serialized store; if not, fall * back to a PKCS#7 signed message, then to a single serialized cert. */ store = CertOpenStore(CERT_STORE_PROV_FILE, 0, hCryptProv, dwFlags, file); CloseHandle(file); } return (PWINECRYPT_CERTSTORE)store; } PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { int len; PWINECRYPT_CERTSTORE ret = NULL; TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_a((LPCSTR)pvPara)); if (!pvPara) { SetLastError(ERROR_FILE_NOT_FOUND); return NULL; } len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0); if (len) { LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); if (storeName) { MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len); ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName); CryptMemFree(storeName); } } return ret; }