Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2012 Red Hat, Inc., 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.apache.tomcat.util.net.jsse;
 
 import static org.jboss.web.CoyoteMessages.MESSAGES;
 
 import java.io.File;
 import  java.nio.channels.AsynchronousChannelGroup;
 import  java.nio.channels.AsynchronousServerSocketChannel;
 import  java.nio.channels.AsynchronousSocketChannel;
 import java.util.List;
 import java.util.Set;
 
 
NioJSSESocketChannelFactory

SSL server socket factory. It _requires_ a valid RSA key and JSSE.

1. Make the JSSE's jars available, either as an installed extension (copy them into jre/lib/ext) or by adding them to the Tomcat classpath. 2. keytool -genkey -alias tomcat -keyalg RSA Use "changeit" as password ( this is the default we use )

Created on Jan 3, 2012 at 2:07:00 PM

Author(s):
Nabil Benothman
 
 
 	private static final boolean RFC_5746_SUPPORTED;
     public static final String[] DEFAULT_SERVER_PROTOCOLS;
 
 	// defaults
 	private static final String defaultProtocol = "TLS";
 	static boolean defaultClientAuth = false;
 	static String defaultKeystoreType = "JKS";
 	private static final String defaultKeystoreFile = System.getProperty("user.home")
 			+ "/.keystore";
	private static final String defaultKeyPass = "changeit";
	private static final int defaultSessionCacheSize = 0;
	private static final int defaultSessionTimeout = 86400;
	// private static SSLContext context;
	static {
		boolean result = false;
        String[] protocols = null;
		try {
			SSLContext context = SSLContext.getInstance();
			context.init(nullnullnew SecureRandom());
			String ciphers[] = ssf.getSupportedCipherSuites();
			for (String cipher : ciphers) {
				if ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV".equals(cipher)) {
					result = true;
					break;
				}
			}
            // There is no API to obtain the default server protocols and cipher
            // suites. Having inspected the OpenJDK code there the same results
            // can be achieved via the standard API but there is no guarantee
            // that every JVM implementation determines the defaults the same
            // way. Therefore the defaults are determined by creating a server
            // socket and requested the configured values.
            SSLServerSocket socket = (SSLServerSocketssf.createServerSocket();
            // Filter out all the insecure protocols
            protocols = filterInsecureProcotols(socket.getEnabledProtocols());
catch (NoSuchAlgorithmException e) {
            // Assume no RFC 5746 support
catch (KeyManagementException e) {
			// Assume no RFC 5746 support
        } catch (IOException e) {
            // Unable to determine default ciphers/protocols so use none
		}
         = protocols;
	}
	protected boolean initialized;
	protected String clientAuth = "false";
	protected String[] enabledCiphers;
	protected boolean allowUnsafeLegacyRenegotiation = false;

Flag to state that we require client authentication.
	protected boolean requireClientAuth = false;

Flag to state that we would like client authentication.
	protected boolean wantClientAuth = false;

Create a new instance of NioJSSESocketChannelFactory
		super();
	}

Create a new instance of NioJSSESocketChannelFactory

Parameters:
threadGroup
	public NioJSSESocketChannelFactory(AsynchronousChannelGroup threadGroup) {
		super(threadGroup);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.DefaultNioServerSocketChannelFactory#acceptChannel
	 * (java.nio.channels.AsynchronousServerSocketChannel)
	 */
	public NioChannel acceptChannel(AsynchronousServerSocketChannel listenerthrows IOException {
		try {
			AsynchronousSocketChannel asyncChannel = listener.accept().get();
			InetSocketAddress addr = (InetSocketAddressasyncChannel.getRemoteAddress();
			NioChannel channel = new SecureNioChannel(asyncChannelengine);
			return channel;
catch (Exception e) {
		}
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.NioServerSocketChannelFactory#initChannel(
	 * org.apache.tomcat.util.net.NioChannel)
	 */
	public void initChannel(NioChannel channelthrows Exception {
		SecureNioChannel sslChannel = (SecureNioChannelchannel;
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.NioServerSocketChannelFactory#handshake(java
	 * .nio.channels.AsynchronousSocketChannel)
	 */
	public void handshake(NioChannel channelthrows IOException {
		// We do getSession instead of startHandshake() so we can call this
		// multiple times
		SecureNioChannel sslChannel = (SecureNioChannelchannel;
		if (sslChannel.handshakeComplete()) {
			// The handshake was already done
			return;
		}
		SSLEngine engine = sslChannel.getSslEngine();
			// Prevent further handshakes by removing all cipher suites
		}
		sslChannel.handshake();
		if (sslChannel.getSSLSession().getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL")) {
		}
	}

Parameters:
ctx
	public void setSslContext(SSLContext ctx) {
		 = ctx;
	}

Returns:
the SSLContext
		return ;
	}

Reads the keystore and initializes the SSL socket factory.

Throws:
IOException
	public void init() throws IOException {
		try {
			String clientAuthStr = (String.get("clientauth");
			if ("true".equalsIgnoreCase(clientAuthStr) || "yes".equalsIgnoreCase(clientAuthStr)) {
else if ("want".equalsIgnoreCase(clientAuthStr)) {
			}
			// SSL protocol variant (e.g., TLS, SSL v3, etc.)
			String protocol = (String.get("protocol");
			if (protocol == null) {
				protocol = ;
			}
			// Certificate encoding algorithm (e.g., SunX509)
			String algorithm = (String.get("algorithm");
			if (algorithm == null) {
				algorithm = KeyManagerFactory.getDefaultAlgorithm();
			}
			String keystoreType = (String.get("keystoreType");
			if (keystoreType == null) {
				keystoreType = ;
			}
			String keystoreProvider = (String.get("keystoreProvider");
			String trustAlgorithm = (String.get("truststoreAlgorithm");
			if (trustAlgorithm == null) {
				trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
			}
			// Create and initialize SSLContext
			 = (SSLContext.get("SSLContext");
			if ( == null) {
				 = SSLContext.getInstance(protocol);
						getKeyManagers(keystoreTypekeystoreProvideralgorithm,
								(String.get("keyAlias")),
						getTrustManagers(keystoreTypekeystoreProvidertrustAlgorithm),
						new SecureRandom());
			}
			// Configure SSL session cache
			int sessionCacheSize;
			if (.get("sessionCacheSize") != null) {
				sessionCacheSize = Integer.parseInt((String.get("sessionCacheSize"));
else {
				sessionCacheSize = ;
			}
			int sessionCacheTimeout;
			if (.get("sessionCacheTimeout") != null) {
				sessionCacheTimeout = Integer.parseInt((String
						.get("sessionCacheTimeout"));
else {
				sessionCacheTimeout = ;
			}
			if (sessionContext != null) {
				sessionContext.setSessionCacheSize(sessionCacheSize);
				sessionContext.setSessionTimeout(sessionCacheTimeout);
			}
			// create proxy
			// Determine which cipher suites to enable
			String requestedCiphers = (String.get("ciphers");
			 = getEnabledCiphers(requestedCiphers,
					.get("allowUnsafeLegacyRenegotiation"));
			// Check that the SSL configuration is OK
catch (Exception e) {
			throw new IOException(e.getMessage(), e);
		}
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.tomcat.util.net.DefaultNioServerSocketChannelFactory#destroy()
	 */
	public void destroy() throws IOException {
		super.destroy();
		this. = null;
	}

Determines the SSL cipher suites to be enabled.

Parameters:
requestedCiphers Comma-separated list of requested ciphers
supportedCiphers Array of supported ciphers
Returns:
Array of SSL cipher suites to be enabled, or null if none of the requested ciphers are supported
	protected String[] getEnabledCiphers(String requestedCiphersString[] supportedCiphersthrows IOException {
		String[] enabledCiphers = null;
		if (requestedCiphers != null) {
		    String[] ciphers = requestedCiphers.split(",");
                    enabledCiphers = JSSEUtils.getEnabledCiphers(cipherssupportedCiphers);
                    if(enabledCiphers == null || enabledCiphers.length == 0) {
			throw new IOException(.noCipherMatch()); // Like openssl.
                    }
else {
		    enabledCiphers = sslProxy.getDefaultCipherSuites();
		}
		return enabledCiphers;
	}

Gets the SSL server's keystore.

Parameters:
type the type of the keystore
provider the keystore provider
pass the keystore password
Returns:
the SSL server's keystore
Throws:
IOException
	protected KeyStore getKeystore(String typeString providerString passthrows IOException {
		String keystoreFile = (String.get("keystore");
                if ("Windows-MY".equalsIgnoreCase(type))
                        keystoreFile = "";
		else if (keystoreFile == null)
			keystoreFile = ;
		return getStore(typeproviderkeystoreFilepass);
	}

Gets the SSL server's keystore password.

Returns:
the keystore password
	protected String getKeystorePassword() {
		String keyPass = (String.get("keypass");
		if (keyPass == null) {
			keyPass = ;
		}
		String keystorePass = (String.get("keystorePass");
		if (keystorePass == null) {
			keystorePass = keyPass;
		}
		return keystorePass;
	}

Gets the key- or truststore with the specified type, path, and password.

Parameters:
type
provider
path
pass
Returns:
Throws:
IOException
	private KeyStore getStore(String typeString providerString pathString pass)
			throws IOException {
		KeyStore ks = null;
		InputStream istream = null;
		try {
			if (provider == null) {
				ks = KeyStore.getInstance(type);
else {
				ks = KeyStore.getInstance(typeprovider);
			}
			if (!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
				File keyStoreFile = new File(path);
				if (!keyStoreFile.isAbsolute()) {
					keyStoreFile = new File(System.getProperty("catalina.base"), path);
				}
				istream = new FileInputStream(keyStoreFile);
			}
			char[] storePass = null;
			if (pass != null) {
				storePass = pass.toCharArray();
			}
			ks.load(istreamstorePass);
catch (FileNotFoundException fnfe) {
			throw fnfe;
catch (IOException ioe) {
			throw ioe;
catch (Exception ex) {
            ..errorLoadingKeystoreWithException(typepathex.getMessage(), ex);
			throw new IOException(ex);
finally {
			if (istream != null) {
				try {
					istream.close();
catch (IOException ioe) {
					// Do nothing
				}
			}
		}
		return ks;
	}

Gets the initialized key managers.

Parameters:
keystoreType
keystoreProvider
algorithm
keyAlias
Returns:
Throws:
Exception
	protected KeyManager[] getKeyManagers(String keystoreTypeString keystoreProvider,
			String algorithmString keyAliasthrows Exception {
		KeyManager[] kms = null;
		String keystorePass = getKeystorePassword();
		KeyStore ks = getKeystore(keystoreTypekeystoreProviderkeystorePass);
		if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
			throw new IOException(.noKeyAlias(keyAlias));
		}
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
		kmf.init(kskeystorePass.toCharArray());
		kms = kmf.getKeyManagers();
		if (keyAlias != null) {
			if (.equals(keystoreType)) {
				keyAlias = keyAlias.toLowerCase(.);
			}
			for (int i = 0; i < kms.lengthi++) {
				kms[i] = new JSSEKeyManager((X509KeyManagerkms[i], keyAlias);
			}
		}
		return kms;
	}

Gets the initialized trust managers.

Parameters:
keystoreType
keystoreProvider
algorithm
Returns:
Throws:
Exception
	protected TrustManager[] getTrustManagers(String keystoreTypeString keystoreProvider,
			String algorithmthrows Exception {
		String crlf = (String.get("crlFile");
		TrustManager[] tms = null;
		KeyStore trustStore = getTrustStore(keystoreTypekeystoreProvider);
		if (trustStore != null) {
			if (crlf == null) {
				TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
				tmf.init(trustStore);
				tms = tmf.getTrustManagers();
else {
				TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
				CertPathParameters params = getParameters(algorithmcrlftrustStore);
				tmf.init(mfp);
				tms = tmf.getTrustManagers();
			}
		}
		return tms;
	}

Gets the SSL server's truststore.

Parameters:
keystoreType
keystoreProvider
Returns:
the SSL server's truststore.
Throws:
IOException
	protected KeyStore getTrustStore(String keystoreTypeString keystoreProvider)
			throws IOException {
		KeyStore trustStore = null;
		String truststoreFile = (String.get("truststoreFile");
		if (truststoreFile == null) {
			truststoreFile = System.getProperty("javax.net.ssl.trustStore");
		}
		    ..debug("Truststore = " + truststoreFile);
		}
		String truststorePassword = (String.get("truststorePass");
		if (truststorePassword == null) {
			truststorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
		}
		    ..debug("TrustPass = " + truststorePassword);
		}
		String truststoreType = (String.get("truststoreType");
		if (truststoreType == null) {
			truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
		}
		if (truststoreType == null) {
			truststoreType = keystoreType;
		}
                if ("Windows-ROOT".equalsIgnoreCase(truststoreType))
                    truststoreFile = "";
 
		    ..debug("trustType = " + truststoreType);
		}
		String truststoreProvider = (String.get("truststoreProvider");
		if (truststoreProvider == null) {
			truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
		}
		if (truststoreProvider == null) {
			truststoreProvider = keystoreProvider;
		}
		    ..debug("trustProvider = " + truststoreProvider);
		}
		if (truststoreFile != null) {
			trustStore = getStore(truststoreTypetruststoreProvidertruststoreFile,
					truststorePassword);
		}
		return trustStore;
	}

Return the initialization parameters for the TrustManager. Currently, only the default PKIX is supported.

Parameters:
algorithm The algorithm to get parameters for.
crlf The path to the CRL file.
trustStore The configured TrustStore.
Returns:
The parameters including the CRLs and TrustStore.
	protected CertPathParameters getParameters(String algorithmString crlfKeyStore trustStore)
			throws Exception {
		CertPathParameters params = null;
		if ("PKIX".equalsIgnoreCase(algorithm)) {
			PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore,
			Collection<?> crls = getCRLs(crlf);
			CertStore store = CertStore.getInstance("Collection"csp);
			xparams.addCertStore(store);
			xparams.setRevocationEnabled(true);
			String trustLength = (String.get("trustMaxCertLength");
			if (trustLength != null) {
				try {
					xparams.setMaxPathLength(Integer.parseInt(trustLength));
catch (Exception ex) {
				}
			}
			params = xparams;
else {
			throw new CRLException(.unsupportedCrl(algorithm));
		}
		return params;
	}

Load the collection of CRLs.

Parameters:
crlf
Returns:
a collection of java.security.cert.CRL
Throws:
IOException
CRLException
CertificateException
	protected Collection<? extends CRLgetCRLs(String crlfthrows IOExceptionCRLException,
		File crlFile = new File(crlf);
		if (!crlFile.isAbsolute()) {
			crlFile = new File(System.getProperty("catalina.base"), crlf);
		}
		Collection<? extends CRLcrls = null;
		InputStream is = null;
		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			is = new FileInputStream(crlFile);
			crls = cf.generateCRLs(is);
catch (IOException iex) {
			throw iex;
catch (CRLException crle) {
			throw crle;
catch (CertificateException ce) {
			throw ce;
finally {
			if (is != null) {
				try {
					is.close();
catch (Exception ex) {
				}
			}
		}
		return crls;
	}

Set the SSL protocol variants to be enabled.

Parameters:
engine the SSLEngine.
protocols the protocols to use.
	protected void setEnabledProtocols(SSLEngine engineString[] protocols) {
        if (protocols == null) {
            engine.setEnabledProtocols();
        } else {
            engine.setEnabledProtocols(protocols);
        }
	}

Determines the SSL protocol variants to be enabled.

Parameters:
engine The SSLEngine to get supported list from.
requestedProtocols Comma-separated list of requested SSL protocol variants
Returns:
Array of SSL protocol variants to be enabled, or null if none of the requested protocol variants are supported
    protected String[] getEnabledProtocols(SSLEngine engine,
            String requestedProtocols){
        Set<StringsupportedProtocols = new HashSet<String>();
        for (String supportedProtocol : engine.getSupportedProtocols()) {
            supportedProtocols.add(supportedProtocol);
        }
        if (requestedProtocols == null) {
            return ;
        }
        String[] requestedProtocolsArr = requestedProtocols.split(",");
        List<StringenabledProtocols = new ArrayList<String>(requestedProtocolsArr.length);
        for (String requestedProtocol : requestedProtocolsArr) {
            String requestedProtocolTrim = requestedProtocol.trim();
            if (supportedProtocols.contains(requestedProtocolTrim)) {
                enabledProtocols.add(requestedProtocolTrim);
            } else {
                ..unsupportedProtocol(requestedProtocolTrim);
            }
        }
        return enabledProtocols.toArray(new String[enabledProtocols.size()]);
    }

Configure the given SSL server socket with the requested cipher suites, protocol versions, and need for client authentication

Parameters:
engine
	private void initSSLEngine(SSLEngine engine) {
		if ( != null) {
		}
		engine.setUseClientMode(false);
		String requestedProtocols = (String.get("protocols");
        engine.setEnabledProtocols(getEnabledProtocols(enginerequestedProtocols));
		// we don't know if client authentication is needed -
		// after parsing the request we may re-handshake
		        engine.setWantClientAuth();
                } else {
		        engine.setNeedClientAuth();
                }
	}

Checks that the certificate is compatible with the enabled cipher suites. If we don't check now, the JIoEndpoint can enter a nasty logging loop. See bug 45528.
	private void checkConfig() throws IOException {
		// Create an unbound server socket
		ServerSocket socket = sslProxy.createServerSocket();
		// SSLEngine engine = sslContext.createSSLEngine();
		// initSSLEngine(engine);
		try {
			// Set the timeout to 1ms as all we care about is if it throws an
			// SSLException on accept.
			socket.setSoTimeout(1);
			socket.accept();
			// Will never get here - no client can connect to an unbound port
catch (SSLException ssle) {
			// SSL configuration is invalid. Possibly cert doesn't match ciphers
			ioe.initCause(ssle);
			throw ioe;
catch (Exception e) {
			/*
			 * Possible ways of getting here socket.accept() throws a
			 * SecurityException socket.setSoTimeout() throws a SocketException
			 * socket.accept() throws some other exception (after a JDK change)
			 * In these cases the test won't work so carry on - essentially the
			 * Behavior before this patch socket.accept() throws a
			 * SocketTimeoutException In this case all is well so carry on
			 */
finally {
			// Should be open here but just in case
			if (!socket.isClosed()) {
				socket.close();
			}
		}
	}
    public static String[] filterInsecureProcotols(String[] protocols) {
        if (protocols == null) {
            return null;
        }
        List<Stringresult = new ArrayList<String>(protocols.length);
        for (String protocol : protocols) {
            if (protocol == null || protocol.toUpperCase(.).contains("SSL")) {
                if (..isDebugEnabled()) {
                    ..debug("Exclude protocol: " + protocol);
                }
                if (protocol != null && protocol.equalsIgnoreCase("SSLv2Hello")) {
                    result.add(protocol);
                }
            } else {
                result.add(protocol);
            }
        }
        return result.toArray(new String[result.size()]);
    }
New to GrepCode? Check out our FAQ X