1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.server.ssl; 20 21 import java.io.IOException; 22 import java.nio.channels.SocketChannel; 23 24 import javax.net.ssl.SSLContext; 25 import javax.net.ssl.SSLEngine; 26 import javax.net.ssl.SSLSession; 27 import javax.net.ssl.SSLSocket; 28 29 import org.eclipse.jetty.http.HttpSchemes; 30 import org.eclipse.jetty.io.AsyncEndPoint; 31 import org.eclipse.jetty.io.Buffers; 32 import org.eclipse.jetty.io.Buffers.Type; 33 import org.eclipse.jetty.io.BuffersFactory; 34 import org.eclipse.jetty.io.EndPoint; 35 import org.eclipse.jetty.io.RuntimeIOException; 36 import org.eclipse.jetty.io.bio.SocketEndPoint; 37 import org.eclipse.jetty.io.nio.AsyncConnection; 38 import org.eclipse.jetty.io.nio.SslConnection; 39 import org.eclipse.jetty.server.Request; 40 import org.eclipse.jetty.server.nio.SelectChannelConnector; 41 import org.eclipse.jetty.util.component.AggregateLifeCycle; 42 import org.eclipse.jetty.util.ssl.SslContextFactory; 43 44 /* ------------------------------------------------------------ */ 45 /** 46 * SslSelectChannelConnector. 47 * 48 * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector" 49 */ 50 public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector 51 { 52 private final SslContextFactory _sslContextFactory; 53 private Buffers _sslBuffers; 54 55 /* ------------------------------------------------------------ */ SslSelectChannelConnector()56 public SslSelectChannelConnector() 57 { 58 this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH)); 59 setSoLingerTime(30000); 60 } 61 62 /* ------------------------------------------------------------ */ 63 /** Construct with explicit SslContextFactory. 64 * The SslContextFactory passed is added via {@link #addBean(Object)} so that 65 * it's lifecycle may be managed with {@link AggregateLifeCycle}. 66 * @param sslContextFactory 67 */ SslSelectChannelConnector(SslContextFactory sslContextFactory)68 public SslSelectChannelConnector(SslContextFactory sslContextFactory) 69 { 70 _sslContextFactory = sslContextFactory; 71 addBean(_sslContextFactory); 72 setUseDirectBuffers(false); 73 setSoLingerTime(30000); 74 } 75 76 /* ------------------------------------------------------------ */ 77 /** 78 * Allow the Listener a chance to customise the request. before the server 79 * does its stuff. <br> 80 * This allows the required attributes to be set for SSL requests. <br> 81 * The requirements of the Servlet specs are: 82 * <ul> 83 * <li> an attribute named "javax.servlet.request.ssl_session_id" of type 84 * String (since Servlet Spec 3.0).</li> 85 * <li> an attribute named "javax.servlet.request.cipher_suite" of type 86 * String.</li> 87 * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li> 88 * <li> an attribute named "javax.servlet.request.X509Certificate" of type 89 * java.security.cert.X509Certificate[]. This is an array of objects of type 90 * X509Certificate, the order of this array is defined as being in ascending 91 * order of trust. The first certificate in the chain is the one set by the 92 * client, the next is the one used to authenticate the first, and so on. 93 * </li> 94 * </ul> 95 * 96 * @param endpoint 97 * The Socket the request arrived on. This should be a 98 * {@link SocketEndPoint} wrapping a {@link SSLSocket}. 99 * @param request 100 * HttpRequest to be customised. 101 */ 102 @Override customize(EndPoint endpoint, Request request)103 public void customize(EndPoint endpoint, Request request) throws IOException 104 { 105 request.setScheme(HttpSchemes.HTTPS); 106 super.customize(endpoint,request); 107 108 SslConnection.SslEndPoint sslEndpoint=(SslConnection.SslEndPoint)endpoint; 109 SSLEngine sslEngine=sslEndpoint.getSslEngine(); 110 SSLSession sslSession=sslEngine.getSession(); 111 112 SslCertificates.customize(sslSession,endpoint,request); 113 } 114 115 /* ------------------------------------------------------------ */ 116 /** 117 * @return True if SSL re-negotiation is allowed (default false) 118 * @deprecated 119 */ 120 @Deprecated isAllowRenegotiate()121 public boolean isAllowRenegotiate() 122 { 123 return _sslContextFactory.isAllowRenegotiate(); 124 } 125 126 /* ------------------------------------------------------------ */ 127 /** 128 * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered 129 * a vulnerability in SSL/TLS with re-negotiation. If your JVM 130 * does not have CVE-2009-3555 fixed, then re-negotiation should 131 * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban 132 * of renegotiate in u19 and with RFC5746 in u22. 133 * @param allowRenegotiate true if re-negotiation is allowed (default false) 134 * @deprecated 135 */ 136 @Deprecated setAllowRenegotiate(boolean allowRenegotiate)137 public void setAllowRenegotiate(boolean allowRenegotiate) 138 { 139 _sslContextFactory.setAllowRenegotiate(allowRenegotiate); 140 } 141 142 /* ------------------------------------------------------------ */ 143 /** 144 * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() 145 * @deprecated 146 */ 147 @Deprecated getExcludeCipherSuites()148 public String[] getExcludeCipherSuites() 149 { 150 return _sslContextFactory.getExcludeCipherSuites(); 151 } 152 153 /* ------------------------------------------------------------ */ 154 /** 155 * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) 156 * @deprecated 157 */ 158 @Deprecated setExcludeCipherSuites(String[] cipherSuites)159 public void setExcludeCipherSuites(String[] cipherSuites) 160 { 161 _sslContextFactory.setExcludeCipherSuites(cipherSuites); 162 } 163 164 /* ------------------------------------------------------------ */ 165 /** 166 * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() 167 * @deprecated 168 */ 169 @Deprecated getIncludeCipherSuites()170 public String[] getIncludeCipherSuites() 171 { 172 return _sslContextFactory.getIncludeCipherSuites(); 173 } 174 175 /* ------------------------------------------------------------ */ 176 /** 177 * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) 178 * @deprecated 179 */ 180 @Deprecated setIncludeCipherSuites(String[] cipherSuites)181 public void setIncludeCipherSuites(String[] cipherSuites) 182 { 183 _sslContextFactory.setIncludeCipherSuites(cipherSuites); 184 } 185 186 /* ------------------------------------------------------------ */ 187 /** 188 * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String) 189 * @deprecated 190 */ 191 @Deprecated setPassword(String password)192 public void setPassword(String password) 193 { 194 _sslContextFactory.setKeyStorePassword(password); 195 } 196 197 /* ------------------------------------------------------------ */ 198 /** 199 * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String) 200 * @deprecated 201 */ 202 @Deprecated setTrustPassword(String password)203 public void setTrustPassword(String password) 204 { 205 _sslContextFactory.setTrustStorePassword(password); 206 } 207 208 /* ------------------------------------------------------------ */ 209 /** 210 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String) 211 * @deprecated 212 */ 213 @Deprecated setKeyPassword(String password)214 public void setKeyPassword(String password) 215 { 216 _sslContextFactory.setKeyManagerPassword(password); 217 } 218 219 /* ------------------------------------------------------------ */ 220 /** 221 * Unsupported. 222 * 223 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) 224 * @deprecated 225 */ 226 @Deprecated getAlgorithm()227 public String getAlgorithm() 228 { 229 throw new UnsupportedOperationException(); 230 } 231 232 /* ------------------------------------------------------------ */ 233 /** 234 * Unsupported. 235 * 236 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) 237 * @deprecated 238 */ 239 @Deprecated setAlgorithm(String algorithm)240 public void setAlgorithm(String algorithm) 241 { 242 throw new UnsupportedOperationException(); 243 } 244 245 /* ------------------------------------------------------------ */ 246 /** 247 * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol() 248 * @deprecated 249 */ 250 @Deprecated getProtocol()251 public String getProtocol() 252 { 253 return _sslContextFactory.getProtocol(); 254 } 255 256 /* ------------------------------------------------------------ */ 257 /** 258 * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String) 259 * @deprecated 260 */ 261 @Deprecated setProtocol(String protocol)262 public void setProtocol(String protocol) 263 { 264 _sslContextFactory.setProtocol(protocol); 265 } 266 267 /* ------------------------------------------------------------ */ 268 /** 269 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String) 270 * @deprecated 271 */ 272 @Deprecated setKeystore(String keystore)273 public void setKeystore(String keystore) 274 { 275 _sslContextFactory.setKeyStorePath(keystore); 276 } 277 278 /* ------------------------------------------------------------ */ 279 /** 280 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore() 281 * @deprecated 282 */ 283 @Deprecated getKeystore()284 public String getKeystore() 285 { 286 return _sslContextFactory.getKeyStorePath(); 287 } 288 289 /* ------------------------------------------------------------ */ 290 /** 291 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType() 292 * @deprecated 293 */ 294 @Deprecated getKeystoreType()295 public String getKeystoreType() 296 { 297 return _sslContextFactory.getKeyStoreType(); 298 } 299 300 /* ------------------------------------------------------------ */ 301 /** 302 * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth() 303 * @deprecated 304 */ 305 @Deprecated getNeedClientAuth()306 public boolean getNeedClientAuth() 307 { 308 return _sslContextFactory.getNeedClientAuth(); 309 } 310 311 /* ------------------------------------------------------------ */ 312 /** 313 * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth() 314 * @deprecated 315 */ 316 @Deprecated getWantClientAuth()317 public boolean getWantClientAuth() 318 { 319 return _sslContextFactory.getWantClientAuth(); 320 } 321 322 /* ------------------------------------------------------------ */ 323 /** 324 * @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean) 325 * @deprecated 326 */ 327 @Deprecated setNeedClientAuth(boolean needClientAuth)328 public void setNeedClientAuth(boolean needClientAuth) 329 { 330 _sslContextFactory.setNeedClientAuth(needClientAuth); 331 } 332 333 /* ------------------------------------------------------------ */ 334 /** 335 * @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean) 336 * @deprecated 337 */ 338 @Deprecated setWantClientAuth(boolean wantClientAuth)339 public void setWantClientAuth(boolean wantClientAuth) 340 { 341 _sslContextFactory.setWantClientAuth(wantClientAuth); 342 } 343 344 /* ------------------------------------------------------------ */ 345 /** 346 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String) 347 * @deprecated 348 */ 349 @Deprecated setKeystoreType(String keystoreType)350 public void setKeystoreType(String keystoreType) 351 { 352 _sslContextFactory.setKeyStoreType(keystoreType); 353 } 354 355 /* ------------------------------------------------------------ */ 356 /** 357 * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider() 358 * @deprecated 359 */ 360 @Deprecated getProvider()361 public String getProvider() 362 { 363 return _sslContextFactory.getProvider(); 364 } 365 366 /* ------------------------------------------------------------ */ 367 /** 368 * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm() 369 * @deprecated 370 */ 371 @Deprecated getSecureRandomAlgorithm()372 public String getSecureRandomAlgorithm() 373 { 374 return _sslContextFactory.getSecureRandomAlgorithm(); 375 } 376 377 /* ------------------------------------------------------------ */ 378 /** 379 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm() 380 * @deprecated 381 */ 382 @Deprecated getSslKeyManagerFactoryAlgorithm()383 public String getSslKeyManagerFactoryAlgorithm() 384 { 385 return _sslContextFactory.getSslKeyManagerFactoryAlgorithm(); 386 } 387 388 /* ------------------------------------------------------------ */ 389 /** 390 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm() 391 * @deprecated 392 */ 393 @Deprecated getSslTrustManagerFactoryAlgorithm()394 public String getSslTrustManagerFactoryAlgorithm() 395 { 396 return _sslContextFactory.getTrustManagerFactoryAlgorithm(); 397 } 398 399 /* ------------------------------------------------------------ */ 400 /** 401 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore() 402 * @deprecated 403 */ 404 @Deprecated getTruststore()405 public String getTruststore() 406 { 407 return _sslContextFactory.getTrustStore(); 408 } 409 410 /* ------------------------------------------------------------ */ 411 /** 412 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType() 413 * @deprecated 414 */ 415 @Deprecated getTruststoreType()416 public String getTruststoreType() 417 { 418 return _sslContextFactory.getTrustStoreType(); 419 } 420 421 /* ------------------------------------------------------------ */ 422 /** 423 * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String) 424 * @deprecated 425 */ 426 @Deprecated setProvider(String provider)427 public void setProvider(String provider) 428 { 429 _sslContextFactory.setProvider(provider); 430 } 431 432 /* ------------------------------------------------------------ */ 433 /** 434 * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String) 435 * @deprecated 436 */ 437 @Deprecated setSecureRandomAlgorithm(String algorithm)438 public void setSecureRandomAlgorithm(String algorithm) 439 { 440 _sslContextFactory.setSecureRandomAlgorithm(algorithm); 441 } 442 443 /* ------------------------------------------------------------ */ 444 /** 445 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String) 446 * @deprecated 447 */ 448 @Deprecated setSslKeyManagerFactoryAlgorithm(String algorithm)449 public void setSslKeyManagerFactoryAlgorithm(String algorithm) 450 { 451 _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm); 452 } 453 454 /* ------------------------------------------------------------ */ 455 /** 456 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String) 457 * @deprecated 458 */ 459 @Deprecated setSslTrustManagerFactoryAlgorithm(String algorithm)460 public void setSslTrustManagerFactoryAlgorithm(String algorithm) 461 { 462 _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm); 463 } 464 465 /* ------------------------------------------------------------ */ 466 /** 467 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String) 468 * @deprecated 469 */ 470 @Deprecated setTruststore(String truststore)471 public void setTruststore(String truststore) 472 { 473 _sslContextFactory.setTrustStore(truststore); 474 } 475 476 /* ------------------------------------------------------------ */ 477 /** 478 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String) 479 * @deprecated 480 */ 481 @Deprecated setTruststoreType(String truststoreType)482 public void setTruststoreType(String truststoreType) 483 { 484 _sslContextFactory.setTrustStoreType(truststoreType); 485 } 486 487 /* ------------------------------------------------------------ */ 488 /** 489 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) 490 * @deprecated 491 */ 492 @Deprecated setSslContext(SSLContext sslContext)493 public void setSslContext(SSLContext sslContext) 494 { 495 _sslContextFactory.setSslContext(sslContext); 496 } 497 498 /* ------------------------------------------------------------ */ 499 /** 500 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) 501 * @deprecated 502 */ 503 @Deprecated getSslContext()504 public SSLContext getSslContext() 505 { 506 return _sslContextFactory.getSslContext(); 507 } 508 509 /* ------------------------------------------------------------ */ 510 /** 511 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory() 512 */ getSslContextFactory()513 public SslContextFactory getSslContextFactory() 514 { 515 return _sslContextFactory; 516 } 517 518 /* ------------------------------------------------------------ */ 519 /** 520 * By default, we're confidential, given we speak SSL. But, if we've been 521 * told about an confidential port, and said port is not our port, then 522 * we're not. This allows separation of listeners providing INTEGRAL versus 523 * CONFIDENTIAL constraints, such as one SSL listener configured to require 524 * client certs providing CONFIDENTIAL, whereas another SSL listener not 525 * requiring client certs providing mere INTEGRAL constraints. 526 */ 527 @Override isConfidential(Request request)528 public boolean isConfidential(Request request) 529 { 530 final int confidentialPort=getConfidentialPort(); 531 return confidentialPort==0||confidentialPort==request.getServerPort(); 532 } 533 534 /* ------------------------------------------------------------ */ 535 /** 536 * By default, we're integral, given we speak SSL. But, if we've been told 537 * about an integral port, and said port is not our port, then we're not. 538 * This allows separation of listeners providing INTEGRAL versus 539 * CONFIDENTIAL constraints, such as one SSL listener configured to require 540 * client certs providing CONFIDENTIAL, whereas another SSL listener not 541 * requiring client certs providing mere INTEGRAL constraints. 542 */ 543 @Override isIntegral(Request request)544 public boolean isIntegral(Request request) 545 { 546 final int integralPort=getIntegralPort(); 547 return integralPort==0||integralPort==request.getServerPort(); 548 } 549 550 /* ------------------------------------------------------------------------------- */ 551 @Override newConnection(SocketChannel channel, AsyncEndPoint endpoint)552 protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint) 553 { 554 try 555 { 556 SSLEngine engine = createSSLEngine(channel); 557 SslConnection connection = newSslConnection(endpoint, engine); 558 AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint()); 559 connection.getSslEndPoint().setConnection(delegate); 560 connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate()); 561 return connection; 562 } 563 catch (IOException e) 564 { 565 throw new RuntimeIOException(e); 566 } 567 } 568 newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)569 protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint) 570 { 571 return super.newConnection(channel, endPoint); 572 } 573 newSslConnection(AsyncEndPoint endpoint, SSLEngine engine)574 protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine) 575 { 576 return new SslConnection(engine, endpoint); 577 } 578 579 /* ------------------------------------------------------------ */ 580 /** 581 * @param channel A channel which if passed is used as to extract remote 582 * host and port for the purposes of SSL session caching 583 * @return A SSLEngine for a new or cached SSL Session 584 * @throws IOException if the SSLEngine cannot be created 585 */ createSSLEngine(SocketChannel channel)586 protected SSLEngine createSSLEngine(SocketChannel channel) throws IOException 587 { 588 SSLEngine engine; 589 if (channel != null) 590 { 591 String peerHost = channel.socket().getInetAddress().getHostAddress(); 592 int peerPort = channel.socket().getPort(); 593 engine = _sslContextFactory.newSslEngine(peerHost, peerPort); 594 } 595 else 596 { 597 engine = _sslContextFactory.newSslEngine(); 598 } 599 600 engine.setUseClientMode(false); 601 return engine; 602 } 603 604 /* ------------------------------------------------------------ */ 605 /** 606 * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStart() 607 */ 608 @Override doStart()609 protected void doStart() throws Exception 610 { 611 _sslContextFactory.checkKeyStore(); 612 _sslContextFactory.start(); 613 614 SSLEngine sslEngine = _sslContextFactory.newSslEngine(); 615 616 sslEngine.setUseClientMode(false); 617 618 SSLSession sslSession = sslEngine.getSession(); 619 620 _sslBuffers = BuffersFactory.newBuffers( 621 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(), 622 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(), 623 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,getMaxBuffers() 624 ); 625 626 if (getRequestHeaderSize()<sslSession.getApplicationBufferSize()) 627 setRequestHeaderSize(sslSession.getApplicationBufferSize()); 628 if (getRequestBufferSize()<sslSession.getApplicationBufferSize()) 629 setRequestBufferSize(sslSession.getApplicationBufferSize()); 630 631 super.doStart(); 632 } 633 634 /* ------------------------------------------------------------ */ 635 /** 636 * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStop() 637 */ 638 @Override doStop()639 protected void doStop() throws Exception 640 { 641 _sslBuffers=null; 642 super.doStop(); 643 } 644 645 /* ------------------------------------------------------------ */ 646 /** 647 * @return SSL buffers 648 */ getSslBuffers()649 public Buffers getSslBuffers() 650 { 651 return _sslBuffers; 652 } 653 } 654