/** * Copyright (C) 2013-2015 all@code-story.net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package net.codestory.http.ssl; import net.codestory.http.WebServer; import net.codestory.http.io.ClassPaths; import org.junit.After; import org.junit.Test; import javax.net.ssl.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; public class SSLTest { WebServer webServer = new WebServer(); @After public void tearDown() { if (webServer != null) { webServer.stop(); } } @Test public void start_server() throws URISyntaxException { Path pathCertificate = resource("certificates/server.crt"); Path pathPrivateKey = resource("certificates/server.der"); webServer.startSSL(0, pathCertificate, pathPrivateKey); } @Test public void certificate_chain() throws Exception { Path pathEECertificate = resource("certificates/ee.crt"); Path pathSubCACertificate = resource("certificates/sub.crt"); Path pathRootCACertificate = resource("certificates/root.crt"); Path pathPrivateKey = resource("certificates/ee.der"); webServer.startSSL(0, asList(pathEECertificate, pathSubCACertificate), pathPrivateKey); HttpsURLConnection conn = httpGet(webServer, getSocketFactory(pathRootCACertificate)); assertThat(conn.getServerCertificates()).hasSize(2); assertThat(conn.getServerCertificates()[0].getEncoded()).isEqualTo(getCertificateFromPath(pathEECertificate).getEncoded()); assertThat(conn.getServerCertificates()[1].getEncoded()).isEqualTo(getCertificateFromPath(pathSubCACertificate).getEncoded()); } @Test public void client_auth() throws Exception { Path pathEECertificate = resource("certificates/ee.crt"); Path pathSubCACertificate = resource("certificates/sub.crt"); Path pathPrivateKey = resource("certificates/ee.der"); Path pathTrustAnchors = resource("certificates/root.crt"); Path pathClientCertificate = resource("certificates/client.pfx"); webServer.startSSL(0, asList(pathEECertificate, pathSubCACertificate), pathPrivateKey, singletonList(pathTrustAnchors)); httpGet(webServer, getSocketFactory(pathTrustAnchors, pathClientCertificate)); } @Test(expected = Exception.class) public void client_auth_failure() throws Exception { Path pathEECertificate = resource("certificates/ee.crt"); Path pathSubCACertificate = resource("certificates/sub.crt"); Path pathPrivateKey = resource("certificates/ee.der"); Path pathTrustAnchors = resource("certificates/root.crt"); webServer.startSSL(0, asList(pathEECertificate, pathSubCACertificate), pathPrivateKey, singletonList(pathTrustAnchors)); httpGet(webServer, getSocketFactory(pathTrustAnchors)); } private HttpsURLConnection httpGet(WebServer webServer, SSLSocketFactory socketFactory) throws IOException { URL url = new URL("https://localhost:" + webServer.port()); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(socketFactory); conn.setRequestMethod("GET"); conn.getResponseCode(); return conn; } private static Path resource(String name) throws URISyntaxException { return Paths.get(ClassPaths.getResource(name).toURI()); } private static SSLSocketFactory getSocketFactory(Path caCertificate) throws Exception { return getSocketFactory(caCertificate, null); } private static SSLSocketFactory getSocketFactory(Path caCertificate, Path clientCertificate) throws Exception { // System.setProperty("https.protocols", "SSLv3"); SSLContext ctx = SSLContext.getInstance("TLS"); KeyStore ts = KeyStore.getInstance("JKS"); ts.load(null); ts.setCertificateEntry("rootca", getCertificateFromPath(caCertificate)); TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ts); TrustManager[] tm = tmf.getTrustManagers(); KeyManager[] km = null; if (clientCertificate != null) { KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(Files.newInputStream(clientCertificate), "password".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); kmf.init(ks, "password".toCharArray()); km = kmf.getKeyManagers(); } ctx.init(km, tm, null); return ctx.getSocketFactory(); } private static Certificate getCertificateFromPath(Path certPath) throws CertificateException, IOException { return CertificateFactory.getInstance("X.509").generateCertificate( new ByteArrayInputStream(Files.readAllBytes(certPath))); } }