From 753ce950283248b931ee9da5158c88156c21e17d Mon Sep 17 00:00:00 2001 From: INOPIAE Date: Mon, 5 Feb 2018 10:43:51 +0100 Subject: [PATCH 1/1] chg: enforce email address for certificate was pinged within 6 months fixes issue #5 Change-Id: I612adef8c99c8eb1cdb6e5c7fa4cf56c34e66f34 --- .../wpia/gigi/dbObjects/EmailAddress.java | 4 +- .../account/certs/CertificateRequest.java | 10 +++- .../pages/account/TestCertificateRequest.java | 51 +++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/club/wpia/gigi/dbObjects/EmailAddress.java b/src/club/wpia/gigi/dbObjects/EmailAddress.java index 319e415b..7d4c984e 100644 --- a/src/club/wpia/gigi/dbObjects/EmailAddress.java +++ b/src/club/wpia/gigi/dbObjects/EmailAddress.java @@ -13,6 +13,7 @@ import club.wpia.gigi.email.MailProbe; import club.wpia.gigi.localisation.Language; import club.wpia.gigi.output.template.SprintfCommand; import club.wpia.gigi.util.RandomToken; +import club.wpia.gigi.util.TimeConditions; public class EmailAddress implements IdCachable, Verifyable { @@ -122,9 +123,10 @@ public class EmailAddress implements IdCachable, Verifyable { } public boolean isVerified() { - try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `status`='success'")) { + try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `status`='success' AND `when` > (now() - interval '1 months' * ?::INTEGER)")) { statmt.setString(1, address); statmt.setInt(2, owner.getId()); + statmt.setInt(3, TimeConditions.getInstance().getEmailPingMonths()); GigiResultSet e = statmt.executeQuery(); return e.next(); } diff --git a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java index 8a1bc594..cdf4dd41 100644 --- a/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java +++ b/src/club/wpia/gigi/pages/account/certs/CertificateRequest.java @@ -35,6 +35,7 @@ import club.wpia.gigi.util.DomainAssessment; import club.wpia.gigi.util.PEM; import club.wpia.gigi.util.RateLimit; import club.wpia.gigi.util.ServerConstants; +import club.wpia.gigi.util.TimeConditions; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs10.PKCS10; import sun.security.pkcs10.PKCS10Attribute; @@ -356,8 +357,8 @@ public class CertificateRequest { valid = false; } } - } else if (san.getType() == SANType.EMAIL) { - if (emailTemp != null && owner.isValidEmail(san.getName())) { + } else if (san.getType() == SANType.EMAIL && emailTemp != null) { + if (owner.isValidEmail(san.getName())) { if (pMail != null && !emailTemp.isMultiple()) { // remove } else { @@ -367,6 +368,11 @@ public class CertificateRequest { filteredSANs.add(san); continue; } + } else { + // remove + error.mergeInto(new GigiApiException(SprintfCommand.createSimple(// + "The requested subject alternate name email address \"{0}\" needs an email ping within the past {1} months.", san.getType().toString().toLowerCase() + ":" + san.getName(), TimeConditions.getInstance().getEmailPingMonths()))); + break; } } error.mergeInto(new GigiApiException(SprintfCommand.createSimple(// diff --git a/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java b/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java index 79edd932..da580ccf 100644 --- a/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java +++ b/tests/club/wpia/gigi/pages/account/TestCertificateRequest.java @@ -6,14 +6,19 @@ import static org.junit.Assert.*; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyPair; +import java.util.Locale; import org.junit.Test; import club.wpia.gigi.GigiApiException; +import club.wpia.gigi.database.GigiPreparedStatement; +import club.wpia.gigi.dbObjects.EmailAddress; import club.wpia.gigi.dbObjects.Group; import club.wpia.gigi.pages.account.certs.CertificateRequest; import club.wpia.gigi.testUtils.ClientTest; +import club.wpia.gigi.testUtils.TestEmailReceiver.TestMail; import club.wpia.gigi.util.AuthorizationContext; +import club.wpia.gigi.util.TimeConditions; public class TestCertificateRequest extends ClientTest { @@ -85,4 +90,50 @@ public class TestCertificateRequest extends ClientTest { } } + + @Test + public void testPingPeriodOneAddress() throws IOException, GeneralSecurityException, GigiApiException { + // get new email address with last ping in past + String furtherEmail = createUniqueName() + "@example.org"; + EmailAddress ea = new EmailAddress(u, furtherEmail, Locale.ENGLISH); + TestMail mail = getMailReceiver().receive(furtherEmail); + try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState`, `when` = (now() - interval '1 months' * ?::INTEGER) WHERE `email`=? ")) { + stmt.setInt(1, TimeConditions.getInstance().getEmailPingMonths()); + stmt.setString(2, furtherEmail); + stmt.executeUpdate(); + } + + try { + CertificateRequest cr = new CertificateRequest(ac, generatePEMCSR(kp, "CN=a ab")); + cr.update("name", "SHA512", "mail", null, null, "email:" + furtherEmail); + cr.draft(); + fail(); + } catch (GigiApiException e) { + assertThat(e.getMessage(), containsString("needs an email ping within the past")); + } + + } + + @Test + public void testPingPeriodTwoAddresses() throws IOException, GeneralSecurityException, GigiApiException { + // get new email address with last ping in past + String furtherEmail = createUniqueName() + "@example.org"; + EmailAddress ea = new EmailAddress(u, furtherEmail, Locale.ENGLISH); + TestMail mail = getMailReceiver().receive(furtherEmail); + try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState`, `when` = (now() - interval '1 months' * ?::INTEGER) WHERE `email`=? ")) { + stmt.setInt(1, TimeConditions.getInstance().getEmailPingMonths()); + stmt.setString(2, furtherEmail); + stmt.executeUpdate(); + } + + try { + CertificateRequest cr = new CertificateRequest(ac, generatePEMCSR(kp, "CN=a ab")); + cr.update("name", "SHA512", "mail", null, null, "email:" + furtherEmail + ",email:" + email); + cr.draft(); + fail(); + } catch (GigiApiException e) { + assertThat(e.getMessage(), containsString("needs an email ping within the past")); + } + + } } -- 2.39.2