static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to) { DWORD root_count = 0; CERT_CHAIN_ENGINE_CONFIG chainEngineConfig = { sizeof(chainEngineConfig), 0 }; HCERTCHAINENGINE engine; TRACE("\n"); CertDuplicateStore(to); engine = CRYPT_CreateChainEngine(to, &chainEngineConfig); if (engine) { PCCERT_CONTEXT cert = NULL; do { cert = CertEnumCertificatesInStore(from, cert); if (cert) { CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } }; PCCERT_CHAIN_CONTEXT chain; BOOL ret = CertGetCertificateChain(engine, cert, NULL, from, &chainPara, 0, NULL, &chain); if (!ret) TRACE("rejecting %s: %s\n", get_cert_common_name(cert), "chain creation failed"); else { /* The only allowed error is CERT_TRUST_IS_UNTRUSTED_ROOT */ if (chain->TrustStatus.dwErrorStatus & ~CERT_TRUST_IS_UNTRUSTED_ROOT) TRACE("rejecting %s: %s\n", get_cert_common_name(cert), trust_status_to_str(chain->TrustStatus.dwErrorStatus & ~CERT_TRUST_IS_UNTRUSTED_ROOT)); else { DWORD i, j; for (i = 0; i < chain->cChain; i++) for (j = 0; j < chain->rgpChain[i]->cElement; j++) if (CertAddCertificateContextToStore(to, chain->rgpChain[i]->rgpElement[j]->pCertContext, CERT_STORE_ADD_NEW, NULL)) root_count++; } CertFreeCertificateChain(chain); } } } while (cert); CertFreeCertificateChainEngine(engine); } TRACE("Added %d root certificates\n", root_count); }
static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to) { DWORD root_count = 0; CERT_CHAIN_ENGINE_CONFIG chainEngineConfig = { sizeof(chainEngineConfig), 0 }; HCERTCHAINENGINE engine; TRACE("\n"); CertDuplicateStore(to); engine = CRYPT_CreateChainEngine(to, CERT_SYSTEM_STORE_CURRENT_USER, &chainEngineConfig); if (engine) { PCCERT_CONTEXT cert = NULL; do { cert = CertEnumCertificatesInStore(from, cert); if (cert) { CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } }; PCCERT_CHAIN_CONTEXT chain; BOOL ret; ret = CertGetCertificateChain(engine, cert, NULL, from, &chainPara, CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL, NULL, &chain); if (!ret) TRACE("rejecting %s: %s\n", get_cert_common_name(cert), "chain creation failed"); else { DWORD allowedErrors = CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_NOT_VALID_FOR_USAGE | CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_NOT_TIME_VALID; /* The certificate chain verification only allows certain * invalid CA certs if they're installed locally: CA * certs missing the key usage extension, and CA certs * missing the basic constraints extension. Of course * there's a chicken and egg problem: we have to accept * them here in order for them to be accepted later. * Expired, locally installed certs are also allowed here, * because we don't know (yet) what date will be checked * for an item signed by one of these certs. * Thus, accept certs with any of the allowed errors. */ if (chain->TrustStatus.dwErrorStatus & ~allowedErrors) TRACE("rejecting %s: %s\n", get_cert_common_name(cert), trust_status_to_str(chain->TrustStatus.dwErrorStatus & ~CERT_TRUST_IS_UNTRUSTED_ROOT)); else { DWORD i, j; for (i = 0; i < chain->cChain; i++) for (j = 0; j < chain->rgpChain[i]->cElement; j++) if (CertAddCertificateContextToStore(to, chain->rgpChain[i]->rgpElement[j]->pCertContext, CERT_STORE_ADD_NEW, NULL)) root_count++; } CertFreeCertificateChain(chain); } } } while (cert); CertFreeCertificateChainEngine(engine); } TRACE("Added %d root certificates\n", root_count); }