]> WPIA git - gigi.git/commitdiff
Use tha new SPKAC-class to verify spkac requests and their keys.
authorFelix Dörre <felix@dogcraft.de>
Tue, 29 Jul 2014 17:53:09 +0000 (19:53 +0200)
committerFelix Dörre <felix@dogcraft.de>
Tue, 29 Jul 2014 17:58:36 +0000 (19:58 +0200)
src/org/cacert/gigi/pages/account/IssueCertificateForm.java

index be8bbb5d34df3dc683efd847a96c697f156bc051..0643f4855eac6024f698909a431677132cef020c 100644 (file)
@@ -1,9 +1,6 @@
 package org.cacert.gigi.pages.account;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.security.GeneralSecurityException;
 import java.security.PublicKey;
@@ -11,6 +8,7 @@ import java.security.interfaces.DSAPublicKey;
 import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAPublicKey;
 import java.sql.SQLException;
+import java.util.Base64;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -23,6 +21,7 @@ import org.cacert.gigi.GigiApiException;
 import org.cacert.gigi.Language;
 import org.cacert.gigi.User;
 import org.cacert.gigi.Certificate.CSRType;
+import org.cacert.gigi.crypto.SPKAC;
 import org.cacert.gigi.output.Form;
 import org.cacert.gigi.output.template.HashAlgorithms;
 import org.cacert.gigi.output.template.IterableDataset;
@@ -33,6 +32,9 @@ import org.cacert.gigi.util.PEM;
 import org.cacert.gigi.util.RandomToken;
 
 import sun.security.pkcs10.PKCS10;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerValue;
