1 29 30 package org.apache.commons.httpclient.contrib.ssl; 31 32 import java.io.IOException ; 33 import java.net.InetAddress ; 34 import java.net.InetSocketAddress ; 35 import java.net.Socket ; 36 import java.net.SocketAddress ; 37 import java.net.URL ; 38 import java.net.UnknownHostException ; 39 import java.security.GeneralSecurityException ; 40 import java.security.KeyStore ; 41 import java.security.KeyStoreException ; 42 import java.security.NoSuchAlgorithmException ; 43 import java.security.UnrecoverableKeyException ; 44 import java.security.cert.Certificate ; 45 import java.security.cert.CertificateException ; 46 import java.security.cert.X509Certificate ; 47 import java.util.Enumeration ; 48 49 import org.apache.commons.httpclient.ConnectTimeoutException; 50 import org.apache.commons.httpclient.params.HttpConnectionParams; 51 import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; 52 import org.apache.commons.logging.Log; 53 import org.apache.commons.logging.LogFactory; 54 55 import javax.net.SocketFactory; 56 import javax.net.ssl.KeyManager; 57 import javax.net.ssl.KeyManagerFactory; 58 import javax.net.ssl.SSLContext; 59 import javax.net.ssl.TrustManager; 60 import javax.net.ssl.TrustManagerFactory; 61 import javax.net.ssl.X509TrustManager; 62 63 174 175 public class AuthSSLProtocolSocketFactory implements SecureProtocolSocketFactory { 176 177 178 private static final Log LOG = LogFactory.getLog(AuthSSLProtocolSocketFactory.class); 179 180 private URL keystoreUrl = null; 181 private String keystorePassword = null; 182 private URL truststoreUrl = null; 183 private String truststorePassword = null; 184 private SSLContext sslcontext = null; 185 186 198 public AuthSSLProtocolSocketFactory( 199 final URL keystoreUrl, final String keystorePassword, 200 final URL truststoreUrl, final String truststorePassword) 201 { 202 super(); 203 this.keystoreUrl = keystoreUrl; 204 this.keystorePassword = keystorePassword; 205 this.truststoreUrl = truststoreUrl; 206 this.truststorePassword = truststorePassword; 207 } 208 209 private static KeyStore createKeyStore(final URL url, final String password) 210 throws KeyStoreException , NoSuchAlgorithmException , CertificateException , IOException 211 { 212 if (url == null) { 213 throw new IllegalArgumentException ("Keystore url may not be null"); 214 } 215 LOG.debug("Initializing key store"); 216 KeyStore keystore = KeyStore.getInstance("jks"); 217 keystore.load(url.openStream(), password != null ? password.toCharArray(): null); 218 return keystore; 219 } 220 221 private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password) 222 throws KeyStoreException , NoSuchAlgorithmException , UnrecoverableKeyException 223 { 224 if (keystore == null) { 225 throw new IllegalArgumentException ("Keystore may not be null"); 226 } 227 LOG.debug("Initializing key manager"); 228 KeyManagerFactory kmfactory = KeyManagerFactory.getInstance( 229 KeyManagerFactory.getDefaultAlgorithm()); 230 kmfactory.init(keystore, password != null ? password.toCharArray(): null); 231 return kmfactory.getKeyManagers(); 232 } 233 234 private static TrustManager[] createTrustManagers(final KeyStore keystore) 235 throws KeyStoreException , NoSuchAlgorithmException 236 { 237 if (keystore == null) { 238 throw new IllegalArgumentException ("Keystore may not be null"); 239 } 240 LOG.debug("Initializing trust manager"); 241 TrustManagerFactory tmfactory = TrustManagerFactory.getInstance( 242 TrustManagerFactory.getDefaultAlgorithm()); 243 tmfactory.init(keystore); 244 TrustManager[] trustmanagers = tmfactory.getTrustManagers(); 245 for (int i = 0; i < trustmanagers.length; i++) { 246 if (trustmanagers[i] instanceof X509TrustManager) { 247 trustmanagers[i] = new AuthSSLX509TrustManager( 248 (X509TrustManager)trustmanagers[i]); 249 } 250 } 251 return trustmanagers; 252 } 253 254 private SSLContext createSSLContext() { 255 try { 256 KeyManager[] keymanagers = null; 257 TrustManager[] trustmanagers = null; 258 if (this.keystoreUrl != null) { 259 KeyStore keystore = createKeyStore(this.keystoreUrl, this.keystorePassword); 260 if (LOG.isDebugEnabled()) { 261 Enumeration aliases = keystore.aliases(); 262 while (aliases.hasMoreElements()) { 263 String alias = (String )aliases.nextElement(); 264 Certificate [] certs = keystore.getCertificateChain(alias); 265 if (certs != null) { 266 LOG.debug("Certificate chain '" + alias + "':"); 267 for (int c = 0; c < certs.length; c++) { 268 if (certs[c] instanceof X509Certificate ) { 269 X509Certificate cert = (X509Certificate )certs[c]; 270 LOG.debug(" Certificate " + (c + 1) + ":"); 271 LOG.debug(" Subject DN: " + cert.getSubjectDN()); 272 LOG.debug(" Signature Algorithm: " + cert.getSigAlgName()); 273 LOG.debug(" Valid from: " + cert.getNotBefore() ); 274 LOG.debug(" Valid until: " + cert.getNotAfter()); 275 LOG.debug(" Issuer: " + cert.getIssuerDN()); 276 } 277 } 278 } 279 } 280 } 281 keymanagers = createKeyManagers(keystore, this.keystorePassword); 282 } 283 if (this.truststoreUrl != null) { 284 KeyStore keystore = createKeyStore(this.truststoreUrl, this.truststorePassword); 285 if (LOG.isDebugEnabled()) { 286 Enumeration aliases = keystore.aliases(); 287 while (aliases.hasMoreElements()) { 288 String alias = (String )aliases.nextElement(); 289 LOG.debug("Trusted certificate '" + alias + "':"); 290 Certificate trustedcert = keystore.getCertificate(alias); 291 if (trustedcert != null && trustedcert instanceof X509Certificate ) { 292 X509Certificate cert = (X509Certificate )trustedcert; 293 LOG.debug(" Subject DN: " + cert.getSubjectDN()); 294 LOG.debug(" Signature Algorithm: " + cert.getSigAlgName()); 295 LOG.debug(" Valid from: " + cert.getNotBefore() ); 296 LOG.debug(" Valid until: " + cert.getNotAfter()); 297 LOG.debug(" Issuer: " + cert.getIssuerDN()); 298 } 299 } 300 } 301 trustmanagers = createTrustManagers(keystore); 302 } 303 SSLContext sslcontext = SSLContext.getInstance("SSL"); 304 sslcontext.init(keymanagers, trustmanagers, null); 305 return sslcontext; 306 } catch (NoSuchAlgorithmException e) { 307 LOG.error(e.getMessage(), e); 308 throw new AuthSSLInitializationError("Unsupported algorithm exception: " + e.getMessage()); 309 } catch (KeyStoreException e) { 310 LOG.error(e.getMessage(), e); 311 throw new AuthSSLInitializationError("Keystore exception: " + e.getMessage()); 312 } catch (GeneralSecurityException e) { 313 LOG.error(e.getMessage(), e); 314 throw new AuthSSLInitializationError("Key management exception: " + e.getMessage()); 315 } catch (IOException e) { 316 LOG.error(e.getMessage(), e); 317 throw new AuthSSLInitializationError("I/O error reading keystore/truststore file: " + e.getMessage()); 318 } 319 } 320 321 private SSLContext getSSLContext() { 322 if (this.sslcontext == null) { 323 this.sslcontext = createSSLContext(); 324 } 325 return this.sslcontext; 326 } 327 328 349 public Socket createSocket( 350 final String host, 351 final int port, 352 final InetAddress localAddress, 353 final int localPort, 354 final HttpConnectionParams params 355 ) throws IOException , UnknownHostException , ConnectTimeoutException { 356 if (params == null) { 357 throw new IllegalArgumentException ("Parameters may not be null"); 358 } 359 int timeout = params.getConnectionTimeout(); 360 SocketFactory socketfactory = getSSLContext().getSocketFactory(); 361 if (timeout == 0) { 362 return socketfactory.createSocket(host, port, localAddress, localPort); 363 } else { 364 Socket socket = socketfactory.createSocket(); 365 SocketAddress localaddr = new InetSocketAddress (localAddress, localPort); 366 SocketAddress remoteaddr = new InetSocketAddress (host, port); 367 socket.bind(localaddr); 368 socket.connect(remoteaddr, timeout); 369 return socket; 370 } 371 } 372 373 376 public Socket createSocket( 377 String host, 378 int port, 379 InetAddress clientHost, 380 int clientPort) 381 throws IOException , UnknownHostException 382 { 383 return getSSLContext().getSocketFactory().createSocket( 384 host, 385 port, 386 clientHost, 387 clientPort 388 ); 389 } 390 391 394 public Socket createSocket(String host, int port) 395 throws IOException , UnknownHostException 396 { 397 return getSSLContext().getSocketFactory().createSocket( 398 host, 399 port 400 ); 401 } 402 403 406 public Socket createSocket( 407 Socket socket, 408 String host, 409 int port, 410 boolean autoClose) 411 throws IOException , UnknownHostException 412 { 413 return getSSLContext().getSocketFactory().createSocket( 414 socket, 415 host, 416 port, 417 autoClose 418 ); 419 } 420 } | Popular Tags |