diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index 9c85a4787ac..f84ecf4a1e0 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -2,6 +2,7 @@ EXTRADEFS = -D_CRYPT32_ MODULE = crypt32.dll IMPORTLIB = crypt32 IMPORTS = user32 advapi32 +DELAYIMPORTS = cryptnet EXTRALIBS = @SECURITYLIB@ C_SRCS = \ diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c index 4a8933bb05e..bbd0aca3289 100644 --- a/dlls/crypt32/chain.c +++ b/dlls/crypt32/chain.c @@ -1974,7 +1974,10 @@ static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine, static PCCERT_CONTEXT CRYPT_FindIssuer(const CertificateChainEngine *engine, const CERT_CONTEXT *cert, HCERTSTORE store, DWORD type, void *para, PCCERT_CONTEXT prev_issuer) { + CRYPT_URL_ARRAY *urls; PCCERT_CONTEXT issuer; + DWORD size; + BOOL res; issuer = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0, type, para, prev_issuer); if(issuer) { @@ -1996,7 +1999,50 @@ static PCCERT_CONTEXT CRYPT_FindIssuer(const CertificateChainEngine *engine, con } } - return NULL; + res = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void*)cert, 0, NULL, &size, NULL, NULL, NULL); + if(!res) + return NULL; + + urls = HeapAlloc(GetProcessHeap(), 0, size); + if(!urls) + return NULL; + + res = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void*)cert, 0, urls, &size, NULL, NULL, NULL); + if(res) + { + CERT_CONTEXT *new_cert; + HCERTSTORE new_store; + unsigned i; + + for(i=0; i < urls->cUrl; i++) + { + TRACE("Trying URL %s\n", debugstr_w(urls->rgwszUrl[i])); + + res = CryptRetrieveObjectByUrlW(urls->rgwszUrl[i], CONTEXT_OID_CERTIFICATE, + CRYPT_CACHE_ONLY_RETRIEVAL /* FIXME */, + 0, (void**)&new_cert, NULL, NULL, NULL, NULL); + if(!res) + { + TRACE("CryptRetrieveObjectByUrlW failed: %u\n", GetLastError()); + continue; + } + + /* FIXME: Use new_cert->hCertStore once cert ref count bug is fixed. */ + new_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + CertAddCertificateContextToStore(new_store, new_cert, CERT_STORE_ADD_NEW, NULL); + issuer = CertFindCertificateInStore(new_store, cert->dwCertEncodingType, 0, type, para, NULL); + CertFreeCertificateContext(new_cert); + CertCloseStore(new_store, 0); + if(issuer) + { + TRACE("Found downloaded issuer %p\n", issuer); + break; + } + } + } + + HeapFree(GetProcessHeap(), 0, urls); + return issuer; } static PCCERT_CONTEXT CRYPT_GetIssuer(const CertificateChainEngine *engine, diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index a89c63605bd..96eafa2c797 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -4005,6 +4005,7 @@ static void testGetCertChain(void) } ok(!chain->TrustStatus.dwErrorStatus, "chain->TrustStatus.dwErrorStatus = %x\n", chain->TrustStatus.dwErrorStatus); + todo_wine ok(chain->TrustStatus.dwInfoStatus == CERT_TRUST_HAS_PREFERRED_ISSUER, "chain->TrustStatus.dwInfoStatus = %x\n", chain->TrustStatus.dwInfoStatus); @@ -4016,6 +4017,7 @@ static void testGetCertChain(void) ok(simple_chain->cbSize == sizeof(*simple_chain), "simple_chain->cbSize = %u\n", simple_chain->cbSize); ok(!simple_chain->TrustStatus.dwErrorStatus, "simple_chain->TrustStatus.dwErrorStatus = %x\n", simple_chain->TrustStatus.dwErrorStatus); + todo_wine ok(simple_chain->TrustStatus.dwInfoStatus == CERT_TRUST_HAS_PREFERRED_ISSUER, "simple_chain->TrustStatus.dwInfoStatus = %x\n", simple_chain->TrustStatus.dwInfoStatus); ok(simple_chain->cElement == 3, "simple_chain->cElement = %u\n", simple_chain->cElement);