From 7c8371fe9fd2fdf2fa2512394713060716bcf75c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Thu, 31 Jul 2014 23:23:16 +0200 Subject: [PATCH] Implement store and load (with testcase) --- src/org/cacert/gigi/Certificate.java | 68 ++++++++++++++++++++-- tests/org/cacert/gigi/TestCertificate.java | 51 ++++++++++++++++ 2 files changed, 114 insertions(+), 5 deletions(-) diff --git a/src/org/cacert/gigi/Certificate.java b/src/org/cacert/gigi/Certificate.java index fca5c5a8..32ada17f 100644 --- a/src/org/cacert/gigi/Certificate.java +++ b/src/org/cacert/gigi/Certificate.java @@ -11,6 +11,10 @@ import java.security.cert.X509Certificate; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.util.Job; @@ -20,6 +24,41 @@ import org.cacert.gigi.util.Notary; public class Certificate { + public enum SANType { + EMAIL("email"), DNS("DNS"); + + private final String opensslName; + + private SANType(String opensslName) { + this.opensslName = opensslName; + } + + public String getOpensslName() { + return opensslName; + } + } + + public static class SubjectAlternateName { + + private SANType type; + + private String name; + + public SubjectAlternateName(SANType type, String name) { + this.type = type; + this.name = name; + } + + public String getName() { + return name; + } + + public SANType getType() { + return type; + } + + } + public enum CSRType { CSR, SPKAC; } @@ -42,12 +81,15 @@ public class Certificate { private CSRType csrType; - public Certificate(int ownerId, String dn, String md, String csr, CSRType csrType) { + private List sans; + + public Certificate(int ownerId, String dn, String md, String csr, CSRType csrType, SubjectAlternateName... sans) { this.ownerId = ownerId; this.dn = dn; this.md = md; this.csr = csr; this.csrType = csrType; + this.sans = Arrays.asList(sans); } private Certificate(String serial) { @@ -65,6 +107,16 @@ public class Certificate { crtName = rs.getString(5); ownerId = rs.getInt(6); this.serial = serial; + + PreparedStatement ps2 = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM `subjectAlternativeNames` WHERE certId=?"); + ps2.setInt(1, id); + ResultSet rs2 = ps2.executeQuery(); + sans = new LinkedList<>(); + while (rs2.next()) { + sans.add(new SubjectAlternateName(SANType.valueOf(rs2.getString("type").toUpperCase()), rs2.getString("contents"))); + } + rs2.close(); + rs.close(); } catch (SQLException e) { e.printStackTrace(); @@ -141,10 +193,12 @@ public class Certificate { // TODO draft to insert SANs PreparedStatement san = DatabaseConnection.getInstance().prepare("INSERT INTO subjectAlternativeNames SET certId=?, contents=?, type=?"); - san.setInt(1, id); - san.setString(2, "
"); - san.setString(3, "email"); - // san.execute(); + for (SubjectAlternateName subjectAlternateName : sans) { + san.setInt(1, id); + san.setString(2, subjectAlternateName.getName()); + san.setString(3, subjectAlternateName.getType().getOpensslName()); + san.execute(); + } PreparedStatement updater = DatabaseConnection.getInstance().prepare("UPDATE emailcerts SET csr_name=? WHERE id=?"); updater.setString(1, csrName); @@ -210,6 +264,10 @@ public class Certificate { return ownerId; } + public List getSans() { + return Collections.unmodifiableList(sans); + } + public static Certificate getBySerial(String serial) { // TODO caching? try { diff --git a/tests/org/cacert/gigi/TestCertificate.java b/tests/org/cacert/gigi/TestCertificate.java index 99dd03e8..c2f47473 100644 --- a/tests/org/cacert/gigi/TestCertificate.java +++ b/tests/org/cacert/gigi/TestCertificate.java @@ -6,9 +6,13 @@ import java.security.KeyPair; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.sql.SQLException; +import java.util.Collection; +import java.util.List; import org.cacert.gigi.Certificate.CSRType; import org.cacert.gigi.Certificate.CertificateStatus; +import org.cacert.gigi.Certificate.SANType; +import org.cacert.gigi.Certificate.SubjectAlternateName; import org.cacert.gigi.testUtils.ManagedTest; import org.junit.Test; @@ -27,6 +31,53 @@ public class TestCertificate extends ManagedTest { assertNotNull(login(pk, ce)); } + @Test + public void testSans() throws IOException, GeneralSecurityException, SQLException, InterruptedException { + KeyPair kp = generateKeypair(); + String key = generatePEMCSR(kp, "CN=testmail@example.com"); + Certificate c = new Certificate(1, "/CN=testmail@example.com", "sha256", key, CSRType.CSR, // + new SubjectAlternateName(SANType.EMAIL, "testmail@example.com"), new SubjectAlternateName(SANType.DNS, "testmail.example.com")); + + testFails(CertificateStatus.DRAFT, c); + c.issue().waitFor(60000); + X509Certificate cert = c.cert(); + Collection> sans = cert.getSubjectAlternativeNames(); + assertEquals(2, sans.size()); + boolean hadDNS = false; + boolean hadEmail = false; + for (List list : sans) { + assertEquals(2, list.size()); + Integer type = (Integer) list.get(0); + if (type == 1) { + hadEmail = true; + assertEquals("testmail@example.com", list.get(1)); + } else if (type == 2) { + hadDNS = true; + assertEquals("testmail.example.com", list.get(1)); + } else { + fail("Unknown type"); + } + } + assertTrue(hadDNS); + assertTrue(hadEmail); + + testFails(CertificateStatus.ISSUED, c); + + Certificate c2 = Certificate.getBySerial(c.getSerial()); + assertEquals(2, c2.getSans().size()); + assertEquals(c.getSans().get(0).getName(), c2.getSans().get(0).getName()); + assertEquals(c.getSans().get(0).getType(), c2.getSans().get(0).getType()); + assertEquals(c.getSans().get(1).getName(), c2.getSans().get(1).getName()); + assertEquals(c.getSans().get(1).getType(), c2.getSans().get(1).getType()); + + try { + c2.getSans().remove(0); + fail("the list should no be modifiable"); + } catch (UnsupportedOperationException e) { + // expected + } + } + @Test public void testCertLifeCycle() throws IOException, GeneralSecurityException, SQLException, InterruptedException { KeyPair kp = generateKeypair(); -- 2.39.2