From: INOPIAE Date: Wed, 27 Dec 2017 07:14:13 +0000 (+0100) Subject: chg: make description work for certificate, save and display description X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=5c4c654bf3cb637a7ba032d0c7fb2c70b115ea2e chg: make description work for certificate, save and display description fixes issue #53 Change-Id: Ib21db362fd593428731269661fd01417d95114d3 --- diff --git a/src/club/wpia/gigi/dbObjects/Certificate.java b/src/club/wpia/gigi/dbObjects/Certificate.java index 51bf41be..825b3392 100644 --- a/src/club/wpia/gigi/dbObjects/Certificate.java +++ b/src/club/wpia/gigi/dbObjects/Certificate.java @@ -162,6 +162,8 @@ public class Certificate implements IdCachable { private CACertificate ca; + private String description = ""; + /** * Creates a new Certificate. WARNING: this is an internal API. Creating * certificates for users must be done using the {@link CertificateRequest} @@ -244,6 +246,7 @@ public class Certificate implements IdCachable { owner = CertificateOwner.getById(rs.getInt("memid")); profile = CertificateProfile.getById(rs.getInt("profile")); this.serial = rs.getString("serial"); + this.description = rs.getString("description"); try (GigiPreparedStatement ps2 = new GigiPreparedStatement("SELECT `contents`, `type` FROM `subjectAlternativeNames` WHERE `certId`=?")) { ps2.setInt(1, id); @@ -408,7 +411,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`,`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`, `certs`.`description` 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()) { @@ -434,7 +437,7 @@ public class Certificate implements IdCachable { } try { - 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")) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial, description 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()) { @@ -566,4 +569,17 @@ public class Certificate implements IdCachable { return s; } } + + public void setDescription(String description) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `certs` SET `description`=? WHERE `id`=?")) { + ps.setString(1, description); + ps.setInt(2, id); + ps.execute(); + } + this.description = description; + } + + public String getDescription() { + return description; + } } diff --git a/src/club/wpia/gigi/output/CertificateIterable.java b/src/club/wpia/gigi/output/CertificateIterable.java index cb4b3523..0932dfa2 100644 --- a/src/club/wpia/gigi/output/CertificateIterable.java +++ b/src/club/wpia/gigi/output/CertificateIterable.java @@ -36,6 +36,7 @@ public class CertificateIterable implements IterableDataset { vars.put("serial", c.getSerial()); vars.put("digest", c.getMessageDigest()); vars.put("profile", c.getProfile().getVisibleName()); + vars.put("description", c.getDescription()); CertificateStatus st = c.getStatus(); vars.put("revokable", st != CertificateStatus.REVOKED && st == CertificateStatus.ISSUED); String issuedWarning = ""; diff --git a/src/club/wpia/gigi/output/CertificateTable.templ b/src/club/wpia/gigi/output/CertificateTable.templ index 539ac1e1..edf01ebc 100644 --- a/src/club/wpia/gigi/output/CertificateTable.templ +++ b/src/club/wpia/gigi/output/CertificateTable.templ @@ -10,6 +10,7 @@ + @@ -26,6 +27,7 @@ + diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.java b/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.java index 86056df4..81925716 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.java +++ b/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.java @@ -99,6 +99,13 @@ public class CertificateIssueForm extends Form { if (login) { result.setLoginEnabled(true); } + if (req.getParameter("description") != null) { + String description = req.getParameter("description").trim(); + if (description.length() > 100) { + throw new GigiApiException("Submitted description is longer than 100 characters."); + } + result.setDescription(description); + } result.issue(issueDate.getFrom(), issueDate.getTo(), c.getActor()).waitFor(60000); this.result = result; Certificate c = result; diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.templ b/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.templ index 494a7ff5..68b87135 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.templ +++ b/src/club/wpia/gigi/pages/account/certs/CertificateIssueForm.templ @@ -97,7 +97,7 @@ -
+
diff --git a/tests/club/wpia/gigi/TestCertificate.java b/tests/club/wpia/gigi/TestCertificate.java index 058c029e..d76c5140 100644 --- a/tests/club/wpia/gigi/TestCertificate.java +++ b/tests/club/wpia/gigi/TestCertificate.java @@ -25,6 +25,7 @@ import club.wpia.gigi.dbObjects.User; import club.wpia.gigi.pages.account.certs.Certificates; import club.wpia.gigi.testUtils.IOUtils; import club.wpia.gigi.testUtils.ManagedTest; +import club.wpia.gigi.util.RandomToken; import sun.security.x509.GeneralNameInterface; public class TestCertificate extends ManagedTest { @@ -159,4 +160,22 @@ public class TestCertificate extends ManagedTest { } } } + + @Test + public void testClientCertDescription() throws IOException, GeneralSecurityException, SQLException, InterruptedException, GigiApiException { + KeyPair kp = generateKeypair(); + String key1 = generatePEMCSR(kp, "CN=testmail@example.com"); + Certificate c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key1, CSRType.CSR, getClientProfile()); + await(c.issue(null, "2y", u)); + String description = RandomToken.generateToken(95) + DIFFICULT_CHARS; + c.setDescription(description); + assertEquals(description, c.getDescription()); + + // test that description is entered to db + int cid = c.getId(); + clearCaches(); + Certificate cn = Certificate.getById(cid); + assertEquals(description, cn.getDescription()); + + } } diff --git a/tests/club/wpia/gigi/pages/account/TestCertificateAdd.java b/tests/club/wpia/gigi/pages/account/TestCertificateAdd.java index bac62175..949085c4 100644 --- a/tests/club/wpia/gigi/pages/account/TestCertificateAdd.java +++ b/tests/club/wpia/gigi/pages/account/TestCertificateAdd.java @@ -1,6 +1,7 @@ package club.wpia.gigi.pages.account; import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; @@ -37,9 +38,11 @@ import club.wpia.gigi.dbObjects.CertificateOwner; import club.wpia.gigi.dbObjects.Digest; import club.wpia.gigi.pages.account.certs.CertificateAdd; import club.wpia.gigi.pages.account.certs.CertificateRequest; +import club.wpia.gigi.pages.account.certs.Certificates; import club.wpia.gigi.testUtils.ClientTest; import club.wpia.gigi.testUtils.IOUtils; import club.wpia.gigi.util.PEM; +import club.wpia.gigi.util.RandomToken; import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs10.PKCS10Attribute; @@ -130,24 +133,7 @@ public class TestCertificateAdd extends ClientTest { @Test public void testIssue() throws IOException, GeneralSecurityException { - PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { - CertificateRequest.OID_KEY_USAGE_SSL_CLIENT - }, new RFC822Name(email)); - - String pem = generatePEMCSR(kp, "CN=a b,email=" + email, atts, "SHA512WithRSA"); - - String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); - assertArrayEquals(new String[] { - "client", "a b", "email:" + email + "\n", Digest.SHA512.toString() - }, res); - - HttpURLConnection huc = (HttpURLConnection) ncert.openConnection(); - huc.setRequestProperty("Cookie", cookie); - huc.setDoOutput(true); - OutputStream out = huc.getOutputStream(); - out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8")); - out.write(("&CN=" + URLEncoder.encode(CertificateRequest.DEFAULT_CN, "UTF-8") + "&profile=client&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8")); - out.write(("&hash_alg=SHA512").getBytes("UTF-8")); + HttpURLConnection huc = sendCertificateForm("description"); URLConnection uc = authenticate(new URL(huc.getHeaderField("Location") + ".crt")); String crt = IOUtils.readURL(new InputStreamReader(uc.getInputStream(), "UTF-8")); @@ -174,7 +160,48 @@ public class TestCertificateAdd extends ClientTest { assertThat(gui, containsString("CN=" + CertificateRequest.DEFAULT_CN)); assertThat(gui, containsString("SHA512withRSA")); assertThat(gui, containsString("RFC822Name: " + email)); + } + + @Test + public void testIssueWithDescription() throws IOException, GeneralSecurityException { + String description = "Just a new comment." + RandomToken.generateToken(32); + HttpURLConnection huc = sendCertificateForm(description); + assertEquals(302, huc.getResponseCode()); + + URLConnection uc = get(Certificates.PATH); + assertThat(IOUtils.readURL(uc), containsString(description)); + + description = "Just a new comment." + RandomToken.generateToken(100); + huc = sendCertificateForm(description); + assertThat(fetchStartErrorMessage(IOUtils.readURL(huc)), containsString("Submitted description is longer than 100 characters.")); + } + + private HttpURLConnection sendCertificateForm(String description) throws IOException, GeneralSecurityException { + HttpURLConnection huc = openCertificateForm(); + OutputStream out = huc.getOutputStream(); + out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8")); + out.write(("&CN=" + URLEncoder.encode(CertificateRequest.DEFAULT_CN, "UTF-8") + "&profile=client&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8")); + out.write(("&hash_alg=SHA512").getBytes("UTF-8")); + out.write(("&description=" + URLEncoder.encode(description, "UTF-8")).getBytes("UTF-8")); + return huc; + } + + private HttpURLConnection openCertificateForm() throws IOException, GeneralSecurityException, UnsupportedEncodingException { + PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { + CertificateRequest.OID_KEY_USAGE_SSL_CLIENT + }, new RFC822Name(email)); + + String pem = generatePEMCSR(kp, "CN=a b,email=" + email, atts, "SHA512WithRSA"); + + String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); + assertArrayEquals(new String[] { + "client", "a b", "email:" + email + "\n", Digest.SHA512.toString() + }, res); + HttpURLConnection huc = (HttpURLConnection) ncert.openConnection(); + huc.setRequestProperty("Cookie", cookie); + huc.setDoOutput(true); + return huc; } private byte[] verifyChain(X509Certificate[] x509Certificates) throws GeneralSecurityException { @@ -257,16 +284,7 @@ public class TestCertificateAdd extends ClientTest { } private X509Certificate createCertWithValidity(String validity, boolean login) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException { - PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { - CertificateRequest.OID_KEY_USAGE_SSL_CLIENT - }, new RFC822Name(email)); - - String pem = generatePEMCSR(kp, "CN=a b", atts, "SHA512WithRSA"); - fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); - - HttpURLConnection huc = (HttpURLConnection) ncert.openConnection(); - huc.setRequestProperty("Cookie", cookie); - huc.setDoOutput(true); + HttpURLConnection huc = openCertificateForm(); OutputStream out = huc.getOutputStream(); out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8")); out.write(("&profile=client&CN=" + CertificateRequest.DEFAULT_CN + "&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8"));