From: Donat Enikeev Subject: [PATCH 1/2] crypt32/tests: whether apps could write to the registry HKLM Root certificates store Message-Id: <1476795555-5813-1-git-send-email-donat@enikeev.net> Date: Tue, 18 Oct 2016 15:59:15 +0300 And, additionally, whether CertAddStoreToCollection() respects read-only flag and priorities Signed-off-by: Donat Enikeev --- dlls/crypt32/tests/store.c | 217 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index 4483936..c9989ff 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -345,6 +345,220 @@ 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 }; +/* Testing whether HKLM\Root store in the collection is availble for adding new certs*/ +static void testRootStoresInCollection(void) +{ + PCCERT_CONTEXT cert1, cert2; + HCERTSTORE collection; + WCHAR keyName[MAX_PATH]; + static const WCHAR rootW[] = {'R','o','o','t',0}, + certificatesW[] = {'C','e','r','t','i','f','i','c','a','t','e','s',0 }, + slashW[] = { '\\',0 }, + bigCert_hashStrW[] = { + '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}; + HKEY key; + BOOL ret; + DWORD res; + + /* Special case of HKLM Root store, with system certificates merged via collection*/ + collection = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, + CERT_SYSTEM_STORE_LOCAL_MACHINE, rootW); + if (!collection) + { + win_skip("Insufficient privileges for the test, skipping\n"); + return; + } + ok (collection!=NULL, "Failed to open root store %x", 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_REPLACE_EXISTING, NULL); + ok (ret, "Adding to root collection failed %x\n", GetLastError()); + CertFreeCertificateContext(cert1); + CertCloseStore(collection, 0); + + lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH); + lstrcatW(keyName, slashW); + lstrcatW(keyName, rootW); + lstrcatW(keyName, slashW); + lstrcatW(keyName, certificatesW); + lstrcatW(keyName, slashW); + lstrcatW(keyName, bigCert_hashStrW); + + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_ALL_ACCESS, &key); + ok (!res, "The cert hasn't been saved %x\n", GetLastError()); + if (!res) RegCloseKey(key); + + /* deleting cert from store */ + collection = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0, + CERT_SYSTEM_STORE_LOCAL_MACHINE, rootW); + ok (collection!=NULL, "Failed to open root store %x", GetLastError()); + cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); + ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError()); + cert2 = CertFindCertificateInStore(collection, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, cert1, NULL); + ok (cert2 != NULL, "Failed to find cert in the store %x\n", GetLastError()); + ret = CertDeleteCertificateFromStore(cert2); + ok (ret, "Failed to delete certificate from store %x\n", GetLastError()); + CertFreeCertificateContext(cert1); + CertFreeCertificateContext(cert2); + CertCloseStore(collection, 0); + + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_ALL_ACCESS, &key); + ok (res, "The cert's registry entry should be absent %x\n", GetLastError()); + if (res) RegCloseKey(key); +} + +/** + * @see testCollectionStore() additionally + * 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; + } + if (0) { + 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 (they are NOT in wine until stores are closed*/ + 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); + + /* now closing stores, certs are only then saved */ + 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 (they should be this time)*/ + 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; @@ -2812,6 +3026,9 @@ START_TEST(store) /* various combinations of CertOpenStore */ testMemStore(); testCollectionStore(); + testStoresInCollection(); + testRootStoresInCollection(); + testRegStore(); testSystemRegStore(); testSystemStore(); -- 2.7.4