1 package club.wpia.gigi.ping;
3 import static org.junit.Assert.*;
4 import static org.junit.Assume.*;
6 import java.io.IOException;
7 import java.security.GeneralSecurityException;
8 import java.security.KeyPair;
10 import java.util.List;
12 import org.hamcrest.CoreMatchers;
13 import org.junit.Test;
15 import club.wpia.gigi.GigiApiException;
16 import club.wpia.gigi.dbObjects.Certificate;
17 import club.wpia.gigi.dbObjects.Certificate.CSRType;
18 import club.wpia.gigi.dbObjects.Certificate.CertificateStatus;
19 import club.wpia.gigi.dbObjects.Certificate.SANType;
20 import club.wpia.gigi.dbObjects.CertificateProfile;
21 import club.wpia.gigi.dbObjects.Digest;
22 import club.wpia.gigi.dbObjects.Domain;
23 import club.wpia.gigi.dbObjects.DomainPingConfiguration;
24 import club.wpia.gigi.dbObjects.DomainPingExecution;
25 import club.wpia.gigi.dbObjects.DomainPingType;
26 import club.wpia.gigi.pages.account.domain.EditDomain;
27 import club.wpia.gigi.ping.DomainPinger.PingState;
28 import club.wpia.gigi.testUtils.PingTest;
29 import club.wpia.gigi.testUtils.TestEmailReceiver.TestMail;
30 import club.wpia.gigi.util.RandomToken;
31 import club.wpia.gigi.util.ServerConstants;
32 import club.wpia.gigi.util.ServerConstants.Host;
33 import club.wpia.gigi.util.SimpleSigner;
35 public class TestTiming extends PingTest {
38 public void httpAndMailSuccessCert() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
39 httpAndMailSuccess(true, false);
43 public void httpAndMailSuccessCertAndCorrect() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
44 httpAndMailSuccess(true, true);
48 public void httpAndMailSuccessNoCert() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
49 httpAndMailSuccess(false, false);
52 public void httpAndMailSuccess(boolean certs, boolean correct) throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
53 String test = getTestProps().getProperty("domain.http");
56 // When we have a domain.
57 Domain d = new Domain(u, u, test);
58 String token = RandomToken.generateToken(16);
59 String value = RandomToken.generateToken(16);
61 // If we run the sub case that we have certificates on the domain,
62 // create a certificate now.
65 KeyPair kp = generateKeypair();
66 String key = generatePEMCSR(kp, "CN=testmail@example.com");
67 c = new Certificate(u, u, Certificate.buildDN("CN", "testmail@example.com"), Digest.SHA256, key, CSRType.CSR, CertificateProfile.getByName("server"), new Certificate.SubjectAlternateName(SANType.DNS, test));
68 await(c.issue(null, "2y", u));
71 // Register HTTP and Email pings.
72 updateService(token, value, "http");
73 d.addPing(DomainPingType.EMAIL, "postmaster");
74 d.addPing(DomainPingType.HTTP, token + ":" + value);
76 // Two successful pings
77 getMailReceiver().receive("postmaster@" + test).verify();
80 assertEquals(0, countFailed(d.getPings(), 2));
82 // An own Pinger Daemon to control ping execution locally.
83 PingerDaemon pd = new PingerDaemon(null);
84 pd.initializeConnectionUsage();
86 // After 6 months the pings are executed again
87 pd.executeNeededPings(new Date(System.currentTimeMillis() + 6 * 31 * 24 * 60 * 60L * 1000));
88 getMailReceiver().receive("postmaster@" + test).verify();
90 assertEquals(0, countFailed(d.getPings(), 4));
92 // After 6 months the pings are executed again, but when the HTTP file
93 // is wrong, that ping fails.
94 updateService(token, value + "broken", "http");
95 // Note that the time is still 6 months in the future, as the pings from
96 // before were still executed (and logged)
98 pd.executeNeededPings(new Date(System.currentTimeMillis() + 6 * 31 * 24 * 60 * 60L * 1000));
99 getMailReceiver().receive("postmaster@" + test).verify();
101 assertEquals(1, countFailed(d.getPings(), 6));
102 // Which renders the domain invalid
103 assertFalse(d.isVerified());
106 // And the user gets a warning-mail if there was a cert
107 TestMail mail = getMailReceiver().receive(u.getEmail());
108 assertThat(mail.getMessage(), CoreMatchers.containsString(d.getSuffix()));
109 assertThat(mail.getMessage(), CoreMatchers.containsString(c.getSerial()));
111 // If the user ignores the warning, after two weeks
112 pd.executeNeededPings(new Date(System.currentTimeMillis() + 15 * 24 * 60 * 60L * 1000));
113 // The user receives another warning mail.
114 mail = getMailReceiver().receive(u.getEmail());
115 assertThat(mail.getMessage(), CoreMatchers.containsString("https://" + ServerConstants.getHostNamePortSecure(Host.WWW) + EditDomain.PATH + d.getId()));
116 assertThat(mail.getMessage(), CoreMatchers.containsString(d.getSuffix()));
117 assertThat(mail.getMessage(), CoreMatchers.containsString(c.getSerial()));
118 // And when the revocation is carried out
120 // ... and the certificate gets revoked.
121 assertEquals(CertificateStatus.REVOKED, c.getStatus());
123 // But if the user corrects the ping, ...
124 updateService(token, value, "http");
125 // ... and the ping is re-executed,
126 pd.handle(getPing(d.getConfiguredPings(), DomainPingType.HTTP));
128 assertEquals(1, countFailed(d.getPings(), 7));
130 // Even after two weeks
131 pd.executeNeededPings(new Date(System.currentTimeMillis() + 15 * 24 * 60 * 60L * 1000));
132 // and all resulting jobs are executed
134 // ... the certificate stays valid.
135 assertEquals(CertificateStatus.ISSUED, c.getStatus());
138 // otherwise there is no mail
143 private DomainPingConfiguration getPing(List<DomainPingConfiguration> cp, DomainPingType tp) {
144 for (DomainPingConfiguration d : cp) {
145 if (d.getType() == tp) {
149 throw new Error("Type not found.");
152 private int countFailed(DomainPingExecution[] pg, int count) {
153 assertEquals(count, pg.length);
155 for (DomainPingExecution e : pg) {
156 PingState state = e.getState();
157 if (e.getConfig().getType() == DomainPingType.HTTP) {
158 if (state == PingState.FAILED) {
163 assertEquals(PingState.SUCCESS, state);