]> WPIA git - gigi.git/commitdiff
Implement testing of internal certificate issuing (and login with it)
authorFelix Dörre <felix@dogcraft.de>
Thu, 10 Jul 2014 10:39:06 +0000 (12:39 +0200)
committerFelix Dörre <felix@dogcraft.de>
Thu, 10 Jul 2014 22:35:16 +0000 (00:35 +0200)
src/org/cacert/gigi/Certificate.java
src/org/cacert/gigi/Launcher.java
tests/org/cacert/gigi/TestCertificate.java [new file with mode: 0644]
tests/org/cacert/gigi/testUtils/ManagedTest.java
tests/org/cacert/gigi/testUtils/PemKey.java [new file with mode: 0644]
util/org/cacert/gigi/util/SimpleSigner.java

index a9d1288283d639babe52d97f0789bf7980854333..71fb5b72fb37453b09293ad6cf8d92f000f5c012 100644 (file)
@@ -123,7 +123,6 @@ public class Certificate {
                        return CertificateStatus.SIGNING;
                }
                crtName = rs.getString(1);
-               System.out.println(crtName);
                if (rs.getTime(2) != null && rs.getTime(3) == null) {
                        return CertificateStatus.ISSUED;
                }
index 6eb5976a6698e504aa3e249714821bfe3186e0df..b3c437ed993072afe382412c4a638c42d7c939e8 100644 (file)
@@ -73,7 +73,8 @@ public class Launcher {
                IOException {
                final SslContextFactory sslContextFactory = generateSSLContextFactory(conf, "www");
                final SslContextFactory secureContextFactory = generateSSLContextFactory(conf, "secure");
-               secureContextFactory.setNeedClientAuth(true);
+               secureContextFactory.setWantClientAuth(true);
+               secureContextFactory.setNeedClientAuth(false);
                final SslContextFactory staticContextFactory = generateSSLContextFactory(conf, "static");
                final SslContextFactory apiContextFactory = generateSSLContextFactory(conf, "api");
                try {
diff --git a/tests/org/cacert/gigi/TestCertificate.java b/tests/org/cacert/gigi/TestCertificate.java
new file mode 100644 (file)
index 0000000..42b1c2f
--- /dev/null
@@ -0,0 +1,130 @@
+package org.cacert.gigi;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.Socket;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.sql.SQLException;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.X509KeyManager;
+
+import org.cacert.gigi.Certificate.CertificateStatus;
+import org.cacert.gigi.testUtils.ManagedTest;
+import org.cacert.gigi.testUtils.PemKey;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestCertificate extends ManagedTest {
+       @Test
+       public void testClientCertLoginStates() throws IOException, GeneralSecurityException, SQLException,
+               InterruptedException {
+               String[] key1 = generateCSR("/CN=testmail@example.com");
+               Certificate c = new Certificate(1, "/CN=testmail@example.com", "sha256", key1[1]);
+               final PrivateKey pk = PemKey.parsePEMPrivateKey(key1[0]);
+               c.issue();
+               c.waitFor(60000);
+               final X509Certificate ce = c.cert();
+               KeyManager km = new X509KeyManager() {
+
+                       @Override
+                       public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
+                               return "client";
+                       }
+
+                       @Override
+                       public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
+                               return null;
+                       }
+
+                       @Override
+                       public X509Certificate[] getCertificateChain(String arg0) {
+                               return new X509Certificate[] { ce };
+                       }
+
+                       @Override
+                       public String[] getClientAliases(String arg0, Principal[] arg1) {
+                               return new String[] { "client" };
+                       }
+
+                       @Override
+                       public PrivateKey getPrivateKey(String arg0) {
+                               if (arg0.equals("client")) {
+                                       return pk;
+                               }
+                               return null;
+                       }
+
+                       @Override
+                       public String[] getServerAliases(String arg0, Principal[] arg1) {
+                               return new String[] { "client" };
+                       }
+               };
+               SSLContext sc = SSLContext.getInstance("TLS");
+               sc.init(new KeyManager[] { km }, null, null);
+
+               HttpURLConnection connection = (HttpURLConnection) new URL("https://"
+                       + getServerName().replaceFirst("^www.", "secure.") + "/login").openConnection();
+               if (connection instanceof HttpsURLConnection) {
+                       ((HttpsURLConnection) connection).setSSLSocketFactory(sc.getSocketFactory());
+               }
+               assertEquals(302, connection.getResponseCode());
+               assertEquals("https://" + getServerName().replaceFirst("^www.", "secure.") + "/",
+                       connection.getHeaderField("Location"));
+       }
+
+       @Test
+       public void testCertLifeCycle() throws IOException, GeneralSecurityException, SQLException, InterruptedException {
+               String[] key1 = generateCSR("/CN=testmail@example.com");
+               Certificate c = new Certificate(1, "/CN=testmail@example.com", "sha256", key1[1]);
+               testFails(CertificateStatus.DRAFT, c);
+               c.issue();
+
+               testFails(CertificateStatus.SIGNING, c);
+               c.waitFor(60000);
+
+               testFails(CertificateStatus.ISSUED, c);
+               c.revoke();
+
+               testFails(CertificateStatus.BEING_REVOKED, c);
+               c.waitFor(60000);
+
+               testFails(CertificateStatus.REVOKED, c);
+
+       }
+
+       private void testFails(CertificateStatus status, Certificate c) throws IOException, GeneralSecurityException,
+               SQLException {
+               if (status != CertificateStatus.ISSUED) {
+                       try {
+                               c.revoke();
+                               fail("is in invalid state");
+                       } catch (IllegalStateException ise) {
+
+                       }
+               }
+               if (status != CertificateStatus.DRAFT) {
+                       try {
+                               c.issue();
+                               fail("is in invalid state");
+                       } catch (IllegalStateException ise) {
+
+                       }
+               }
+               if (status != CertificateStatus.ISSUED) {
+                       try {
+                               c.cert();
+                               fail("is in invalid state");
+                       } catch (IllegalStateException ise) {
+
+                       }
+               }
+       }
+}
index 5f441d2b9185eb16fdebf9d12f1266fd85f0e827..2159a66322f002e709208907bd151367ee95d922 100644 (file)
@@ -284,4 +284,19 @@ public class ManagedTest {
                }
                return m.group(1);
        }
