316382: support a more strict SSL option with certificates
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/sandbox/trunk@2749 7e9141cc-0065-0410-87d8-b60c137991c4
diff --git a/jetty-exssl/pom.xml b/jetty-exssl/pom.xml
index 2cd3556..e35eafa 100644
--- a/jetty-exssl/pom.xml
+++ b/jetty-exssl/pom.xml
@@ -74,10 +74,25 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
new file mode 100644
index 0000000..5bf5fc9
--- /dev/null
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -0,0 +1,817 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.eclipse.jetty.client.security.Authentication;
+import org.eclipse.jetty.client.security.RealmResolver;
+import org.eclipse.jetty.client.security.SecurityListener;
+import org.eclipse.jetty.http.HttpBuffers;
+import org.eclipse.jetty.http.HttpSchemes;
+import org.eclipse.jetty.http.security.Password;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.io.SslContextFactory;
+import org.eclipse.jetty.io.nio.DirectNIOBuffer;
+import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
+import org.eclipse.jetty.util.Attributes;
+import org.eclipse.jetty.util.AttributesMap;
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.util.thread.ThreadPool;
+import org.eclipse.jetty.util.thread.Timeout;
+
+/**
+ * Http Client.
+ * <p/>
+ * HttpClient is the main active component of the client API implementation.
+ * It is the opposite of the Connectors in standard Jetty, in that it listens
+ * for responses rather than requests. Just like the connectors, there is a
+ * blocking socket version and a non-blocking NIO version (implemented as nested classes
+ * selected by {@link #setConnectorType(int)}).
+ * <p/>
+ * The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
+ * to send a request. The exchange contains both the headers and content (source) of the request
+ * plus the callbacks to handle responses. A HttpClient can have many exchanges outstanding
+ * and they may be queued on the {@link HttpDestination} waiting for a {@link HttpConnection},
+ * queued in the {@link HttpConnection} waiting to be transmitted or pipelined on the actual
+ * TCP/IP connection waiting for a response.
+ * <p/>
+ * The {@link HttpDestination} class is an aggregation of {@link HttpConnection}s for the
+ * same host, port and protocol. A destination may limit the number of connections
+ * open and they provide a pool of open connections that may be reused. Connections may also
+ * be allocated from a destination, so that multiple request sources are not multiplexed
+ * over the same connection.
+ *
+ * @see HttpExchange
+ * @see HttpDestination
+ */
+public class HttpClient extends HttpBuffers implements Attributes
+{
+ public static final int CONNECTOR_SOCKET = 0;
+ public static final int CONNECTOR_SELECT_CHANNEL = 2;
+
+ private int _connectorType = CONNECTOR_SELECT_CHANNEL;
+ private boolean _useDirectBuffers = true;
+ private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
+ private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
+ ThreadPool _threadPool;
+ Connector _connector;
+ private long _idleTimeout = 20000;
+ private long _timeout = 320000;
+ private int _connectTimeout = 75000;
+ private Timeout _timeoutQ = new Timeout();
+ private Timeout _idleTimeoutQ = new Timeout();
+ private Address _proxy;
+ private Authentication _proxyAuthentication;
+ private Set<String> _noProxy;
+ private int _maxRetries = 3;
+ private int _maxRedirects = 20;
+ private LinkedList<String> _registeredListeners;
+
+ private SslContextFactory _sslContextFactory;
+
+ private RealmResolver _realmResolver;
+
+ private AttributesMap _attributes=new AttributesMap();
+
+ public HttpClient()
+ {
+ this(new SslContextFactory());
+ }
+
+ public HttpClient(SslContextFactory sslContextFactory)
+ {
+ _sslContextFactory = sslContextFactory;
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ public void dump()
+ {
+ try
+ {
+ for (Map.Entry<Address, HttpDestination> entry : _destinations.entrySet())
+ {
+ Log.info("\n" + entry.getKey() + ":");
+ entry.getValue().dump();
+ }
+ }
+ catch(Exception e)
+ {
+ Log.warn(e);
+ }
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ public void send(HttpExchange exchange) throws IOException
+ {
+ boolean ssl = HttpSchemes.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
+ exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
+ HttpDestination destination = getDestination(exchange.getAddress(), ssl);
+ destination.send(exchange);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return the threadPool
+ */
+ public ThreadPool getThreadPool()
+ {
+ return _threadPool;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param threadPool the threadPool to set
+ */
+ public void setThreadPool(ThreadPool threadPool)
+ {
+ _threadPool = threadPool;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param name
+ * @return Attribute associated with client
+ */
+ public Object getAttribute(String name)
+ {
+ return _attributes.getAttribute(name);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return names of attributes associated with client
+ */
+ public Enumeration getAttributeNames()
+ {
+ return _attributes.getAttributeNames();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param name
+ */
+ public void removeAttribute(String name)
+ {
+ _attributes.removeAttribute(name);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set an attribute on the HttpClient.
+ * Attributes are not used by the client, but are provided for
+ * so that users of a shared HttpClient may share other structures.
+ * @param name
+ * @param attribute
+ */
+ public void setAttribute(String name, Object attribute)
+ {
+ _attributes.setAttribute(name,attribute);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void clearAttributes()
+ {
+ _attributes.clearAttributes();
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ public HttpDestination getDestination(Address remote, boolean ssl) throws UnknownHostException, IOException
+ {
+ if (remote == null)
+ throw new UnknownHostException("Remote socket address cannot be null.");
+
+ HttpDestination destination = _destinations.get(remote);
+ if (destination == null)
+ {
+ destination = new HttpDestination(this, remote, ssl, _maxConnectionsPerAddress);
+ if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
+ {
+ destination.setProxy(_proxy);
+ if (_proxyAuthentication != null)
+ destination.setProxyAuthentication(_proxyAuthentication);
+ }
+ HttpDestination other =_destinations.putIfAbsent(remote, destination);
+ if (other!=null)
+ destination=other;
+ }
+ return destination;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void schedule(Timeout.Task task)
+ {
+ _timeoutQ.schedule(task);
+ }
+
+ public void schedule(Timeout.Task task, long timeout)
+ {
+ _timeoutQ.schedule(task, timeout);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void scheduleIdle(Timeout.Task task)
+ {
+ _idleTimeoutQ.schedule(task);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void cancel(Timeout.Task task)
+ {
+ task.cancel();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Get whether the connector can use direct NIO buffers.
+ */
+ public boolean getUseDirectBuffers()
+ {
+ return _useDirectBuffers;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set a RealmResolver for client Authentication.
+ * If a realmResolver is set, then the HttpDestinations created by
+ * this client will instantiate a {@link SecurityListener} so that
+ * BASIC and DIGEST authentication can be performed.
+ * @param resolver
+ */
+ public void setRealmResolver(RealmResolver resolver)
+ {
+ _realmResolver = resolver;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
+ *
+ * @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
+ */
+ public RealmResolver getRealmResolver()
+ {
+ return _realmResolver;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean hasRealms()
+ {
+ return _realmResolver == null ? false : true;
+ }
+
+
+ /**
+ * Registers a listener that can listen to the stream of execution between the client and the
+ * server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding
+ * listener in a delegation model.
+ * <p/>
+ * NOTE: the SecurityListener is a special listener which doesn't need to be added via this
+ * mechanic, if you register security realms then it will automatically be added as the top listener of the
+ * delegation stack.
+ *
+ * @param listenerClass
+ */
+ public void registerListener(String listenerClass)
+ {
+ if (_registeredListeners == null)
+ {
+ _registeredListeners = new LinkedList<String>();
+ }
+ _registeredListeners.add(listenerClass);
+ }
+
+ /* ------------------------------------------------------------ */
+ public LinkedList<String> getRegisteredListeners()
+ {
+ return _registeredListeners;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set to use NIO direct buffers.
+ *
+ * @param direct If True (the default), the connector can use NIO direct
+ * buffers. Some JVMs have memory management issues (bugs) with
+ * direct buffers.
+ */
+ public void setUseDirectBuffers(boolean direct)
+ {
+ _useDirectBuffers = direct;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Get the type of connector (socket, blocking or select) in use.
+ */
+ public int getConnectorType()
+ {
+ return _connectorType;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setConnectorType(int connectorType)
+ {
+ this._connectorType = connectorType;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.http.HttpBuffers#newRequestBuffer(int)
+ */
+ @Override
+ protected Buffer newRequestBuffer(int size)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return new ByteArrayBuffer(size);
+ return _useDirectBuffers?new DirectNIOBuffer(size):new IndirectNIOBuffer(size);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.http.HttpBuffers#newRequestHeader(int)
+ */
+ @Override
+ protected Buffer newRequestHeader(int size)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return new ByteArrayBuffer(size);
+ return new IndirectNIOBuffer(size);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.http.HttpBuffers#newResponseBuffer(int)
+ */
+ @Override
+ protected Buffer newResponseBuffer(int size)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return new ByteArrayBuffer(size);
+ return _useDirectBuffers?new DirectNIOBuffer(size):new IndirectNIOBuffer(size);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.http.HttpBuffers#newResponseHeader(int)
+ */
+ @Override
+ protected Buffer newResponseHeader(int size)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return new ByteArrayBuffer(size);
+ return new IndirectNIOBuffer(size);
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ @Override
+ protected boolean isRequestHeader(Buffer buffer)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return buffer instanceof ByteArrayBuffer;
+ return buffer instanceof IndirectNIOBuffer;
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ @Override
+ protected boolean isResponseHeader(Buffer buffer)
+ {
+ if (_connectorType == CONNECTOR_SOCKET)
+ return buffer instanceof ByteArrayBuffer;
+ return buffer instanceof IndirectNIOBuffer;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public int getMaxConnectionsPerAddress()
+ {
+ return _maxConnectionsPerAddress;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
+ {
+ _maxConnectionsPerAddress = maxConnectionsPerAddress;
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ protected void doStart() throws Exception
+ {
+ super.doStart();
+
+ _timeoutQ.setDuration(_timeout);
+ _timeoutQ.setNow();
+ _idleTimeoutQ.setDuration(_idleTimeout);
+ _idleTimeoutQ.setNow();
+
+ if (_threadPool == null)
+ {
+ QueuedThreadPool pool = new QueuedThreadPool();
+ pool.setMaxThreads(16);
+ pool.setDaemon(true);
+ pool.setName("HttpClient");
+ _threadPool = pool;
+ }
+
+ if (_threadPool instanceof LifeCycle)
+ {
+ ((LifeCycle)_threadPool).start();
+ }
+
+
+ if (_connectorType == CONNECTOR_SELECT_CHANNEL)
+ {
+
+ _connector = new SelectConnector(this);
+ }
+ else
+ {
+ _connector = new SocketConnector(this);
+ }
+ _connector.start();
+
+ _threadPool.dispatch(new Runnable()
+ {
+ public void run()
+ {
+ while (isRunning())
+ {
+ _timeoutQ.tick(System.currentTimeMillis());
+ _idleTimeoutQ.tick(_timeoutQ.getNow());
+ try
+ {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ });
+
+ }
+
+ /* ------------------------------------------------------------ */
+ long getNow()
+ {
+ return _timeoutQ.getNow();
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ protected void doStop() throws Exception
+ {
+ _connector.stop();
+ _connector = null;
+ if (_threadPool instanceof LifeCycle)
+ {
+ ((LifeCycle)_threadPool).stop();
+ }
+ for (HttpDestination destination : _destinations.values())
+ {
+ destination.close();
+ }
+
+ _timeoutQ.cancelAll();
+ _idleTimeoutQ.cancelAll();
+ super.doStop();
+ }
+
+ /* ------------------------------------------------------------ */
+ interface Connector extends LifeCycle
+ {
+ public void startConnection(HttpDestination destination) throws IOException;
+ }
+
+ /**
+ * if a keystore location has been provided then client will attempt to use it as the keystore,
+ * otherwise we simply ignore certificates and run with a loose ssl context.
+ *
+ * @return the SSL context
+ */
+ protected SSLContext getSSLContext()
+ {
+ return _sslContextFactory.getClientSslContext();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
+ */
+ public long getIdleTimeout()
+ {
+ return _idleTimeout;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param ms the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
+ */
+ public void setIdleTimeout(long ms)
+ {
+ _idleTimeout = ms;
+ }
+
+ /**
+ * @return the period in ms that an exchange will wait for a response from the server.
+ * @deprecated use {@link #getTimeout()} instead.
+ */
+ @Deprecated
+ public int getSoTimeout()
+ {
+ return Long.valueOf(getTimeout()).intValue();
+ }
+
+ /**
+ * @deprecated use {@link #setTimeout(long)} instead.
+ * @param timeout the period in ms that an exchange will wait for a response from the server.
+ */
+ @Deprecated
+ public void setSoTimeout(int timeout)
+ {
+ setTimeout(timeout);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return the period in ms that an exchange will wait for a response from the server.
+ */
+ public long getTimeout()
+ {
+ return _timeout;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param timeout the period in ms that an exchange will wait for a response from the server.
+ */
+ public void setTimeout(long timeout)
+ {
+ _timeout = timeout;
+ }
+
+ /**
+ * @return the period in ms before timing out an attempt to connect
+ */
+ public int getConnectTimeout()
+ {
+ return _connectTimeout;
+ }
+
+ /**
+ * @param connectTimeout the period in ms before timing out an attempt to connect
+ */
+ public void setConnectTimeout(int connectTimeout)
+ {
+ this._connectTimeout = connectTimeout;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Address getProxy()
+ {
+ return _proxy;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setProxy(Address proxy)
+ {
+ this._proxy = proxy;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Authentication getProxyAuthentication()
+ {
+ return _proxyAuthentication;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setProxyAuthentication(Authentication authentication)
+ {
+ _proxyAuthentication = authentication;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean isProxied()
+ {
+ return this._proxy != null;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Set<String> getNoProxy()
+ {
+ return _noProxy;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setNoProxy(Set<String> noProxyAddresses)
+ {
+ _noProxy = noProxyAddresses;
+ }
+
+ /* ------------------------------------------------------------ */
+ public int maxRetries()
+ {
+ return _maxRetries;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setMaxRetries(int retries)
+ {
+ _maxRetries = retries;
+ }
+
+ /* ------------------------------------------------------------ */
+ public int maxRedirects()
+ {
+ return _maxRedirects;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setMaxRedirects(int redirects)
+ {
+ _maxRedirects = redirects;
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getTrustStoreLocation()
+ {
+ return _sslContextFactory.getTruststore();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setTrustStoreLocation(String trustStoreLocation)
+ {
+ _sslContextFactory.setTruststore(trustStoreLocation);
+ }
+
+ public InputStream getTrustStoreInputStream()
+ {
+ return _sslContextFactory.getTruststoreInputStream();
+ }
+
+ public void setTrustStoreInputStream(InputStream trustStoreInputStream)
+ {
+ _sslContextFactory.setTruststoreInputStream(trustStoreInputStream);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getKeyStoreLocation()
+ {
+ return _sslContextFactory.getKeystore();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setKeyStoreLocation(String keyStoreLocation)
+ {
+ _sslContextFactory.setKeystore(keyStoreLocation);
+ }
+
+ public InputStream getKeyStoreInputStream()
+ {
+ return _sslContextFactory.getKeystoreInputStream();
+ }
+
+ public void setKeyStoreInputStream(InputStream keyStoreInputStream)
+ {
+ _sslContextFactory.setKeystoreInputStream(keyStoreInputStream);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setKeyStorePassword(String keyStorePassword)
+ {
+ _sslContextFactory.setKeyStorePassword(keyStorePassword);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setKeyManagerPassword(String keyManagerPassword)
+ {
+ _sslContextFactory.setKeyManagerPassword(keyManagerPassword);
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setTrustStorePassword(String trustStorePassword)
+ {
+ _sslContextFactory.setTrustStorePassword(trustStorePassword);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getKeyStoreType()
+ {
+ return _sslContextFactory.getKeystoreType();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setKeyStoreType(String keyStoreType)
+ {
+ _sslContextFactory.setKeystoreType(keyStoreType);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getTrustStoreType()
+ {
+ return _sslContextFactory.getTruststoreType();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setTrustStoreType(String trustStoreType)
+ {
+ _sslContextFactory.setTruststoreType(trustStoreType);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getKeyManagerAlgorithm()
+ {
+ return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
+ {
+ _sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getTrustManagerAlgorithm()
+ {
+ return _sslContextFactory.getTrustManagerFactoryAlgorithm();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
+ {
+ _sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getProtocol()
+ {
+ return _sslContextFactory.getProtocol();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setProtocol(String protocol)
+ {
+ _sslContextFactory.setProtocol(protocol);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getProvider()
+ {
+ return _sslContextFactory.getProvider();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setProvider(String provider)
+ {
+ setProvider(provider);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String getSecureRandomAlgorithm()
+ {
+ return _sslContextFactory.getSecureRandomAlgorithm();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
+ {
+ _sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
+ }
+}
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/CertificateValidator.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/CertificateValidator.java
deleted file mode 100644
index a467dfc..0000000
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/CertificateValidator.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.eclipse.jetty.exssl;
-
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.cert.CRL;
-import java.security.cert.CertPathBuilder;
-import java.security.cert.CertPathBuilderResult;
-import java.security.cert.CertPathValidator;
-import java.security.cert.CertStore;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CollectionCertStoreParameters;
-import java.security.cert.PKIXBuilderParameters;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.eclipse.jetty.util.log.Log;
-
-public class CertificateValidator
-{
- private KeyStore _keyStore;
- private KeyStore _trustStore;
- private Collection<? extends CRL> _crls;
- private int _maxCertPathLength = -1;
-
- public CertificateValidator(KeyStore keyStore, KeyStore trustStore, Collection<? extends CRL> crls)
- {
- _keyStore = keyStore;
- _trustStore = trustStore;
- _crls = crls;
- }
-
- public String validate(String keyAlias) throws CertificateException
- {
- String result = null;
-
- if (keyAlias != null)
- {
- try
- {
- validate(_keyStore.getCertificate(keyAlias));
- }
- catch (KeyStoreException ex)
- {
- Log.debug(ex);
- throw new CertificateException("Unable to validate certificate for alias [" +
- keyAlias + "]: " + ex.getMessage());
- }
- result = keyAlias;
- }
-
- return result;
- }
-
- public void validate(Certificate cert) throws CertificateException
- {
- if (cert != null && cert instanceof X509Certificate)
- {
- ((X509Certificate)cert).checkValidity();
-
- String certAlias = "[none]";
- try
- {
- certAlias = _keyStore.getCertificateAlias((X509Certificate)cert);
- Certificate[] certChain = _keyStore.getCertificateChain(certAlias);
-
- ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
- for (Certificate item : certChain)
- {
- if (!(item instanceof X509Certificate))
- {
- throw new CertificateException("Invalid certificate type in chain");
- }
- certList.add((X509Certificate)item);
- }
-
- if (certList.isEmpty())
- {
- throw new CertificateException("Invalid certificate chain");
-
- }
-
- X509CertSelector certSelect = new X509CertSelector();
- certSelect.setCertificate(certList.get(0));
-
- // Configure certification path builder parameters
- PKIXBuilderParameters pbParams = new PKIXBuilderParameters(_trustStore, certSelect);
- pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList)));
-
- // Set static Certificate Revocation List
- if (_crls != null && !_crls.isEmpty())
- {
- pbParams.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(_crls)));
- }
-
- // Enable revocation checking
- pbParams.setRevocationEnabled(true);
-
- // Set maximum certification path length
- pbParams.setMaxPathLength(_maxCertPathLength);
-
- // Build certification path
- CertPathBuilderResult buildResult = CertPathBuilder.getInstance("PKIX").build(pbParams);
-
- // Validate certification path
- CertPathValidator.getInstance("PKIX").validate(buildResult.getCertPath(),pbParams);
- }
- catch (Exception ex)
- {
- Log.debug(ex);
- throw new CertificateException("Unable to validate certificate for alias [" +
- certAlias + "]: " + ex.getMessage());
- }
- }
- }
-
- public int getMaxCertPathLength()
- {
- return _maxCertPathLength;
- }
-
- public void setMaxCertPathLength(int maxCertPathLength)
- {
- _maxCertPathLength = maxCertPathLength;
- }
-
- public KeyStore getKeyStore()
- {
- return _keyStore;
- }
-
- public KeyStore getTrustStore()
- {
- return _trustStore;
- }
-
- public Collection<? extends CRL> getCrls()
- {
- return _crls;
- }
-}
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
index c5dfabc..1508157 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSelectChannelConnector.java
@@ -28,6 +28,7 @@
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.SslContextFactory;
import org.eclipse.jetty.io.ThreadLocalBuffers;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
@@ -53,19 +54,19 @@
*/
public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector
{
- private final SslParameters _sslParams;
+ private final SslContextFactory _sslContextFactory;
private Buffers _sslBuffers;
/* ------------------------------------------------------------ */
public SslSelectChannelConnector()
{
- this(new SslParameters());
+ this(new SslContextFactory().setKeystore(SslContextFactory.DEFAULT_KEYSTORE_PATH));
}
/* ------------------------------------------------------------ */
- public SslSelectChannelConnector(SslParameters sslParams)
+ public SslSelectChannelConnector(SslContextFactory sslContextFactory)
{
- _sslParams = sslParams;
+ _sslContextFactory = sslContextFactory;
setUseDirectBuffers(false);
}
@@ -114,7 +115,7 @@
*/
public boolean isAllowRenegotiate()
{
- return _sslParams.isAllowRenegotiate();
+ return _sslContextFactory.isAllowRenegotiate();
}
/* ------------------------------------------------------------ */
@@ -127,7 +128,7 @@
*/
public void setAllowRenegotiate(boolean allowRenegotiate)
{
- _sslParams.setAllowRenegotiate(allowRenegotiate);
+ _sslContextFactory.setAllowRenegotiate(allowRenegotiate);
}
/* ------------------------------------------------------------ */
@@ -136,7 +137,7 @@
*/
public String[] getExcludeCipherSuites()
{
- return _sslParams.getExcludeCipherSuites();
+ return _sslContextFactory.getExcludeCipherSuites();
}
/* ------------------------------------------------------------ */
@@ -145,7 +146,7 @@
*/
public void setExcludeCipherSuites(String[] cipherSuites)
{
- _sslParams.setExcludeCipherSuites(cipherSuites);
+ _sslContextFactory.setExcludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
@@ -154,7 +155,7 @@
*/
public String[] getIncludeCipherSuites()
{
- return _sslParams.getIncludeCipherSuites();
+ return _sslContextFactory.getIncludeCipherSuites();
}
/* ------------------------------------------------------------ */
@@ -163,7 +164,7 @@
*/
public void setIncludeCipherSuites(String[] cipherSuites)
{
- _sslParams.setIncludeCipherSuites(cipherSuites);
+ _sslContextFactory.setIncludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
@@ -172,7 +173,7 @@
*/
public void setPassword(String password)
{
- _sslParams.setPassword(password);
+ _sslContextFactory.setKeyStorePassword(password);
}
/* ------------------------------------------------------------ */
@@ -181,7 +182,7 @@
*/
public void setTrustPassword(String password)
{
- _sslParams.setTrustPassword(password);
+ _sslContextFactory.setTrustStorePassword(password);
}
/* ------------------------------------------------------------ */
@@ -190,7 +191,7 @@
*/
public void setKeyPassword(String password)
{
- _sslParams.setKeyPassword(password);
+ _sslContextFactory.setKeyManagerPassword(password);
}
/* ------------------------------------------------------------ */
@@ -221,7 +222,7 @@
*/
public String getProtocol()
{
- return _sslParams.getProtocol();
+ return _sslContextFactory.getProtocol();
}
/* ------------------------------------------------------------ */
@@ -230,7 +231,7 @@
*/
public void setProtocol(String protocol)
{
- _sslParams.setProtocol(protocol);
+ _sslContextFactory.setProtocol(protocol);
}
/* ------------------------------------------------------------ */
@@ -239,7 +240,7 @@
*/
public void setKeystore(String keystore)
{
- _sslParams.setKeystore(keystore);
+ _sslContextFactory.setKeystore(keystore);
}
/* ------------------------------------------------------------ */
@@ -248,7 +249,7 @@
*/
public String getKeystore()
{
- return _sslParams.getKeystore();
+ return _sslContextFactory.getKeystore();
}
/* ------------------------------------------------------------ */
@@ -257,7 +258,7 @@
*/
public String getKeystoreType()
{
- return _sslParams.getKeystoreType();
+ return _sslContextFactory.getKeystoreType();
}
/* ------------------------------------------------------------ */
@@ -266,7 +267,7 @@
*/
public boolean getNeedClientAuth()
{
- return _sslParams.getNeedClientAuth();
+ return _sslContextFactory.getNeedClientAuth();
}
/* ------------------------------------------------------------ */
@@ -275,7 +276,7 @@
*/
public boolean getWantClientAuth()
{
- return _sslParams.getWantClientAuth();
+ return _sslContextFactory.getWantClientAuth();
}
/* ------------------------------------------------------------ */
@@ -284,7 +285,7 @@
*/
public void setNeedClientAuth(boolean needClientAuth)
{
- _sslParams.setNeedClientAuth(needClientAuth);
+ _sslContextFactory.setNeedClientAuth(needClientAuth);
}
/* ------------------------------------------------------------ */
@@ -293,7 +294,7 @@
*/
public void setWantClientAuth(boolean wantClientAuth)
{
- _sslParams.setWantClientAuth(wantClientAuth);
+ _sslContextFactory.setWantClientAuth(wantClientAuth);
}
/* ------------------------------------------------------------ */
@@ -302,7 +303,7 @@
*/
public void setKeystoreType(String keystoreType)
{
- _sslParams.setKeystoreType(keystoreType);
+ _sslContextFactory.setKeystoreType(keystoreType);
}
/* ------------------------------------------------------------ */
@@ -311,7 +312,7 @@
*/
public String getProvider()
{
- return _sslParams.getProvider();
+ return _sslContextFactory.getProvider();
}
/* ------------------------------------------------------------ */
@@ -320,7 +321,7 @@
*/
public String getSecureRandomAlgorithm()
{
- return _sslParams.getSecureRandomAlgorithm();
+ return _sslContextFactory.getSecureRandomAlgorithm();
}
/* ------------------------------------------------------------ */
@@ -329,7 +330,7 @@
*/
public String getSslKeyManagerFactoryAlgorithm()
{
- return _sslParams.getSslKeyManagerFactoryAlgorithm();
+ return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@@ -338,7 +339,7 @@
*/
public String getSslTrustManagerFactoryAlgorithm()
{
- return _sslParams.getSslTrustManagerFactoryAlgorithm();
+ return _sslContextFactory.getTrustManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@@ -347,7 +348,7 @@
*/
public String getTruststore()
{
- return _sslParams.getTruststore();
+ return _sslContextFactory.getTruststore();
}
/* ------------------------------------------------------------ */
@@ -356,7 +357,7 @@
*/
public String getTruststoreType()
{
- return _sslParams.getTruststoreType();
+ return _sslContextFactory.getTruststoreType();
}
/* ------------------------------------------------------------ */
@@ -365,7 +366,7 @@
*/
public void setProvider(String provider)
{
- _sslParams.setProvider(provider);
+ _sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */
@@ -374,7 +375,7 @@
*/
public void setSecureRandomAlgorithm(String algorithm)
{
- _sslParams.setSecureRandomAlgorithm(algorithm);
+ _sslContextFactory.setSecureRandomAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
@@ -383,7 +384,7 @@
*/
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
- _sslParams.setSslKeyManagerFactoryAlgorithm(algorithm);
+ _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
@@ -392,7 +393,7 @@
*/
public void setSslTrustManagerFactoryAlgorithm(String algorithm)
{
- _sslParams.setSslTrustManagerFactoryAlgorithm(algorithm);
+ _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
@@ -401,7 +402,7 @@
*/
public void setTruststore(String truststore)
{
- _sslParams.setTruststore(truststore);
+ _sslContextFactory.setTruststore(truststore);
}
/* ------------------------------------------------------------ */
@@ -410,7 +411,7 @@
*/
public void setTruststoreType(String truststoreType)
{
- _sslParams.setTruststoreType(truststoreType);
+ _sslContextFactory.setTruststoreType(truststoreType);
}
/* ------------------------------------------------------------ */
@@ -419,7 +420,7 @@
*/
public void setSslContext(SSLContext sslContext)
{
- _sslParams.setSslContext(sslContext);
+ _sslContextFactory.setSslContext(sslContext);
}
/* ------------------------------------------------------------ */
@@ -428,7 +429,7 @@
*/
public SSLContext getSslContext()
{
- return _sslParams.getSslContext();
+ return _sslContextFactory.getSslContext();
}
/* ------------------------------------------------------------ */
@@ -468,7 +469,7 @@
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
SslSelectChannelEndPoint endp = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,createSSLEngine(), SslSelectChannelConnector.this._maxIdleTime);
- endp.setAllowRenegotiate(_sslParams.isAllowRenegotiate());
+ endp.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate());
return endp;
}
@@ -505,15 +506,15 @@
@Override
protected void doStart() throws Exception
{
- _sslParams.createSSLContext(); // called here to prevent exception wrapping
+ _sslContextFactory.createSSLContext(); // called here to prevent exception wrapping
- SSLEngine sslEngine = _sslParams.getSslContext().createSSLEngine();
+ SSLEngine sslEngine = _sslContextFactory.getSslContext().createSSLEngine();
sslEngine.setUseClientMode(false);
- sslEngine.setWantClientAuth(_sslParams.getWantClientAuth());
- sslEngine.setNeedClientAuth(_sslParams.getNeedClientAuth());
+ sslEngine.setWantClientAuth(_sslContextFactory.getWantClientAuth());
+ sslEngine.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
- sslEngine.setEnabledCipherSuites(_sslParams.selectCipherSuites(
+ sslEngine.setEnabledCipherSuites(_sslContextFactory.selectCipherSuites(
sslEngine.getEnabledCipherSuites(),
sslEngine.getSupportedCipherSuites()));
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
index a441329..b826344 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslSocketConnector.java
@@ -29,6 +29,7 @@
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.SslContextFactory;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.bio.SocketConnector;
@@ -53,7 +54,7 @@
*/
public class SslSocketConnector extends SocketConnector implements SslConnector
{
- private final SslParameters _sslParams;
+ private final SslContextFactory _sslContextFactory;
private int _handshakeTimeout = 0; //0 means use maxIdleTime
/* ------------------------------------------------------------ */
@@ -62,12 +63,12 @@
*/
public SslSocketConnector()
{
- this(new SslParameters());
+ this(new SslContextFactory().setKeystore(SslContextFactory.DEFAULT_KEYSTORE_PATH));
}
- public SslSocketConnector(SslParameters sslParams)
+ public SslSocketConnector(SslContextFactory sslContextFactory)
{
- _sslParams = sslParams;
+ _sslContextFactory = sslContextFactory;
}
/* ------------------------------------------------------------ */
@@ -76,7 +77,7 @@
*/
public boolean isAllowRenegotiate()
{
- return _sslParams.isAllowRenegotiate();
+ return _sslContextFactory.isAllowRenegotiate();
}
/* ------------------------------------------------------------ */
@@ -89,7 +90,7 @@
*/
public void setAllowRenegotiate(boolean allowRenegotiate)
{
- _sslParams.setAllowRenegotiate(allowRenegotiate);
+ _sslContextFactory.setAllowRenegotiate(allowRenegotiate);
}
/* ------------------------------------------------------------ */
@@ -148,78 +149,78 @@
/* ------------------------------------------------------------ */
public String[] getExcludeCipherSuites() {
- return _sslParams.getExcludeCipherSuites();
+ return _sslContextFactory.getExcludeCipherSuites();
}
/* ------------------------------------------------------------ */
public String[] getIncludeCipherSuites()
{
- return _sslParams.getIncludeCipherSuites();
+ return _sslContextFactory.getIncludeCipherSuites();
}
/* ------------------------------------------------------------ */
public String getKeystore()
{
- return _sslParams.getKeystore();
+ return _sslContextFactory.getKeystore();
}
/* ------------------------------------------------------------ */
public String getKeystoreType()
{
- return _sslParams.getKeystoreType();
+ return _sslContextFactory.getKeystoreType();
}
/* ------------------------------------------------------------ */
public boolean getNeedClientAuth()
{
- return _sslParams.getNeedClientAuth();
+ return _sslContextFactory.getNeedClientAuth();
}
/* ------------------------------------------------------------ */
public String getProtocol()
{
- return _sslParams.getProtocol();
+ return _sslContextFactory.getProtocol();
}
/* ------------------------------------------------------------ */
public String getProvider() {
- return _sslParams.getProvider();
+ return _sslContextFactory.getProvider();
}
/* ------------------------------------------------------------ */
public String getSecureRandomAlgorithm()
{
- return _sslParams.getSecureRandomAlgorithm();
+ return _sslContextFactory.getSecureRandomAlgorithm();
}
/* ------------------------------------------------------------ */
public String getSslKeyManagerFactoryAlgorithm()
{
- return _sslParams.getSslKeyManagerFactoryAlgorithm();
+ return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
public String getSslTrustManagerFactoryAlgorithm()
{
- return _sslParams.getSslTrustManagerFactoryAlgorithm();
+ return _sslContextFactory.getTrustManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
public String getTruststore()
{
- return _sslParams.getTruststore();
+ return _sslContextFactory.getTruststore();
}
/* ------------------------------------------------------------ */
public String getTruststoreType()
{
- return _sslParams.getTruststoreType();
+ return _sslContextFactory.getTruststoreType();
}
/* ------------------------------------------------------------ */
public boolean getWantClientAuth()
{
- return _sslParams.getWantClientAuth();
+ return _sslContextFactory.getWantClientAuth();
}
/* ------------------------------------------------------------ */
@@ -259,7 +260,7 @@
@Override
protected void doStart() throws Exception
{
- _sslParams.createSSLContext(); // called here to prevent exception wrapping
+ _sslContextFactory.createSSLContext(); // called here to prevent exception wrapping
super.doStart();
}
@@ -278,17 +279,17 @@
@Override
protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
{
- SSLServerSocketFactory factory = _sslParams.getSslContext().getServerSocketFactory();
+ SSLServerSocketFactory factory = _sslContextFactory.getSslContext().getServerSocketFactory();
SSLServerSocket socket =
(SSLServerSocket) (host==null ?
factory.createServerSocket(port,backlog):
factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
- socket.setWantClientAuth(_sslParams.getWantClientAuth());
- socket.setNeedClientAuth(_sslParams.getNeedClientAuth());
+ socket.setWantClientAuth(_sslContextFactory.getWantClientAuth());
+ socket.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
- socket.setEnabledCipherSuites(_sslParams.selectCipherSuites(
+ socket.setEnabledCipherSuites(_sslContextFactory.selectCipherSuites(
socket.getEnabledCipherSuites(),
socket.getSupportedCipherSuites()));
return socket;
@@ -300,19 +301,19 @@
*/
public void setExcludeCipherSuites(String[] cipherSuites)
{
- _sslParams.setExcludeCipherSuites(cipherSuites);
+ _sslContextFactory.setExcludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
public void setIncludeCipherSuites(String[] cipherSuites)
{
- _sslParams.setIncludeCipherSuites(cipherSuites);
+ _sslContextFactory.setIncludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
public void setKeyPassword(String password)
{
- _sslParams.setKeyPassword(password);
+ _sslContextFactory.setKeyManagerPassword(password);
}
/* ------------------------------------------------------------ */
@@ -321,13 +322,13 @@
*/
public void setKeystore(String keystore)
{
- _sslParams.setKeystore(keystore);
+ _sslContextFactory.setKeystore(keystore);
}
/* ------------------------------------------------------------ */
public void setKeystoreType(String keystoreType)
{
- _sslParams.setKeystoreType(keystoreType);
+ _sslContextFactory.setKeystoreType(keystoreType);
}
/* ------------------------------------------------------------ */
@@ -338,65 +339,65 @@
*/
public void setNeedClientAuth(boolean needClientAuth)
{
- _sslParams.setNeedClientAuth(needClientAuth);
+ _sslContextFactory.setNeedClientAuth(needClientAuth);
}
/* ------------------------------------------------------------ */
public void setPassword(String password)
{
- _sslParams.setPassword(password);
+ _sslContextFactory.setKeyStorePassword(password);
}
/* ------------------------------------------------------------ */
public void setTrustPassword(String password)
{
- _sslParams.setTrustPassword(password);
+ _sslContextFactory.setTrustStorePassword(password);
}
/* ------------------------------------------------------------ */
public void setProtocol(String protocol)
{
- _sslParams.setProtocol(protocol);
+ _sslContextFactory.setProtocol(protocol);
}
/* ------------------------------------------------------------ */
public void setProvider(String provider) {
- _sslParams.setProvider(provider);
+ _sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */
public void setSecureRandomAlgorithm(String algorithm)
{
- _sslParams.setSecureRandomAlgorithm(algorithm);
+ _sslContextFactory.setSecureRandomAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
- _sslParams.setSslKeyManagerFactoryAlgorithm(algorithm);
+ _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
public void setSslTrustManagerFactoryAlgorithm(String algorithm)
{
- _sslParams.setSslTrustManagerFactoryAlgorithm(algorithm);
+ _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm);
}
public void setTruststore(String truststore)
{
- _sslParams.setTruststore(truststore);
+ _sslContextFactory.setTruststore(truststore);
}
public void setTruststoreType(String truststoreType)
{
- _sslParams.setTruststoreType(truststoreType);
+ _sslContextFactory.setTruststoreType(truststoreType);
}
public void setSslContext(SSLContext sslContext)
{
- _sslParams.setSslContext(sslContext);
+ _sslContextFactory.setSslContext(sslContext);
}
/* ------------------------------------------------------------ */
@@ -405,7 +406,7 @@
*/
public SSLContext getSslContext()
{
- return _sslParams.getSslContext();
+ return _sslContextFactory.getSslContext();
}
/* ------------------------------------------------------------ */
@@ -418,7 +419,7 @@
*/
public void setWantClientAuth(boolean wantClientAuth)
{
- _sslParams.setWantClientAuth(wantClientAuth);
+ _sslContextFactory.setWantClientAuth(wantClientAuth);
}
/* ------------------------------------------------------------ */
@@ -471,7 +472,7 @@
{
if (handshook)
{
- if (!_sslParams.isAllowRenegotiate())
+ if (!_sslContextFactory.isAllowRenegotiate())
{
Log.warn("SSL renegotiate denied: "+ssl);
try{ssl.close();}catch(IOException e){Log.warn(e);}
diff --git a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslParameters.java b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
similarity index 65%
rename from jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslParameters.java
rename to jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
index 90f9e40..b052194 100644
--- a/jetty-exssl/src/main/java/org/eclipse/jetty/exssl/SslParameters.java
+++ b/jetty-exssl/src/main/java/org/eclipse/jetty/io/SslContextFactory.java
@@ -1,6 +1,9 @@
-package org.eclipse.jetty.exssl;
+package org.eclipse.jetty.io;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
@@ -26,21 +29,25 @@
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import org.eclipse.jetty.exssl.SslExtendedKeyManager;
import org.eclipse.jetty.http.security.Password;
+import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.security.CertificateValidator;
-public class SslParameters
+public class SslContextFactory
{
- public static final String DEFAULT_KEYSTORE_ALGORITHM =
+ public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
(Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
"SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
- public static final String DEFAULT_TRUSTSTORE_ALGORITHM =
+ public static final String DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM =
(Security.getProperty("ssl.TrustManagerFactory.algorithm") == null ?
"SunX509" : Security.getProperty("ssl.TrustManagerFactory.algorithm"));
/** Default value for the keystore location path. */
- public static final String DEFAULT_KEYSTORE =
+ public static final String DEFAULT_KEYSTORE_PATH =
System.getProperty("user.home") + File.separator + ".keystore";
/** String name of key password property. */
@@ -54,21 +61,26 @@
/** Included cipher suites. */
private String _includeCipherSuites[] = null;
- /** KeyStore path. */
- private String _keystorePath = DEFAULT_KEYSTORE;
- /** KeyStore provider name */
+ /** Keystore path. */
+ private String _keystorePath;
+ /** Keystore provider name */
private String _keystoreProvider;
- /** KeyStore type */
+ /** Keystore type */
private String _keystoreType = "JKS";
+ /** Keystore input stream */
+ private InputStream _keystoreInputStream;
+
/** SSL certificate alias */
private String _certAlias;
- /** TrustStore path */
+ /** Truststore path */
private String _truststorePath;
- /** TrustStore provider name */
+ /** Truststore provider name */
private String _truststoreProvider;
- /** TrustStore type */
+ /** Truststore type */
private String _truststoreType = "JKS";
+ /** Truststore input stream */
+ private InputStream _truststoreInputStream;
/** Set to true if client certificate authentication is required */
private boolean _needClientAuth = false;
@@ -80,11 +92,11 @@
private boolean _allowRenegotiate = false;
/** KeyStore password */
- private transient Password _password;
+ private transient Password _keystorePassword;
/** Key password */
- private transient Password _keyPassword;
+ private transient Password _keymanagerPassword;
/** TrustStore password */
- private transient Password _trustPassword;
+ private transient Password _truststorePassword;
/** SSL Provider name */
private String _sslProvider;
@@ -94,9 +106,9 @@
/** SecureRandom algorithm */
private String _secureRandomAlgorithm;
/** KeyManager factory algorithm */
- private String _sslKeyManagerFactoryAlgorithm = DEFAULT_KEYSTORE_ALGORITHM;
+ private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
/** TrustManager factory algorithm */
- private String _sslTrustManagerFactoryAlgorithm = DEFAULT_TRUSTSTORE_ALGORITHM;
+ private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
/** Path to file that contains Certificate Revocation List */
private String _crlPath;
@@ -122,9 +134,11 @@
* The array of cipher suite names to exclude from
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
- public void setExcludeCipherSuites(String[] cipherSuites)
+ public SslContextFactory setExcludeCipherSuites(String[] cipherSuites)
{
_excludeCipherSuites = cipherSuites;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -143,9 +157,11 @@
* The array of cipher suite names to include in
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
- public void setIncludeCipherSuites(String[] cipherSuites)
+ public SslContextFactory setIncludeCipherSuites(String[] cipherSuites)
{
_includeCipherSuites = cipherSuites;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -162,9 +178,11 @@
* @param keystore
* The file or URL of the SSL Key store.
*/
- public void setKeystore(String keystore)
+ public SslContextFactory setKeystore(String keystore)
{
_keystorePath = keystore;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -181,9 +199,11 @@
* @param keystoreProvider
* The provider of the key store
*/
- public void setKeystoreProvider(String keystoreProvider)
+ public SslContextFactory setKeystoreProvider(String keystoreProvider)
{
_keystoreProvider = keystoreProvider;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -200,9 +220,33 @@
* @param keystoreType
* The type of the key store (default "JKS")
*/
- public void setKeystoreType(String keystoreType)
+ public SslContextFactory setKeystoreType(String keystoreType)
{
_keystoreType = keystoreType;
+
+ return this;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Get the _keystoreInputStream.
+ * @return the _keystoreInputStream
+ */
+ public InputStream getKeystoreInputStream()
+ {
+ checkConfig();
+
+ return _keystoreInputStream;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set the _keystoreInputStream.
+ * @param _keystoreInputStream the _keystoreInputStream to set
+ */
+ public SslContextFactory setKeystoreInputStream(InputStream keystoreInputStream)
+ {
+ _keystoreInputStream = keystoreInputStream;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -219,9 +263,11 @@
* @param certAlias
* Alias of SSL certificate for the connector
*/
- public void setCertAlias(String certAlias)
+ public SslContextFactory setCertAlias(String certAlias)
{
_certAlias = certAlias;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -238,9 +284,11 @@
* @param truststore
* The file name or URL of the trust store location
*/
- public void setTruststore(String truststore)
+ public SslContextFactory setTruststore(String truststore)
{
_truststorePath = truststore;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -257,9 +305,11 @@
* @param truststoreProvider
* The provider of the trust store
*/
- public void setTruststoreProvider(String truststoreProvider)
+ public SslContextFactory setTruststoreProvider(String truststoreProvider)
{
_truststoreProvider = truststoreProvider;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -276,9 +326,33 @@
* @param truststoreType
* The type of the trust store (default "JKS")
*/
- public void setTruststoreType(String truststoreType)
+ public SslContextFactory setTruststoreType(String truststoreType)
{
_truststoreType = truststoreType;
+
+ return this;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Get the _truststoreInputStream.
+ * @return the _truststoreInputStream
+ */
+ public InputStream getTruststoreInputStream()
+ {
+ checkConfig();
+
+ return _truststoreInputStream;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set the _truststoreInputStream.
+ * @param _truststoreInputStream the _truststoreInputStream to set
+ */
+ public SslContextFactory setTruststoreInputStream(InputStream truststoreInputStream)
+ {
+ _truststoreInputStream = truststoreInputStream;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -297,9 +371,11 @@
* True if SSL needs client authentication.
* @see SSLEngine#getNeedClientAuth()
*/
- public void setNeedClientAuth(boolean needClientAuth)
+ public SslContextFactory setNeedClientAuth(boolean needClientAuth)
{
_needClientAuth = needClientAuth;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -318,9 +394,11 @@
* True if SSL wants client authentication.
* @see SSLEngine#getWantClientAuth()
*/
- public void setWantClientAuth(boolean wantClientAuth)
+ public SslContextFactory setWantClientAuth(boolean wantClientAuth)
{
_wantClientAuth = wantClientAuth;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -337,9 +415,11 @@
* @param validateServerCert
* true if SSL certificate has to be validated
*/
- public void setValidateCerts(boolean validateCerts)
+ public SslContextFactory setValidateCerts(boolean validateCerts)
{
_validateCerts = validateCerts;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -360,9 +440,11 @@
* @param allowRenegotiate
* true if re-negotiation is allowed (default false)
*/
- public void setAllowRenegotiate(boolean allowRenegotiate)
+ public SslContextFactory setAllowRenegotiate(boolean allowRenegotiate)
{
_allowRenegotiate = allowRenegotiate;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -370,9 +452,11 @@
* @param password
* The password for the key store
*/
- public void setPassword(String password)
+ public SslContextFactory setKeyStorePassword(String password)
{
- _password = Password.getPassword(PASSWORD_PROPERTY,password,null);
+ _keystorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -380,9 +464,11 @@
* @param password
* The password (if any) for the specific key within the key store
*/
- public void setKeyPassword(String password)
+ public SslContextFactory setKeyManagerPassword(String password)
{
- _keyPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
+ _keymanagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -390,9 +476,11 @@
* @param password
* The password for the trust store
*/
- public void setTrustPassword(String password)
+ public SslContextFactory setTrustStorePassword(String password)
{
- _trustPassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
+ _truststorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -411,9 +499,11 @@
* The SSL provider name, which if set is passed to
* {@link SSLContext#getInstance(String, String)}
*/
- public void setProvider(String provider)
+ public SslContextFactory setProvider(String provider)
{
_sslProvider = provider;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -432,9 +522,11 @@
* The SSL protocol (default "TLS") passed to
* {@link SSLContext#getInstance(String, String)}
*/
- public void setProtocol(String protocol)
+ public SslContextFactory setProtocol(String protocol)
{
_sslProtocol = protocol;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -455,9 +547,11 @@
* {@link SecureRandom#getInstance(String)} to obtain the {@link SecureRandom} instance passed to
* {@link SSLContext#init(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], SecureRandom)}
*/
- public void setSecureRandomAlgorithm(String algorithm)
+ public SslContextFactory setSecureRandomAlgorithm(String algorithm)
{
_secureRandomAlgorithm = algorithm;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -466,7 +560,7 @@
*/
public String getSslKeyManagerFactoryAlgorithm()
{
- return (_sslKeyManagerFactoryAlgorithm);
+ return (_keyManagerFactoryAlgorithm);
}
/* ------------------------------------------------------------ */
@@ -474,18 +568,20 @@
* @param algorithm
* The algorithm name (default "SunX509") used by the {@link KeyManagerFactory}
*/
- public void setSslKeyManagerFactoryAlgorithm(String algorithm)
+ public SslContextFactory setSslKeyManagerFactoryAlgorithm(String algorithm)
{
- _sslKeyManagerFactoryAlgorithm = algorithm;
+ _keyManagerFactoryAlgorithm = algorithm;
+
+ return this;
}
/* ------------------------------------------------------------ */
/**
* @return The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
*/
- public String getSslTrustManagerFactoryAlgorithm()
+ public String getTrustManagerFactoryAlgorithm()
{
- return (_sslTrustManagerFactoryAlgorithm);
+ return (_trustManagerFactoryAlgorithm);
}
/* ------------------------------------------------------------ */
@@ -493,9 +589,11 @@
* @param algorithm
* The algorithm name (default "SunX509") used by the {@link TrustManagerFactory}
*/
- public void setSslTrustManagerFactoryAlgorithm(String algorithm)
+ public SslContextFactory setTrustManagerFactoryAlgorithm(String algorithm)
{
- _sslTrustManagerFactoryAlgorithm = algorithm;
+ _trustManagerFactoryAlgorithm = algorithm;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -512,9 +610,11 @@
* @param crlPath
* Path to file that contains Certificate Revocation List
*/
- public void setCrlPath(String crlPath)
+ public SslContextFactory setCrlPath(String crlPath)
{
_crlPath = crlPath;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -533,9 +633,11 @@
* maximum number of intermediate certificates in
* the certification path (-1 for unlimited)
*/
- public void setMaxCertPathLength(int maxCertPathLength)
+ public SslContextFactory setMaxCertPathLength(int maxCertPathLength)
{
_maxCertPathLength = maxCertPathLength;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -562,16 +664,80 @@
* @param sslContext
* Set a preconfigured SSLContext
*/
- public void setSslContext(SSLContext sslContext)
+ public SslContextFactory setSslContext(SSLContext sslContext)
{
_context = sslContext;
+
+ return this;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return The SSLContext
+ */
+ public SSLContext getClientSslContext()
+ {
+ try
+ {
+ if (_context == null)
+ _context = createClientSSLContext();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return _context;
}
/* ------------------------------------------------------------ */
- protected SSLContext createSSLContext() throws Exception
+ /**
+ * @return SSL context for the client code
+ */
+ public SSLContext createClientSSLContext() throws Exception
{
- KeyStore keyStore = getKeyStore(_keystorePath,_keystoreType,_keystoreProvider,_password == null?null:_password.toString());
- KeyStore trustStore = getTrustStore(_truststorePath,_truststoreType,_truststoreProvider,_trustPassword == null?null:_trustPassword.toString());
+ SSLContext sslContext = null;
+
+ if (_keystoreInputStream == null && _keystorePath == null &&
+ _truststoreInputStream == null && _truststorePath == null )
+ {
+ // Create a trust manager that does not validate certificate chains
+ TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager()
+ {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers()
+ {
+ return null;
+ }
+
+ public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
+ {
+ }
+
+ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
+ {
+ }
+ }};
+
+ sslContext = SSLContext.getInstance(_sslProtocol);
+ sslContext.init(null, trustAllCerts, null);
+ }
+ else
+ {
+ sslContext = createSSLContext();
+ }
+
+ return sslContext;
+ }
+
+ /* ------------------------------------------------------------ */
+ public SSLContext createSSLContext() throws Exception
+ {
+ checkConfig();
+
+ KeyStore keyStore = getKeyStore(_keystoreInputStream, _keystorePath, _keystoreType,
+ _keystoreProvider, _keystorePassword==null? null: _keystorePassword.toString());
+ KeyStore trustStore = getKeyStore(_truststoreInputStream, _truststorePath, _truststoreType,
+ _truststoreProvider, _truststorePassword==null? null: _truststorePassword.toString());
Collection<? extends CRL> crls = loadCRL(_crlPath);
if (_certAlias == null)
@@ -588,8 +754,8 @@
if (_validateCerts)
{
- CertificateValidator validator = new CertificateValidator(keyStore,trustStore,crls);
- validator.validate(cert);
+ CertificateValidator validator = new CertificateValidator(trustStore,crls);
+ validator.validate(keyStore, cert);
}
KeyManager[] keyManagers = getKeyManagers(keyStore);
@@ -603,10 +769,10 @@
}
/* ------------------------------------------------------------ */
- public KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
+ protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
{
- KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm);
- keyManagerFactory.init(keyStore,_keyPassword == null?(_password == null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray());
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_keyManagerFactoryAlgorithm);
+ keyManagerFactory.init(keyStore,_keymanagerPassword == null?(_keystorePassword == null?null:_keystorePassword.toString().toCharArray()):_keymanagerPassword.toString().toCharArray());
KeyManager[] managers = keyManagerFactory.getKeyManagers();
if (_certAlias != null)
@@ -624,13 +790,13 @@
}
/* ------------------------------------------------------------ */
- public TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
+ protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
{
TrustManager[] managers = null;
if (trustStore != null && _validateCerts)
{
// Revocation checking is only supported for PKIX algorithm
- if (_sslTrustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
+ if (_trustManagerFactoryAlgorithm.equalsIgnoreCase("PKIX"))
{
PKIXBuilderParameters pbParams = new PKIXBuilderParameters(trustStore,new X509CertSelector());
@@ -651,14 +817,14 @@
// Enable Certificate Revocation List Distribution Points (CRLDP) support
System.setProperty("com.sun.security.enableCRLDP","true");
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
managers = trustManagerFactory.getTrustManagers();
}
else
{
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
trustManagerFactory.init(trustStore);
managers = trustManagerFactory.getTrustManagers();
@@ -669,63 +835,45 @@
}
/* ------------------------------------------------------------ */
- public KeyStore getKeyStore(String storePath, String storeType, String storeProvider, String storePassword) throws Exception
+ protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
{
- if (storePath == null)
- return null;
-
KeyStore keystore = null;
- InputStream inStream = null;
- try
- {
- if (storeProvider != null)
- {
- keystore = KeyStore.getInstance(storeType,storeProvider);
- }
- else
- {
- keystore = KeyStore.getInstance(storeType);
- }
- inStream = Resource.newResource(storePath).getInputStream();
- keystore.load(inStream,storePassword == null?null:storePassword.toCharArray());
-
- return keystore;
- }
- finally
+ if (storeStream != null || storePath != null)
{
- if (inStream != null)
+ InputStream inStream = storeStream;
+ try
{
- inStream.close();
+ if (inStream == null)
+ {
+ inStream = Resource.newResource(storePath).getInputStream();
+ }
+
+ if (storeProvider != null)
+ {
+ keystore = KeyStore.getInstance(storeType, storeProvider);
+ }
+ else
+ {
+ keystore = KeyStore.getInstance(storeType);
+ }
+
+ keystore.load(inStream, storePassword == null ? null : storePassword.toCharArray());
+ }
+ finally
+ {
+ if (inStream != null)
+ {
+ inStream.close();
+ }
}
}
+
+ return keystore;
}
/* ------------------------------------------------------------ */
- public KeyStore getTrustStore(String trustPath, String trustType, String trustProvider, String trustPassword) throws Exception
- {
- if (trustPath == null)
- {
- trustPath = System.getProperty("javax.net.ssl.trustStore");
- trustType = System.getProperty("javax.net.ssl.trustStoreType");
- trustProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
- trustPassword = System.getProperty("javax.net.ssl.trustStorePassword");
- }
-
- if (trustPath == null)
- {
- trustPath = _keystorePath;
- trustType = _keystoreType;
- trustProvider = _keystoreProvider;
- trustPassword = _password.toString();
- _sslTrustManagerFactoryAlgorithm = _sslKeyManagerFactoryAlgorithm;
- }
-
- return getKeyStore(trustPath,trustType,trustProvider,trustPassword);
- }
-
- /* ------------------------------------------------------------ */
- private Collection<? extends CRL> loadCRL(String crlPath) throws Exception
+ protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
{
Collection<? extends CRL> crlList = null;
@@ -748,6 +896,43 @@
return crlList;
}
+
+ protected void checkConfig()
+ {
+ /*
+ * if the keystore exists but the trust store doesn't use the keystore as the trust store
+ */
+ if (_keystoreInputStream != null || _keystorePath != null)
+ {
+ if (_truststoreInputStream == null && _truststorePath == null)
+ {
+ _truststorePath = _keystorePath;
+ _truststoreInputStream = _keystoreInputStream;
+ _truststoreType = _keystoreType;
+ _truststoreProvider = _keystoreProvider;
+ _truststorePassword = _keystorePassword;
+ _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
+ }
+ }
+
+ // It's the same stream and we cannot read it twice, so we read it once in memory
+ if (_keystoreInputStream != null && _keystoreInputStream == _truststoreInputStream)
+ {
+ try
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ IO.copy(_keystoreInputStream, baos);
+ _keystoreInputStream.close();
+
+ _keystoreInputStream = new ByteArrayInputStream(baos.toByteArray());
+ _truststoreInputStream = new ByteArrayInputStream(baos.toByteArray());
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
{
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
new file mode 100644
index 0000000..3267530
--- /dev/null
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/client/ContentExchangeTest.java
@@ -0,0 +1,346 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.client;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jetty.client.security.Realm;
+import org.eclipse.jetty.client.security.SimpleRealmResolver;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.io.EofException;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.IO;
+
+public class ContentExchangeTest
+ extends TestCase
+{
+ private static String _content =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
+
+ private File _docRoot;
+ private Server _server;
+ private HttpClient _client;
+ private Realm _realm;
+ private String _protocol;
+ private String _baseUrl;
+ private String _requestContent;
+
+ public void setUp()
+ throws Exception
+ {
+ _docRoot = new File("target/test-output/docroot/");
+ _docRoot.mkdirs();
+ _docRoot.deleteOnExit();
+
+ File content = new File(_docRoot,"input.txt");
+ FileOutputStream out = new FileOutputStream(content);
+ out.write(_content.getBytes("utf-8"));
+ out.close();
+
+ _server = new Server();
+ configureServer(_server);
+ _server.start();
+
+ int port = _server.getConnectors()[0].getLocalPort();
+ _baseUrl = _protocol+"://localhost:"+port+ "/";
+ }
+
+ public void tearDown()
+ throws Exception
+ {
+ if (_server != null)
+ {
+ _server.stop();
+ _server = null;
+ }
+ }
+
+ public void testPut() throws Exception
+ {
+ startClient(_realm);
+
+ ContentExchange putExchange = new ContentExchange();
+ putExchange.setURL(getBaseUrl() + "output.txt");
+ putExchange.setMethod(HttpMethods.PUT);
+ putExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
+
+ _client.send(putExchange);
+ int state = putExchange.waitForDone();
+
+ int responseStatus = putExchange.getResponseStatus();
+
+ stopClient();
+
+ boolean statusOk = (responseStatus == 200 || responseStatus == 201);
+ assertTrue(statusOk);
+
+ String content = IO.toString(new FileInputStream(new File(_docRoot,"output.txt")));
+ assertEquals(_content,content);
+ }
+
+ public void testGet() throws Exception
+ {
+ startClient(_realm);
+
+ ContentExchange getExchange = new ContentExchange();
+ getExchange.setURL(getBaseUrl() + "input.txt");
+ getExchange.setMethod(HttpMethods.GET);
+
+ _client.send(getExchange);
+ int state = getExchange.waitForDone();
+
+ String content = "";
+ int responseStatus = getExchange.getResponseStatus();
+ if (responseStatus == HttpStatus.OK_200)
+ {
+ content = getExchange.getResponseContent();
+ }
+
+ stopClient();
+
+ assertEquals(HttpStatus.OK_200,responseStatus);
+ assertEquals(_content,content);
+ }
+
+ public void testHead() throws Exception
+ {
+ startClient(_realm);
+
+ ContentExchange getExchange = new ContentExchange();
+ getExchange.setURL(getBaseUrl() + "input.txt");
+ getExchange.setMethod(HttpMethods.HEAD);
+
+ _client.send(getExchange);
+ getExchange.waitForDone();
+
+ int responseStatus = getExchange.getResponseStatus();
+
+ stopClient();
+
+ assertEquals(HttpStatus.OK_200,responseStatus);
+ }
+
+ public void testPost() throws Exception
+ {
+ startClient(_realm);
+
+ ContentExchange postExchange = new ContentExchange();
+ postExchange.setURL(getBaseUrl() + "test");
+ postExchange.setMethod(HttpMethods.POST);
+ postExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
+
+ _client.send(postExchange);
+ int state = postExchange.waitForDone();
+
+ int responseStatus = postExchange.getResponseStatus();
+
+ stopClient();
+
+ assertEquals(HttpStatus.OK_200,responseStatus);
+ assertEquals(_content,_requestContent);
+ }
+
+ protected void configureServer(Server server)
+ throws Exception
+ {
+ setProtocol("http");
+
+ SelectChannelConnector connector = new SelectChannelConnector();
+ server.addConnector(connector);
+
+ Handler handler = new TestHandler(getBasePath());
+
+ ServletContextHandler root = new ServletContextHandler();
+ root.setContextPath("/");
+ root.setResourceBase(_docRoot.getAbsolutePath());
+ ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
+ servletHolder.setInitParameter( "gzip", "true" );
+ root.addServlet( servletHolder, "/*" );
+
+ HandlerCollection handlers = new HandlerCollection();
+ handlers.setHandlers(new Handler[]{handler, root});
+ server.setHandler( handlers );
+
+ }
+
+ protected void startClient(Realm realm)
+ throws Exception
+ {
+ _client = new HttpClient();
+ _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ if (realm != null)
+ _client.setRealmResolver(new SimpleRealmResolver(realm));
+ _client.start();
+ }
+
+ protected void stopClient()
+ throws Exception
+ {
+ if (_client != null)
+ {
+ _client.stop();
+ _client = null;
+ }
+ }
+
+ protected String getBasePath()
+ {
+ return _docRoot.getAbsolutePath();
+ }
+
+ protected String getBaseUrl()
+ {
+ return _baseUrl;
+ }
+
+ protected HttpClient getClient()
+ {
+ return _client;
+ }
+
+ protected Realm getRealm()
+ {
+ return _realm;
+ }
+
+ protected String getContent()
+ {
+ return _content;
+ }
+
+ protected void setProtocol(String protocol)
+ {
+ _protocol = protocol;
+ }
+
+ protected void setRealm(Realm realm)
+ {
+ _realm = realm;
+ }
+
+ public static void copyStream(InputStream in, OutputStream out)
+ {
+ try
+ {
+ byte[] buffer=new byte[1024];
+ int len;
+ while ((len=in.read(buffer))>=0)
+ {
+ out.write(buffer,0,len);
+ }
+ }
+ catch (EofException e)
+ {
+ System.err.println(e);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected class TestHandler extends AbstractHandler {
+ private final String resourcePath;
+
+ public TestHandler(String repositoryPath) {
+ this.resourcePath = repositoryPath;
+ }
+
+ public void handle(String target, Request baseRequest,
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException
+ {
+ if (baseRequest.isHandled())
+ {
+ return;
+ }
+
+ OutputStream out = null;
+
+ if (baseRequest.getMethod().equals("PUT"))
+ {
+ baseRequest.setHandled(true);
+
+ File file = new File(resourcePath, URLDecoder.decode(request.getPathInfo()));
+ file.getParentFile().mkdirs();
+ file.deleteOnExit();
+
+ out = new FileOutputStream(file);
+
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ }
+
+ if (baseRequest.getMethod().equals("POST"))
+ {
+ baseRequest.setHandled(true);
+ out = new ByteArrayOutputStream();
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+
+ if (out != null)
+ {
+ ServletInputStream in = request.getInputStream();
+ try
+ {
+ copyStream( in, out );
+ }
+ finally
+ {
+ in.close();
+ out.close();
+ }
+
+ if (!(out instanceof FileOutputStream))
+ _requestContent = out.toString();
+ }
+
+ }
+ }
+}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java b/jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java
new file mode 100644
index 0000000..7dfb21e
--- /dev/null
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/client/SslContentExchangeTest.java
@@ -0,0 +1,56 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.client;
+
+import java.io.File;
+
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+
+public class SslContentExchangeTest
+ extends ContentExchangeTest
+{
+
+ protected void configureServer(Server server)
+ throws Exception
+ {
+ setProtocol("https");
+
+ SslSelectChannelConnector connector = new SslSelectChannelConnector();
+ File keystore = MavenTestingUtils.getTestResourceFile("jetty-valid.keystore");
+ connector.setKeystore(keystore.getAbsolutePath());
+ connector.setPassword("webtide");
+ connector.setKeyPassword("webtide");
+ server.addConnector(connector);
+
+ Handler handler = new TestHandler(getBasePath());
+
+ ServletContextHandler root = new ServletContextHandler();
+ root.setContextPath("/");
+ root.setResourceBase(getBasePath());
+ ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
+ servletHolder.setInitParameter( "gzip", "true" );
+ root.addServlet( servletHolder, "/*" );
+
+ HandlerCollection handlers = new HandlerCollection();
+ handlers.setHandlers(new Handler[]{handler, root});
+ server.setHandler( handlers );
+ }
+}
diff --git a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java
index da25770..c823bd3 100644
--- a/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java
+++ b/jetty-exssl/src/test/java/org/eclipse/jetty/exssl/CertificateValidationTestBase.java
@@ -4,6 +4,7 @@
import java.lang.reflect.Constructor;
import java.security.cert.CertificateException;
+import org.eclipse.jetty.io.SslContextFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@@ -32,17 +33,17 @@
String trustpath = new File(System.getProperty("java.home"),"./lib/security/cacerts").getAbsolutePath();
String crlpath = MavenTestingUtils.getTestResourceFile("crlfile.pem").getAbsolutePath();
- SslParameters sslParams = new SslParameters();
- sslParams.setValidateCerts(true);
- sslParams.setKeystore(keypath);
- sslParams.setPassword("webtide");
- sslParams.setKeyPassword("webtide");
- sslParams.setTruststore(trustpath);
- sslParams.setTrustPassword("changeit");
- sslParams.setCrlPath(crlpath);
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ sslContextFactory.setValidateCerts(true);
+ sslContextFactory.setKeystore(keypath);
+ sslContextFactory.setKeyStorePassword("webtide");
+ sslContextFactory.setKeyManagerPassword("webtide");
+ sslContextFactory.setTruststore(trustpath);
+ sslContextFactory.setTrustStorePassword("changeit");
+ sslContextFactory.setCrlPath(crlpath);
- Constructor<? extends SslConnector> constructor = _klass.getConstructor(SslParameters.class);
- SslConnector connector = constructor.newInstance(sslParams);
+ Constructor<? extends SslConnector> constructor = _klass.getConstructor(SslContextFactory.class);
+ SslConnector connector = constructor.newInstance(sslContextFactory);
connector.setPort(0);
_server = new Server();