X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2Fpages%2Faccount%2Fcerts%2FCertificates.java;h=8acd48422c03044aa9f06f36e6952e787d97e5c4;hp=a0afe7a9091de272b06d85537b09ee296ee9001f;hb=17a15662212d973d12ed4cea3f5eaa9c0d1169ed;hpb=b58a76fd82cff44fb6e1cdf09c8b04d890ac2e1e diff --git a/src/org/cacert/gigi/pages/account/certs/Certificates.java b/src/org/cacert/gigi/pages/account/certs/Certificates.java index a0afe7a9..8acd4842 100644 --- a/src/org/cacert/gigi/pages/account/certs/Certificates.java +++ b/src/org/cacert/gigi/pages/account/certs/Certificates.java @@ -2,81 +2,56 @@ package org.cacert.gigi.pages.account.certs; import java.io.IOException; import java.io.PrintWriter; -import java.math.BigInteger; import java.net.URLEncoder; import java.security.GeneralSecurityException; -import java.security.cert.CRLException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; +import java.util.List; import java.util.Map; -import java.util.Set; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.cacert.gigi.dbObjects.CACertificate; import org.cacert.gigi.dbObjects.Certificate; +import org.cacert.gigi.dbObjects.Certificate.CertificateStatus; +import org.cacert.gigi.dbObjects.Certificate.SubjectAlternateName; +import org.cacert.gigi.dbObjects.CertificateOwner; +import org.cacert.gigi.dbObjects.Organisation; +import org.cacert.gigi.dbObjects.SupportedUser; +import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.output.TrustchainIterable; import org.cacert.gigi.output.template.Form; import org.cacert.gigi.output.template.IterableDataset; import org.cacert.gigi.output.template.Template; import org.cacert.gigi.pages.HandlesMixedRequest; import org.cacert.gigi.pages.LoginPage; import org.cacert.gigi.pages.Page; +import org.cacert.gigi.util.AuthorizationContext; +import org.cacert.gigi.util.CertExporter; import org.cacert.gigi.util.PEM; -import sun.security.pkcs.ContentInfo; -import sun.security.pkcs.PKCS7; -import sun.security.pkcs.SignerInfo; -import sun.security.util.DerOutputStream; -import sun.security.util.DerValue; -import sun.security.x509.AlgorithmId; -import sun.security.x509.X509CRLImpl; -import sun.security.x509.X509CertImpl; - public class Certificates extends Page implements HandlesMixedRequest { - private Template certDisplay = new Template(Certificates.class.getResource("CertificateDisplay.templ")); + private static final Template certDisplay = new Template(Certificates.class.getResource("CertificateDisplay.templ")); public static final String PATH = "/account/certs"; - static class TrustchainIterable implements IterableDataset { - - CACertificate cert; + public static final String SUPPORT_PATH = "/support/certs"; - public TrustchainIterable(CACertificate cert) { - this.cert = cert; - } - - @Override - public boolean next(Language l, Map vars) { - if (cert == null) { - return false; - } - vars.put("name", cert.getKeyname()); - vars.put("link", cert.getLink()); - if (cert.isSelfsigned()) { - cert = null; - return true; - } - cert = cert.getParent(); - return true; - } + private final boolean support; - } - - public Certificates() { - super("Certificates"); + public Certificates(boolean support) { + super(support ? "Support Certificates" : "Certificates"); + this.support = support; } @Override public boolean beforeTemplate(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if ("POST".equals(req.getMethod())) { + return beforePost(req, resp); + } String pi = req.getPathInfo().substring(PATH.length()); if (pi.length() == 0) { @@ -95,9 +70,6 @@ public class Certificates extends Page implements HandlesMixedRequest { } else if (pi.endsWith(".cer")) { cer = true; pi = pi.substring(0, pi.length() - 4); - } else if (pi.endsWith(".cer")) { - cer = true; - pi = pi.substring(0, pi.length() - 4); } String serial = pi; try { @@ -106,35 +78,17 @@ public class Certificates extends Page implements HandlesMixedRequest { resp.sendError(404); return true; } - X509Certificate cert = c.cert(); if ( !crt && !cer) { return false; } ServletOutputStream out = resp.getOutputStream(); + boolean doChain = req.getParameter("chain") != null; + boolean includeAnchor = req.getParameter("noAnchor") == null; + boolean includeLeaf = req.getParameter("noLeaf") == null; if (crt) { - out.println(PEM.encode("CERTIFICATE", cert.getEncoded())); - if (req.getParameter("chain") != null) { - CACertificate ca = c.getParent(); - while ( !ca.isSelfsigned()) { - out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded())); - ca = ca.getParent(); - } - if (req.getParameter("noAnchor") == null) { - out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded())); - } - } + CertExporter.writeCertCrt(c, out, doChain, includeAnchor, includeLeaf); } else if (cer) { - if (req.getParameter("chain") != null) { - PKCS7 p7 = toP7Chain(c); - p7.encodeSignedData(out); - /* - * ContentInfo ci = toCIChain(c); try (DerOutputStream dos = - * new DerOutputStream()) { ci.encode(dos); - * out.write(dos.toByteArray()); } - */ - } else { - out.write(cert.getEncoded()); - } + CertExporter.writeCertCer(c, out, doChain, includeAnchor); } } catch (IllegalArgumentException e) { resp.sendError(404); @@ -147,111 +101,24 @@ public class Certificates extends Page implements HandlesMixedRequest { return true; } - private static PKCS7 toP7Chain(Certificate c) throws IOException, GeneralSecurityException { - LinkedList 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]) { - - @Override - public void encodeSignedData(DerOutputStream out) throws IOException { - DerOutputStream signedData = new DerOutputStream(); - BigInteger version = getVersion(); - AlgorithmId[] digestAlgorithmIds = getDigestAlgorithmIds(); - ContentInfo contentInfo = getContentInfo(); - X509Certificate[] certificates = getCertificates(); - X509CRL[] crls = getCRLs(); - SignerInfo[] signerInfos = getSignerInfos(); - - // version - signedData.putInteger(version); - - // digestAlgorithmIds - signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds); - - // contentInfo - contentInfo.encode(signedData); - - // certificates (optional) - if (certificates != null && certificates.length != 0) { - DerOutputStream sub = new DerOutputStream(); - // cast to X509CertImpl[] since X509CertImpl implements - // DerEncoder - X509CertImpl implCerts[] = new X509CertImpl[certificates.length]; - for (int i = 0; i < certificates.length; i++) { - try { - sub.write(certificates[i].getEncoded()); - } catch (CertificateEncodingException e) { - sub.close(); - throw new IOException(e); - } - if (certificates[i] instanceof X509CertImpl) { - implCerts[i] = (X509CertImpl) certificates[i]; - } else { - try { - byte[] encoded = certificates[i].getEncoded(); - implCerts[i] = new X509CertImpl(encoded); - } catch (CertificateException ce) { - sub.close(); - throw new IOException(ce); - } - } - } - - // Add the certificate set (tagged with [0] IMPLICIT) - // to the signed data - signedData.write((byte) 0xA0, sub); - sub.close(); - } - - // CRLs (optional) - if (crls != null && crls.length != 0) { - // cast to X509CRLImpl[] since X509CRLImpl implements - // DerEncoder - Set implCRLs = new HashSet(crls.length); - for (X509CRL crl : crls) { - if (crl instanceof X509CRLImpl) { - implCRLs.add((X509CRLImpl) crl); - } else { - try { - byte[] encoded = crl.getEncoded(); - implCRLs.add(new X509CRLImpl(encoded)); - } catch (CRLException ce) { - throw new IOException(ce); - } - } - } - - // Add the CRL set (tagged with [1] IMPLICIT) - // to the signed data - signedData.putOrderedSetOf((byte) 0xA1, implCRLs.toArray(new X509CRLImpl[implCRLs.size()])); - } - - // signerInfos - signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos); - - // making it a signed data block - DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, signedData.toByteArray()); - - // making it a content info sequence - ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, signedDataSeq); - - // writing out the contentInfo sequence - block.encode(out); + @Override + public boolean beforePost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (support && "revoke".equals(req.getParameter("action"))) { + if (Form.getForm(req, RevokeSingleCertForm.class).submitExceptionProtected(req)) { + resp.sendRedirect(req.getPathInfo()); + return true; } - - }; - return p7; - } - - private static LinkedList getChain(Certificate c) throws IOException, GeneralSecurityException { - LinkedList ll = new LinkedList<>(); - ll.add(c.cert()); - CACertificate ca = c.getParent(); - while ( !ca.isSelfsigned()) { - ll.add(ca.getCertificate()); - ca = ca.getParent(); + return false; } - ll.add(ca.getCertificate()); - return ll; + if ( !req.getPathInfo().equals(PATH)) { + resp.sendError(500); + return true; + } + if (Form.getForm(req, CertificateModificationForm.class).submitExceptionProtected(req)) { + resp.sendRedirect(PATH); + return true; + } + return false; } @Override @@ -259,12 +126,18 @@ public class Certificates extends Page implements HandlesMixedRequest { if (req.getQueryString() != null && !req.getQueryString().equals("") && !req.getQueryString().equals("withRevoked")) { return;// Block actions by get parameters. } + + if (support && "revoke".equals(req.getParameter("action"))) { + if (Form.printFormErrors(req, resp.getWriter())) { + Form.getForm(req, RevokeSingleCertForm.class).output(resp.getWriter(), getLanguage(req), new HashMap()); + } + return; + } if ( !req.getPathInfo().equals(PATH)) { resp.sendError(500); return; } - Form.getForm(req, CertificateModificationForm.class).submit(resp.getWriter(), req); - doGet(req, resp); + Form.getForm(req, CertificateModificationForm.class).output(resp.getWriter(), getLanguage(req), new HashMap()); } @Override @@ -276,15 +149,89 @@ public class Certificates extends Page implements HandlesMixedRequest { String serial = pi; Certificate c = Certificate.getBySerial(serial); - if (c == null || LoginPage.getAuthorizationContext(req).getTarget().getId() != c.getOwner().getId()) { + Language l = LoginPage.getLanguage(req); + + if ( !support && (c == null || LoginPage.getAuthorizationContext(req).getTarget().getId() != c.getOwner().getId())) { resp.sendError(404); return; } HashMap vars = new HashMap<>(); vars.put("serial", URLEncoder.encode(serial, "UTF-8")); - vars.put("trustchain", new TrustchainIterable(c.getParent())); + + CertificateStatus st = c.getStatus(); + + if (support) { + vars.put("support", "support"); + CertificateOwner user = c.getOwner(); + if (st == CertificateStatus.ISSUED) { + if (user instanceof User) { + vars.put("revokeForm", new RevokeSingleCertForm(req, c, new SupportedUser((User) user, getUser(req), LoginPage.getAuthorizationContext(req).getSupporterTicketId()))); + } + } + } + + CertificateOwner co = c.getOwner(); + int ownerId = co.getId(); + vars.put("certid", c.getStatus()); + if (co instanceof Organisation) { + vars.put("type", l.getTranslation("Organisation Acount")); + vars.put("name", Organisation.getById(ownerId).getName()); + vars.put("link", ""); // TODO + } else { + vars.put("type", l.getTranslation("Personal Account")); + vars.put("name", User.getById(ownerId).getPreferredName()); + vars.put("link", "/support/user/" + ownerId + "/"); + } + vars.put("status", c.getStatus()); + vars.put("DN", c.getDistinguishedName()); + vars.put("digest", c.getMessageDigest()); + vars.put("profile", c.getProfile().getVisibleName()); + vars.put("fingerprint", "TBD"); // TODO function needs to be + // implemented in Certificate.java try { - vars.put("cert", PEM.encode("CERTIFICATE", c.cert().getEncoded())); + + if (st == CertificateStatus.ISSUED || st == CertificateStatus.REVOKED) { + X509Certificate certx = c.cert(); + vars.put("issued", certx.getNotBefore()); + vars.put("expire", certx.getNotAfter()); + vars.put("cert", PEM.encode("CERTIFICATE", c.cert().getEncoded())); + } else { + vars.put("issued", l.getTranslation("N/A")); + vars.put("expire", l.getTranslation("N/A")); + vars.put("cert", l.getTranslation("N/A")); + } + if (st == CertificateStatus.REVOKED) { + vars.put("revoked", c.getRevocationDate()); + } else { + vars.put("revoked", l.getTranslation("N/A")); + } + if (st == CertificateStatus.ISSUED || st == CertificateStatus.REVOKED) { + vars.put("trustchain", new TrustchainIterable(c.getParent())); + try { + vars.put("cert", PEM.encode("CERTIFICATE", c.cert().getEncoded())); + } catch (GeneralSecurityException e) { + e.printStackTrace(); + } + } else { + vars.put("trustchain", l.getTranslation("N/A")); + vars.put("cert", l.getTranslation("N/A")); + } + final List san = c.getSANs(); + vars.put("san", new IterableDataset() { + + int j = 0; + + @Override + public boolean next(Language l, Map vars) { + if (j == san.size()) { + return false; + } + vars.put("entry", san.get(j).getName() + (j < san.size() - 1 ? ", " : "")); + j++; + return true; + } + }); + vars.put("login", c.isLoginEnabled()); } catch (GeneralSecurityException e) { e.printStackTrace(); } @@ -297,4 +244,15 @@ public class Certificates extends Page implements HandlesMixedRequest { new CertificateModificationForm(req, req.getParameter("withRevoked") != null).output(out, getLanguage(req), vars); } + @Override + public boolean isPermitted(AuthorizationContext ac) { + if (ac == null) { + return false; + } + if (support) { + return ac.canSupport(); + } else { + return true; + } + } }