root/trunk/src/java/org/jcoderz/commons/connector/http/transport/SslSocketFactory.java

Revision 1011, 9.9 kB (checked in by amandel, 4 years ago)

Aligned svn keyword settings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.connector.http.transport;
34
35import java.io.FileInputStream;
36import java.io.FileNotFoundException;
37import java.io.IOException;
38import java.net.InetAddress;
39import java.net.Socket;
40import java.net.SocketAddress;
41import java.net.InetSocketAddress;
42import java.net.UnknownHostException;
43import java.security.GeneralSecurityException;
44import java.security.KeyStore;
45import java.security.Security;
46import java.util.logging.Logger;
47
48import javax.net.ssl.KeyManager;
49import javax.net.ssl.SSLContext;
50import javax.net.ssl.SSLSocketFactory;
51import javax.net.ssl.TrustManager;
52import javax.net.ssl.TrustManagerFactory;
53
54import org.apache.commons.httpclient.ConnectTimeoutException;
55import org.apache.commons.httpclient.params.HttpConnectionParams;
56import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
57import org.jcoderz.commons.connector.InitializingSslFailedException;
58import org.jcoderz.commons.util.Assert;
59
60
61
62/**
63 * Factory used to create SSLSocket.
64 */
65public final class SslSocketFactory
66      implements SecureProtocolSocketFactory
67{
68   /** The class name used for logging */
69   private static final String CLASSNAME = SslSocketFactory.class.getName();
70   /** The logger in use */
71   private static final Logger logger = Logger.getLogger(CLASSNAME);
72
73   /** Cache for SSLSocketFactories */
74   private static final ThreadLocal SSL_SOCKET_FACTORIES = new ThreadLocal();
75
76   private final String mKeyStoreLocation;
77   private final String mKeyStorePassword;
78   private final String mTrustStoreLocation;
79   private final String mTrustStorePassword;
80   private final String mKeyAlias;
81   private final String mKeyPassword;
82   private KeyStore mKeyStore = null;
83   private KeyStore mTrustStore = null;
84
85   /**
86    * Constructor.
87    * @param keyStoreLocation
88    *          the location of the key store in use
89    * @param keyStorePassword
90    *          the password of the key store in use
91    * @param trustStoreLocation
92    *          the location of the trust store in use
93    * @param trustStorePassword
94    *          the password of the trust store in use
95    * @param keyAlias
96    *          the alias of the key in use
97    * @param keyPassword
98    *          the password of the key in use
99    */
100   public SslSocketFactory (
101         String keyStoreLocation,
102         String keyStorePassword,
103         String trustStoreLocation,
104         String trustStorePassword,
105         String keyAlias,
106         String keyPassword)
107   {
108      Assert.notNull(keyStoreLocation, "keyStoreLocation");
109      Assert.notNull(keyStorePassword, "keyStorePassword");
110      Assert.notNull(trustStoreLocation, "trustStoreLocation");
111      Assert.notNull(trustStorePassword, "trustStorePassword");
112      Assert.notNull(keyAlias, "keyAlias");
113      Assert.notNull(keyPassword, "keyPassword");
114      mKeyStoreLocation = keyStoreLocation;
115      mKeyStorePassword = keyStorePassword;
116      mTrustStoreLocation = trustStoreLocation;
117      mTrustStorePassword = trustStorePassword;
118      mKeyAlias = keyAlias;
119      mKeyPassword = keyPassword;
120   }
121
122  /**
123   * Constructor.
124   * @param keyStore the keystore to use
125   * @param trustStore the truststore in use
126   * @param keyAlias the alias of the key in use
127   * @param keyPassword the password of the key in use
128   */
129   public SslSocketFactory (
130         KeyStore keyStore,
131         KeyStore trustStore,
132         String keyAlias,
133         String keyPassword)
134   {
135      Assert.notNull(keyStore, "keyStore");
136      Assert.notNull(keyAlias, "keyAlias");
137      Assert.notNull(keyPassword, "keyPassword");
138      mKeyStore = keyStore;
139      mTrustStore = trustStore;
140      mKeyAlias = keyAlias;
141      mKeyPassword = keyPassword;
142      mKeyStoreLocation = null;
143      mKeyStorePassword = null;
144      mTrustStoreLocation = null;
145      mTrustStorePassword = null;
146   }
147
148   /**
149    * Gets a CtsKeyManager as a specific X509KeyManager for the alias in use.
150    *
151    * @return KeyManager[]  contains only one KeyManager for the alias in use
152    * @throws GeneralSecurityException
153    *          in case of an keystore failure
154    */
155   private KeyManager[] getKeyManagers ()
156   {
157      final KeyManager manager
158            = new HttpsKeyManager(null, mKeyStore, mKeyAlias, mKeyPassword);
159      final KeyManager[] managers = {manager};
160      return managers;
161   }
162
163   /**
164    * Gets the TrustManagers for the specified algorithm.
165    *
166    * @return TrustManager[]  the TrustManger for the algorithm
167    * @throws GeneralSecurityException
168    *          in case of an keystore failure
169    */
170   private TrustManager[] getTrustManagers ()
171         throws GeneralSecurityException
172   {
173      final TrustManagerFactory tmf
174            = TrustManagerFactory.getInstance(
175                  Security.getProperty("ssl.TrustManagerFactory.algorithm"));
176      tmf.init(mTrustStore);
177      return tmf.getTrustManagers();
178   }
179
180   private SSLSocketFactory getSslSocketFactory ()
181         throws IOException, FileNotFoundException
182   {
183      SSLSocketFactory result;
184      result = (SSLSocketFactory) SSL_SOCKET_FACTORIES.get();
185
186      if (result == null)
187      {
188         logger.fine("Creating new SSL_SOCKET_FACTORY for Thread.");
189         SSLContext ctx = null;
190         try
191         {
192            // loading keystore/truststore if necessary (test mode only!!)
193            if (mKeyStore == null)
194            {
195               logger.finest("Loading keystore from file system - "
196                     + mKeyStoreLocation);
197               final char[] passphraseKeyStore
198                     = mKeyStorePassword.toCharArray();
199               mKeyStore = KeyStore.getInstance("JKS");
200               mKeyStore.load(new FileInputStream(
201                     mKeyStoreLocation), passphraseKeyStore);
202            }
203            if (mTrustStore == null)
204            {
205               logger.finest("Loading truststore from file system - "
206                     + mTrustStoreLocation);
207               final char[] passphraseTrustStore
208                     = mTrustStorePassword.toCharArray();
209               mTrustStore = KeyStore.getInstance("JKS");
210               mTrustStore.load(new FileInputStream(
211                     mTrustStoreLocation), passphraseTrustStore);
212            }
213
214            if (!mKeyStore.containsAlias(mKeyAlias))
215            {
216               final String reason
217                     = "Keystore does not contain key for alias "
218                        + "<" + mKeyAlias + ">";
219               final InitializingSslFailedException sse
220                     = new InitializingSslFailedException(reason);
221               throw sse;
222            }
223            ctx = SSLContext.getInstance("TLS");
224            ctx.init(getKeyManagers(), getTrustManagers(), null);
225         }
226         catch (GeneralSecurityException gse)
227         {
228            final String reason = gse.getMessage();
229            final InitializingSslFailedException sse
230                  = new InitializingSslFailedException(reason, gse);
231            throw sse;
232         }
233         result = ctx.getSocketFactory();
234         SSL_SOCKET_FACTORIES.set(result);
235      }
236      return result;
237   }
238
239   /** {@inheritDoc} */
240   public Socket createSocket (
241         String host, int port, InetAddress localAddress ,
242         int localPort, HttpConnectionParams params)
243         throws IOException, UnknownHostException, ConnectTimeoutException
244   {
245      // This is an IBM JSSE workaround: SSLSocket.connect() does not
246      // connect the socket in the IBM JSSE implementation, so we
247      // first connect a plain TCP socket and then layer it with an
248      // SSL Socket.
249      final Socket tcpSock = new Socket();
250      final SocketAddress endPoint = new InetSocketAddress(host, port);
251      tcpSock.connect(endPoint, params.getConnectionTimeout());
252      final Socket sock
253            = getSslSocketFactory().createSocket(tcpSock, host, port, true);
254      return sock;
255   }
256
257   /** {@inheritDoc} */
258   public Socket createSocket (String host, int port)
259         throws IOException, UnknownHostException
260   {
261      throw new UnsupportedOperationException("Method not supported");
262   }
263
264   /** {@inheritDoc} */
265   public Socket createSocket (
266         Socket socket, String host, int port, boolean autoClose)
267   {
268      throw new UnsupportedOperationException("Method not supported");
269   }
270
271   /** {@inheritDoc} */
272   public Socket createSocket (
273         String arg0, int arg1, InetAddress arg2, int arg3)
274         throws IOException, UnknownHostException
275   {
276      throw new UnsupportedOperationException("Method not supported");
277   }
278}
Note: See TracBrowser for help on using the browser.