From: Felix Dörre Date: Mon, 14 Jul 2014 20:13:45 +0000 (+0200) Subject: Build out certificate issuing. X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=606cafcb5da873370c9b614d7951c164159681ad Build out certificate issuing. --- diff --git a/doc/exoticKeys.sh b/doc/exoticKeys.sh new file mode 100644 index 00000000..caa4c769 --- /dev/null +++ b/doc/exoticKeys.sh @@ -0,0 +1,7 @@ +#!/bin/bash +openssl ecparam -out ec.pem -name secp521r1 -genkey +openssl req -new -key ec.pem -out ec.csr -subj "/CN=bla" + +openssl dsaparam -genkey 1024 -out dsa.pem +openssl req -new -key dsa.pem -out dsa.csr -subj "/CN=bla" + diff --git a/src/org/cacert/gigi/Digest.java b/src/org/cacert/gigi/Digest.java new file mode 100644 index 00000000..e183be72 --- /dev/null +++ b/src/org/cacert/gigi/Digest.java @@ -0,0 +1,21 @@ +package org.cacert.gigi; + +public enum Digest { + SHA256("Currently recommended, because the other algorithms" + + " might break on some older versions of the GnuTLS library" + + " (older than 3.x) still shipped in Debian for example."), SHA384(null), SHA512( + "Highest protection against hash collision attacks of the algorithms offered here."); + final String exp; + + private Digest(String explanation) { + exp = explanation; + } + + public String getExp() { + return exp; + } + + public static Digest getDefault() { + return SHA256; + } +} diff --git a/src/org/cacert/gigi/output/Form.java b/src/org/cacert/gigi/output/Form.java index 11209ca5..2ffb8731 100644 --- a/src/org/cacert/gigi/output/Form.java +++ b/src/org/cacert/gigi/output/Form.java @@ -12,6 +12,7 @@ import org.cacert.gigi.pages.Page; import org.cacert.gigi.util.RandomToken; public abstract class Form implements Outputable { + public static final String CSRF_FIELD = "csrf"; String csrf; public Form(HttpServletRequest hsr) { @@ -27,7 +28,7 @@ public abstract class Form implements Outputable { public final void output(PrintWriter out, Language l, Map vars) { out.println("
"); outputContent(out, l, vars); - out.print("
"); } @@ -45,13 +46,13 @@ public abstract class Form implements Outputable { } protected void checkCSRF(HttpServletRequest req) { - if (!csrf.equals(req.getParameter("csrf"))) { + if (!csrf.equals(req.getParameter(CSRF_FIELD))) { throw new CSRFError(); } } public static T getForm(HttpServletRequest req, Class target) { - String csrf = req.getParameter("csrf"); + String csrf = req.getParameter(CSRF_FIELD); if (csrf == null) { throw new CSRFError(); } diff --git a/src/org/cacert/gigi/output/template/HashAlgorithms.java b/src/org/cacert/gigi/output/template/HashAlgorithms.java new file mode 100644 index 00000000..453e0d05 --- /dev/null +++ b/src/org/cacert/gigi/output/template/HashAlgorithms.java @@ -0,0 +1,30 @@ +package org.cacert.gigi.output.template; + +import java.util.Map; + +import org.cacert.gigi.Digest; +import org.cacert.gigi.Language; + +public class HashAlgorithms implements IterableDataset { + + int i = 0; + Digest selected; + + public HashAlgorithms(Digest selected) { + this.selected = selected; + } + + @Override + public boolean next(Language l, Map vars) { + Digest[] length = Digest.values(); + if (i >= length.length) { + return false; + } + Digest d = length[i++]; + vars.put("algorithm", d.toString()); + vars.put("name", d.toString()); + vars.put("info", l.getTranslation(d.getExp())); + vars.put("checked", selected == d ? " checked='checked'" : ""); + return true; + } +} diff --git a/src/org/cacert/gigi/pages/account/IssueCertificateForm.java b/src/org/cacert/gigi/pages/account/IssueCertificateForm.java new file mode 100644 index 00000000..e8e50001 --- /dev/null +++ b/src/org/cacert/gigi/pages/account/IssueCertificateForm.java @@ -0,0 +1,143 @@ +package org.cacert.gigi.pages.account; + +import java.io.IOException; +import java.io.PrintWriter; +import java.security.GeneralSecurityException; +import java.security.PublicKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.cacert.gigi.Certificate; +import org.cacert.gigi.Digest; +import org.cacert.gigi.Language; +import org.cacert.gigi.User; +import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.output.Form; +import org.cacert.gigi.output.template.HashAlgorithms; +import org.cacert.gigi.output.template.IterableDataset; +import org.cacert.gigi.output.template.Template; +import org.cacert.gigi.pages.LoginPage; + +import sun.security.pkcs10.PKCS10; + +/** + * This class represents a form that is used for issuing certificates. + * + * This class uses "sun.security" and therefore needs "-XDignore.symbol.file" + * + */ +public class IssueCertificateForm extends Form { + User u; + Digest selectedDigest = Digest.getDefault(); + + private final static Template t = new Template(IssueCertificateForm.class.getResource("IssueCertificateForm.templ")); + + public IssueCertificateForm(HttpServletRequest hsr) { + super(hsr); + u = LoginPage.getUser(hsr); + } + + @Override + public boolean submit(PrintWriter out, HttpServletRequest req) { + String csr = req.getParameter("CSR"); + String spkac = req.getParameter("spkac"); + try { + if (csr != null && !"".equals(csr)) { + PKCS10 parsed = parseCSR(csr); + out.println(parsed.getSubjectName().getCommonName()); + out.println(parsed.getSubjectName().getCountry()); + out.println("CSR DN: " + parsed.getSubjectName() + "
"); + PublicKey pk = parsed.getSubjectPublicKeyInfo(); + out.println("Type: " + pk.getAlgorithm() + "
"); + if (pk instanceof RSAPublicKey) { + out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "
"); + out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength()); + } else if (pk instanceof DSAPublicKey) { + DSAPublicKey dpk = (DSAPublicKey) pk; + out.println("Length: " + dpk.getY().bitLength() + "
"); + out.println(dpk.getParams()); + } else if (pk instanceof ECPublicKey) { + ECPublicKey epk = (ECPublicKey) pk; + out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "
"); + out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "
"); + out.println(epk.getParams().getCurve()); + } + out.println("
digest: sha256
"); + + } + } catch (IOException e) { + e.printStackTrace(); + } catch (GeneralSecurityException e) { + e.printStackTrace(); + } + return false; + } + + private void issue(HttpServletRequest req, HttpServletResponse resp, String csr) throws IOException { + Certificate c = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", "sha256", csr); + c.issue(); + try { + c.waitFor(60000); + resp.sendRedirect(MailCertificates.PATH + "/" + c.getSerial()); + } catch (SQLException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException { + csr = csr.replaceFirst("-----BEGIN (NEW )?CERTIFICATE REQUEST-----", ""); + csr = csr.replaceFirst("-----END (NEW )?CERTIFICATE REQUEST-----", ""); + csr = csr.replace("\r", ""); + csr = csr.replace("\n", ""); + byte[] b = Base64.getDecoder().decode(csr); + // Also checks signature validity + return new PKCS10(b); + } + + @Override + protected void outputContent(PrintWriter out, Language l, Map vars) { + HashMap vars2 = new HashMap(vars); + vars2.put("CCA", "CCA"); + + try { + PreparedStatement ps = DatabaseConnection.getInstance().prepare( + "SELECT `id`,`email` from `email` WHERE `memid`=? AND `deleted`=0"); + ps.setInt(1, u.getId()); + final ResultSet rs = ps.executeQuery(); + vars2.put("emails", new IterableDataset() { + + @Override + public boolean next(Language l, Map vars) { + try { + if (!rs.next()) { + return false; + } + vars.put("id", rs.getString(1)); + vars.put("value", rs.getString(2)); + return true; + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + }); + vars2.put("hashs", new HashAlgorithms(selectedDigest)); + t.output(out, l, vars2); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/org/cacert/gigi/pages/account/MailCertificateAdd.templ b/src/org/cacert/gigi/pages/account/IssueCertificateForm.templ similarity index 85% rename from src/org/cacert/gigi/pages/account/MailCertificateAdd.templ rename to src/org/cacert/gigi/pages/account/IssueCertificateForm.templ index 6ce1b15b..575066fb 100644 --- a/src/org/cacert/gigi/pages/account/MailCertificateAdd.templ +++ b/src/org/cacert/gigi/pages/account/IssueCertificateForm.templ @@ -75,7 +75,10 @@
- + + /> +
+ @@ -91,25 +94,6 @@ - - - - - - - - - - - -
- - - - - diff --git a/src/org/cacert/gigi/pages/account/MailCertificateAdd.java b/src/org/cacert/gigi/pages/account/MailCertificateAdd.java index 5a343954..4a9a2c82 100644 --- a/src/org/cacert/gigi/pages/account/MailCertificateAdd.java +++ b/src/org/cacert/gigi/pages/account/MailCertificateAdd.java @@ -1,27 +1,28 @@ package org.cacert.gigi.pages.account; import java.io.IOException; -import java.io.PrintWriter; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.cacert.gigi.Certificate; import org.cacert.gigi.Language; import org.cacert.gigi.User; import org.cacert.gigi.database.DatabaseConnection; -import org.cacert.gigi.output.ClientCSRGenerate; import org.cacert.gigi.output.template.IterableDataset; import org.cacert.gigi.pages.LoginPage; +import org.cacert.gigi.output.Form; +import org.cacert.gigi.output.template.Template; import org.cacert.gigi.pages.Page; public class MailCertificateAdd extends Page { public static final String PATH = "/account/certs/email/new"; + Template t = new Template(MailCertificateAdd.class.getResource("RequestCertificate.templ")); public MailCertificateAdd() { super("Create Email certificate"); @@ -64,27 +65,14 @@ public class MailCertificateAdd extends Page { @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - PrintWriter out = resp.getWriter(); - if (req.getParameter("optionalCSR") == null || req.getParameter("optionalCSR").equals("")) { - out.println("csr missing"); - ClientCSRGenerate.output(req, resp); - } - String csr = req.getParameter("optionalCSR"); - if (!"on".equals(req.getParameter("CCA"))) { - // Error. - return; - } - Certificate c = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", "sha256", csr); - c.issue(); - try { - c.waitFor(60000); - resp.sendRedirect(MailCertificates.PATH + "/" + c.getSerial()); - } catch (SQLException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); + IssueCertificateForm f; + if (req.getParameter(Form.CSRF_FIELD) != null) { + f = Form.getForm(req, IssueCertificateForm.class); + } else { + f = new IssueCertificateForm(req); + f.submit(resp.getWriter(), req); } + f.output(resp.getWriter(), getLanguage(req), Collections. emptyMap()); } - } diff --git a/src/org/cacert/gigi/pages/account/RequestCertificate.templ b/src/org/cacert/gigi/pages/account/RequestCertificate.templ new file mode 100644 index 00000000..2a329630 --- /dev/null +++ b/src/org/cacert/gigi/pages/account/RequestCertificate.templ @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + +
+

+
+

+ +
diff --git a/static/static/default.css b/static/static/default.css index 20aeac42..2f0bf528 100644 --- a/static/static/default.css +++ b/static/static/default.css @@ -758,3 +758,6 @@ pre{ .dataTable select, .dataTable option { font-size: 92%; } +.dataTable textarea{ + width: 100%; +}