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