All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xnio.ssl.JsseSslUtils Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 *
 * Copyright 2011 Red Hat, Inc. and/or its affiliates, and individual
 * contributors as indicated by the @author tags.
 *
 * 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 org.xnio.ssl;

import static org.xnio._private.Messages.msg;

import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;

import org.xnio.OptionMap;
import org.xnio.Options;
import org.xnio.Sequence;
import org.xnio.Xnio;

/**
 * Utility methods for creating JSSE constructs and configuring them via XNIO option maps.
 *
 * @author David M. Lloyd
 */
public final class JsseSslUtils {

    private JsseSslUtils() {
    }

    /**
     * Create a new SSL context, configured from an option map.
     *
     * @param optionMap the SSL context options
     * @return a new context
     * @throws NoSuchProviderException if there is no matching provider
     * @throws NoSuchAlgorithmException if there is no matching algorithm
     * @throws KeyManagementException if the context initialization fails
     */
    public static SSLContext createSSLContext(OptionMap optionMap) throws NoSuchProviderException, NoSuchAlgorithmException, KeyManagementException {
        return createSSLContext(null, null, null, optionMap);
    }

    /**
     * Create a new SSL context, configured from an option map and the given parameters.
     *
     * @param keyManagers the key managers to use, or {@code null} to configure from the option map
     * @param trustManagers the trust managers to use, or {@code null} to configure from the option map
     * @param secureRandom the secure RNG to use, or {@code null} to choose a system default
     * @param optionMap the SSL context options
     * @return a new context
     * @throws NoSuchProviderException if there is no matching provider
     * @throws NoSuchAlgorithmException if there is no matching algorithm
     * @throws KeyManagementException if the context initialization fails
     */
    public static SSLContext createSSLContext(KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom secureRandom, OptionMap optionMap) throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        final String provider = optionMap.get(Options.SSL_PROVIDER);
        final String protocol = optionMap.get(Options.SSL_PROTOCOL);
        final SSLContext sslContext;
        if (protocol == null) {
            // Default context is initialized automatically
            return SSLContext.getDefault();
        } else if (provider == null) {
            sslContext = SSLContext.getInstance(protocol);
        } else {
            sslContext = SSLContext.getInstance(protocol, provider);
        }
        if (keyManagers == null) {
            final Sequence> keyManagerClasses = optionMap.get(Options.SSL_JSSE_KEY_MANAGER_CLASSES);
            if (keyManagerClasses != null) {
                final int size = keyManagerClasses.size();
                keyManagers = new KeyManager[size];
                for (int i = 0; i < size; i ++) {
                    keyManagers[i] = instantiate(keyManagerClasses.get(i));
                }
            }
        }
        if (trustManagers == null) {
            final Sequence> trustManagerClasses = optionMap.get(Options.SSL_JSSE_TRUST_MANAGER_CLASSES);
            if (trustManagerClasses != null) {
                final int size = trustManagerClasses.size();
                trustManagers = new TrustManager[size];
                for (int i = 0; i < size; i ++) {
                    trustManagers[i] = instantiate(trustManagerClasses.get(i));
                }
            }
        }
        sslContext.init(keyManagers, trustManagers, secureRandom);
        sslContext.getClientSessionContext().setSessionCacheSize(optionMap.get(Options.SSL_CLIENT_SESSION_CACHE_SIZE, 0));
        sslContext.getClientSessionContext().setSessionTimeout(optionMap.get(Options.SSL_CLIENT_SESSION_TIMEOUT, 0));
        sslContext.getServerSessionContext().setSessionCacheSize(optionMap.get(Options.SSL_SERVER_SESSION_CACHE_SIZE, 0));
        sslContext.getServerSessionContext().setSessionTimeout(optionMap.get(Options.SSL_SERVER_SESSION_TIMEOUT, 0));
        return sslContext;
    }

    @SuppressWarnings("TryWithIdenticalCatches")
    private static  T instantiate(Class clazz) {
        try {
            return clazz.getConstructor().newInstance();
        } catch (InstantiationException e) {
            throw msg.cantInstantiate(clazz, e);
        } catch (IllegalAccessException e) {
            throw msg.cantInstantiate(clazz, e);
        } catch (NoSuchMethodException e) {
            throw msg.cantInstantiate(clazz, e);
        } catch (InvocationTargetException e) {
            throw msg.cantInstantiate(clazz, e.getCause());
        }
    }

    /**
     * Create a new client mode SSL engine, configured from an option map.
     *
     * @param sslContext the SSL context
     * @param optionMap the SSL options
     * @param peerAddress the peer address of the connection
     * @return the configured SSL engine
     */
    public static SSLEngine createSSLEngine(SSLContext sslContext, OptionMap optionMap, InetSocketAddress peerAddress) {
        final SSLEngine engine = sslContext.createSSLEngine(
                optionMap.get(Options.SSL_PEER_HOST_NAME, getHostNameNoResolve(peerAddress)),
                optionMap.get(Options.SSL_PEER_PORT, peerAddress.getPort())
        );
        engine.setUseClientMode(true);
        engine.setEnableSessionCreation(optionMap.get(Options.SSL_ENABLE_SESSION_CREATION, true));
        final Sequence cipherSuites = optionMap.get(Options.SSL_ENABLED_CIPHER_SUITES);
        if (cipherSuites != null) {
            final Set supported = new HashSet(Arrays.asList(engine.getSupportedCipherSuites()));
            final List finalList = new ArrayList();
            for (String name : cipherSuites) {
                if (supported.contains(name)) {
                    finalList.add(name);
                }
            }
            engine.setEnabledCipherSuites(finalList.toArray(new String[finalList.size()]));
        }
        final Sequence protocols = optionMap.get(Options.SSL_ENABLED_PROTOCOLS);
        if (protocols != null) {
            final Set supported = new HashSet(Arrays.asList(engine.getSupportedProtocols()));
            final List finalList = new ArrayList();
            for (String name : protocols) {
                if (supported.contains(name)) {
                    finalList.add(name);
                }
            }
            engine.setEnabledProtocols(finalList.toArray(new String[finalList.size()]));
        }
        return engine;
    }

    static String getHostNameNoResolve(InetSocketAddress socketAddress) {
        if (Xnio.NIO2) {
            return socketAddress.getHostString();
        } else {
            String hostName;
            if (socketAddress.isUnresolved()) {
                hostName = socketAddress.getHostName();
            } else {
                final InetAddress address = socketAddress.getAddress();
                final String string = address.toString();
                final int slash = string.indexOf('/');
                if (slash == -1 || slash == 0) {
                    // unresolved both ways
                    hostName = string.substring(slash + 1);
                } else {
                    // has a cached host name
                    hostName = string.substring(0, slash);
                }
            }
            return hostName;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy