no.kantega.kwashc.server.test.SSLProtocolTest.java Source code

Java tutorial

Introduction

Here is the source code for no.kantega.kwashc.server.test.SSLProtocolTest.java

Source

/*
 * Copyright 2013 Kantega AS
 *
 * 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 no.kantega.kwashc.server.test;

import no.kantega.kwashc.server.model.ResultEnum;
import no.kantega.kwashc.server.model.Site;
import no.kantega.kwashc.server.model.TestResult;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Test if the web application servlet container and underlying SSL/TLS Protocol implementation support TLS 1.2, and
 * does not allow usage of SSL 3.0 protocol.
 *
 * Solution, part 1: Either use Oracle JDK 8u31, JDK 7u75 or JDK 6u91 which has SSLv3.0 disabled by default, or add the
 * following to jetty-maven-plugin config:
 *
 * <excludeProtocols>
 *     <excludeProtocol>SSLv3</excludeProtocol>
 * </excludeProtocols>
 *
 * Solution, part 2: Running Jetty 8+ with oracle-jdk 1.7+. Old versions of oracle/sun jdk do not support TLSv 1.2.
 *
 *
 * References:
 * http://en.wikipedia.org/wiki/Transport_Layer_Security#Browser_implementations
 * http://www.oracle.com/technetwork/java/javase/documentation/cve-2014-3566-2342133.html
 *
 * @author Espen A. Fossen, (www.kantega.no)
 */
public class SSLProtocolTest extends AbstractTest {

    @Override
    public String getName() {
        return "Secure SSL/TLS Protocol";
    }

    @Override
    public String getDescription() {
        return DESCRIPTION_SECURE_COMMUNICATION + "<br><br>To ensure that the communication is secure it is "
                + "important to only support strong versions of the protocols.";
    }

    @Override
    public String getInformationURL() {
        return "https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet";
    }

    @Override
    public String getExploit(Site site) {
        return null;
    }

    @Override
    public String getHint() {
        return "SSLv3 has been disabled by default in Oracle JDK 7u75 or JDK 8u31 or newer, upgrading might be in order.";
    }

    @Override
    protected TestResult testSite(Site site, TestResult testResult) throws Throwable {
        long startTime = System.nanoTime();

        int httpsPort;
        try {
            httpsPort = new Integer(site.getSecureport());
        } catch (NumberFormatException e) {
            testResult.setResultEnum(ResultEnum.failed);
            testResult.setMessage("No HTTPS port specified, test not run!");
            setDuration(testResult, startTime);
            return testResult;
        }

        HttpClient httpclient = HttpClientUtil.getHttpClient();

        try {

            HttpClient httpClient = HttpClientUtil.getHttpClient();
            HttpResponse response = checkClient(site, httpsPort, httpClient, new String[] { "SSLv3" }, null);

            if (response.getStatusLine().getStatusCode() == 200) {
                testResult.setResultEnum(ResultEnum.failed);
                testResult.setMessage("Your application accepts an insecure SSL protocol!");
            } else {
                testResult.setResultEnum(ResultEnum.failed);
                testResult.setMessage("Actual testing failed, check that the connection is working!");
            }

        } catch (KeyManagementException e) {
            testResult.setResultEnum(ResultEnum.failed);
            testResult.setMessage(
                    "Certificate configuration does not seem to be correct, check certificate on remote environment!");
            return testResult;
        } catch (IOException e) {
            if (e.getMessage().contains("peer not authenticated")) {

                HttpClient httpClient = HttpClientUtil.getHttpClient();
                HttpResponse response = checkClient(site, httpsPort, httpClient, new String[] { "TLSv1.2" }, null);

                if (response.getStatusLine().getStatusCode() == 200) {
                    testResult.setResultEnum(ResultEnum.passed);
                    testResult
                            .setMessage("That`s better, you application supports secure SSL/TLS protocol TLSv1.2!");
                } else {
                    testResult.setResultEnum(ResultEnum.failed);
                    testResult.setMessage("Your application does not support secure SSL/TLS Protocols!");
                }
                return testResult;

            } else {
                testResult.setResultEnum(ResultEnum.failed);
                testResult.setMessage("Actual testing failed, check that the connection is working!");
            }
        } finally {
            httpclient.getConnectionManager().shutdown();
            setDuration(testResult, startTime);
        }

        return testResult;
    }

    private HttpResponse checkClient(Site site, int httpsPort, HttpClient httpclient, String[] protocols,
            String[] ciphers) throws NoSuchAlgorithmException, KeyManagementException, IOException {
        SSLContext sslcontext = SSLContext.getInstance("TLS");
        sslcontext.init(null, new TrustManager[] { allowAllTrustManager }, null);

        SSLSocketFactory sf = new SSLSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 1000);
        params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 1000);

        SSLSocket socket = (SSLSocket) sf.createSocket(params);
        if (protocols != null) {
            socket.setEnabledProtocols(protocols);
        }
        if (ciphers != null) {
            socket.setEnabledCipherSuites(ciphers);
        }

        URL url = new URL(site.getAddress());

        InetSocketAddress address = new InetSocketAddress(url.getHost(), httpsPort);
        sf.connectSocket(socket, address, null, params);

        Scheme sch = new Scheme("https", httpsPort, sf);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);

        HttpGet request = new HttpGet(
                "https://" + url.getHost() + ":" + site.getSecureport() + url.getPath() + "blog");

        return httpclient.execute(request);
    }

    TrustManager allowAllTrustManager = new X509TrustManager() {

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

    };

    @Override
    public TestCategory getTestCategory() {
        return TestCategory.crypto;
    }
}