]> WPIA git - gigi.git/commitdiff
chg: use certificate attachment to store CRT and CSR files
authorFelix Dörre <felix@dogcraft.de>
Sat, 4 Nov 2017 23:04:39 +0000 (00:04 +0100)
committerFelix Dörre <felix@dogcraft.de>
Tue, 7 Nov 2017 14:04:27 +0000 (15:04 +0100)
Note: requires an updated version of cassiopeia

Change-Id: I6d71e70ec84a95a0323ab945e69bc6e29c332a81

15 files changed:
src/club/wpia/gigi/database/DatabaseConnection.java
src/club/wpia/gigi/database/tableStructure.sql
src/club/wpia/gigi/dbObjects/Certificate.java
src/club/wpia/gigi/output/CertificateIterable.java
src/club/wpia/gigi/pages/account/certs/Certificates.java
src/club/wpia/gigi/pages/admin/support/SupportRevokeCertificatesForm.java
src/club/wpia/gigi/util/CertExporter.java
src/club/wpia/gigi/util/KeyStorage.java [deleted file]
tests/club/wpia/gigi/TestSeparateSessionScope.java
tests/club/wpia/gigi/api/ImportCATSResult.java
tests/club/wpia/gigi/dbObjects/TestCertificate.java
tests/club/wpia/gigi/pages/account/TestCertificateAdd.java
tests/club/wpia/gigi/pages/main/KeyCompromiseTest.java
tests/club/wpia/gigi/pages/main/KeyCompromiseTestMessage.java
util-testing/club/wpia/gigi/util/SimpleSigner.java

index 2a3691bfbd6639680d2da62a5b5c7ad46d6f1856..c8bb43997966e6bbba604983dbfb7905e6d2a67c 100644 (file)
@@ -1,8 +1,12 @@
 package club.wpia.gigi.database;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.io.Reader;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
