/* * Copyright (c) 2011-2012 ICM Uniwersytet Warszawski All rights reserved. * See LICENCE.txt file for licensing information. */ package eu.emi.security.authn.x509.impl; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; import java.security.cert.CertPath; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; import static org.junit.Assert.*; import org.apache.commons.io.FileUtils; import org.junit.Test; import eu.emi.security.authn.x509.CrlCheckingMode; import eu.emi.security.authn.x509.OCSPCheckingMode; import eu.emi.security.authn.x509.OCSPParametes; import eu.emi.security.authn.x509.ProxySupport; import eu.emi.security.authn.x509.ValidationError; import eu.emi.security.authn.x509.StoreUpdateListener; import eu.emi.security.authn.x509.ValidationErrorListener; import eu.emi.security.authn.x509.ValidationResult; import eu.emi.security.authn.x509.impl.CertificateUtils.Encoding; /** * Testing of {@link InMemoryKeystoreCertChainValidator} and {@link KeystoreCertChainValidator} * is done here. The tests are in fact designed also to test all their parent classes * which provide a lot o shared functionality also for other validators. * * @author K. Benedyczak */ public class TestKSValidators { private boolean gotError; private int vError; public static File initDir() throws IOException { File dir = new File("target/test-tmp/truststores"); FileUtils.deleteDirectory(dir); dir.mkdirs(); return dir; } /** * Tests creation, basic validation */ @Test public void testKeystoreValidator() throws Exception { String path = "src/test/resources/truststores/truststore1.jks"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator( path, "the!njs".toCharArray(), "JKS", -1, new ValidatorParamsExt(RevocationParametersExt.IGNORE, ProxySupport.DENY)); X509Certificate[] toValidate = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client.cert"), Encoding.PEM); CertificateFactory factory = CertificateFactory.getInstance("X.509"); CertPath certPath = factory.generateCertPath(Arrays.asList(toValidate)); ValidationResult res = validator1.validate(toValidate); assertTrue(res.isValid()); ValidationResult res1 = validator1.validate(certPath); assertTrue(res1.isValid()); assertEquals(validator1.getTruststorePath(), path); validator1.dispose(); } /** * Tests creation, basic validation */ @Test public void testInMemoryKeystoreValidator() throws Exception { String path = "src/test/resources/truststores/truststore1.jks"; KeyStore normalKs = KeyStore.getInstance("JKS"); normalKs.load(new FileInputStream(path), "the!njs".toCharArray()); InMemoryKeystoreCertChainValidator validator1 = new InMemoryKeystoreCertChainValidator( normalKs, new ValidatorParamsExt(RevocationParametersExt.IGNORE, ProxySupport.DENY)); X509Certificate[] toValidate = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client.cert"), Encoding.PEM); CertificateFactory factory = CertificateFactory.getInstance("X.509"); CertPath certPath = factory.generateCertPath(Arrays.asList(toValidate)); ValidationResult res = validator1.validate(toValidate); assertTrue(res.isValid()); ValidationResult res1 = validator1.validate(certPath); assertTrue(res1.isValid()); KeyStore emptyKs = KeyStore.getInstance("JKS"); emptyKs.load(null); validator1.setTruststore(emptyKs); ValidationResult res2 = validator1.validate(toValidate); assertFalse(res2.isValid()); assertEquals(validator1.getTruststore(), emptyKs); validator1.dispose(); } /** * Tests creation, basic validation */ @Test public void testValidationListener() throws Exception { KeyStore emptyKs = KeyStore.getInstance("JKS"); emptyKs.load(null); InMemoryKeystoreCertChainValidator validator1 = new InMemoryKeystoreCertChainValidator( emptyKs, new ValidatorParamsExt(RevocationParametersExt.IGNORE, ProxySupport.DENY)); X509Certificate[] toValidate = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client.cert"), Encoding.PEM); ValidationErrorListener l1 = new ValidationErrorListener() { public boolean onValidationError(ValidationError error) { vError++; System.out.println("L1: " + error); return false; } }; ValidationErrorListener l2 = new ValidationErrorListener() { public boolean onValidationError(ValidationError error) { vError++; System.out.println("L2: " + error); return true; } }; validator1.addValidationListener(l1); vError = 0; ValidationResult res = validator1.validate(toValidate); assertFalse(res.isValid()); assertEquals(2, vError); validator1.addValidationListener(l2); vError = 0; ValidationResult res1 = validator1.validate(toValidate); assertTrue(res1.getErrors().toString(), res1.isValid()); assertEquals(4, vError); validator1.removeValidationListener(l1); vError = 0; ValidationResult res2 = validator1.validate(toValidate); assertTrue(res2.isValid()); assertEquals(2, vError); validator1.dispose(); } /** * Tests update and notifications */ @Test public void testKeystoreValidatorUpdate() throws Exception { File dir = initDir(); File ks = new File(dir, "work.jks"); FileUtils.copyFile(new File("src/test/resources/truststores/empty.jks"), ks); KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator( ks.getPath(), "the!njs".toCharArray(), "JKS", -1, new ValidatorParamsExt( RevocationParametersExt.IGNORE, ProxySupport.DENY)); X509Certificate[] toValidate = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client.cert"), Encoding.PEM); gotError = false; validator1.addUpdateListener(new StoreUpdateListener() { @Override public void loadingNotification(String location, String type, Severity level, Exception cause) { assertEquals(type, StoreUpdateListener.CA_CERT); System.out.println(location + " " + cause); gotError = true; } }); ValidationResult res = validator1.validate(toValidate); assertFalse(res.isValid()); validator1.setTruststoreUpdateInterval(200); FileUtils.copyFile(new File("src/test/resources/truststores/truststore1.jks"), ks); Thread.sleep(500); ValidationResult res2 = validator1.validate(toValidate); assertTrue(res2.isValid()); ks.delete(); Thread.sleep(500); assertTrue(gotError); validator1.dispose(); } /** * Tests update and notifications */ @Test public void testKeystoreValidatorCRL() throws Exception { String path = "src/test/resources/truststores/truststore1.jks"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator( path, "the!njs".toCharArray(), "JKS", -1, new ValidatorParamsExt( new RevocationParametersExt(CrlCheckingMode.REQUIRE, new CRLParameters(), new OCSPParametes(OCSPCheckingMode.IGNORE)), ProxySupport.DENY)); X509Certificate[] toValidate1 = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client.cert"), Encoding.PEM); X509Certificate[] toValidate2 = CertificateUtils.loadCertificateChain( new FileInputStream("src/test/resources/validator-certs/trusted_client_rev.cert"), Encoding.PEM); ValidationResult res = validator1.validate(toValidate1); assertFalse(res.isValid()); ValidationResult res2 = validator1.validate(toValidate2); assertFalse(res2.isValid()); File dir = initDir(); validator1.setCrls(Collections.singletonList(dir.getPath() + "/*.crl")); res = validator1.validate(toValidate1); assertFalse(res.isValid()); res2 = validator1.validate(toValidate2); assertFalse(res2.isValid()); validator1.setCRLUpdateInterval(200); FileUtils.copyFile(new File("src/test/resources/truststores/maincacrl.pem"), new File(dir, "crl1.crl")); Thread.sleep(500); res = validator1.validate(toValidate1); assertTrue(res.isValid()); res2 = validator1.validate(toValidate2); assertFalse(res2.isValid()); validator1.dispose(); } /** * Tests self-signed certificate which is not in the truststore. * This should fail. */ @Test public void testInvalidSelfSigned() throws Exception { String path = "src/test/resources/truststores/empty.jks"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator(path, "the!njs".toCharArray(), "JKS", -1); X509Certificate[] toValidate = new KeystoreCredential("src/test/resources/selfsigned.jks", "the!client".toCharArray(), "the!client".toCharArray(), "mykey", "JKS").getCertificateChain(); ValidationResult res = validator1.validate(toValidate); assertFalse(res.isValid()); } /** * Tests self-signed certificate which is one of trust anchors * Note: this should succeed as issuer (==the checked cert) is trusted */ @Test public void testSelfSignedTA() throws Exception { String path = "src/test/resources/selfsigned.jks"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator(path, "the!client".toCharArray(), "JKS", -1); X509Certificate[] toValidate = new KeystoreCredential(path, "the!client".toCharArray(), "the!client".toCharArray(), "mykey", "JKS").getCertificateChain(); ValidationResult res = validator1.validate(toValidate); assertTrue(res.isValid()); } /** * Tests non-self signed certificate which is one of trust anchors * Note: this should fail as *issuer is not trusted* */ @Test public void testNonSelfSignedTA() throws Exception { String path = "src/test/resources/nonselfsigned.jks"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator(path, "the!client".toCharArray(), "JKS", -1); X509Certificate[] toValidate = new KeystoreCredential(path, "the!client".toCharArray(), "the!client".toCharArray(), "httpclient", "JKS").getCertificateChain(); ValidationResult res = validator1.validate(toValidate); System.out.println(res); assertFalse(res.isValid()); } /** * Simple test using PKCS12 as truststore */ @Test public void testPkcs12Truststore() throws Exception { String path = "src/test/resources/truststore.p12"; KeystoreCertChainValidator validator1 = new KeystoreCertChainValidator(path, "the!njs".toCharArray(), "PKCS12", -1); assertEquals(1, validator1.getTrustedIssuers().length); } }