ucar.httpservices.CustomSSLProtocolSocketFactory.java Source code

Java tutorial

Introduction

Here is the source code for ucar.httpservices.CustomSSLProtocolSocketFactory.java

Source

/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 ucar.httpservices;

import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.*;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.io.IOException;

public class CustomSSLProtocolSocketFactory implements SchemeLayeredSocketFactory {
    private SSLContext sslcontext = null;

    private SSLContext createSSLContext(HttpParams params) throws IOException {
        if (this.sslcontext == null)
            try {
                // Get the Desired kind of authentication
                this.sslcontext = trustedauthentication(params);
                if (this.sslcontext == null)
                    this.sslcontext = stdauthentication();
            } catch (KeyManagementException e) {
                throw new HTTPException("Key Management exception: " + e.getMessage());
            } catch (NoSuchAlgorithmException e) {
                throw new HTTPException("Unsupported algorithm exception: " + e.getMessage());
            } catch (KeyStoreException e) {
                throw new HTTPException("Keystore exception: " + e.getMessage());
            } catch (GeneralSecurityException e) {
                throw new HTTPException("Key management exception: " + e.getMessage());
            } catch (IOException e) {
                throw new HTTPException("I/O error reading keystore/truststore file: " + e.getMessage());
            } catch (Exception e) {
                throw new IOException(e.getMessage(), e);
            }
        return this.sslcontext;
    }

    // Default is to try self-signed certificates
    private SSLContext stdauthentication() throws Exception {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[] { new CustomX509TrustManager(null) }, null);
        return context;
    }

    private SSLContext trustedauthentication(HttpParams params) throws Exception {
        String keypath = null;
        String keypassword = null;
        String trustpath = null;
        String trustpassword = null;
        HTTPSSLProvider provider = null;
        if (params == null)
            return null;
        Object o = params.getParameter(HTTPAuthPolicy.PROVIDER);
        if (o == null)
            return null;
        if (!(o instanceof HTTPSSLProvider))
            throw new HTTPException("CustomSSLProtocolSocketFactory: provide is not SSL provider");
        provider = (HTTPSSLProvider) o;
        keypath = provider.getKeystore();
        keypassword = provider.getKeypassword();
        trustpath = provider.getTruststore();
        trustpassword = provider.getTrustpassword();

        TrustManager[] trustmanagers = null;
        KeyManager[] keymanagers = null;

        KeyStore keystore = buildstore(keypath, keypassword, "key");
        if (keystore != null) {
            KeyManagerFactory kmfactory = KeyManagerFactory.getInstance("SunX509");
            kmfactory.init(keystore, keypassword.toCharArray());
            keymanagers = kmfactory.getKeyManagers();
        }
        KeyStore truststore = buildstore(trustpath, trustpassword, "trust");
        if (truststore != null) {
            //todo: TrustManagerFactory trfactory = TrustManagerFactory.getInstance("SunX509");
            //trfactory.init(truststore, trustpassword.toCharArray());
            //trustmanagers = trfactory.getTrustManagers();
            trustmanagers = new TrustManager[] { new CustomX509TrustManager(truststore) };
        }
        if (trustmanagers == null)
            trustmanagers = new TrustManager[] { new CustomX509TrustManager(null) };

        SSLContext sslcontext = SSLContext.getInstance("TSL");
        sslcontext.init(keymanagers, trustmanagers, null);
        return sslcontext;
    }

    static KeyStore buildstore(String path, String password, String prefix) throws HTTPException {
        KeyStore store = null;
        try {
            if (path != null && password != null) {
                File storefile = new File(path);
                if (!storefile.canRead())
                    throw new HTTPException(
                            "Cannot read specified " + prefix + "store:" + storefile.getAbsolutePath());
                store = KeyStore.getInstance("JKS");
                InputStream is = null;
                try {
                    is = new FileInputStream(storefile);
                    store.load(is, password.toCharArray());
                } finally {
                    if (is != null)
                        is.close();
                }
            }
        } catch (Exception e) {
            throw new HTTPException(e);
        }
        return store;
    }

    // -------------------------------------------------------------------
    // javadoc in org.apache.http.conn.scheme.SocketFactory says :
    // Both Object.equals() and Object.hashCode() must be overridden
    // for the correct operation of some connection managers
    // -------------------------------------------------------------------

    public boolean equals(Object obj) {
        return ((obj != null) && (obj instanceof CustomSSLProtocolSocketFactory));
    }

    public int hashCode() {
        return CustomSSLProtocolSocketFactory.class.hashCode();
    }

    //SchemeLayeredSocketFactory API

    @Override
    public boolean isSecure(Socket socket) throws IllegalArgumentException {
        return true;
    }

    @Override
    public Socket createLayeredSocket(Socket socket, String s, int i, HttpParams httpParams) throws IOException {
        return createSSLContext(httpParams).getSocketFactory().createSocket();
    }

    public Socket createSocket(HttpParams httpParams) throws IOException {
        return createSSLContext(httpParams).getSocketFactory().createSocket();
    }

    public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress, InetSocketAddress localAddress,
            HttpParams params) throws IOException {
        int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
        int soTimeout = HttpConnectionParams.getSoTimeout(params);

        SSLSocket sslsocket = (SSLSocket) ((sock != null) ? sock : createSocket(params));

        if (localAddress != null) {
            sslsocket.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
            sslsocket.bind(localAddress);
        }

        try {
            sslsocket.setSoTimeout(soTimeout);
            sslsocket.connect(remoteAddress, connTimeout);
        } catch (SocketTimeoutException ex) {
            throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
        }
        return sslsocket;
    }

}