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.net.ServerSocket; 23 import java.net.Socket; 24 25 import javax.net.ssl.HandshakeCompletedEvent; 26 import javax.net.ssl.HandshakeCompletedListener; 27 import javax.net.ssl.SSLContext; 28 import javax.net.ssl.SSLException; 29 import javax.net.ssl.SSLServerSocket; 30 import javax.net.ssl.SSLSession; 31 import javax.net.ssl.SSLSocket; 32 33 import org.eclipse.jetty.http.HttpSchemes; 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.server.Request; 38 import org.eclipse.jetty.server.bio.SocketConnector; 39 import org.eclipse.jetty.util.log.Log; 40 import org.eclipse.jetty.util.log.Logger; 41 import org.eclipse.jetty.util.ssl.SslContextFactory; 42 43 /* ------------------------------------------------------------ */ 44 /** 45 * SSL Socket Connector. 46 * 47 * This specialization of SocketConnector is an abstract listener that can be used as the basis for a 48 * specific JSSE listener. 49 * 50 * The original of this class was heavily based on the work from Court Demas, which in turn is 51 * based on the work from Forge Research. Since JSSE, this class has evolved significantly from 52 * that early work. 53 * 54 * @org.apache.xbean.XBean element="sslSocketConnector" description="Creates an ssl socket connector" 55 * 56 * 57 */ 58 public class SslSocketConnector extends SocketConnector implements SslConnector 59 { 60 private static final Logger LOG = Log.getLogger(SslSocketConnector.class); 61 62 private final SslContextFactory _sslContextFactory; 63 private int _handshakeTimeout = 0; //0 means use maxIdleTime 64 65 /* ------------------------------------------------------------ */ 66 /** 67 * Constructor. 68 */ SslSocketConnector()69 public SslSocketConnector() 70 { 71 this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH)); 72 setSoLingerTime(30000); 73 } 74 75 /* ------------------------------------------------------------ */ SslSocketConnector(SslContextFactory sslContextFactory)76 public SslSocketConnector(SslContextFactory sslContextFactory) 77 { 78 _sslContextFactory = sslContextFactory; 79 } 80 81 /* ------------------------------------------------------------ */ 82 /** 83 * @return True if SSL re-negotiation is allowed (default false) 84 */ isAllowRenegotiate()85 public boolean isAllowRenegotiate() 86 { 87 return _sslContextFactory.isAllowRenegotiate(); 88 } 89 90 /* ------------------------------------------------------------ */ 91 /** 92 * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered 93 * a vulnerability in SSL/TLS with re-negotiation. If your JVM 94 * does not have CVE-2009-3555 fixed, then re-negotiation should 95 * not be allowed. 96 * @param allowRenegotiate true if re-negotiation is allowed (default false) 97 */ setAllowRenegotiate(boolean allowRenegotiate)98 public void setAllowRenegotiate(boolean allowRenegotiate) 99 { 100 _sslContextFactory.setAllowRenegotiate(allowRenegotiate); 101 } 102 103 /* ------------------------------------------------------------ */ 104 @Override accept(int acceptorID)105 public void accept(int acceptorID) 106 throws IOException, InterruptedException 107 { 108 Socket socket = _serverSocket.accept(); 109 configure(socket); 110 111 ConnectorEndPoint connection=new SslConnectorEndPoint(socket); 112 connection.dispatch(); 113 } 114 115 /* ------------------------------------------------------------ */ 116 @Override configure(Socket socket)117 protected void configure(Socket socket) 118 throws IOException 119 { 120 super.configure(socket); 121 } 122 123 /* ------------------------------------------------------------ */ 124 /** 125 * Allow the Listener a chance to customise the request. before the server does its stuff. <br> 126 * This allows the required attributes to be set for SSL requests. <br> 127 * The requirements of the Servlet specs are: 128 * <ul> 129 * <li> an attribute named "javax.servlet.request.ssl_id" of type String (since Spec 3.0).</li> 130 * <li> an attribute named "javax.servlet.request.cipher_suite" of type String.</li> 131 * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li> 132 * <li> an attribute named "javax.servlet.request.X509Certificate" of type 133 * java.security.cert.X509Certificate[]. This is an array of objects of type X509Certificate, 134 * the order of this array is defined as being in ascending order of trust. The first 135 * certificate in the chain is the one set by the client, the next is the one used to 136 * authenticate the first, and so on. </li> 137 * </ul> 138 * 139 * @param endpoint The Socket the request arrived on. 140 * This should be a {@link SocketEndPoint} wrapping a {@link SSLSocket}. 141 * @param request HttpRequest to be customised. 142 */ 143 @Override customize(EndPoint endpoint, Request request)144 public void customize(EndPoint endpoint, Request request) 145 throws IOException 146 { 147 super.customize(endpoint, request); 148 request.setScheme(HttpSchemes.HTTPS); 149 150 SocketEndPoint socket_end_point = (SocketEndPoint)endpoint; 151 SSLSocket sslSocket = (SSLSocket)socket_end_point.getTransport(); 152 SSLSession sslSession = sslSocket.getSession(); 153 154 SslCertificates.customize(sslSession,endpoint,request); 155 } 156 157 /* ------------------------------------------------------------ */ 158 /** 159 * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() 160 * @deprecated 161 */ 162 @Deprecated getExcludeCipherSuites()163 public String[] getExcludeCipherSuites() { 164 return _sslContextFactory.getExcludeCipherSuites(); 165 } 166 167 /* ------------------------------------------------------------ */ 168 /** 169 * @see org.eclipse.jetty.server.ssl.SslConnector#getIncludeCipherSuites() 170 * @deprecated 171 */ 172 @Deprecated getIncludeCipherSuites()173 public String[] getIncludeCipherSuites() 174 { 175 return _sslContextFactory.getIncludeCipherSuites(); 176 } 177 178 /* ------------------------------------------------------------ */ 179 /** 180 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore() 181 * @deprecated 182 */ 183 @Deprecated getKeystore()184 public String getKeystore() 185 { 186 return _sslContextFactory.getKeyStorePath(); 187 } 188 189 /* ------------------------------------------------------------ */ 190 /** 191 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType() 192 * @deprecated 193 */ 194 @Deprecated getKeystoreType()195 public String getKeystoreType() 196 { 197 return _sslContextFactory.getKeyStoreType(); 198 } 199 200 /* ------------------------------------------------------------ */ 201 /** 202 * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth() 203 * @deprecated 204 */ 205 @Deprecated getNeedClientAuth()206 public boolean getNeedClientAuth() 207 { 208 return _sslContextFactory.getNeedClientAuth(); 209 } 210 211 /* ------------------------------------------------------------ */ 212 /** 213 * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol() 214 * @deprecated 215 */ 216 @Deprecated getProtocol()217 public String getProtocol() 218 { 219 return _sslContextFactory.getProtocol(); 220 } 221 222 /* ------------------------------------------------------------ */ 223 /** 224 * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider() 225 * @deprecated 226 */ 227 @Deprecated getProvider()228 public String getProvider() { 229 return _sslContextFactory.getProvider(); 230 } 231 232 /* ------------------------------------------------------------ */ 233 /** 234 * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm() 235 * @deprecated 236 */ 237 @Deprecated getSecureRandomAlgorithm()238 public String getSecureRandomAlgorithm() 239 { 240 return _sslContextFactory.getSecureRandomAlgorithm(); 241 } 242 243 /* ------------------------------------------------------------ */ 244 /** 245 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm() 246 * @deprecated 247 */ 248 @Deprecated getSslKeyManagerFactoryAlgorithm()249 public String getSslKeyManagerFactoryAlgorithm() 250 { 251 return _sslContextFactory.getSslKeyManagerFactoryAlgorithm(); 252 } 253 254 /* ------------------------------------------------------------ */ 255 /** 256 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm() 257 * @deprecated 258 */ 259 @Deprecated getSslTrustManagerFactoryAlgorithm()260 public String getSslTrustManagerFactoryAlgorithm() 261 { 262 return _sslContextFactory.getTrustManagerFactoryAlgorithm(); 263 } 264 265 /* ------------------------------------------------------------ */ 266 /** 267 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore() 268 * @deprecated 269 */ 270 @Deprecated getTruststore()271 public String getTruststore() 272 { 273 return _sslContextFactory.getTrustStore(); 274 } 275 276 /* ------------------------------------------------------------ */ 277 /** 278 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory() 279 */ 280 // @Override getSslContextFactory()281 public SslContextFactory getSslContextFactory() 282 { 283 return _sslContextFactory; 284 } 285 286 /* ------------------------------------------------------------ */ 287 /** 288 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType() 289 * @deprecated 290 */ 291 @Deprecated getTruststoreType()292 public String getTruststoreType() 293 { 294 return _sslContextFactory.getTrustStoreType(); 295 } 296 297 /* ------------------------------------------------------------ */ 298 /** 299 * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth() 300 * @deprecated 301 */ 302 @Deprecated getWantClientAuth()303 public boolean getWantClientAuth() 304 { 305 return _sslContextFactory.getWantClientAuth(); 306 } 307 308 /* ------------------------------------------------------------ */ 309 /** 310 * By default, we're confidential, given we speak SSL. But, if we've been told about an 311 * confidential port, and said port is not our port, then we're not. This allows separation of 312 * listeners providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener 313 * configured to require client certs providing CONFIDENTIAL, whereas another SSL listener not 314 * requiring client certs providing mere INTEGRAL constraints. 315 */ 316 @Override isConfidential(Request request)317 public boolean isConfidential(Request request) 318 { 319 final int confidentialPort = getConfidentialPort(); 320 return confidentialPort == 0 || confidentialPort == request.getServerPort(); 321 } 322 323 /* ------------------------------------------------------------ */ 324 /** 325 * By default, we're integral, given we speak SSL. But, if we've been told about an integral 326 * port, and said port is not our port, then we're not. This allows separation of listeners 327 * providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener configured to 328 * require client certs providing CONFIDENTIAL, whereas another SSL listener not requiring 329 * client certs providing mere INTEGRAL constraints. 330 */ 331 @Override isIntegral(Request request)332 public boolean isIntegral(Request request) 333 { 334 final int integralPort = getIntegralPort(); 335 return integralPort == 0 || integralPort == request.getServerPort(); 336 } 337 338 /* ------------------------------------------------------------ */ 339 @Override open()340 public void open() throws IOException 341 { 342 _sslContextFactory.checkKeyStore(); 343 try 344 { 345 _sslContextFactory.start(); 346 } 347 catch(Exception e) 348 { 349 throw new RuntimeIOException(e); 350 } 351 super.open(); 352 } 353 354 /* ------------------------------------------------------------ */ 355 /** 356 * {@inheritDoc} 357 */ 358 @Override doStart()359 protected void doStart() throws Exception 360 { 361 _sslContextFactory.checkKeyStore(); 362 _sslContextFactory.start(); 363 364 super.doStart(); 365 } 366 367 /* ------------------------------------------------------------ */ 368 /** 369 * @see org.eclipse.jetty.server.bio.SocketConnector#doStop() 370 */ 371 @Override doStop()372 protected void doStop() throws Exception 373 { 374 _sslContextFactory.stop(); 375 376 super.doStop(); 377 } 378 379 /* ------------------------------------------------------------ */ 380 /** 381 * @param host The host name that this server should listen on 382 * @param port the port that this server should listen on 383 * @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)} 384 * @return A new {@link ServerSocket socket object} bound to the supplied address with all other 385 * settings as per the current configuration of this connector. 386 * @see #setWantClientAuth(boolean) 387 * @see #setNeedClientAuth(boolean) 388 * @exception IOException 389 */ 390 @Override newServerSocket(String host, int port,int backlog)391 protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException 392 { 393 return _sslContextFactory.newSslServerSocket(host,port,backlog); 394 } 395 396 /* ------------------------------------------------------------ */ 397 /** 398 * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) 399 * @deprecated 400 */ 401 @Deprecated setExcludeCipherSuites(String[] cipherSuites)402 public void setExcludeCipherSuites(String[] cipherSuites) 403 { 404 _sslContextFactory.setExcludeCipherSuites(cipherSuites); 405 } 406 407 /* ------------------------------------------------------------ */ 408 /** 409 * @see org.eclipse.jetty.server.ssl.SslConnector#setIncludeCipherSuites(java.lang.String[]) 410 * @deprecated 411 */ 412 @Deprecated setIncludeCipherSuites(String[] cipherSuites)413 public void setIncludeCipherSuites(String[] cipherSuites) 414 { 415 _sslContextFactory.setIncludeCipherSuites(cipherSuites); 416 } 417 418 /* ------------------------------------------------------------ */ 419 /** 420 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String) 421 * @deprecated 422 */ 423 @Deprecated setKeyPassword(String password)424 public void setKeyPassword(String password) 425 { 426 _sslContextFactory.setKeyManagerPassword(password); 427 } 428 429 /* ------------------------------------------------------------ */ 430 /** 431 * @param keystore The resource path to the keystore, or null for built in keystores. 432 * @deprecated 433 */ 434 @Deprecated setKeystore(String keystore)435 public void setKeystore(String keystore) 436 { 437 _sslContextFactory.setKeyStorePath(keystore); 438 } 439 440 /* ------------------------------------------------------------ */ 441 /** 442 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String) 443 * @deprecated 444 */ 445 @Deprecated setKeystoreType(String keystoreType)446 public void setKeystoreType(String keystoreType) 447 { 448 _sslContextFactory.setKeyStoreType(keystoreType); 449 } 450 451 /* ------------------------------------------------------------ */ 452 /** 453 * Set the value of the needClientAuth property 454 * 455 * @param needClientAuth true iff we require client certificate authentication. 456 * @deprecated 457 */ 458 @Deprecated setNeedClientAuth(boolean needClientAuth)459 public void setNeedClientAuth(boolean needClientAuth) 460 { 461 _sslContextFactory.setNeedClientAuth(needClientAuth); 462 } 463 464 /* ------------------------------------------------------------ */ 465 /** 466 * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String) 467 * @deprecated 468 */ 469 @Deprecated setPassword(String password)470 public void setPassword(String password) 471 { 472 _sslContextFactory.setKeyStorePassword(password); 473 } 474 475 /* ------------------------------------------------------------ */ 476 /** 477 * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String) 478 * @deprecated 479 */ 480 @Deprecated setTrustPassword(String password)481 public void setTrustPassword(String password) 482 { 483 _sslContextFactory.setTrustStorePassword(password); 484 } 485 486 /* ------------------------------------------------------------ */ 487 /** 488 * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String) 489 * @deprecated 490 */ 491 @Deprecated setProtocol(String protocol)492 public void setProtocol(String protocol) 493 { 494 _sslContextFactory.setProtocol(protocol); 495 } 496 497 /* ------------------------------------------------------------ */ 498 /** 499 * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String) 500 * @deprecated 501 */ 502 @Deprecated setProvider(String provider)503 public void setProvider(String provider) { 504 _sslContextFactory.setProvider(provider); 505 } 506 507 /* ------------------------------------------------------------ */ 508 /** 509 * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String) 510 * @deprecated 511 */ 512 @Deprecated setSecureRandomAlgorithm(String algorithm)513 public void setSecureRandomAlgorithm(String algorithm) 514 { 515 _sslContextFactory.setSecureRandomAlgorithm(algorithm); 516 } 517 518 /* ------------------------------------------------------------ */ 519 /** 520 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String) 521 * @deprecated 522 */ 523 @Deprecated setSslKeyManagerFactoryAlgorithm(String algorithm)524 public void setSslKeyManagerFactoryAlgorithm(String algorithm) 525 { 526 _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm); 527 } 528 529 /* ------------------------------------------------------------ */ 530 /** 531 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String) 532 * @deprecated 533 */ 534 @Deprecated setSslTrustManagerFactoryAlgorithm(String algorithm)535 public void setSslTrustManagerFactoryAlgorithm(String algorithm) 536 { 537 _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm); 538 } 539 540 /* ------------------------------------------------------------ */ 541 /** 542 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String) 543 * @deprecated 544 */ 545 @Deprecated setTruststore(String truststore)546 public void setTruststore(String truststore) 547 { 548 _sslContextFactory.setTrustStore(truststore); 549 } 550 551 /* ------------------------------------------------------------ */ 552 /** 553 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String) 554 * @deprecated 555 */ 556 @Deprecated setTruststoreType(String truststoreType)557 public void setTruststoreType(String truststoreType) 558 { 559 _sslContextFactory.setTrustStoreType(truststoreType); 560 } 561 562 /* ------------------------------------------------------------ */ 563 /** 564 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) 565 * @deprecated 566 */ 567 @Deprecated setSslContext(SSLContext sslContext)568 public void setSslContext(SSLContext sslContext) 569 { 570 _sslContextFactory.setSslContext(sslContext); 571 } 572 573 /* ------------------------------------------------------------ */ 574 /** 575 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) 576 * @deprecated 577 */ 578 @Deprecated getSslContext()579 public SSLContext getSslContext() 580 { 581 return _sslContextFactory.getSslContext(); 582 } 583 584 /* ------------------------------------------------------------ */ 585 /** 586 * Set the value of the _wantClientAuth property. This property is used 587 * internally when opening server sockets. 588 * 589 * @param wantClientAuth true if we want client certificate authentication. 590 * @see SSLServerSocket#setWantClientAuth 591 * @deprecated 592 */ 593 @Deprecated setWantClientAuth(boolean wantClientAuth)594 public void setWantClientAuth(boolean wantClientAuth) 595 { 596 _sslContextFactory.setWantClientAuth(wantClientAuth); 597 } 598 599 /* ------------------------------------------------------------ */ 600 /** 601 * Set the time in milliseconds for so_timeout during ssl handshaking 602 * @param msec a non-zero value will be used to set so_timeout during 603 * ssl handshakes. A zero value means the maxIdleTime is used instead. 604 */ setHandshakeTimeout(int msec)605 public void setHandshakeTimeout (int msec) 606 { 607 _handshakeTimeout = msec; 608 } 609 610 611 /* ------------------------------------------------------------ */ getHandshakeTimeout()612 public int getHandshakeTimeout () 613 { 614 return _handshakeTimeout; 615 } 616 617 /* ------------------------------------------------------------ */ 618 public class SslConnectorEndPoint extends ConnectorEndPoint 619 { SslConnectorEndPoint(Socket socket)620 public SslConnectorEndPoint(Socket socket) throws IOException 621 { 622 super(socket); 623 } 624 625 @Override shutdownOutput()626 public void shutdownOutput() throws IOException 627 { 628 close(); 629 } 630 631 @Override shutdownInput()632 public void shutdownInput() throws IOException 633 { 634 close(); 635 } 636 637 @Override run()638 public void run() 639 { 640 try 641 { 642 int handshakeTimeout = getHandshakeTimeout(); 643 int oldTimeout = _socket.getSoTimeout(); 644 if (handshakeTimeout > 0) 645 _socket.setSoTimeout(handshakeTimeout); 646 647 final SSLSocket ssl=(SSLSocket)_socket; 648 ssl.addHandshakeCompletedListener(new HandshakeCompletedListener() 649 { 650 boolean handshook=false; 651 public void handshakeCompleted(HandshakeCompletedEvent event) 652 { 653 if (handshook) 654 { 655 if (!_sslContextFactory.isAllowRenegotiate()) 656 { 657 LOG.warn("SSL renegotiate denied: "+ssl); 658 try{ssl.close();}catch(IOException e){LOG.warn(e);} 659 } 660 } 661 else 662 handshook=true; 663 } 664 }); 665 ssl.startHandshake(); 666 667 if (handshakeTimeout>0) 668 _socket.setSoTimeout(oldTimeout); 669 670 super.run(); 671 } 672 catch (SSLException e) 673 { 674 LOG.debug(e); 675 try{close();} 676 catch(IOException e2){LOG.ignore(e2);} 677 } 678 catch (IOException e) 679 { 680 LOG.debug(e); 681 try{close();} 682 catch(IOException e2){LOG.ignore(e2);} 683 } 684 } 685 } 686 687 /* ------------------------------------------------------------ */ 688 /** 689 * Unsupported. 690 * 691 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) 692 * @deprecated 693 */ 694 @Deprecated getAlgorithm()695 public String getAlgorithm() 696 { 697 throw new UnsupportedOperationException(); 698 } 699 700 /* ------------------------------------------------------------ */ 701 /** 702 * Unsupported. 703 * 704 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) 705 * @deprecated 706 */ 707 @Deprecated setAlgorithm(String algorithm)708 public void setAlgorithm(String algorithm) 709 { 710 throw new UnsupportedOperationException(); 711 } 712 } 713