SECURITY_STATUS SSL_SOCKET :: Verify(PCCERT_CONTEXT px) { if (px == 0) return SEC_E_WRONG_PRINCIPAL; // Time int iRc = CertVerifyTimeValidity(NULL,px->pCertInfo); if (iRc != 0) return SEC_E_CERT_EXPIRED; // Chain CERT_CHAIN_PARA ChainPara = {0}; PCCERT_CHAIN_CONTEXT pChainContext = NULL; ChainPara.cbSize = sizeof(ChainPara); if (!CertGetCertificateChain(0,px,0,0,&ChainPara,0,0,&pChainContext)) return SEC_E_INVALID_TOKEN; /* ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData)); polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); polHttps.dwAuthType = AUTHTYPE_SERVER; polHttps.fdwChecks = dwCertFlags; polHttps.pwszServerName = pwszServerName; memset(&PolicyPara, 0, sizeof(PolicyPara)); PolicyPara.cbSize = sizeof(PolicyPara); PolicyPara.pvExtraPolicyPara = &polHttps; memset(&PolicyStatus, 0, sizeof(PolicyStatus)); PolicyStatus.cbSize = sizeof(PolicyStatus); if (!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) { Status = ::GetLastError(); SetLastError(Status); break; } */ PCCERT_CONTEXT j[2]; j[0] = px; CERT_REVOCATION_STATUS cs = {0}; cs.cbSize = sizeof(cs); SECURITY_STATUS ss = CertVerifyRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,CERT_CONTEXT_REVOCATION_TYPE, 1,(void**)j,0,0,&cs); if (pChainContext) CertFreeCertificateChain(pChainContext); return ss; }
static void test_verifyRevocation(void) { HMODULE hCryptNet = GetModuleHandleA("cryptnet.dll"); BOOL ret; CERT_REVOCATION_STATUS status = { sizeof(status), 0 }; PCCERT_CONTEXT certs[2]; CERT_REVOCATION_PARA revPara = { sizeof(revPara), 0 }; FILETIME time; pCertVerifyRevocation = (void *)GetProcAddress(hCryptNet, "CertDllVerifyRevocation"); if (!pCertVerifyRevocation) { win_skip("no CertDllVerifyRevocation\n"); return; } if (0) { /* Crash */ pCertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL); } SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status); ok(!ret && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(X509_ASN_ENCODING, 0, 0, NULL, 0, NULL, &status); ok(!ret && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 0, NULL, 0, NULL, &status); ok(!ret && GetLastError() == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", GetLastError()); certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert)); SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)certs, 0, NULL, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); CertFreeCertificateContext(certs[0]); certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING, rootWithKeySignAndCRLSign, sizeof(rootWithKeySignAndCRLSign)); certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING, revokedCert, sizeof(revokedCert)); /* The root cert itself can't be checked for revocation */ SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)certs, 0, NULL, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Neither can the end cert */ SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, NULL, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Both certs together can't, either (they're not CRLs) */ SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 2, (void **)certs, 0, NULL, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Now add a CRL to the hCrlStore */ revPara.hCrlStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); CertAddEncodedCRLToStore(revPara.hCrlStore, X509_ASN_ENCODING, rootSignedCRLWithBadAKI, sizeof(rootSignedCRLWithBadAKI), CERT_STORE_ADD_ALWAYS, NULL); SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 2, (void **)certs, 0, &revPara, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Specifying CERT_VERIFY_REV_CHAIN_FLAG doesn't change things either */ SetLastError(0xdeadbeef); ret = pCertVerifyRevocation(0, CERT_CONTEXT_REVOCATION_TYPE, 2, (void **)certs, CERT_VERIFY_REV_CHAIN_FLAG, &revPara, &status); ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK, "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Again, specifying the issuer cert: no change */ revPara.pIssuerCert = certs[0]; SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); /* Win2k thinks the cert is revoked, and it is, except the CRL contains a * bad authority key ID extension and can't be matched with the issuer * cert, hence the revocation status should be unknown. */ if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) { win_skip("CERT_CONTEXT_REVOCATION_TYPE unsupported, skipping\n"); return; } ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK || broken(GetLastError() == CRYPT_E_REVOKED /* Win2k */)), "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK || broken(status.dwError == CRYPT_E_REVOKED /* Win2k */), "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); /* Specifying the time to check: still no change */ SystemTimeToFileTime(&oct2007, &time); revPara.pftTimeToUse = &time; ret = pCertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret, "Expected failure\n"); ok(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK || broken(GetLastError() == CRYPT_E_REVOKED), /* W2K SP3/SP4 */ "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError()); ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK || broken(GetLastError() == CRYPT_E_REVOKED), /* W2K SP3/SP4 */ "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError); ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex); CertCloseStore(revPara.hCrlStore, 0); /* Test again with a valid CRL. This time, the cert should be revoked when * the time is after the validity period of the CRL, or considered * "revocation offline" when the checked time precedes the validity * period of the CRL. */ revPara.hCrlStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); ret = CertAddEncodedCRLToStore(revPara.hCrlStore, X509_ASN_ENCODING, rootSignedCRL, sizeof(rootSignedCRL), CERT_STORE_ADD_ALWAYS, NULL); ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError()); revPara.pftTimeToUse = NULL; SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOKED || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOKED, got %08x\n", GetLastError()); revPara.pftTimeToUse = &time; SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOKED || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOKED, got %08x\n", GetLastError()); SystemTimeToFileTime(&may2007, &time); SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOCATION_OFFLINE || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOCATION_OFFLINE, got %08x\n", GetLastError()); CertFreeCertificateContext(certs[1]); /* Test again with a valid CRL and an un-revoked cert. No matter the * time checked, it's reported as revocation offline. */ certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING, unRevokedCert, sizeof(unRevokedCert)); ok(certs[1] != NULL, "CertCreateCertificateContext failed: %08x\n", GetLastError()); revPara.pftTimeToUse = NULL; SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOCATION_OFFLINE || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOCATION_OFFLINE, got %08x\n", GetLastError()); revPara.pftTimeToUse = &time; SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOCATION_OFFLINE || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOCATION_OFFLINE, got %08x\n", GetLastError()); SystemTimeToFileTime(&may2007, &time); SetLastError(0xdeadbeef); ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certs[1], 0, &revPara, &status); ok(!ret && (GetLastError() == CRYPT_E_REVOCATION_OFFLINE || broken(GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* NT4 */)), "expected CRYPT_E_REVOCATION_OFFLINE, got %08x\n", GetLastError()); CertCloseStore(revPara.hCrlStore, 0); CertFreeCertificateContext(certs[1]); CertFreeCertificateContext(certs[0]); }