Juan Lang : crypt32: Implement opening file name stores from files that contain PKCS7 messages.
Alexandre Julliard
julliard at winehq.org
Mon Oct 1 07:54:57 CDT 2007
Module: wine
Branch: master
Commit: 15cab3304108a78609d002dd7942a9c54bf3bffa
URL: http://source.winehq.org/git/wine.git/?a=commit;h=15cab3304108a78609d002dd7942a9c54bf3bffa
Author: Juan Lang <juan.lang at gmail.com>
Date: Fri Sep 28 09:03:53 2007 -0700
crypt32: Implement opening file name stores from files that contain PKCS7 messages.
---
dlls/crypt32/filestore.c | 112 +++++++++++++++++++++++++++++++++++++-------
dlls/crypt32/tests/store.c | 2 +-
2 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/dlls/crypt32/filestore.c b/dlls/crypt32/filestore.c
index 9dde31c..8294e82 100644
--- a/dlls/crypt32/filestore.c
+++ b/dlls/crypt32/filestore.c
@@ -21,6 +21,7 @@
#include "wincrypt.h"
#include "winnls.h"
#include "wine/debug.h"
+#include "wine/unicode.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@@ -87,6 +88,24 @@ static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
return TRUE;
}
+static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob)
+{
+ BOOL ret = TRUE;
+
+ blob->cbData = GetFileSize(file, NULL);
+ if (blob->cbData)
+ {
+ blob->pbData = CryptMemAlloc(blob->cbData);
+ if (blob->pbData)
+ {
+ DWORD read;
+
+ ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
+ }
+ }
+ return ret;
+}
+
static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
DWORD dwCtrlType, void const *pvCtrlPara)
{
@@ -106,8 +125,37 @@ static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
store->memStore);
else if (store->type == CERT_STORE_SAVE_AS_PKCS7)
{
- FIXME("unimplemented for PKCS stores\n");
- ret = FALSE;
+ CERT_BLOB blob = { 0, NULL };
+
+ ret = CRYPT_ReadBlobFromFile(store->file, &blob);
+ if (ret)
+ {
+ HCERTSTORE messageStore;
+
+ ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
+ CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
+ CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
+ &messageStore, NULL, NULL);
+ if (ret)
+ {
+ PCCERT_CONTEXT cert = NULL;
+ PCCRL_CONTEXT crl = NULL;
+
+ do {
+ cert = CertEnumCertificatesInStore(messageStore, cert);
+ if (cert)
+ CertAddCertificateContextToStore(store->memStore,
+ cert, CERT_STORE_ADD_ALWAYS, NULL);
+ } while (cert);
+ do {
+ crl = CertEnumCRLsInStore(messageStore, crl);
+ if (crl)
+ CertAddCRLContextToStore(store->memStore, crl,
+ CERT_STORE_ADD_ALWAYS, NULL);
+ } while (crl);
+ }
+ CryptMemFree(blob.pbData);
+ }
}
else
{
@@ -262,27 +310,57 @@ PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
FILE_ATTRIBUTE_NORMAL, NULL);
if (file != INVALID_HANDLE_VALUE)
{
- HCERTSTORE memStore;
+ HCERTSTORE memStore = NULL;
+ DWORD size = GetFileSize(file, NULL), type = 0;
- memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
- CERT_STORE_CREATE_NEW_FLAG, NULL);
- if (memStore)
+ /* If the file isn't empty, try to get the type from the file itself */
+ if (size)
{
- if (CRYPT_ReadSerializedStoreFromFile(file, memStore))
+ DWORD contentType;
+ BOOL ret;
+
+ /* Close the file so CryptQueryObject can succeed.. */
+ CloseHandle(file);
+ ret = CryptQueryObject(CERT_QUERY_OBJECT_FILE, fileName,
+ CERT_QUERY_CONTENT_FLAG_CERT |
+ CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
+ CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
+ CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, &contentType, NULL,
+ &memStore, NULL, NULL);
+ if (ret)
{
- store = CRYPT_CreateFileStore(dwFlags, memStore, file,
- CERT_STORE_SAVE_AS_STORE);
- /* File store doesn't need crypto provider, so close it */
- if (hCryptProv &&
- !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
- CryptReleaseContext(hCryptProv, 0);
+ if (contentType == CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
+ type = CERT_STORE_SAVE_AS_PKCS7;
+ else
+ type = CERT_STORE_SAVE_AS_STORE;
+ /* and reopen the file. */
+ file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL,
+ create, FILE_ATTRIBUTE_NORMAL, NULL);
}
- else
+ }
+ else
+ {
+ static const WCHAR spc[] = { 's','p','c',0 };
+ static const WCHAR p7c[] = { 'p','7','c',0 };
+ LPCWSTR ext = strrchrW(fileName, '.');
+
+ if (ext)
{
- /* FIXME: fall back to a PKCS#7 signed message, then to a
- * single serialized cert.
- */
+ ext++;
+ if (!lstrcmpiW(ext, spc) || !lstrcmpiW(ext, p7c))
+ type = CERT_STORE_SAVE_AS_PKCS7;
}
+ if (!type)
+ type = CERT_STORE_SAVE_AS_STORE;
+ memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
+ CERT_STORE_CREATE_NEW_FLAG, NULL);
+ }
+ if (memStore)
+ {
+ store = CRYPT_CreateFileStore(dwFlags, memStore, file, type);
+ /* File store doesn't need crypto provider, so close it */
+ if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
+ CryptReleaseContext(hCryptProv, 0);
}
}
return (PWINECRYPT_CERTSTORE)store;
diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c
index 450352f..b14dbc2 100644
--- a/dlls/crypt32/tests/store.c
+++ b/dlls/crypt32/tests/store.c
@@ -1244,7 +1244,7 @@ static void testFileNameStore(void)
ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
cert = CertEnumCertificatesInStore(store, NULL);
- todo_wine ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
+ ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
GetLastError());
cert = CertEnumCertificatesInStore(store, cert);
ok(!cert, "Expected only one cert\n");
More information about the wine-cvs
mailing list