1 16 package org.mortbay.http; 17 18 import java.io.ByteArrayInputStream ; 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.net.ServerSocket ; 22 import java.net.Socket ; 23 import java.security.KeyStore ; 24 import java.security.cert.X509Certificate ; 25 26 import javax.net.ssl.SSLException; 27 import javax.net.ssl.SSLPeerUnverifiedException; 28 import javax.net.ssl.SSLServerSocket; 29 import javax.net.ssl.SSLServerSocketFactory; 30 import javax.net.ssl.SSLSession; 31 import javax.net.ssl.SSLSocket; 32 33 import org.apache.commons.logging.Log; 34 import org.mortbay.log.LogFactory; 35 import org.mortbay.jetty.servlet.ServletSSL; 36 import org.mortbay.util.InetAddrPort; 37 import org.mortbay.util.LogSupport; 38 39 40 57 public abstract class JsseListener extends SocketListener 58 { 59 private static Log log = LogFactory.getLog(JsseListener.class); 60 61 62 public static final String KEYSTORE_PROPERTY = "jetty.ssl.keystore"; 63 64 65 public static final String KEYSTORE_TYPE_PROPERTY = "jetty.ssl.keystore.type"; 66 67 68 public static final String DEFAULT_KEYSTORE_TYPE = System.getProperty(KEYSTORE_TYPE_PROPERTY, KeyStore.getDefaultType()); 69 70 71 public static final String KEYSTORE_PROVIDER_NAME_PROPERTY = "jetty.ssl.keystore.provider.name"; 72 73 74 public static final String KEYSTORE_PROVIDER_CLASS_PROPERTY = "jetty.ssl.keystore.provider.class"; 75 76 77 public static final String DEFAULT_KEYSTORE_PROVIDER_CLASS = System.getProperty(KEYSTORE_PROVIDER_CLASS_PROPERTY); 78 79 80 public static final String DEFAULT_KEYSTORE = System.getProperty("user.home") + File.separator + ".keystore"; 81 82 83 public static final String DEFAULT_KEYSTORE_PROVIDER_NAME = System.getProperty(KEYSTORE_PROVIDER_NAME_PROPERTY); 84 85 86 public static final String PASSWORD_PROPERTY = "jetty.ssl.password"; 87 88 89 public static final String KEYPASSWORD_PROPERTY = "jetty.ssl.keypassword"; 90 91 94 static final String CACHED_INFO_ATTR = CachedInfo.class.getName(); 95 96 97 private boolean _needClientAuth = false; 98 99 100 103 public JsseListener() 104 { 105 super(); 106 setDefaultScheme(HttpMessage.__SSL_SCHEME); 107 } 108 109 110 115 public JsseListener(InetAddrPort p_address) 116 { 117 super(p_address); 118 if (p_address.getPort() == 0) 119 { 120 p_address.setPort(443); 121 setPort(443); 122 } 123 setDefaultScheme(HttpMessage.__SSL_SCHEME); 124 } 125 126 127 132 public void setNeedClientAuth(boolean needClientAuth) 133 { 134 _needClientAuth = needClientAuth; 135 } 136 137 138 public boolean getNeedClientAuth() 139 { 140 return _needClientAuth; 141 } 142 143 144 151 public boolean isIntegral(HttpConnection connection) 152 { 153 final int integralPort = getIntegralPort(); 154 return integralPort == 0 || integralPort == getPort(); 155 } 156 157 158 165 public boolean isConfidential(HttpConnection connection) 166 { 167 final int confidentialPort = getConfidentialPort(); 168 return confidentialPort == 0 || confidentialPort == getPort(); 169 } 170 171 172 protected abstract SSLServerSocketFactory createFactory() throws Exception ; 173 174 175 181 protected ServerSocket newServerSocket(InetAddrPort p_address, int p_acceptQueueSize) throws IOException 182 { 183 SSLServerSocketFactory factory = null; 184 SSLServerSocket socket = null; 185 186 try 187 { 188 factory = createFactory(); 189 190 if (p_address == null) 191 { 192 socket = (SSLServerSocket) factory.createServerSocket(0, p_acceptQueueSize); 193 } 194 else 195 { 196 socket = (SSLServerSocket) factory.createServerSocket(p_address.getPort(), p_acceptQueueSize, p_address.getInetAddress()); 197 } 198 199 socket.setNeedClientAuth(_needClientAuth); 200 log.info("JsseListener.needClientAuth=" + _needClientAuth); 201 } 202 catch (IOException e) 203 { 204 throw e; 205 } 206 catch (Exception e) 207 { 208 log.warn(LogSupport.EXCEPTION, e); 209 throw new IOException ("Could not create JsseListener: " + e.toString()); 210 } 211 return socket; 212 } 213 214 215 220 protected Socket accept(ServerSocket p_serverSocket) throws IOException 221 { 222 try 223 { 224 SSLSocket s = (SSLSocket) p_serverSocket.accept(); 225 if (getMaxIdleTimeMs() > 0) 226 s.setSoTimeout(getMaxIdleTimeMs()); 227 s.startHandshake(); return s; 229 } 230 catch (SSLException e) 231 { 232 log.warn(LogSupport.EXCEPTION, e); 233 throw new IOException (e.getMessage()); 234 } 235 } 236 237 238 255 protected void customizeRequest(Socket socket, HttpRequest request) 256 { 257 super.customizeRequest(socket, request); 258 259 if (!(socket instanceof javax.net.ssl.SSLSocket)) 260 return; 262 try 263 { 264 SSLSocket sslSocket = (SSLSocket) socket; 265 SSLSession sslSession = sslSocket.getSession(); 266 String cipherSuite = sslSession.getCipherSuite(); 267 Integer keySize; 268 X509Certificate [] certs; 269 270 CachedInfo cachedInfo = (CachedInfo) sslSession.getValue(CACHED_INFO_ATTR); 271 if (cachedInfo != null) 272 { 273 keySize = cachedInfo.getKeySize(); 274 certs = cachedInfo.getCerts(); 275 } 276 else 277 { 278 keySize = new Integer (ServletSSL.deduceKeyLength(cipherSuite)); 279 certs = getCertChain(sslSession); 280 cachedInfo = new CachedInfo(keySize, certs); 281 sslSession.putValue(CACHED_INFO_ATTR, cachedInfo); 282 } 283 284 if (certs != null) 285 request.setAttribute("javax.servlet.request.X509Certificate", certs); 286 else if (_needClientAuth) throw new HttpException(HttpResponse.__403_Forbidden); 288 289 request.setAttribute("javax.servlet.request.cipher_suite", cipherSuite); 290 request.setAttribute("javax.servlet.request.key_size", keySize); 291 } 292 catch (Exception e) 293 { 294 log.warn(LogSupport.EXCEPTION, e); 295 } 296 } 297 298 309 private static X509Certificate [] getCertChain(SSLSession sslSession) 310 { 311 try 312 { 313 javax.security.cert.X509Certificate javaxCerts[] = sslSession.getPeerCertificateChain(); 314 if (javaxCerts == null || javaxCerts.length == 0) 315 return null; 316 317 int length = javaxCerts.length; 318 X509Certificate [] javaCerts = new X509Certificate [length]; 319 320 java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509"); 321 for (int i = 0; i < length; i++) 322 { 323 byte bytes[] = javaxCerts[i].getEncoded(); 324 ByteArrayInputStream stream = new ByteArrayInputStream (bytes); 325 javaCerts[i] = (X509Certificate ) cf.generateCertificate(stream); 326 } 327 328 return javaCerts; 329 } 330 catch (SSLPeerUnverifiedException pue) 331 { 332 return null; 333 } 334 catch (Exception e) 335 { 336 log.warn(LogSupport.EXCEPTION, e); 337 return null; 338 } 339 } 340 341 345 private class CachedInfo 346 { 347 private Integer _keySize; 348 private X509Certificate [] _certs; 349 350 CachedInfo(Integer keySize, X509Certificate [] certs) 351 { 352 this._keySize = keySize; 353 this._certs = certs; 354 } 355 356 Integer getKeySize() 357 { 358 return _keySize; 359 } 360 361 X509Certificate [] getCerts() 362 { 363 return _certs; 364 } 365 } 366 } 367 | Popular Tags |