+import sun.security.x509.AlgorithmId;
 
 /**
  * This class represents a form that is used for issuing certificates. This
@@ -73,107 +75,95 @@ public class IssueCertificateForm extends Form {
         String csr = req.getParameter("CSR");
         String spkac = req.getParameter("SPKAC");
         try {
-            if (csr != null) {
-                PKCS10 parsed = parseCSR(csr);
-                out.println(parsed.getSubjectName().getCommonName());
-                out.println(parsed.getSubjectName().getCountry());
-                out.println("CSR DN: " + parsed.getSubjectName() + "<br/>");
-                PublicKey pk = parsed.getSubjectPublicKeyInfo();
-                out.println("Type: " + pk.getAlgorithm() + "<br/>");
-                if (pk instanceof RSAPublicKey) {
-                    out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "<br/>");
-                    out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength());
-                } else if (pk instanceof DSAPublicKey) {
-                    DSAPublicKey dpk = (DSAPublicKey) pk;
-                    out.println("Length: " + dpk.getY().bitLength() + "<br/>");
-                    out.println(dpk.getParams());
-                } else if (pk instanceof ECPublicKey) {
-                    ECPublicKey epk = (ECPublicKey) pk;
-                    out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "<br/>");
-                    out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "<br/>");
-                    out.println(epk.getParams().getCurve());
-                }
-                out.println("<br/>digest: sha256<br/>");
-                this.csr = csr;
-                this.csrType = CSRType.CSR;
-            } else if (spkac != null) {
-                String cleanedSPKAC = "SPKAC=" + spkac.replaceAll("[\r\n]", "");
-                try {
-                    checkSPKAC(cleanedSPKAC, spkacChallange);
-                    this.csr = cleanedSPKAC;
+            try {
+                if (csr != null) {
+                    byte[] data = PEM.decode("(NEW )?CERTIFICATE REQUEST", csr);
+                    PKCS10 parsed = new PKCS10(data);
+
+                    out.println(parsed.getSubjectName().getCommonName());
+                    out.println(parsed.getSubjectName().getCountry());
+                    out.println("CSR DN: " + parsed.getSubjectName() + "<br/>");
+                    PublicKey pk = parsed.getSubjectPublicKeyInfo();
+                    checkKeyStrength(pk, out);
+                    String sign = getSignatureAlgorithm(data);
+                    out.println("<br/>digest: " + sign + "<br/>");
+
+                    this.csr = csr;
+                    this.csrType = CSRType.CSR;
+                } else if (spkac != null) {
+                    String cleanedSPKAC = spkac.replaceAll("[\r\n]", "");
+                    byte[] data = Base64.getDecoder().decode(cleanedSPKAC);
+                    SPKAC parsed = new SPKAC(data);
+                    if ( !parsed.getChallenge().equals(spkacChallange)) {
+                        throw new GigiApiException("Challange mismatch");
+                    }
+                    checkKeyStrength(parsed.getPubkey(), out);
+                    String sign = getSignatureAlgorithm(data);
+                    out.println("<br/>digest: " + sign + "<br/>");
+
+                    // spkacChallange
+                    this.csr = "SPKAC=" + cleanedSPKAC;
                     this.csrType = CSRType.SPKAC;
-                } catch (GigiApiException e) {
-                    e.format(out, Page.getLanguage(req));
-                }
 
-            } else {
-                login = "1".equals(req.getParameter("login"));
-                String hashAlg = req.getParameter("hash_alg");
-                if (hashAlg != null) {
-                    selectedDigest = Digest.valueOf(hashAlg);
-                }
-                if (req.getParameter("CCA") == null) {
-                    outputError(out, req, "You need to accept the CCA.");
-                    return false;
-                }
-                System.out.println("issuing " + selectedDigest);
-                result = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", selectedDigest.toString(), this.csr, this.csrType);
-                try {
+                } else {
+                    login = "1".equals(req.getParameter("login"));
+                    String hashAlg = req.getParameter("hash_alg");
+                    if (hashAlg != null) {
+                        selectedDigest = Digest.valueOf(hashAlg);
+                    }
+                    if (req.getParameter("CCA") == null) {
+                        outputError(out, req, "You need to accept the CCA.");
+                        return false;
+                    }
+                    System.out.println("issuing " + selectedDigest);
+                    result = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", selectedDigest.toString(), this.csr, this.csrType);
                     result.issue().waitFor(60000);
                     return true;
-                } catch (SQLException e) {
-                    e.printStackTrace();
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
                 }
-                return false;
+            } catch (IOException e) {
+                e.printStackTrace();
+            } catch (IllegalArgumentException e) {
+                throw new GigiApiException("Certificate Request format is invalid.");
+            } catch (GeneralSecurityException e) {
+                throw new GigiApiException("Certificate Request format is invalid.");
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            } catch (SQLException e) {
+                throw new GigiApiException(e);
             }
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (GeneralSecurityException e) {
-            e.printStackTrace();
+        } catch (GigiApiException e) {
+            e.format(out, Page.getLanguage(req));
         }
         return false;
     }
 
-    private static void checkSPKAC(String csr, String spkacChallange) throws IOException, GigiApiException {
-        Process p = Runtime.getRuntime().exec(new String[] {
-                "openssl", "spkac", "-verify"
-        });
-        OutputStream outputStream = p.getOutputStream();
-        outputStream.write(csr.getBytes());
-        outputStream.flush();
-        outputStream.close();
-        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "UTF-8"));
-        String line;
-        String challenge = null;
-        while ((line = br.readLine()) != null) {
-            line = line.trim();
-            String challengePrefix = "Challenge String: ";
-            if (line.startsWith(challengePrefix)) {
-                challenge = line.substring(challengePrefix.length());
-            }
-        }
-        GigiApiException gae = new GigiApiException();
-        if ( !spkacChallange.equals(challenge)) {
-            gae.mergeInto(new GigiApiException("The challenge-response code of your certificate request did not match. Can't continue with certificaterequest."));
-        }
-        try {
-            if (p.waitFor() != 0) {
-                gae.mergeInto(new GigiApiException("The signature of your certificate request is invalid. Can't continue with certificaterequest."));
-            }
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        if ( !gae.isEmpty()) {
-            throw gae;
+    private void checkKeyStrength(PublicKey pk, PrintWriter out) {
+        out.println("Type: " + pk.getAlgorithm() + "<br/>");
+        if (pk instanceof RSAPublicKey) {
+            out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "<br/>");
+            out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength());
+        } else if (pk instanceof DSAPublicKey) {
+            DSAPublicKey dpk = (DSAPublicKey) pk;
+            out.println("Length: " + dpk.getY().bitLength() + "<br/>");
+            out.println(dpk.getParams());
+        } else if (pk instanceof ECPublicKey) {
+            ECPublicKey epk = (ECPublicKey) pk;
+            out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "<br/>");
+            out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "<br/>");
+            out.println(epk.getParams().getCurve());
         }
     }
 
-    private PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException {
+    private static PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException {
         return new PKCS10(PEM.decode("(NEW )?CERTIFICATE REQUEST", csr));
     }
 
+    private static String getSignatureAlgorithm(byte[] data) throws IOException {
+        DerInputStream in = new DerInputStream(data);
+        DerValue[] seq = in.getSequence(3);
+        return AlgorithmId.parse(seq[1]).getName();
+    }
+
     @Override
     public void output(PrintWriter out, Language l, Map<String, Object> vars) {
         if (csr == null) {