1 17 package org.mortbay.http; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.net.ServerSocket ; 23 import java.net.Socket ; 24 import java.security.KeyStore ; 25 import java.security.cert.X509Certificate ; 26 27 import javax.net.ssl.KeyManagerFactory; 28 import javax.net.ssl.SSLContext; 29 import javax.net.ssl.SSLException; 30 import javax.net.ssl.SSLPeerUnverifiedException; 31 import javax.net.ssl.SSLServerSocket; 32 import javax.net.ssl.SSLServerSocketFactory; 33 import javax.net.ssl.SSLSession; 34 import javax.net.ssl.SSLSocket; 35 36 import org.apache.commons.logging.Log; 37 import org.mortbay.log.LogFactory; 38 import org.mortbay.jetty.servlet.ServletSSL; 39 import org.mortbay.util.InetAddrPort; 40 import org.mortbay.util.LogSupport; 41 import org.mortbay.util.Password; 42 import org.mortbay.util.Resource; 43 44 45 57 public class SslListener extends SocketListener 58 { 59 private static Log log = LogFactory.getLog(SslListener.class); 60 61 62 private String cipherSuites[] = null; 63 64 65 public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator 66 + ".keystore"; 67 68 69 public static final String PASSWORD_PROPERTY = "jetty.ssl.password"; 70 71 72 public static final String KEYPASSWORD_PROPERTY = "jetty.ssl.keypassword"; 73 74 77 static final String CACHED_INFO_ATTR = CachedInfo.class.getName(); 78 79 80 private String _keystore=DEFAULT_KEYSTORE ; 81 private transient Password _password; 82 private transient Password _keypassword; 83 private boolean _needClientAuth = false; private boolean _wantClientAuth = false; private String _protocol= "TLS"; 86 private String _algorithm = "SunX509"; private String _keystoreType = "JKS"; private String _provider = null; 89 90 91 92 93 96 public SslListener() 97 { 98 super(); 99 setDefaultScheme(HttpMessage.__SSL_SCHEME); 100 } 101 102 103 108 public SslListener(InetAddrPort p_address) 109 { 110 super(p_address); 111 if (p_address.getPort() == 0) 112 { 113 p_address.setPort(443); 114 setPort(443); 115 } 116 setDefaultScheme(HttpMessage.__SSL_SCHEME); 117 } 118 119 120 public String [] getCipherSuites() { 121 return cipherSuites; 122 } 123 124 125 128 public void setCipherSuites(String [] cipherSuites) { 129 this.cipherSuites = cipherSuites; 130 } 131 132 133 public void setPassword(String password) 134 { 135 _password = Password.getPassword(PASSWORD_PROPERTY,password,null); 136 } 137 138 139 public void setKeyPassword(String password) 140 { 141 _keypassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null); 142 } 143 144 145 public String getAlgorithm() 146 { 147 return (this._algorithm); 148 } 149 150 151 public void setAlgorithm(String algorithm) 152 { 153 this._algorithm = algorithm; 154 } 155 156 157 public String getProtocol() 158 { 159 return _protocol; 160 } 161 162 163 public void setProtocol(String protocol) 164 { 165 _protocol = protocol; 166 } 167 168 169 public void setKeystore(String keystore) 170 { 171 _keystore = keystore; 172 } 173 174 175 public String getKeystore() 176 { 177 return _keystore; 178 } 179 180 181 public String getKeystoreType() 182 { 183 return (_keystoreType); 184 } 185 186 187 public void setKeystoreType(String keystoreType) 188 { 189 _keystoreType = keystoreType; 190 } 191 192 193 198 public void setNeedClientAuth(boolean needClientAuth) 199 { 200 _needClientAuth = needClientAuth; 201 } 202 203 204 public boolean getNeedClientAuth() 205 { 206 return _needClientAuth; 207 } 208 209 210 215 public void setWantClientAuth(boolean wantClientAuth) 216 { 217 _wantClientAuth = wantClientAuth; 218 } 219 220 221 public boolean getWantClientAuth() 222 { 223 return _wantClientAuth; 224 } 225 226 227 234 public boolean isIntegral(HttpConnection connection) 235 { 236 final int integralPort = getIntegralPort(); 237 return integralPort == 0 || integralPort == getPort(); 238 } 239 240 241 248 public boolean isConfidential(HttpConnection connection) 249 { 250 final int confidentialPort = getConfidentialPort(); 251 return confidentialPort == 0 || confidentialPort == getPort(); 252 } 253 254 255 protected SSLServerSocketFactory createFactory() 256 throws Exception 257 { 258 SSLContext context; 259 if (_provider == null) { 260 context = SSLContext.getInstance(_protocol); 261 } else { 262 context = SSLContext.getInstance(_protocol, _provider); 263 } 264 265 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(_algorithm); 266 KeyStore keyStore = KeyStore.getInstance(_keystoreType); 267 keyStore.load(Resource.newResource(_keystore).getInputStream(), _password.toString().toCharArray()); 268 keyManagerFactory.init(keyStore,_keypassword.toString().toCharArray()); 269 270 context.init(keyManagerFactory.getKeyManagers(), null, new java.security.SecureRandom ()); 271 272 return context.getServerSocketFactory(); 273 } 274 275 276 281 protected ServerSocket newServerSocket(InetAddrPort p_address, int p_acceptQueueSize) 282 throws IOException 283 { 284 SSLServerSocketFactory factory = null; 285 SSLServerSocket socket = null; 286 287 try 288 { 289 factory = createFactory(); 290 291 if (p_address == null) 292 { 293 socket = (SSLServerSocket) factory.createServerSocket(0, p_acceptQueueSize); 294 } 295 else 296 { 297 socket = (SSLServerSocket) factory.createServerSocket(p_address.getPort(), 298 p_acceptQueueSize, p_address.getInetAddress()); 299 } 300 301 if (_needClientAuth) 302 socket.setNeedClientAuth(true); 303 else if (_wantClientAuth) 304 socket.setWantClientAuth(true); 305 306 if(cipherSuites != null && cipherSuites.length >0) { 307 socket.setEnabledCipherSuites(cipherSuites); 308 for ( int i=0; i<cipherSuites.length; i++ ) { 309 log.debug("SslListener enabled ciphersuite: " + cipherSuites[i]); 310 } 311 } 312 } 313 catch (IOException e) 314 { 315 throw e; 316 } 317 catch (Exception e) 318 { 319 log.warn(LogSupport.EXCEPTION, e); 320 throw new IOException ("Could not create JsseListener: " + e.toString()); 321 } 322 return socket; 323 } 324 325 326 330 protected Socket accept(ServerSocket p_serverSocket) throws IOException 331 { 332 try 333 { 334 SSLSocket s = (SSLSocket) p_serverSocket.accept(); 335 if (getMaxIdleTimeMs() > 0) s.setSoTimeout(getMaxIdleTimeMs()); 336 s.startHandshake(); return s; 338 } 339 catch (SSLException e) 340 { 341 log.warn(LogSupport.EXCEPTION, e); 342 throw new IOException (e.getMessage()); 343 } 344 } 345 346 347 364 protected void customizeRequest(Socket socket, HttpRequest request) 365 { 366 super.customizeRequest(socket, request); 367 368 if (!(socket instanceof javax.net.ssl.SSLSocket)) return; 371 try 372 { 373 SSLSocket sslSocket = (SSLSocket) socket; 374 SSLSession sslSession = sslSocket.getSession(); 375 String cipherSuite = sslSession.getCipherSuite(); 376 Integer keySize; 377 X509Certificate [] certs; 378 379 CachedInfo cachedInfo = (CachedInfo) sslSession.getValue(CACHED_INFO_ATTR); 380 if (cachedInfo != null) 381 { 382 keySize = cachedInfo.getKeySize(); 383 certs = cachedInfo.getCerts(); 384 } 385 else 386 { 387 keySize = new Integer (ServletSSL.deduceKeyLength(cipherSuite)); 388 certs = getCertChain(sslSession); 389 cachedInfo = new CachedInfo(keySize, certs); 390 sslSession.putValue(CACHED_INFO_ATTR, cachedInfo); 391 } 392 393 if (certs != null) 394 request.setAttribute("javax.servlet.request.X509Certificate", certs); 395 else if (_needClientAuth) throw new HttpException(HttpResponse.__403_Forbidden); 397 398 request.setAttribute("javax.servlet.request.cipher_suite", cipherSuite); 399 request.setAttribute("javax.servlet.request.key_size", keySize); 400 } 401 catch (Exception e) 402 { 403 log.warn(LogSupport.EXCEPTION, e); 404 } 405 } 406 407 418 private static X509Certificate [] getCertChain(SSLSession sslSession) 419 { 420 try 421 { 422 javax.security.cert.X509Certificate javaxCerts[] = sslSession.getPeerCertificateChain(); 423 if (javaxCerts == null || javaxCerts.length == 0) return null; 424 425 int length = javaxCerts.length; 426 X509Certificate [] javaCerts = new X509Certificate [length]; 427 428 java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory 429 .getInstance("X.509"); 430 for (int i = 0; i < length; i++) 431 { 432 byte bytes[] = javaxCerts[i].getEncoded(); 433 ByteArrayInputStream stream = new ByteArrayInputStream (bytes); 434 javaCerts[i] = (X509Certificate ) cf.generateCertificate(stream); 435 } 436 437 return javaCerts; 438 } 439 catch (SSLPeerUnverifiedException pue) 440 { 441 return null; 442 } 443 catch (Exception e) 444 { 445 log.warn(LogSupport.EXCEPTION, e); 446 return null; 447 } 448 } 449 450 454 private class CachedInfo 455 { 456 private Integer _keySize; 457 private X509Certificate [] _certs; 458 459 CachedInfo(Integer keySize, X509Certificate [] certs) 460 { 461 this._keySize = keySize; 462 this._certs = certs; 463 } 464 465 Integer getKeySize() 466 { 467 return _keySize; 468 } 469 470 X509Certificate [] getCerts() 471 { 472 return _certs; 473 } 474 } 475 476 public String getProvider() { 477 return _provider; 478 } 479 480 public void setProvider(String _provider) { 481 this._provider = _provider; 482 } 483 } 484 | Popular Tags |