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.Digest;
36 import org.cacert.gigi.dbObjects.User;
37 import org.cacert.gigi.pages.account.domain.DomainOverview;
38 import org.cacert.gigi.testUtils.IOUtils;
39 import org.cacert.gigi.testUtils.PingTest;
40 import org.cacert.gigi.testUtils.TestEmailReceiver.TestMail;
41 import org.junit.Test;
43 public class TestSSL extends PingTest {
45 public abstract static class AsyncTask<T> {
53 public T join() throws InterruptedException {
62 runner = new Thread() {
67 res = AsyncTask.this.run();
68 } catch (Exception e) {
76 public abstract T run() throws Exception;
82 private Certificate c;
84 @Test(timeout = 70000)
85 public void sslAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
86 testEmailAndSSL(0, 0, true);
89 @Test(timeout = 70000)
90 public void sslWongTypeAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
91 testEmailAndSSL(1, 0, true);
94 @Test(timeout = 70000)
95 public void sslOneMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
96 testEmailAndSSL(2, 0, true);
99 @Test(timeout = 70000)
100 public void sslBothMissingAndMailSuccess() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
101 testEmailAndSSL(3, 0, true);
104 @Test(timeout = 70000)
105 public void sslWrongTypeAndMailFail() throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
106 testEmailAndSSL(1, 1, false);
112 * <li>0= all valid</li>
113 * <li>1= wrong type</li>
114 * <li>2= one server missing</li>
115 * <li>3= both servers missing</li>
117 * @param emailVariant
120 * @throws IOException
121 * @throws InterruptedException
122 * @throws SQLException
123 * @throws GeneralSecurityException
124 * @throws GigiApiException
127 private void testEmailAndSSL(int sslVariant, int emailVariant, boolean successMail) throws IOException, InterruptedException, SQLException, GeneralSecurityException, GigiApiException {
128 String test = getTestProps().getProperty("domain.local");
130 URL u = new URL("https://" + getServerName() + DomainOverview.PATH);
132 initailizeDomainForm(u);
134 createCertificate(test, CertificateProfile.getByName(sslVariant == 1 ? "client" : "server"));
135 final SSLServerSocket sss = createSSLServer(kp.getPrivate(), c.cert());
136 int port = sss.getLocalPort();
137 final SSLServerSocket sss2 = createSSLServer(kp.getPrivate(), c.cert());
138 int port2 = sss2.getLocalPort();
139 if (sslVariant == 3 || sslVariant == 2) {
141 if (sslVariant == 3) {
145 String content = "adddomain&newdomain=" + URLEncoder.encode(test, "UTF-8") + //
146 "&emailType=y&email=2&SSLType=y" + //
147 "&ssl-type-0=direct&ssl-port-0=" + port + //
148 "&ssl-type-1=direct&ssl-port-1=" + port2 + //
149 "&ssl-type-2=direct&ssl-port-2=" + //
150 "&ssl-type-3=direct&ssl-port-3=" + //
151 "&adddomain&csrf=" + csrf;
152 URL u2 = sendDomainForm(u, content);
153 boolean firstSucceeds = sslVariant != 0 && sslVariant != 2;
154 AsyncTask<Boolean> ass = new AsyncTask<Boolean>() {
157 public Boolean run() throws Exception {
158 return acceptSSLServer(sss);
162 System.out.println(port + " and " + port2 + " ready");
163 System.err.println(port + " and " + port2 + " ready");
164 boolean accept2 = acceptSSLServer(sss2);
165 boolean accept1 = ass.join();
166 assertTrue(firstSucceeds ^ accept1);
167 boolean secondsSucceeds = sslVariant != 0;
168 assertTrue(secondsSucceeds ^ accept2);
170 TestMail mail = getMailReciever().receive();
171 if (emailVariant == 0) {
176 String newcontent = IOUtils.readURL(cookie(u2.openConnection(), cookie));
177 Pattern pat = Pattern.compile("<td>ssl</td>\\s*<td>success</td>");
178 Matcher matcher = pat.matcher(newcontent);
179 assertTrue(newcontent, firstSucceeds ^ matcher.find());
180 assertTrue(newcontent, secondsSucceeds ^ matcher.find());
181 assertFalse(newcontent, matcher.find());
182 pat = Pattern.compile("<td>email</td>\\s*<td>success</td>");
183 assertTrue(newcontent, !successMail ^ pat.matcher(newcontent).find());
186 private void createCertificate(String test, CertificateProfile profile) throws GeneralSecurityException, IOException, SQLException, InterruptedException, GigiApiException {
187 kp = generateKeypair();
188 String csr = generatePEMCSR(kp, "CN=" + test);
189 User u = User.getById(id);
190 c = new Certificate(u, u, Certificate.buildDN("CN", test), Digest.SHA256, csr, CSRType.CSR, profile);
191 c.issue(null, "2y", u).waitFor(60000);
194 private boolean acceptSSLServer(SSLServerSocket sss) throws IOException {
195 try (Socket s = sss.accept()) {
196 s.getOutputStream().write('b');
197 s.getOutputStream().close();
199 } catch (IOException e) {
204 private SSLServerSocket createSSLServer(final PrivateKey priv, final X509Certificate cert) throws Error, IOException {
207 sc = SSLContext.getInstance("SSL");
208 sc.init(new KeyManager[] {
209 new X509KeyManager() {
212 public String[] getServerAliases(String keyType, Principal[] issuers) {
213 return new String[] {
219 public PrivateKey getPrivateKey(String alias) {
224 public String[] getClientAliases(String keyType, Principal[] issuers) {
229 public X509Certificate[] getCertificateChain(String alias) {
230 return new X509Certificate[] {
236 public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
241 public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
246 }, new TrustManager[] {
247 new X509TrustManager() {
250 public X509Certificate[] getAcceptedIssuers() {
255 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
258 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
260 }, new SecureRandom());
261 } catch (NoSuchAlgorithmException e) {
264 } catch (KeyManagementException e) {
269 SSLServerSocketFactory sssf = sc.getServerSocketFactory();
270 return (SSLServerSocket) sssf.createServerSocket(0);
273 public static void main(String[] args) throws Exception {
275 TestSSL t1 = new TestSSL();
276 t1.sslAndMailSuccess();