]> WPIA git - gigi.git/blob - tests/org/cacert/gigi/ping/TestSSL.java
ADD: Verify, only act on POST (+CSRF)
[gigi.git] / tests / org / cacert / gigi / ping / TestSSL.java
1 package org.cacert.gigi.ping;
2
3 import static org.junit.Assert.*;
4 import static org.junit.Assume.*;
5
6 import java.io.IOException;
7 import java.net.Socket;
8 import java.net.URL;
9 import java.net.URLEncoder;
10 import java.security.GeneralSecurityException;
11 import java.security.KeyManagementException;
12 import java.security.KeyPair;
13 import java.security.NoSuchAlgorithmException;
14 import java.security.Principal;
15 import java.security.PrivateKey;
16 import java.security.SecureRandom;
17 import java.security.cert.CertificateException;
18 import java.security.cert.X509Certificate;
19 import java.sql.SQLException;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import javax.net.ssl.KeyManager;
24 import javax.net.ssl.SSLContext;
25 import javax.net.ssl.SSLServerSocket;
26 import javax.net.ssl.SSLServerSocketFactory;
27 import javax.net.ssl.TrustManager;
28 import javax.net.ssl.X509KeyManager;
29 import javax.net.ssl.X509TrustManager;
30
31 import org.cacert.gigi.GigiApiException;
32 import org.cacert.gigi.dbObjects.Certificate;
33 import org.cacert.gigi.dbObjects.Certificate.CSRType;
34 import org.cacert.gigi.dbObjects.CertificateProfile;
35 import org.cacert.gigi.dbObjects.User;
36 import org.cacert.gigi.pages.account.domain.DomainOverview;
37 import org.cacert.gigi.testUtils.IOUtils;
38 import org.cacert.gigi.testUtils.PingTest;
39 import org.cacert.gigi.testUtils.TestEmailReciever.TestMail;
40 import org.junit.Test;
41
42 public class TestSSL extends PingTest {
43
44     private KeyPair kp;
45
46     private Certificate c;
47
48     @Test(timeout = 70000)
49     public void sslAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
50         testEmailAndSSL(0, 0, true);
51     }
52
53     @Test(timeout = 70000)
54     public void sslWongTypeAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
55         testEmailAndSSL(1, 0, true);
56     }
57
58     @Test(timeout = 70000)
59     public void sslOneMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
60         testEmailAndSSL(2, 0, true);
61     }
62
63     @Test(timeout = 70000)
64     public void sslBothMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
65         testEmailAndSSL(3, 0, true);
66     }
67
68     @Test(timeout = 70000)
69     public void sslWrongTypeAndMailFail() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
70         testEmailAndSSL(1, 1, false);
71     }
72
73     /**
74      * @param sslVariant
75      *            <ul>
76      *            <li>0= all valid</li>
77      *            <li>1= wrong type</li>
78      *            <li>2= one server missing</li>
79      *            <li>3= both servers missing</li>
80      *            </ul>
81      * @param emailVariant
82      * @param successSSL
83      * @param successMail
84      * @throws IOException
85      * @throws InterruptedException
86      * @throws SQLException
87      * @throws GeneralSecurityException
88      * @throws GigiApiException
89      */
90
91     private void testEmailAndSSL(int sslVariant, int emailVariant, boolean successMail) throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
92         String test = getTestProps().getProperty("domain.local");
93         assumeNotNull(test);
94         URL u = new URL("https://" + getServerName() + DomainOverview.PATH);
95
96         initailizeDomainForm(u);
97
98         createCertificate(test, CertificateProfile.getByName(sslVariant == 1 ? "client" : "server"));
99         SSLServerSocket sss = createSSLServer(kp.getPrivate(), c.cert());
100         int port = sss.getLocalPort();
101         SSLServerSocket sss2 = createSSLServer(kp.getPrivate(), c.cert());
102         int port2 = sss2.getLocalPort();
103         if (sslVariant == 3 || sslVariant == 2) {
104             sss2.close();
105             if (sslVariant == 3) {
106                 sss.close();
107             }
108         }
109         String content = "newdomain=" + URLEncoder.encode(test, "UTF-8") + //
110                 "&emailType=y&email=2&SSLType=y" + //
111                 "&ssl-type-0=direct&ssl-port-0=" + port + //
112                 "&ssl-type-1=direct&ssl-port-1=" + port2 + //
113                 "&ssl-type-2=direct&ssl-port-2=" + //
114                 "&ssl-type-3=direct&ssl-port-3=" + //
115                 "&adddomain&csrf=" + csrf;
116         URL u2 = sendDomainForm(u, content);
117         boolean firstSucceeds = sslVariant != 0 && sslVariant != 2;
118         assertTrue(firstSucceeds ^ acceptSSLServer(sss));
119         boolean secondsSucceeds = sslVariant != 0;
120         assertTrue(secondsSucceeds ^ acceptSSLServer(sss2));
121
122         TestMail mail = getMailReciever().recieve();
123         if (emailVariant == 0) {
124             mail.verify();
125         }
126         waitForPings(3);
127
128         String newcontent = IOUtils.readURL(cookie(u2.openConnection(), cookie));
129         Pattern pat = Pattern.compile("<td>ssl</td>\\s*<td>success</td>");
130         Matcher matcher = pat.matcher(newcontent);
131         assertTrue(newcontent, firstSucceeds ^ matcher.find());
132         assertTrue(newcontent, secondsSucceeds ^ matcher.find());
133         assertFalse(newcontent, matcher.find());
134         pat = Pattern.compile("<td>email</td>\\s*<td>success</td>");
135         assertTrue(newcontent, !successMail ^ pat.matcher(newcontent).find());
136     }
137
138     private void createCertificate(String test, CertificateProfile profile) throws GeneralSecurityException, IOException, SQLException, InterruptedException, GigiApiException {
139         kp = generateKeypair();
140         String csr = generatePEMCSR(kp, "CN=" + test);
141         c = new Certificate(User.getById(id), Certificate.buildDN("CN", test), "sha256", csr, CSRType.CSR, profile);
142         c.issue(null, "2y").waitFor(60000);
143     }
144
145     private boolean acceptSSLServer(SSLServerSocket sss) throws IOException {
146         try {
147             Socket s = sss.accept();
148             s.getOutputStream().write('b');
149             s.getOutputStream().close();
150             return true;
151         } catch (IOException e) {
152             return false;
153         }
154     }
155
156     private SSLServerSocket createSSLServer(final PrivateKey priv, final X509Certificate cert) throws Error, IOException {
157         SSLContext sc;
158         try {
159             sc = SSLContext.getInstance("SSL");
160             sc.init(new KeyManager[] {
161                 new X509KeyManager() {
162
163                     @Override
164                     public String[] getServerAliases(String keyType, Principal[] issuers) {
165                         return new String[] {
166                             "server"
167                         };
168                     }
169
170                     @Override
171                     public PrivateKey getPrivateKey(String alias) {
172                         return priv;
173                     }
174
175                     @Override
176                     public String[] getClientAliases(String keyType, Principal[] issuers) {
177                         throw new Error();
178                     }
179
180                     @Override
181                     public X509Certificate[] getCertificateChain(String alias) {
182                         return new X509Certificate[] {
183                             cert
184                         };
185                     }
186
187                     @Override
188                     public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
189                         throw new Error();
190                     }
191
192                     @Override
193                     public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
194                         return "server";
195                     }
196
197                 }
198             }, new TrustManager[] {
199                 new X509TrustManager() {
200
201                     @Override
202                     public X509Certificate[] getAcceptedIssuers() {
203                         return null;
204                     }
205
206                     @Override
207                     public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
208
209                     @Override
210                     public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
211                 }
212             }, new SecureRandom());
213         } catch (NoSuchAlgorithmException e) {
214             e.printStackTrace();
215             throw new Error(e);
216         } catch (KeyManagementException e) {
217             e.printStackTrace();
218             throw new Error(e);
219         }
220
221         SSLServerSocketFactory sssf = sc.getServerSocketFactory();
222         return (SSLServerSocket) sssf.createServerSocket(0);
223     }
224
225 }