/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.util; import static org.candlepin.test.MatchesPattern.matchesPattern; import static org.junit.Assert.*; import org.candlepin.TestingModules; import org.candlepin.model.CertificateSerialCurator; import org.candlepin.pki.PKIReader; import org.candlepin.pki.PKIUtility; import com.google.inject.Guice; import com.google.inject.Injector; import org.apache.commons.io.IOUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.math.BigInteger; import java.net.URL; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.inject.Inject; /** * CrlFileUtilTest */ @RunWith(MockitoJUnitRunner.class) public class CrlFileUtilTest { private static final BouncyCastleProvider BC = new BouncyCastleProvider(); private CrlFileUtil cfu; @Inject private PKIReader pkiReader; @Inject private PKIUtility pkiUtility; @Mock private CertificateSerialCurator certSerialCurator; private File temp; private Set<BigInteger> initialEntry; @Before public void init() throws Exception { Injector injector = Guice.createInjector( new TestingModules.MockJpaModule(), new TestingModules.ServletEnvironmentModule(), new TestingModules.StandardTest() ); injector.injectMembers(this); this.cfu = new CrlFileUtil(this.pkiReader, this.pkiUtility, this.certSerialCurator); this.temp = File.createTempFile("cp_test_crl-", ".pem"); this.initialEntry = new HashSet<BigInteger>(); this.initialEntry.add(BigInteger.ONE); } @After public void tearDown() { temp.delete(); } @Test public void testStripCRLFile() throws Exception { URL pemUrl = CrlFileUtilTest.class.getClassLoader().getResource("crl.pem"); File pemFile = new File(pemUrl.getFile()); File strippedFile = cfu.stripCRLFile(pemFile); BufferedReader r = new BufferedReader(new FileReader(strippedFile)); String l; while ((l = r.readLine()) != null) { assertThat(l, matchesPattern("^[A-Za-z0-9+/=]*$")); } r.close(); } @Test public void testNewCRLIsUnmodified() throws Exception { this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, null, null); assertThat(new HashSet<BigInteger>(), new ContainsSerials(temp)); } @Test public void testNewCRLContainsRevokedSerials() throws Exception { Set<BigInteger> revoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("9711838712"), new BigInteger("1122402922"), new BigInteger("1032531028") )); this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, revoke, null); assertThat(revoke, new ContainsSerials(temp)); } @Test public void testNewCRLContainsRevokedSerialsButNotUnrevokedSerials() throws Exception { Set<BigInteger> revoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("3512918537"), new BigInteger("1631181032"), new BigInteger("9136184178") )); Set<BigInteger> unrevoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("1235821531"), new BigInteger("1631181032"), new BigInteger("3823318120") )); this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, revoke, unrevoke); revoke.removeAll(unrevoke); assertThat(revoke, new ContainsSerials(temp)); } @Test public void testExistingCRLIsUnmodified() throws Exception { Set<BigInteger> prime = new HashSet<BigInteger>(Arrays.asList( new BigInteger("1321822616"), new BigInteger("3216227128"), new BigInteger("2231351827") )); this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, prime, null); assertThat(prime, new ContainsSerials(temp)); this.cfu.updateCRLFile(temp, null, null); assertThat(prime, new ContainsSerials(temp)); } @Test public void testModifiedCRLContainsRevokedSerials() throws Exception { Set<BigInteger> prime = new HashSet<BigInteger>(Arrays.asList( new BigInteger("2358215310"), new BigInteger("7231352433"), new BigInteger("8233181205") )); Set<BigInteger> revoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("1132072301"), new BigInteger("7717218925"), new BigInteger("2196151762") )); this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, prime, null); assertThat(prime, new ContainsSerials(temp)); this.cfu.updateCRLFile(temp, revoke, null); revoke.addAll(prime); assertThat(revoke, new ContainsSerials(temp)); } @Test public void testModifiedCRLContainsRevokedSerialsButNotUnrevokedSerials() throws Exception { Set<BigInteger> prime = new HashSet<BigInteger>(Arrays.asList( new BigInteger("4420205175"), new BigInteger("2475450918"), new BigInteger("1501013497") )); Set<BigInteger> revoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("5219615176"), new BigInteger("2239819513"), new BigInteger("21822616321") )); Set<BigInteger> unrevoke = new HashSet<BigInteger>(Arrays.asList( new BigInteger("2239819513"), new BigInteger("6227128223"), new BigInteger("4420205175") )); this.cfu.initializeCRLFile(temp, initialEntry); this.cfu.updateCRLFile(temp, prime, null); assertThat(prime, new ContainsSerials(temp)); this.cfu.updateCRLFile(temp, revoke, unrevoke); revoke.addAll(prime); revoke.removeAll(unrevoke); assertThat(revoke, new ContainsSerials(temp)); assertFalse(new ContainsSerials(temp).matchesSafely(unrevoke)); } public class ContainsSerials extends TypeSafeMatcher<Set<BigInteger>> { private Set<BigInteger> serials; public ContainsSerials(File f) { BufferedInputStream in = null; X509CRL x509crl = null; try { in = new BufferedInputStream(new FileInputStream(f)); x509crl = (X509CRL) CertificateFactory.getInstance("X.509").generateCRL(in); x509crl.verify(pkiReader.getCACert().getPublicKey(), BC.PROVIDER_NAME); Set<BigInteger> s = new HashSet<BigInteger>(); for (X509CRLEntry entry : x509crl.getRevokedCertificates()) { s.add(entry.getSerialNumber()); } this.serials = s; } catch (Exception e) { throw new RuntimeException(e); } finally { IOUtils.closeQuietly(in); } } public ContainsSerials(Set<BigInteger> serials) { this.serials = serials; } @Override public boolean matchesSafely(Set<BigInteger> items) { return serials.containsAll(items); } @Override public void describeTo(Description description) { description.appendText("Found serials ") .appendValue(serials); } @Override public void describeMismatchSafely(Set<BigInteger> items, Description mismatchDescription) { mismatchDescription.appendText("are not a superset of ").appendValue(items); } } }