Package com.urswolfer.intellij.plugin.gerrit.rest

Source Code of com.urswolfer.intellij.plugin.gerrit.rest.SslSupport

/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2013 Urs Wolfer
*
* 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 com.urswolfer.intellij.plugin.gerrit.rest;

import com.google.common.base.Throwables;
import com.google.inject.Inject;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.CalledInAwt;
import com.urswolfer.gerrit.client.rest.http.HttpRequestExecutor;
import com.urswolfer.intellij.plugin.gerrit.GerritSettings;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.security.validator.ValidatorException;

import javax.net.ssl.SSLException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

/**
* Provides various methods to work with SSL certificate protected HTTPS connections.
* Parts based on org.jetbrains.plugins.github.GithubSslSupport
*
* @author Kirill Likhodedov
* @author Urs Wolfer
*/
public class SslSupport extends HttpRequestExecutor {

    @Inject
    private GerritSettings gerritSettings;

    /**
     * Tries to execute the {@link HttpRequestBase} and captures the {@link ValidatorException exception} which is thrown if user connects
     * to an HTTPS server with a non-trusted (probably, self-signed) SSL certificate. In which case proposes to cancel the connection
     * or to proceed without certificate check.
     *
     * @return the HttpMethod instance which was actually executed
     *         and which can be {@link org.apache.http.HttpResponse#getEntity()} asked for the response.
     * @throws IOException in case of other errors or if user declines the proposal of non-trusted connection.
     */
    @Override
    public HttpResponse execute(HttpClientBuilder client,
                                HttpRequestBase method,
                                @Nullable HttpContext context)
            throws IOException {
        try {
            return client.build().execute(method, context);
        } catch (IOException e) {
            method.reset();
            HttpResponse m = handleCertificateExceptionAndRetry(e, method, client, context);
            if (m == null) {
                throw e;
            }
            return m;
        }
    }

    @Nullable
    private HttpResponse handleCertificateExceptionAndRetry(IOException e,
                                                            HttpRequestBase method,
                                                            HttpClientBuilder client,
                                                            @Nullable HttpContext context)
            throws IOException {
        if (!isCertificateException(e)) {
            throw e;
        }

        if (isTrusted(method.getURI().getAuthority())) {
            // creating a special configuration that allows connections to non-trusted HTTPS hosts
            try {
                SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
                sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                });
                SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                        sslContextBuilder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("https", sslConnectionSocketFactory)
                        .build();

                PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                client.setConnectionManager(connectionManager);
            } catch (Exception sslException) {
                throw Throwables.propagate(sslException);
            }
            return client.build().execute(method, context);
        }
        throw e;
    }

    public boolean isCertificateException(Exception e) {
        List<Throwable> causalChain = Throwables.getCausalChain(e);
        for (Throwable throwable : causalChain) {
            if (throwable instanceof ValidatorException) {
                return true;
            }
            if (throwable instanceof SSLException) { // e.g. "SSLException: hostname in certificate didn't match: <localhost> != <unknown>"
                return true;
            }
        }
        return false;
    }

    private boolean isTrusted(@NotNull String host) {
        return gerritSettings.getTrustedHosts().contains(host);
    }

    private void saveToTrusted(@NotNull String host) {
        try {
            gerritSettings.addTrustedHost(new java.net.URI(host).getAuthority());
        } catch (URISyntaxException e) {
            throw Throwables.propagate(e);
        }
    }

    @CalledInAwt
    public boolean askIfShouldProceed(final String host) {
        int choice = Messages.showYesNoDialog("The security certificate of " + host + " is not trusted. Do you want to proceed anyway?",
                "Not Trusted Certificate", "Proceed anyway", "No, I don't trust", Messages.getErrorIcon());
        boolean trust = (choice == Messages.YES);
        if (trust) {
            saveToTrusted(host);
        }
        return trust;
    }
}
TOP

Related Classes of com.urswolfer.intellij.plugin.gerrit.rest.SslSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.