1 package org.cacert.gigi.ping;
3 import static org.junit.Assert.*;
4 import static org.junit.Assume.*;
6 import java.io.IOException;
7 import java.net.Socket;
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;
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;
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.TestEmailReceiver.TestMail;
40 import org.junit.Test;
42 public class TestSSL extends PingTest {
44 public abstract static class AsyncTask<T> {
52 public T join() throws InterruptedException {
61 runner = new Thread() {
66 res = AsyncTask.this.run();
67 } catch (Exception e) {
75 public abstract T run() throws Exception;
81 private Certificate c;
83 @Test(timeout = 70000)
84 public void sslAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
85 testEmailAndSSL(0, 0, true);
88 @Test(timeout = 70000)
89 public void sslWongTypeAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
90 testEmailAndSSL(1, 0, true);
93 @Test(timeout = 70000)
94 public void sslOneMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
95 testEmailAndSSL(2, 0, true);
98 @Test(timeout = 70000)
99 public void sslBothMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
100 testEmailAndSSL(3, 0, true);
103 @Test(timeout = 70000)
104 public void sslWrongTypeAndMailFail() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
105 testEmailAndSSL(1, 1, false);
111 * <li>0= all valid</li>
112 * <li>1= wrong type</li>
113 * <li>2= one server missing</li>
114 * <li>3= both servers missing</li>
116 * @param emailVariant
119 * @throws IOException
120 * @throws InterruptedException
121 * @throws SQLException
122 * @throws GeneralSecurityException
123 * @throws GigiApiException
126 private void testEmailAndSSL(int sslVariant, int emailVariant, boolean successMail) throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
127 String test = getTestProps().getProperty("domain.local");
129 URL u = new URL("https://" + getServerName() + DomainOverview.PATH);
131 initailizeDomainForm(u);
133 createCertificate(test, CertificateProfile.getByName(sslVariant == 1 ? "client" : "server"));
134 final SSLServerSocket sss = createSSLServer(kp.getPrivate(), c.cert());
135 int port = sss.getLocalPort();
136 final SSLServerSocket sss2 = createSSLServer(kp.getPrivate(), c.cert());
137 int port2 = sss2.getLocalPort();
138 if (sslVariant == 3 || sslVariant == 2) {
140 if (sslVariant == 3) {
144 String content = "adddomain&newdomain=" + URLEncoder.encode(test, "UTF-8") + //
145 "&emailType=y&email=2&SSLType=y" + //
146 "&ssl-type-0=direct&ssl-port-0=" + port + //
147 "&ssl-type-1=direct&ssl-port-1=" + port2 + //
148 "&ssl-type-2=direct&ssl-port-2=" + //
149 "&ssl-type-3=direct&ssl-port-3=" + //
150 "&adddomain&csrf=" + csrf;
151 URL u2 = sendDomainForm(u, content);
152 boolean firstSucceeds = sslVariant != 0 && sslVariant != 2;
153 AsyncTask<Boolean> ass = new AsyncTask<Boolean>() {
156 public Boolean run() throws Exception {
157 return acceptSSLServer(sss);
161 System.out.println(port + " and " + port2 + " ready");
162 System.err.println(port + " and " + port2 + " ready");
163 boolean accept2 = acceptSSLServer(sss2);
164 boolean accept1 = ass.join();
165 assertTrue(firstSucceeds ^ accept1);
166 boolean secondsSucceeds = sslVariant != 0;
167 assertTrue(secondsSucceeds ^ accept2);
169 TestMail mail = getMailReciever().receive();
170 if (emailVariant == 0) {
175 String newcontent = IOUtils.readURL(cookie(u2.openConnection(), cookie));
176 Pattern pat = Pattern.compile("<td>ssl</td>\\s*<td>success</td>");
177 Matcher matcher = pat.matcher(newcontent);
178 assertTrue(newcontent, firstSucceeds ^ matcher.find());
179 assertTrue(newcontent, secondsSucceeds ^ matcher.find());
180 assertFalse(newcontent, matcher.find());
181 pat = Pattern.compile("<td>email</td>\\s*<td>success</td>");
182 assertTrue(newcontent, !successMail ^ pat.matcher(newcontent).find());
185 private void createCertificate(String test, CertificateProfile profile) throws GeneralSecurityException, IOException, SQLException, InterruptedException, GigiApiException {
186 kp = generateKeypair();
187 String csr = generatePEMCSR(kp, "CN=" + test);
188 User u = User.getById(id);
189 c = new Certificate(u, u, Certificate.buildDN("CN", test), "sha256", csr, CSRType.CSR, profile);
190 c.issue(null, "2y", u).waitFor(60000);
193 private boolean acceptSSLServer(SSLServerSocket sss) throws IOException {
194 try (Socket s = sss.accept()) {
195 s.getOutputStream().write('b');
196 s.getOutputStream().close();
198 } catch (IOException e) {
203 private SSLServerSocket createSSLServer(final PrivateKey priv, final X509Certificate cert) throws Error, IOException {
206 sc = SSLContext.getInstance("SSL");
207 sc.init(new KeyManager[] {
208 new X509KeyManager() {
211 public String[] getServerAliases(String keyType, Principal[] issuers) {
212 return new String[] {
218 public PrivateKey getPrivateKey(String alias) {
223 public String[] getClientAliases(String keyType, Principal[] issuers) {
228 public X509Certificate[] getCertificateChain(String alias) {
229 return new X509Certificate[] {
235 public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
240 public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
245 }, new TrustManager[] {
246 new X509TrustManager() {
249 public X509Certificate[] getAcceptedIssuers() {
254 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
257 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
259 }, new SecureRandom());
260 } catch (NoSuchAlgorithmException e) {
263 } catch (KeyManagementException e) {
268 SSLServerSocketFactory sssf = sc.getServerSocketFactory();
269 return (SSLServerSocket) sssf.createServerSocket(0);
272 public static void main(String[] args) throws Exception {
274 TestSSL t1 = new TestSSL();
275 t1.sslAndMailSuccess();