@@ -19,9 +23,64 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import club.wpia.gigi.database.SQLFileManager.ImportType;
+import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.AttachmentType;
 
 public class DatabaseConnection {
 
+    public static final class Upgrade32 {
+
+        public static void execute() throws IOException {
+            // "csr_name" varchar(255) NOT NULL DEFAULT '',
+            // "csr_type" "csrType" NOT NULL,
+            // "crt_name" varchar(255) NOT NULL DEFAULT '',
+            try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `id`, `csr_name`, `crt_name` FROM `certs`")) {
+                GigiResultSet rs = ps.executeQuery();
+                while (rs.next()) {
+                    // Load CSR
+                    load(rs.getInt(1), rs.getString(2), Certificate.AttachmentType.CSR);
+                    load(rs.getInt(1), rs.getString(3), Certificate.AttachmentType.CRT);
+                }
+            }
+        }
+
+        private static void load(int id, String file, AttachmentType type) throws IOException {
+            if ("".equals(file) && type == AttachmentType.CRT) {
+                // this is ok, certificates might be in DRAFT state
+                return;
+            }
+            File f = new File(file);
+            System.out.println("Upgrade 32: loading " + f);
+            if (f.exists()) {
+                StringBuilder sb = new StringBuilder();
+                try (Reader r = new InputStreamReader(new FileInputStream(f), "UTF-8")) {
+                    int len;
+                    char[] buf = new char[4096];
+                    while ((len = r.read(buf)) > 0) {
+                        sb.append(buf, 0, len);
+                    }
+                }
+                String csrS = sb.toString();
+                try (GigiPreparedStatement ps1 = new GigiPreparedStatement("INSERT INTO `certificateAttachment` SET `certid`=?, `type`=?::`certificateAttachmentType`, `content`=?")) {
+                    ps1.setInt(1, id);
+                    ps1.setEnum(2, type);
+                    ps1.setString(3, csrS);
+                    ps1.execute();
+                }
+                f.delete();
+            } else {
+                try (GigiPreparedStatement ps1 = new GigiPreparedStatement("SELECT 1 FROM `certificateAttachment` WHERE `certid`=? AND `type`=?::`certificateAttachmentType`")) {
+                    ps1.setInt(1, id);
+                    ps1.setEnum(2, type);
+                    GigiResultSet rs1 = ps1.executeQuery();
+                    if ( !rs1.next()) {
+                        throw new Error("file " + f + " not found, and attachment is missing as well.");
+                    }
+                }
+            }
+        }
+    }
+
     public static class Link implements AutoCloseable {
 
         private DatabaseConnection target;
@@ -122,7 +181,7 @@ public class DatabaseConnection {
 
     }
 
-    public static final int CURRENT_SCHEMA_VERSION = 31;
+    public static final int CURRENT_SCHEMA_VERSION = 32;
 
     public static final int CONNECTION_TIMEOUT = 24 * 60 * 60;
 
@@ -278,10 +337,10 @@ public class DatabaseConnection {
                 while (version < CURRENT_SCHEMA_VERSION) {
                     addUpgradeScript(Integer.toString(version), s);
                     version++;
+                    System.out.println("UPGRADING Database to version " + version);
+                    s.addBatch("UPDATE \"schemeVersion\" SET version='" + version + "'");
+                    s.executeBatch();
                 }
-                s.addBatch("UPDATE \"schemeVersion\" SET version='" + version + "'");
-                System.out.println("UPGRADING Database to version " + version);
-                s.executeBatch();
                 System.out.println("done.");
             }
         } catch (SQLException e) {
@@ -292,11 +351,15 @@ public class DatabaseConnection {
     }
 
     private static void addUpgradeScript(String version, Statement s) throws Error, IOException, SQLException {
-        try (InputStream resourceAsStream = DatabaseConnection.class.getResourceAsStream("upgrade/from_" + version + ".sql")) {
-            if (resourceAsStream == null) {
-                throw new Error("Upgrade script from version " + version + " was not found.");
+        if (version.equals("31")) {
+            Upgrade32.execute();
+        } else {
+            try (InputStream resourceAsStream = DatabaseConnection.class.getResourceAsStream("upgrade/from_" + version + ".sql")) {
+                if (resourceAsStream == null) {
+                    throw new Error("Upgrade script from version " + version + " was not found.");
+                }
+                SQLFileManager.addFile(s, resourceAsStream, ImportType.PRODUCTION);
             }
-            SQLFileManager.addFile(s, resourceAsStream, ImportType.PRODUCTION);
         }
     }
 
index 0a96801cc5eee16082a22dcfc1631f334db10487..41da72a3ed9b5565268d8dcc90a74dcced199373 100644 (file)
@@ -381,7 +381,7 @@ CREATE TABLE "schemeVersion" (
   "version" smallint NOT NULL,
   PRIMARY KEY ("version")
 );
-INSERT INTO "schemeVersion" (version)  VALUES(31);
+INSERT INTO "schemeVersion" (version)  VALUES(32);
 
 DROP TABLE IF EXISTS `passwordResetTickets`;
 CREATE TABLE `passwordResetTickets` (
index d5679029c474d51b819049fe0e4083e419375ac3..51bf41be136687041cdca9b3e511958a9dc01682 100644 (file)
@@ -1,10 +1,7 @@
 package club.wpia.gigi.dbObjects;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.security.GeneralSecurityException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
@@ -24,7 +21,7 @@ import club.wpia.gigi.database.GigiResultSet;
 import club.wpia.gigi.output.template.Outputable;
 import club.wpia.gigi.output.template.TranslateCommand;
 import club.wpia.gigi.pages.account.certs.CertificateRequest;
-import club.wpia.gigi.util.KeyStorage;
+import club.wpia.gigi.util.PEM;
 
 public class Certificate implements IdCachable {
 
@@ -151,10 +148,6 @@ public class Certificate implements IdCachable {
 
     private Digest md;
 
-    private String csrName;
-
-    private String crtName;
-
     private String csr = null;
 
     private CSRType csrType;
@@ -213,7 +206,7 @@ public class Certificate implements IdCachable {
         this.sans = Arrays.asList(sans);
         synchronized (Certificate.class) {
 
-            try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, crt_name='', memid=?, profile=?")) {
+            try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?")) {
                 inserter.setString(1, md.toString().toLowerCase());
                 inserter.setString(2, this.csrType.toString());
                 inserter.setInt(3, owner.getId());
@@ -239,17 +232,7 @@ public class Certificate implements IdCachable {
                     insertAVA.execute();
                 }
             }
-            File csrFile = KeyStorage.locateCsr(id);
-            csrName = csrFile.getPath();
-            try (FileOutputStream fos = new FileOutputStream(csrFile)) {
-                fos.write(this.csr.getBytes("UTF-8"));
-            }
-            try (GigiPreparedStatement updater = new GigiPreparedStatement("UPDATE `certs` SET `csr_name`=? WHERE id=?")) {
-                updater.setString(1, csrName);
-                updater.setInt(2, id);
-                updater.execute();
-            }
-
+            addAttachment(AttachmentType.CSR, csr);
             cache.put(this);
         }
     }
@@ -258,8 +241,6 @@ public class Certificate implements IdCachable {
         this.id = rs.getInt("id");
         dnString = rs.getString("subject");
         md = Digest.valueOf(rs.getString("md").toUpperCase());
-        csrName = rs.getString("csr_name");
-        crtName = rs.getString("crt_name");
         owner = CertificateOwner.getById(rs.getInt("memid"));
         profile = CertificateProfile.getById(rs.getInt("profile"));
         this.serial = rs.getString("serial");
@@ -311,20 +292,19 @@ public class Certificate implements IdCachable {
     }
 
     public synchronized CertificateStatus getStatus() {
-        try (GigiPreparedStatement searcher = new GigiPreparedStatement("SELECT crt_name, created, revoked, serial, caid FROM certs WHERE id=?")) {
+        try (GigiPreparedStatement searcher = new GigiPreparedStatement("SELECT created, revoked, serial, caid FROM certs WHERE id=?")) {
             searcher.setInt(1, id);
             GigiResultSet rs = searcher.executeQuery();
             if ( !rs.next()) {
                 throw new IllegalStateException("Certificate not in Database");
             }
 
-            crtName = rs.getString(1);
-            serial = rs.getString(4);
-            if (rs.getTimestamp(2) == null) {
+            serial = rs.getString(3);
+            if (rs.getTimestamp(1) == null) {
                 return CertificateStatus.DRAFT;
             }
             ca = CACertificate.getById(rs.getInt("caid"));
-            if (rs.getTimestamp(2) != null && rs.getTimestamp(3) == null) {
+            if (rs.getTimestamp(1) != null && rs.getTimestamp(2) == null) {
                 return CertificateStatus.ISSUED;
             }
             return CertificateStatus.REVOKED;
@@ -376,23 +356,16 @@ public class Certificate implements IdCachable {
         return ca;
     }
 
-    public X509Certificate cert() throws IOException, GeneralSecurityException {
+    public X509Certificate cert() throws IOException, GeneralSecurityException, GigiApiException {
         CertificateStatus status = getStatus();
         if (status != CertificateStatus.REVOKED && status != CertificateStatus.ISSUED) {
             throw new IllegalStateException(status + " is not wanted here.");
         }
-        InputStream is = null;
-        X509Certificate crt = null;
-        try {
-            is = new FileInputStream(crtName);
+        String crtS = getAttachment(AttachmentType.CRT);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(PEM.decode("CERTIFICATE", crtS))) {
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
-            crt = (X509Certificate) cf.generateCertificate(is);
-        } finally {
-            if (is != null) {
-                is.close();
-            }
+            return (X509Certificate) cf.generateCertificate(bais);
         }
-        return crt;
     }
 
     public Certificate renew() {
@@ -435,7 +408,7 @@ public class Certificate implements IdCachable {
         if (serial == null || "".equals(serial)) {
             return null;
         }
-        try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`, `csr_name`, `crt_name`,`memid`, `profile`, `certs`.`serial` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) {
+        try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`,`memid`, `profile`, `certs`.`serial` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) {
             ps.setString(1, serial);
             GigiResultSet rs = ps.executeQuery();
             if ( !rs.next()) {
@@ -461,7 +434,7 @@ public class Certificate implements IdCachable {
         }
 
         try {
-            try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, csr_name, crt_name,memid, profile, certs.serial FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id")) {
+            try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id")) {
                 ps.setInt(1, id);
                 GigiResultSet rs = ps.executeQuery();
                 if ( !rs.next()) {
index 15abbf0a5074b3445f26576c33fd4f3b53e14e56..cb4b35235d7d0dad931f5a9d74e327f5d515e132 100644 (file)
@@ -6,6 +6,7 @@ import java.security.cert.X509Certificate;
 import java.util.Date;
 import java.util.Map;
 
+import club.wpia.gigi.GigiApiException;
 import club.wpia.gigi.dbObjects.Certificate;
 import club.wpia.gigi.dbObjects.Certificate.CertificateStatus;
 import club.wpia.gigi.localisation.Language;
@@ -68,6 +69,8 @@ public class CertificateIterable implements IterableDataset {
             if (st == CertificateStatus.REVOKED) {
                 vars.put("revoked", c.getRevocationDate());
             }
+        } catch (GigiApiException e) {
+            e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (GeneralSecurityException e) {
index 5abf20e52a75035b4a88d31fed00b5611cc0cac5..78d8a09f1fa696dfb9d9b1623a92926376e6ef7c 100644 (file)
@@ -13,6 +13,7 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import club.wpia.gigi.GigiApiException;
 import club.wpia.gigi.dbObjects.Certificate;
 import club.wpia.gigi.dbObjects.Certificate.CertificateStatus;
 import club.wpia.gigi.dbObjects.Certificate.SubjectAlternateName;
@@ -93,6 +94,9 @@ public class Certificates extends Page implements HandlesMixedRequest {
         } catch (IllegalArgumentException e) {
             resp.sendError(404);
             return true;
+        } catch (GigiApiException e) {
+            resp.sendError(404);
+            return true;
         } catch (GeneralSecurityException e) {
             resp.sendError(404);
             return true;
@@ -226,6 +230,8 @@ public class Certificates extends Page implements HandlesMixedRequest {
                 vars.put("login", c.isLoginEnabled());
             } catch (GeneralSecurityException e) {
                 e.printStackTrace();
+            } catch (GigiApiException e) {
+                e.format(out, l);
             }
             certDisplay.output(out, getLanguage(req), vars);
 
index f3d725c110bb59c23ae03c1dc7ea831579bb98db..bf4c00908991dd003c49630865dafdef521c79d4 100644 (file)
@@ -10,9 +10,9 @@ import javax.servlet.http.HttpServletRequest;
 
 import club.wpia.gigi.GigiApiException;
 import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.CertificateStatus;
 import club.wpia.gigi.dbObjects.CertificateProfile;
 import club.wpia.gigi.dbObjects.SupportedUser;
-import club.wpia.gigi.dbObjects.Certificate.CertificateStatus;
 import club.wpia.gigi.localisation.Language;
 import club.wpia.gigi.output.template.Form;
 import club.wpia.gigi.output.template.IterableDataset;
@@ -71,7 +71,7 @@ public class SupportRevokeCertificatesForm extends Form {
                         certs[i].cert().checkValidity();
                         lastExpire = Math.max(lastExpire, certs[i].cert().getNotAfter().getTime());
                         valid++;
-                    } catch (GeneralSecurityException | IOException e) {
+                    } catch (GeneralSecurityException | IOException | GigiApiException e) {
                         continue;
                     }
                 }
index cfe97ef2c847430711289e752837ddc41ca5f720..06102fc006ba482fe31ae80074552c3829875e36 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Set;
 
 import javax.servlet.ServletOutputStream;
 
+import club.wpia.gigi.GigiApiException;
 import club.wpia.gigi.dbObjects.CACertificate;
 import club.wpia.gigi.dbObjects.Certificate;
 import sun.security.pkcs.ContentInfo;
@@ -29,7 +30,7 @@ public class CertExporter {
 
     private CertExporter() {}
 
-    public static void writeCertCrt(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor, boolean includeLeaf) throws IOException, GeneralSecurityException {
+    public static void writeCertCrt(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor, boolean includeLeaf) throws IOException, GeneralSecurityException, GigiApiException {
         X509Certificate cert = c.cert();
         if (includeLeaf) {
             out.println(PEM.encode("CERTIFICATE", cert.getEncoded()));
@@ -46,7 +47,7 @@ public class CertExporter {
         }
     }
 
-    public static void writeCertCer(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor) throws IOException, GeneralSecurityException {
+    public static void writeCertCer(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor) throws IOException, GeneralSecurityException, GigiApiException {
         X509Certificate cert = c.cert();
         if (doChain) {
             PKCS7 p7 = toP7Chain(c);
@@ -56,7 +57,7 @@ public class CertExporter {
         }
     }
 
-    private static PKCS7 toP7Chain(Certificate c) throws IOException, GeneralSecurityException {
+    private static PKCS7 toP7Chain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
         LinkedList<X509Certificate> ll = getChain(c);
         PKCS7 p7 = new PKCS7(new AlgorithmId[0], new ContentInfo(ContentInfo.DATA_OID, null), ll.toArray(new X509Certificate[ll.size()]), new SignerInfo[0]) {
 
@@ -151,7 +152,7 @@ public class CertExporter {
         return p7;
     }
 
-    private static LinkedList<X509Certificate> getChain(Certificate c) throws IOException, GeneralSecurityException {
+    private static LinkedList<X509Certificate> getChain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
         LinkedList<X509Certificate> ll = new LinkedList<>();
         ll.add(c.cert());
         CACertificate ca = c.getParent();
diff --git a/src/club/wpia/gigi/util/KeyStorage.java b/src/club/wpia/gigi/util/KeyStorage.java
deleted file mode 100644 (file)
index b87df9a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package club.wpia.gigi.util;
-
-import java.io.File;
-
-public class KeyStorage {
-
-    private static final File csr = new File("keys/csr");
-
-    private static final File crt = new File("keys/crt");
-
-    public static File locateCrt(int id) {
-        File parent = new File(crt, (id / 1000) + "");
-        if ( !parent.exists() && !parent.mkdirs()) {
-            throw new Error("cert folder could not be created");
-        }
-        return new File(parent, id + ".crt");
-    }
-
-    public static File locateCsr(int id) {
-        File parent = new File(csr, (id / 1000) + "");
-        if ( !parent.exists() && !parent.mkdirs()) {
-            throw new Error("csr folder could not be created");
-        }
-        return new File(parent, id + ".csr");
-    }
-}
index e3ad9286c14ad10c1c2796f05e78fcc5a181487f..02635bef3d9a8ec890806ce9e62bd574ec06c869 100644 (file)
@@ -6,9 +6,7 @@ import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
 import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 import java.sql.SQLException;
@@ -69,7 +67,7 @@ public class TestSeparateSessionScope extends ManagedTest {
 
     }
 
-    private void checkCertLogin(Certificate c2, final PrivateKey pk, String scookie, int expected) throws IOException, NoSuchAlgorithmException, KeyManagementException, GeneralSecurityException {
+    private void checkCertLogin(Certificate c2, final PrivateKey pk, String scookie, int expected) throws IOException, GeneralSecurityException, GigiApiException {
         URL u = new URL("https://" + getSecureServerName() + SECURE_REFERENCE);
         HttpURLConnection huc = (HttpURLConnection) u.openConnection();
         authenticateClientCert(pk, c2.cert(), huc);
index 18f1ae90538626f1b953c4b7ed56c40a8f21d9ef..c345257a67ea15155d6e05df169da64af9e21d5c 100644 (file)
@@ -14,15 +14,13 @@ import java.security.NoSuchAlgorithmException;
 import org.junit.Test;
 
 import club.wpia.gigi.GigiApiException;
-import club.wpia.gigi.api.CATSImport;
-import club.wpia.gigi.api.CATSResolve;
+import club.wpia.gigi.dbObjects.CATS.CATSType;
 import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.CSRType;
+import club.wpia.gigi.dbObjects.Certificate.SANType;
 import club.wpia.gigi.dbObjects.CertificateProfile;
 import club.wpia.gigi.dbObjects.Digest;
 import club.wpia.gigi.dbObjects.User;
-import club.wpia.gigi.dbObjects.CATS.CATSType;
-import club.wpia.gigi.dbObjects.Certificate.CSRType;
-import club.wpia.gigi.dbObjects.Certificate.SANType;
 import club.wpia.gigi.testUtils.IOUtils;
 import club.wpia.gigi.testUtils.RestrictedApiTest;
 import club.wpia.gigi.util.ServerConstants;
@@ -89,7 +87,7 @@ public class ImportCATSResult extends RestrictedApiTest {
         return doApi(CATSImport.PATH, query);
     }
 
-    private String apiLookup(Certificate target) throws IOException, GeneralSecurityException {
+    private String apiLookup(Certificate target) throws IOException, GeneralSecurityException, GigiApiException {
         HttpURLConnection connection = doApi(CATSResolve.PATH, "serial=" + target.cert().getSerialNumber().toString(16).toLowerCase());
         if (connection.getResponseCode() != 200) {
             throw new Error(connection.getResponseMessage());
index 694bc491c8f514550664419d54528cecf9273b72..fe35729aed4a8e3c98c8455a5c7844977f39f618 100644 (file)
@@ -38,10 +38,7 @@ public class TestCertificate extends ClientBusinessTest {
         String key = generatePEMCSR(kp, "CN=testmail@example.com");
         Certificate c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key, CSRType.CSR, getClientProfile());
         assertNull(c.getAttachment(AttachmentType.CRT));
-        assertNull(c.getAttachment(AttachmentType.CSR));
-        c.addAttachment(AttachmentType.CSR, "a");
-        assertNull(c.getAttachment(AttachmentType.CRT));
-        assertEquals("a", c.getAttachment(AttachmentType.CSR));
+        assertEquals(key, c.getAttachment(AttachmentType.CSR));
         try {
             c.addAttachment(AttachmentType.CSR, "different CSR");
             fail("double add attachment must fail");
@@ -49,7 +46,7 @@ public class TestCertificate extends ClientBusinessTest {
             // expected
         }
         assertNull(c.getAttachment(AttachmentType.CRT));
-        assertEquals("a", c.getAttachment(AttachmentType.CSR));
+        assertEquals(key, c.getAttachment(AttachmentType.CSR));
         try {
             c.addAttachment(AttachmentType.CRT, null);
             fail("attachment must not be null");
@@ -57,9 +54,9 @@ public class TestCertificate extends ClientBusinessTest {
             // expected
         }
         assertNull(c.getAttachment(AttachmentType.CRT));
-        assertEquals("a", c.getAttachment(AttachmentType.CSR));
+        assertEquals(key, c.getAttachment(AttachmentType.CSR));
         c.addAttachment(AttachmentType.CRT, "b");
-        assertEquals("a", c.getAttachment(AttachmentType.CSR));
+        assertEquals(key, c.getAttachment(AttachmentType.CSR));
         assertEquals("b", c.getAttachment(AttachmentType.CRT));
         try {
             c.addAttachment(AttachmentType.CRT, "different CRT");
@@ -67,7 +64,7 @@ public class TestCertificate extends ClientBusinessTest {
         } catch (GigiApiException e) {
             // expected
         }
-        assertEquals("a", c.getAttachment(AttachmentType.CSR));
+        assertEquals(key, c.getAttachment(AttachmentType.CSR));
         assertEquals("b", c.getAttachment(AttachmentType.CRT));
     }
 }
index 854cca7a54ba16daabdf64b5c730c4e63da50471..986442b13c3f854c9a17099fbdbd832d276a3aa8 100644 (file)
@@ -82,7 +82,6 @@ public class TestCertificateAdd extends ClientTest {
         }, new DNSName(uniq + ".tld"));
 
         String pem = generatePEMCSR(kp, "CN=a." + uniq + ".tld", atts);
-
         String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8"));
         assertArrayEquals(new String[] {
                 "server", CertificateRequest.DEFAULT_CN, "dns:a." + uniq + ".tld\ndns:" + uniq + ".tld\n", Digest.SHA512.toString()
index 46ffe0dd13a9024ff6f5fcc86d0bbb753661e168..49ffd80128d268e648068dd078bcd4796a3daeac 100644 (file)
@@ -127,7 +127,7 @@ public class KeyCompromiseTest extends ClientTest {
         };
     }
 
-    private String getQuery(String data) {
+    private String getQuery(String data) throws GigiApiException {
         String cData = null;
         {
             Pattern challenge = Pattern.compile(" data-challenge=\"([a-zA-Z0-9]+)\"");
index 7dfb4155ffbbdef0fd1683644b94576914c5bac2..0cc355d4ae4743367811e1c891f617e119f65efe 100644 (file)
@@ -105,7 +105,7 @@ public class KeyCompromiseTestMessage extends ClientTest {
         assertEquals(CertificateStatus.ISSUED, cert.getStatus());
     }
 
-    private TestMail reportCompromiseAndCheck(String params) throws IOException, UnsupportedEncodingException, CertificateEncodingException, GeneralSecurityException {
+    private TestMail reportCompromiseAndCheck(String params) throws IOException, UnsupportedEncodingException, CertificateEncodingException, GeneralSecurityException, GigiApiException {
         HttpURLConnection huc = reportCompromise(params);
         assertThat(IOUtils.readURL(huc), hasNoError());
         TestMail rc = getMailReceiver().receive(email);
@@ -115,7 +115,7 @@ public class KeyCompromiseTestMessage extends ClientTest {
         return rc;
     }
 
-    private HttpURLConnection reportCompromise(String params) throws IOException, UnsupportedEncodingException, CertificateEncodingException, GeneralSecurityException {
+    private HttpURLConnection reportCompromise(String params) throws IOException, UnsupportedEncodingException, CertificateEncodingException, GeneralSecurityException, GigiApiException {
         if ( !params.isEmpty() && !params.startsWith("&")) {
             params = "&" + params;
         }
index 45d86a74bf6154750ab0bfdd1900e9be9868e339..b1c31509e88926e38f2dd49752e4852bd92d48a4 100644 (file)
@@ -1,5 +1,6 @@
 package club.wpia.gigi.util;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -39,11 +40,14 @@ import java.util.TimeZone;
 
 import javax.security.auth.x500.X500Principal;
 
+import club.wpia.gigi.GigiApiException;
 import club.wpia.gigi.crypto.SPKAC;
 import club.wpia.gigi.database.DatabaseConnection;
 import club.wpia.gigi.database.DatabaseConnection.Link;
 import club.wpia.gigi.database.GigiPreparedStatement;
 import club.wpia.gigi.database.GigiResultSet;
+import club.wpia.gigi.dbObjects.Certificate;
+import club.wpia.gigi.dbObjects.Certificate.AttachmentType;
 import club.wpia.gigi.dbObjects.Certificate.CSRType;
 import club.wpia.gigi.dbObjects.Certificate.SANType;
 import club.wpia.gigi.dbObjects.Certificate.SubjectAlternateName;
@@ -125,7 +129,7 @@ public class SimpleSigner {
             @Override
             public void run() {
                 try (Link l = DatabaseConnection.newLink(false)) {
-                    readyCerts = new GigiPreparedStatement("SELECT certs.id AS id, certs.csr_name, jobs.id AS jobid, csr_type, md, `executeFrom`, `executeTo`, profile FROM jobs " + //
+                    readyCerts = new GigiPreparedStatement("SELECT certs.id AS id, jobs.id AS jobid, csr_type, md, `executeFrom`, `executeTo`, profile FROM jobs " + //
                             "INNER JOIN certs ON certs.id=jobs.`targetId` " + //
                             "INNER JOIN profiles ON profiles.id=certs.profile " + //
                             "WHERE jobs.state='open' " + //
@@ -134,10 +138,10 @@ public class SimpleSigner {
                     getSANSs = new GigiPreparedStatement("SELECT contents, type FROM `subjectAlternativeNames` " + //
                             "WHERE `certId`=?");
 
-                    updateMail = new GigiPreparedStatement("UPDATE certs SET crt_name=?," + " created=NOW(), serial=?, caid=?, expire=? WHERE id=?");
+                    updateMail = new GigiPreparedStatement("UPDATE certs SET created=NOW(), serial=?, caid=?, expire=? WHERE id=?");
                     warnMail = new GigiPreparedStatement("UPDATE jobs SET warning=warning+1, state=CASE WHEN warning<3 THEN 'open'::`jobState` ELSE 'error'::`jobState` END WHERE id=?");
 
-                    revoke = new GigiPreparedStatement("SELECT certs.id, certs.csr_name,jobs.id FROM jobs INNER JOIN certs ON jobs.`targetId`=certs.id" + " WHERE jobs.state='open' AND task='revoke'");
+                    revoke = new GigiPreparedStatement("SELECT certs.id, jobs.id FROM jobs INNER JOIN certs ON jobs.`targetId`=certs.id" + " WHERE jobs.state='open' AND task='revoke'");
                     revokeCompleted = new GigiPreparedStatement("UPDATE `certs` SET revoked=NOW() WHERE id=?");
 
                     finishJob = new GigiPreparedStatement("UPDATE jobs SET state='done' WHERE id=?");
@@ -200,7 +204,7 @@ public class SimpleSigner {
             System.out.println("Revoke faked: " + id);
             revokeCompleted.setInt(1, id);
             revokeCompleted.executeUpdate();
-            finishJob.setInt(1, rs.getInt(3));
+            finishJob.setInt(1, rs.getInt(2));
             finishJob.executeUpdate();
         }
         if (worked) {
@@ -240,13 +244,12 @@ public class SimpleSigner {
         Calendar c = Calendar.getInstance();
         c.setTimeZone(TimeZone.getTimeZone("UTC"));
         while (rs.next()) {
-            String csrname = rs.getString("csr_name");
             int id = rs.getInt("id");
-            System.out.println("sign: " + csrname);
+            System.out.println("sign: " + id);
             try {
+                Certificate crt = Certificate.getById(id);
                 String csrType = rs.getString("csr_type");
                 CSRType ct = CSRType.valueOf(csrType);
-                File crt = KeyStorage.locateCrt(id);
 
                 Timestamp from = rs.getTimestamp("executeFrom");
                 String length = rs.getString("executeTo");
@@ -315,7 +318,7 @@ public class SimpleSigner {
                 System.out.println(subj);
 
                 PublicKey pk;
-                byte[] data = IOUtils.readURL(new FileInputStream(csrname));
+                byte[] data = crt.getAttachment(AttachmentType.CSR).getBytes("UTF-8");
                 if (ct == CSRType.SPKAC) {
                     String dt = new String(data, "UTF-8");
                     if (dt.startsWith("SPKAC=")) {
@@ -350,13 +353,13 @@ public class SimpleSigner {
 
                 X509Certificate root = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new FileInputStream("signer/ca/" + ca + "/ca.crt"));
                 byte[] cert = generateCert(pk, i, subj, root.getSubjectX500Principal(), altnames, fromDate, toDate, Digest.valueOf(rs.getString("md").toUpperCase()), caP.getProperty("eku"));
-                PrintWriter out = new PrintWriter(crt);
-                out.println("-----BEGIN CERTIFICATE-----");
-                out.println(Base64.getMimeEncoder().encodeToString(cert));
-                out.println("-----END CERTIFICATE-----");
-                out.close();
+                StringBuilder b = new StringBuilder();
+                b.append("-----BEGIN CERTIFICATE-----\r\n");
+                b.append(Base64.getMimeEncoder().encodeToString(cert));
+                b.append("-----END CERTIFICATE-----\r\n");
+                crt.addAttachment(AttachmentType.CRT, b.toString());
 
-                try (InputStream is = new FileInputStream(crt)) {
+                try (InputStream is = new ByteArrayInputStream(cert)) {
                     locateCA.setString(1, ca);
                     GigiResultSet caRs = locateCA.executeQuery();
                     if ( !caRs.next()) {
@@ -366,11 +369,10 @@ public class SimpleSigner {
                     CertificateFactory cf = CertificateFactory.getInstance("X.509");
                     X509Certificate crtp = (X509Certificate) cf.generateCertificate(is);
                     BigInteger serial = crtp.getSerialNumber();
-                    updateMail.setString(1, crt.getPath());
-                    updateMail.setString(2, serial.toString(16));
-                    updateMail.setInt(3, caRs.getInt("id"));
-                    updateMail.setTimestamp(4, new Timestamp(toDate.getTime()));
-                    updateMail.setInt(5, id);
+                    updateMail.setString(1, serial.toString(16));
+                    updateMail.setInt(2, caRs.getInt("id"));
+                    updateMail.setTimestamp(3, new Timestamp(toDate.getTime()));
+                    updateMail.setInt(4, id);
                     updateMail.executeUpdate();
 
                     finishJob.setInt(1, rs.getInt("jobid"));
@@ -385,6 +387,8 @@ public class SimpleSigner {
                 e.printStackTrace();
             } catch (ParseException e) {
                 e.printStackTrace();
+            } catch (GigiApiException e) {
+                e.printStackTrace();
             }
             System.out.println("Error with: " + id);
             warnMail.setInt(1, rs.getInt("jobid"));