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