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.ping.DomainPinger.PingState;
27 import club.wpia.gigi.testUtils.PingTest;
28 import club.wpia.gigi.testUtils.TestEmailReceiver.TestMail;
29 import club.wpia.gigi.util.RandomToken;
30 import club.wpia.gigi.util.SimpleSigner;
32 public class TestTiming extends PingTest {
35 public void httpAndMailSuccessCert() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
36 httpAndMailSuccess(true, false);
40 public void httpAndMailSuccessCertAndCorrect() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
41 httpAndMailSuccess(true, true);
45 public void httpAndMailSuccessNoCert() throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
46 httpAndMailSuccess(false, false);
49 public void httpAndMailSuccess(boolean certs, boolean correct) throws GigiApiException, IOException, InterruptedException, GeneralSecurityException {
50 String test = getTestProps().getProperty("domain.http");
53 // When we have a domain.
54 Domain d = new Domain(u, u, test);
55 String token = RandomToken.generateToken(16);
56 String value = RandomToken.generateToken(16);
58 // If we run the sub case that we have certificates on the domain,
59 // create a certificate now.
62 KeyPair kp = generateKeypair();
63 String key = generatePEMCSR(kp, "CN=testmail@example.com");
64 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));
65 await(c.issue(null, "2y", u));
68 // Register HTTP and Email pings.
69 updateService(token, value, "http");
70 d.addPing(DomainPingType.EMAIL, "postmaster");
71 d.addPing(DomainPingType.HTTP, token + ":" + value);
73 // Two successful pings
74 getMailReceiver().receive("postmaster@" + test).verify();
77 assertEquals(0, countFailed(d.getPings(), 2));
79 // An own Pinger Daemon to control ping execution locally.
80 PingerDaemon pd = new PingerDaemon(null);
81 pd.initializeConnectionUsage();
83 // After 6 months the pings are executed again
84 pd.executeNeededPings(new Date(System.currentTimeMillis() + 6 * 31 * 24 * 60 * 60L * 1000));
85 getMailReceiver().receive("postmaster@" + test).verify();
87 assertEquals(0, countFailed(d.getPings(), 4));
89 // After 6 months the pings are executed again, but when the HTTP file
90 // is wrong, that ping fails.
91 updateService(token, value + "broken", "http");
92 // Note that the time is still 6 months in the future, as the pings from
93 // before were still executed (and logged)
95 pd.executeNeededPings(new Date(System.currentTimeMillis() + 6 * 31 * 24 * 60 * 60L * 1000));
96 getMailReceiver().receive("postmaster@" + test).verify();
98 assertEquals(1, countFailed(d.getPings(), 6));
99 // Which renders the domain invalid
100 assertFalse(d.isVerified());
103 // And the user gets a warning-mail if there was a cert
104 TestMail mail = getMailReceiver().receive(u.getEmail());
105 assertThat(mail.getMessage(), CoreMatchers.containsString(d.getSuffix()));
106 assertThat(mail.getMessage(), CoreMatchers.containsString(c.getSerial()));
108 // If the user ignores the warning, after two weeks
109 pd.executeNeededPings(new Date(System.currentTimeMillis() + 15 * 24 * 60 * 60L * 1000));
110 // The user receives another warning mail.
111 mail = getMailReceiver().receive(u.getEmail());
112 assertThat(mail.getMessage(), CoreMatchers.containsString(d.getSuffix()));
113 assertThat(mail.getMessage(), CoreMatchers.containsString(c.getSerial()));
114 // And when the revocation is carried out
116 // ... and the certificate gets revoked.
117 assertEquals(CertificateStatus.REVOKED, c.getStatus());
119 // But if the user corrects the ping, ...
120 updateService(token, value, "http");
121 // ... and the ping is re-executed,
122 pd.handle(getPing(d.getConfiguredPings(), DomainPingType.HTTP));
124 assertEquals(1, countFailed(d.getPings(), 7));
126 // Even after two weeks
127 pd.executeNeededPings(new Date(System.currentTimeMillis() + 15 * 24 * 60 * 60L * 1000));
128 // and all resulting jobs are executed
130 // ... the certificate stays valid.
131 assertEquals(CertificateStatus.ISSUED, c.getStatus());
134 // otherwise there is no mail
139 private DomainPingConfiguration getPing(List<DomainPingConfiguration> cp, DomainPingType tp) {
140 for (DomainPingConfiguration d : cp) {
141 if (d.getType() == tp) {
145 throw new Error("Type not found.");
148 private int countFailed(DomainPingExecution[] pg, int count) {
149 assertEquals(count, pg.length);
151 for (DomainPingExecution e : pg) {
152 PingState state = e.getState();
153 if (e.getConfig().getType() == DomainPingType.HTTP) {
154 if (state == PingState.FAILED) {
159 assertEquals(PingState.SUCCESS, state);