diff --git a/reactos/dll/win32/crypt32/chain.c b/reactos/dll/win32/crypt32/chain.c index b64f121faee..45bb8f3a42a 100644 --- a/reactos/dll/win32/crypt32/chain.c +++ b/reactos/dll/win32/crypt32/chain.c @@ -2697,10 +2697,20 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain, revocationPara.pIssuerCert = chain->rgpChain[i]->rgpElement[j + 1]->pCertContext; else - revocationPara.pIssuerCert = NULL; + revocationPara.pIssuerCert = certToCheck; + ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certToCheck, revocationFlags, &revocationPara, &revocationStatus); + + if (!ret && revocationStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK && + revocationPara.pIssuerCert == certToCheck) + { + FIXME("Unable to find CRL for CA certificate\n"); + ret = TRUE; + revocationStatus.dwError = 0; + } + if (!ret) { PCERT_CHAIN_ELEMENT element = CRYPT_FindIthElementInChain( diff --git a/reactos/dll/win32/crypt32/crypt32.spec b/reactos/dll/win32/crypt32/crypt32.spec index 0d2a477c8eb..b5ce48c6ecf 100644 --- a/reactos/dll/win32/crypt32/crypt32.spec +++ b/reactos/dll/win32/crypt32/crypt32.spec @@ -78,6 +78,7 @@ @ stdcall CertRDNValueToStrA(long ptr ptr long) @ stdcall CertRDNValueToStrW(long ptr ptr long) @ stdcall CertRegisterPhysicalStore(ptr long wstr ptr ptr) +@ stdcall CertRegisterSystemStore(ptr long ptr ptr) @ stdcall CertRemoveEnhancedKeyUsageIdentifier(ptr str) @ stdcall CertRemoveStoreFromCollection(ptr ptr) @ stdcall CertSaveStore(ptr long long long ptr long) @@ -190,6 +191,7 @@ @ stdcall CryptUnprotectMemory(ptr long long) @ stdcall CryptUnregisterDefaultOIDFunction(long str wstr) @ stdcall CryptUnregisterOIDFunction(long str str) +@ stdcall CertUnregisterSystemStore(ptr long) @ stub CryptUnregisterOIDInfo @ stdcall CryptVerifyCertificateSignature(long long ptr long ptr) @ stdcall CryptVerifyCertificateSignatureEx(long long long ptr long ptr long ptr) diff --git a/reactos/dll/win32/crypt32/crypt32_private.h b/reactos/dll/win32/crypt32/crypt32_private.h index 75c04979f9e..9ef8655223b 100644 --- a/reactos/dll/win32/crypt32/crypt32_private.h +++ b/reactos/dll/win32/crypt32/crypt32_private.h @@ -365,7 +365,11 @@ WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) DECLSPEC_HIDDEN; WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) DECLSPEC_HIDDEN; -WINECRYPT_CERTSTORE *CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags) DECLSPEC_HIDDEN; + +void CRYPT_ImportSystemRootCertsToReg(void) DECLSPEC_HIDDEN; +BOOL CRYPT_SerializeContextsToReg(HKEY key, DWORD flags, const WINE_CONTEXT_INTERFACE *contextInterface, + HCERTSTORE memStore) DECLSPEC_HIDDEN; + BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert) DECLSPEC_HIDDEN; /* Allocates and initializes a certificate chain engine, but without creating diff --git a/reactos/dll/win32/crypt32/main.c b/reactos/dll/win32/crypt32/main.c index 66d2b89bf47..8f2902e5c73 100644 --- a/reactos/dll/win32/crypt32/main.c +++ b/reactos/dll/win32/crypt32/main.c @@ -40,7 +40,6 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved) if (pvReserved) break; crypt_oid_free(); crypt_sip_free(); - root_store_free(); default_chain_engine_free(); if (hDefProv) CryptReleaseContext(hDefProv, 0); break; diff --git a/reactos/dll/win32/crypt32/regstore.c b/reactos/dll/win32/crypt32/regstore.c index 783149c1105..ba4b439a267 100644 --- a/reactos/dll/win32/crypt32/regstore.c +++ b/reactos/dll/win32/crypt32/regstore.c @@ -174,7 +174,7 @@ static void CRYPT_RegReadFromReg(HKEY key, HCERTSTORE store) } /* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */ -static BOOL CRYPT_WriteSerializedToReg(HKEY key, const BYTE *hash, const BYTE *buf, +static BOOL CRYPT_WriteSerializedToReg(HKEY key, DWORD flags, const BYTE *hash, const BYTE *buf, DWORD len) { WCHAR asciiHash[20 * 2 + 1]; @@ -183,7 +183,7 @@ static BOOL CRYPT_WriteSerializedToReg(HKEY key, const BYTE *hash, const BYTE *b BOOL ret; CRYPT_HashToStr(hash, asciiHash); - rc = RegCreateKeyExW(key, asciiHash, 0, NULL, 0, KEY_ALL_ACCESS, NULL, + rc = RegCreateKeyExW(key, asciiHash, 0, NULL, flags, KEY_ALL_ACCESS, NULL, &subKey, NULL); if (!rc) { @@ -200,7 +200,7 @@ static BOOL CRYPT_WriteSerializedToReg(HKEY key, const BYTE *hash, const BYTE *b return ret; } -static BOOL CRYPT_SerializeContextsToReg(HKEY key, +BOOL CRYPT_SerializeContextsToReg(HKEY key, DWORD flags, const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE memStore) { const void *context = NULL; @@ -227,7 +227,7 @@ static BOOL CRYPT_SerializeContextsToReg(HKEY key, { ret = contextInterface->serialize(context, 0, buf, &size); if (ret) - ret = CRYPT_WriteSerializedToReg(key, hash, buf, size); + ret = CRYPT_WriteSerializedToReg(key, flags, hash, buf, size); } CryptMemFree(buf); } @@ -282,8 +282,7 @@ static BOOL CRYPT_RegWriteToReg(WINE_REGSTOREINFO *store) } LeaveCriticalSection(&store->cs); } - ret = CRYPT_SerializeContextsToReg(key, interfaces[i], - store->memStore); + ret = CRYPT_SerializeContextsToReg(key, 0, interfaces[i], store->memStore); RegCloseKey(key); } else diff --git a/reactos/dll/win32/crypt32/rootstore.c b/reactos/dll/win32/crypt32/rootstore.c index e0a85e95a99..48b072e7cb5 100644 --- a/reactos/dll/win32/crypt32/rootstore.c +++ b/reactos/dll/win32/crypt32/rootstore.c @@ -428,53 +428,6 @@ static BOOL import_certs_from_path(LPCSTR path, HCERTSTORE store, return ret; } -static BOOL WINAPI CRYPT_RootWriteCert(HCERTSTORE hCertStore, - PCCERT_CONTEXT cert, DWORD dwFlags) -{ - /* The root store can't have certs added */ - return FALSE; -} - -static BOOL WINAPI CRYPT_RootDeleteCert(HCERTSTORE hCertStore, - PCCERT_CONTEXT cert, DWORD dwFlags) -{ - /* The root store can't have certs deleted */ - return FALSE; -} - -static BOOL WINAPI CRYPT_RootWriteCRL(HCERTSTORE hCertStore, - PCCRL_CONTEXT crl, DWORD dwFlags) -{ - /* The root store can have CRLs added. At worst, a malicious application - * can DoS itself, as the changes aren't persisted in any way. - */ - return TRUE; -} - -static BOOL WINAPI CRYPT_RootDeleteCRL(HCERTSTORE hCertStore, - PCCRL_CONTEXT crl, DWORD dwFlags) -{ - /* The root store can't have CRLs deleted */ - return FALSE; -} - -static void *rootProvFuncs[] = { - NULL, /* CERT_STORE_PROV_CLOSE_FUNC */ - NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */ - CRYPT_RootWriteCert, - CRYPT_RootDeleteCert, - NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */ - NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */ - CRYPT_RootWriteCRL, - CRYPT_RootDeleteCRL, - 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 */ - NULL, /* CERT_STORE_PROV_CONTROL_FUNC */ -}; - static const char * const CRYPT_knownLocations[] = { "/etc/ssl/certs/ca-certificates.crt", "/etc/ssl/certs", @@ -783,68 +736,65 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store) static HCERTSTORE create_root_store(void) { - HCERTSTORE root = NULL; HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); if (memStore) { - CERT_STORE_PROV_INFO provInfo = { - sizeof(CERT_STORE_PROV_INFO), - sizeof(rootProvFuncs) / sizeof(rootProvFuncs[0]), - rootProvFuncs, - NULL, - 0, - NULL - }; - read_trusted_roots_from_known_locations(memStore); add_ms_root_certs(memStore); - root = CRYPT_ProvCreateStore(0, memStore, &provInfo); -#ifdef __REACTOS__ + } + + TRACE("returning %p\n", memStore); + return memStore; +} + +static const WCHAR certs_root_pathW[] = + {'S','o','f','t','w','a','r','e','\\','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','\\', + 'R','o','o','t','\\', 'C','e','r','t','i','f','i','c','a','t','e','s', 0}; +static const WCHAR semaphoreW[] = + {'c','r','y','p','t','3','2','_','r','o','o','t','_','s','e','m','a','p','h','o','r','e',0}; + +void CRYPT_ImportSystemRootCertsToReg(void) +{ + HCERTSTORE store = NULL; + HKEY key; + LONG rc; + HANDLE hsem; + + static BOOL root_certs_imported = FALSE; + + if (root_certs_imported) + return; + + hsem = CreateSemaphoreW( NULL, 0, 1, semaphoreW); + if (!hsem) + { + ERR("Failed to create semaphore\n"); + return; + } + + if(GetLastError() == ERROR_ALREADY_EXISTS) + WaitForSingleObject(hsem, INFINITE); + else + { + if ((store = create_root_store())) { - HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"AuthRoot"); - if (regStore) + rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, certs_root_pathW, 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &key, 0); + if (!rc) { - HCERTSTORE collStore = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, - CERT_STORE_CREATE_NEW_FLAG, NULL); - CertAddStoreToCollection(collStore, regStore, 0, 0); - CertAddStoreToCollection(collStore, root, 0, 0); - root = collStore; + if (!CRYPT_SerializeContextsToReg(key, REG_OPTION_VOLATILE, pCertInterface, store)) + ERR("Failed to import system certs into registry, %08x\n", GetLastError()); + RegCloseKey(key); } - } -#endif + CertCloseStore(store, 0); + } else + ERR("Failed to create root store\n"); } - TRACE("returning %p\n", root); - return root; -} - -static WINECRYPT_CERTSTORE *CRYPT_rootStore; - -WINECRYPT_CERTSTORE *CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags) -{ - TRACE("(%ld, %08x)\n", hCryptProv, dwFlags); - - if (dwFlags & CERT_STORE_DELETE_FLAG) - { - WARN("root store can't be deleted\n"); - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - if (!CRYPT_rootStore) - { - HCERTSTORE root = create_root_store(); - - InterlockedCompareExchangePointer((PVOID *)&CRYPT_rootStore, root, - NULL); - if (CRYPT_rootStore != root) - CertCloseStore(root, 0); - } - CRYPT_rootStore->vtbl->addref(CRYPT_rootStore); - return CRYPT_rootStore; -} - -void root_store_free(void) -{ - CertCloseStore(CRYPT_rootStore, 0); + + root_certs_imported = TRUE; + ReleaseSemaphore(hsem, 1, NULL); + CloseHandle(hsem); } diff --git a/reactos/dll/win32/crypt32/store.c b/reactos/dll/win32/crypt32/store.c index b0a77f68bfe..7910635a299 100644 --- a/reactos/dll/win32/crypt32/store.c +++ b/reactos/dll/win32/crypt32/store.c @@ -411,21 +411,15 @@ static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv, SetLastError(E_INVALIDARG); return NULL; } - /* FIXME: In Windows, the root store (even the current user location) is - * protected: adding to it or removing from it present a user interface, - * and the keys are owned by the system process, not the current user. - * Wine's registry doesn't implement access controls, so a similar - * mechanism isn't possible yet. - */ - if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == - CERT_SYSTEM_STORE_LOCAL_MACHINE && !lstrcmpiW(storeName, rootW)) - return CRYPT_RootOpenStore(hCryptProv, dwFlags); switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) { case CERT_SYSTEM_STORE_LOCAL_MACHINE: root = HKEY_LOCAL_MACHINE; base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; + /* If the HKLM\Root certs are requested, expressing system certs into the registry */ + if (!lstrcmpiW(storeName, rootW)) + CRYPT_ImportSystemRootCertsToReg(); break; case CERT_SYSTEM_STORE_CURRENT_USER: root = HKEY_CURRENT_USER; @@ -1377,6 +1371,51 @@ BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags, return FALSE; } +BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags, + PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved) +{ + HCERTSTORE hstore; + + if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG ) + { + FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved); + return FALSE; + } + + TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved); + + hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore); + if (hstore) + { + CertCloseStore(hstore, 0); + return TRUE; + } + + return FALSE; +} + +BOOL WINAPI CertUnregisterSystemStore(void *pvSystemStore, DWORD dwFlags) +{ + HCERTSTORE hstore; + + if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) + { + FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags); + return FALSE; + } + TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags); + + hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore); + if (hstore == NULL) + return FALSE; + + hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore); + if (hstore == NULL && GetLastError() == 0) + return TRUE; + + return FALSE; +} + static void EmptyStore_addref(WINECRYPT_CERTSTORE *store) { TRACE("(%p)\n", store); diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 7e6b5c4d9ea..c3175669b61 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -58,7 +58,7 @@ reactos/dll/win32/comctl32 # Synced to WineStaging-1.9.23 reactos/dll/win32/comdlg32 # Synced to WineStaging-1.9.23 reactos/dll/win32/compstui # Synced to WineStaging-1.9.11 reactos/dll/win32/credui # Synced to WineStaging-1.9.16 -reactos/dll/win32/crypt32 # Synced to WineStaging-1.9.16 +reactos/dll/win32/crypt32 # Synced to WineStaging-1.9.23 reactos/dll/win32/cryptdlg # Synced to WineStaging-1.9.11 reactos/dll/win32/cryptdll # Synced to WineStaging-1.9.11 reactos/dll/win32/cryptnet # Synced to WineStaging-1.9.11