crypt32/tests: Testing priorities and flags of stores in a collection; and whether certs are saved in registry endpoint.

Signed-off-by: Donat Enikeev <donat@enikeev.net>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Donat Enikeev 2016-11-07 17:37:48 +01:00 committed by Alexandre Julliard
parent c2b0dfd73d
commit 30164ea3e8
2 changed files with 286 additions and 1 deletions

View File

@ -1,5 +1,5 @@
TESTDLL = crypt32.dll
IMPORTS = crypt32 advapi32
IMPORTS = crypt32 advapi32 user32 shlwapi shell32
C_SRCS = \
base64.c \

View File

@ -23,6 +23,9 @@
#include <windef.h>
#include <winbase.h>
#include <winuser.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <winreg.h>
#include <winerror.h>
#include <wincrypt.h>
@ -347,6 +350,284 @@ static const BYTE serializedStoreWithCert[] = {
0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00 };
static const struct
{
HKEY key;
DWORD cert_store;
BOOL appdata_file;
WCHAR store_name[16];
const WCHAR *base_reg_path;
} reg_store_saved_certs[] = {
{ HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
{'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
{ HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
{'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
{ HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
{'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
/* Adding to HKCU\Root triggers safety warning. */
{ HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE,
{'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
{ HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE,
{'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }
};
/* Testing whether system stores are available for adding new certs
* and checking directly in the registry whether they are actually saved or deleted.
* Windows treats HKCU\My (at least) as a special case and uses AppData directory
* for storing certs, not registry.
*/
static void testRegStoreSavedCerts(void)
{
static const WCHAR fmt[] =
{ '%','s','\\','%','s','\\','%','s','\\','%','s',0},
ms_certs[] =
{ 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0},
certs[] =
{'C','e','r','t','i','f','i','c','a','t','e','s',0},
bigCert_hash[] = {
'6','E','3','0','9','0','7','1','5','F','D','9','2','3',
'5','6','E','B','A','E','2','5','4','0','E','6','2','2',
'D','A','1','9','2','6','0','2','A','6','0','8',0};
PCCERT_CONTEXT cert1, cert2;
HCERTSTORE store;
HANDLE cert_file;
HRESULT pathres;
WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH];
HKEY key;
BOOL ret;
DWORD res,i;
for (i = 0; i < sizeof(reg_store_saved_certs) / sizeof(reg_store_saved_certs[0]); i++)
{
DWORD err;
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
err = GetLastError();
if (!store)
{
ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err);
skip("Insufficient privileges for the test %d\n", i);
continue;
}
ok (store!=NULL, "Failed to open the store at %d, %x", i, GetLastError());
cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
ok (ret, "Adding to the store failed at %d, %x\n", i, GetLastError());
CertFreeCertificateContext(cert1);
CertCloseStore(store, 0);
wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path,
reg_store_saved_certs[i].store_name, certs, bigCert_hash);
if (!reg_store_saved_certs[i].appdata_file)
{
res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError());
if (!res) RegCloseKey(key);
} else
{
pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path);
ok (pathres == S_OK,
"Failed to get app data path at %d (%x)\n", pathres, GetLastError());
if (pathres == S_OK)
{
PathAppendW(appdata_path, ms_certs);
PathAppendW(appdata_path, reg_store_saved_certs[i].store_name);
PathAppendW(appdata_path, certs);
PathAppendW(appdata_path, bigCert_hash);
cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
todo_wine ok (cert_file != INVALID_HANDLE_VALUE,
"Cert was not saved in AppData at %d (%x)\n", i, GetLastError());
CloseHandle(cert_file);
}
}
/* deleting cert from store */
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
ok (store!=NULL, "Failed to open the store at %d, %x", i, GetLastError());
cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
CERT_FIND_EXISTING, cert1, NULL);
ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError());
ret = CertDeleteCertificateFromStore(cert2);
ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError());
CertFreeCertificateContext(cert1);
CertFreeCertificateContext(cert2);
CertCloseStore(store, 0);
res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError());
if (!res) RegCloseKey(key);
if (reg_store_saved_certs[i].appdata_file)
{
cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ok (cert_file == INVALID_HANDLE_VALUE,
"Cert should have been absent in AppData %d\n", i);
CloseHandle(cert_file);
}
}
}
/**
* This test checks that certificate falls into correct store of a collection
* depending on the access flags and priorities.
*/
static void testStoresInCollection(void)
{
PCCERT_CONTEXT cert1, cert2, tcert1;
HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore;
static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 },
WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 },
WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 };
BOOL ret;
if (!pCertAddStoreToCollection)
{
win_skip("CertAddStoreToCollection() is not available\n");
return;
}
collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError());
/* Add read-only store to collection with very high priority*/
ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W);
ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError());
ret = CertAddStoreToCollection(collection, ro_store, 0, 1000);
ok (ret, "Failed to add read-only store to collection %x\n", GetLastError());
cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError());
ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL);
ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError());
/* Add read-write store to collection with the lowest priority*/
rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError());
ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
ok (ret, "Failed to add rw store to collection %x\n", GetLastError());
/** Adding certificate to collection should fall into rw store,
* even though prioirty of the ro_store is higher */
ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
ok (ret, "Failed to add cert to the collection %x\n", GetLastError());
tcert1 = CertEnumCertificatesInStore(ro_store, NULL);
ok (!tcert1, "Read-only ro_store contains cert\n");
tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
"Unexpected cert in the rw store\n");
CertFreeCertificateContext(tcert1);
tcert1 = CertEnumCertificatesInStore(collection, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
"Unexpected cert in the collection\n");
CertFreeCertificateContext(tcert1);
/** adding one more rw store with higher priority*/
rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError());
ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50);
ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError());
cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert));
ok (cert2 != NULL, "Failed to create cert context %x \n", GetLastError());
ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
ok (ret, "Failed to add cert3 to the store %x\n",GetLastError());
/** checking certificates in the stores */
tcert1 = CertEnumCertificatesInStore(ro_store, 0);
ok (tcert1 == NULL, "Read-only store not empty\n");
tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
"Unexpected cert in the rw_store\n");
CertFreeCertificateContext(tcert1);
tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
"Unexpected cert in the rw_store_2\n");
CertFreeCertificateContext(tcert1);
/** checking certificates in the collection */
tcert1 = CertEnumCertificatesInStore(collection, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
"cert2 expected in the collection got %p, %x\n",tcert1, GetLastError());
tcert1 = CertEnumCertificatesInStore(collection, tcert1);
ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
"cert1 expected in the collection got %p, %x\n",tcert1, GetLastError());
tcert1 = CertEnumCertificatesInStore(collection, tcert1);
ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError());
/* checking whether certs had been saved */
tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W);
ok (tstore!=NULL, "Failed to open existing rw store\n");
tcert1 = CertEnumCertificatesInStore(tstore, NULL);
todo_wine
ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n");
CertFreeCertificateContext(tcert1);
CertCloseStore(tstore,0);
tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W);
ok (tstore!=NULL, "Failed to open existing rw2 store\n");
tcert1 = CertEnumCertificatesInStore(tstore, NULL);
todo_wine
ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n");
CertFreeCertificateContext(tcert1);
CertCloseStore(tstore,0);
CertCloseStore(collection,0);
CertCloseStore(ro_store,0);
CertCloseStore(rw_store,0);
CertCloseStore(rw_store_2,0);
/* reopening registry stores to check whether certs had been saved */
rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
"Unexpected cert in store %p\n", tcert1);
CertFreeCertificateContext(tcert1);
CertCloseStore(rw_store,0);
rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
"Unexpected cert in store %p\n", tcert1);
CertFreeCertificateContext(tcert1);
CertCloseStore(rw_store_2,0);
CertFreeCertificateContext(cert1);
CertFreeCertificateContext(cert2);
CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W);
CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W);
CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W);
}
static void testCollectionStore(void)
{
HCERTSTORE store1, store2, collection, collection2;
@ -2894,7 +3175,11 @@ START_TEST(store)
/* various combinations of CertOpenStore */
testMemStore();
testCollectionStore();
testStoresInCollection();
testRegStore();
testRegStoreSavedCerts();
testSystemRegStore();
testSystemStore();
testFileStore();