+
+       public static String[] generateCSR(String dn) throws IOException {
+               Process p = Runtime.getRuntime().exec(
+                       new String[] { "openssl", "req", "-newkey", "rsa:1024", "-nodes", "-subj", dn, "-config",
+                                       "keys/selfsign.config" });
+               String csr = IOUtils.readURL(new InputStreamReader(p.getInputStream()));
+
+               String[] parts = csr.split("(?<=-----)\n(?=-----)");
+               if (parts.length != 2) {
+                       System.err.println(IOUtils.readURL(new InputStreamReader(p.getErrorStream())));
+                       throw new Error();
+               }
+               return parts;
+       }
+
 }
diff --git a/tests/org/cacert/gigi/testUtils/PemKey.java b/tests/org/cacert/gigi/testUtils/PemKey.java
new file mode 100644 (file)
index 0000000..9f5a27c
--- /dev/null
@@ -0,0 +1,26 @@
+package org.cacert.gigi.testUtils;
+
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
+
+public class PemKey {
+       public static PrivateKey parsePEMPrivateKey(String privKeyPEM) throws NoSuchAlgorithmException,
+               InvalidKeySpecException {
+               privKeyPEM = privKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "").replace("\n", "");
+               // Remove the first and last lines
+               privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
+
+               // Base64 decode the data
+               byte[] encoded = Base64.getDecoder().decode(privKeyPEM);
+
+               // PKCS8 decode the encoded RSA private key
+               PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
+               KeyFactory kf = KeyFactory.getInstance("RSA");
+               PrivateKey privKey = kf.generatePrivate(keySpec);
+               return privKey;
+       }
+}
index 2aaa1659d79a7cf7c3793f06af7a80aa13b73be7..cb4e492899fc45dd4ef7f3c413d7d0a16460800b 100644 (file)
@@ -66,30 +66,35 @@ public class SimpleSigner {
                runner = new Thread() {
                        @Override
                        public void run() {
-                               try {
-                                       gencrl();
-                               } catch (IOException e2) {
-                                       e2.printStackTrace();
-                               } catch (InterruptedException e2) {
-                                       e2.printStackTrace();
-                               }
-                               while (running) {
-                                       try {
-                                               signCertificates();
-                                               revokeCertificates();
-                                               Thread.sleep(5000);
-                                       } catch (IOException e) {
-                                               e.printStackTrace();
-                                       } catch (SQLException e) {
-                                               e.printStackTrace();
-                                       } catch (InterruptedException e1) {
-                                       }
-                               }
+                               work();
                        }
+
                };
                runner.start();
        }
 
+       private static void work() {
+               try {
+                       gencrl();
+               } catch (IOException e2) {
+                       e2.printStackTrace();
+               } catch (InterruptedException e2) {
+                       e2.printStackTrace();
+               }
+               while (running) {
+                       try {
+                               signCertificates();
+                               revokeCertificates();
+                               Thread.sleep(5000);
+                       } catch (IOException e) {
+                               e.printStackTrace();
+                       } catch (SQLException e) {
+                               e.printStackTrace();
+                       } catch (InterruptedException e1) {
+                       }
+               }
+       }
+
        private static void revokeCertificates() throws SQLException, IOException, InterruptedException {
                ResultSet rs = revoke.executeQuery();
                boolean worked = false;
@@ -163,7 +168,7 @@ public class SimpleSigner {
                                        X509Certificate crtp = (X509Certificate) cf.generateCertificate(is);
                                        BigInteger serial = crtp.getSerialNumber();
                                        updateMail.setString(1, crt.getPath());
-                                       updateMail.setString(2, serial.toString());
+                                       updateMail.setString(2, serial.toString(16));
                                        updateMail.setInt(3, id);
                                        updateMail.execute();
                                        System.out.println("sign: " + id);