001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.extensions; 028 029 030 031 import java.io.IOException; 032 import java.net.InetAddress; 033 import java.net.Socket; 034 import java.nio.ByteBuffer; 035 import java.nio.channels.SocketChannel; 036 import java.security.cert.Certificate; 037 import javax.net.ssl.SSLContext; 038 import javax.net.ssl.SSLEngine; 039 import javax.net.ssl.SSLEngineResult; 040 import javax.net.ssl.SSLSession; 041 042 import org.opends.messages.Message; 043 import org.opends.server.api.ClientConnection; 044 import org.opends.server.api.ConnectionSecurityProvider; 045 import org.opends.server.api.KeyManagerProvider; 046 import org.opends.server.api.TrustManagerProvider; 047 import org.opends.server.config.ConfigEntry; 048 import org.opends.server.config.ConfigException; 049 import org.opends.server.core.DirectoryServer; 050 import org.opends.server.loggers.debug.DebugTracer; 051 import org.opends.server.types.DebugLogLevel; 052 import org.opends.server.types.DirectoryException; 053 import org.opends.server.types.DisconnectReason; 054 import org.opends.server.types.InitializationException; 055 import org.opends.server.types.SSLClientAuthPolicy; 056 import org.opends.server.util.SelectableCertificateKeyManager; 057 058 import static org.opends.messages.ExtensionMessages.*; 059 import static org.opends.server.loggers.debug.DebugLogger.*; 060 import static org.opends.server.util.StaticUtils.*; 061 062 063 064 /** 065 * This class provides an implementation of a connection security provider that 066 * uses SSL/TLS to encrypt the communication to and from the client. It uses 067 * the {@code javax.net.ssl.SSLEngine} class to provide the actual SSL 068 * communication layer, and the Directory Server key and trust store providers 069 * to determine which key and trust stores to use. 070 */ 071 public class TLSConnectionSecurityProvider 072 extends ConnectionSecurityProvider 073 { 074 /** 075 * The tracer object for the debug logger. 076 */ 077 private static final DebugTracer TRACER = getTracer(); 078 079 080 081 /** 082 * The SSL context name that should be used for this TLS connection security 083 * provider. 084 */ 085 private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS"; 086 087 088 089 // The buffer that will be used when reading clear-text data. 090 private ByteBuffer clearInBuffer; 091 092 // The buffer that will be used when writing clear-text data. 093 private ByteBuffer clearOutBuffer; 094 095 // The buffer that will be used when reading encrypted data. 096 private ByteBuffer sslInBuffer; 097 098 // The buffer that willa be used when writing encrypted data. 099 private ByteBuffer sslOutBuffer; 100 101 // The client connection with which this security provider is associated. 102 private ClientConnection clientConnection; 103 104 // The size in bytes that should be used for the buffer holding clear-text 105 // data. 106 private int clearBufferSize; 107 108 // The size in bytes that should be used for the buffer holding the encrypted 109 // data. 110 private int sslBufferSize; 111 112 // The socket channel that may be used to communicate with the client. 113 private SocketChannel socketChannel; 114 115 // The SSL client certificate policy. 116 private SSLClientAuthPolicy sslClientAuthPolicy; 117 118 // The SSL context that will be used for all SSL/TLS communication. 119 private SSLContext sslContext; 120 121 // The SSL engine that will be used for this connection. 122 private SSLEngine sslEngine; 123 124 // The set of cipher suites to allow. 125 private String[] enabledCipherSuites; 126 127 // The set of protocols to allow. 128 private String[] enabledProtocols; 129 130 131 132 /** 133 * Creates a new instance of this connection security provider. Note that 134 * no initialization should be done here, since it should all be done in the 135 * {@code initializeConnectionSecurityProvider} method. Also note that this 136 * instance should only be used to create new instances that are associated 137 * with specific client connections. This instance itself should not be used 138 * to attempt secure communication with the client. 139 */ 140 public TLSConnectionSecurityProvider() 141 { 142 super(); 143 144 } 145 146 147 148 /** 149 * Creates a new instance of this connection security provider that will be 150 * associated with the provided client connection. 151 * 152 * @param clientConnection The client connection with which this connection 153 * security provider should be associated. 154 * @param socketChannel The socket channel that may be used to 155 * communicate with the client. 156 * @param parentProvider A reference to the parent TLS connection security 157 * provider that is being used to create this 158 * instance. 159 */ 160 private TLSConnectionSecurityProvider(ClientConnection clientConnection, 161 SocketChannel socketChannel, 162 TLSConnectionSecurityProvider 163 parentProvider) 164 throws DirectoryException 165 { 166 super(); 167 168 169 this.clientConnection = clientConnection; 170 this.socketChannel = socketChannel; 171 172 Socket socket = socketChannel.socket(); 173 InetAddress inetAddress = socketChannel.socket().getInetAddress(); 174 175 176 // Create an SSL session based on the configured key and trust stores in the 177 // Directory Server. 178 KeyManagerProvider keyManagerProvider = 179 DirectoryServer.getKeyManagerProvider( 180 clientConnection.getKeyManagerProviderDN()); 181 if (keyManagerProvider == null) 182 { 183 keyManagerProvider = new NullKeyManagerProvider(); 184 } 185 186 TrustManagerProvider trustManagerProvider = 187 DirectoryServer.getTrustManagerProvider( 188 clientConnection.getTrustManagerProviderDN()); 189 if (trustManagerProvider == null) 190 { 191 trustManagerProvider = new NullTrustManagerProvider(); 192 } 193 194 try 195 { 196 // FIXME -- Is it bad to create a new SSLContext for each connection? 197 sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME); 198 199 String alias = clientConnection.getCertificateAlias(); 200 if (alias == null) 201 { 202 sslContext.init(keyManagerProvider.getKeyManagers(), 203 trustManagerProvider.getTrustManagers(), null); 204 } 205 else 206 { 207 sslContext.init(SelectableCertificateKeyManager.wrap( 208 keyManagerProvider.getKeyManagers(), alias), 209 trustManagerProvider.getTrustManagers(), null); 210 } 211 } 212 catch (Exception e) 213 { 214 if (debugEnabled()) 215 { 216 TRACER.debugCaught(DebugLogLevel.ERROR, e); 217 } 218 219 Message message = ERR_TLS_SECURITY_PROVIDER_CANNOT_INITIALIZE.get( 220 getExceptionMessage(e)); 221 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 222 message, e); 223 } 224 225 sslEngine = sslContext.createSSLEngine(inetAddress.getHostName(), 226 socket.getPort()); 227 sslEngine.setUseClientMode(false); 228 229 enabledProtocols = parentProvider.enabledProtocols; 230 if (enabledProtocols != null) 231 { 232 sslEngine.setEnabledProtocols(enabledProtocols); 233 } 234 235 enabledCipherSuites = parentProvider.enabledCipherSuites; 236 if (enabledCipherSuites != null) 237 { 238 sslEngine.setEnabledCipherSuites(enabledCipherSuites); 239 } 240 241 sslClientAuthPolicy = parentProvider.sslClientAuthPolicy; 242 if (sslClientAuthPolicy == null) 243 { 244 sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL; 245 } 246 switch (sslClientAuthPolicy) 247 { 248 case REQUIRED: 249 sslEngine.setWantClientAuth(true); 250 sslEngine.setNeedClientAuth(true); 251 break; 252 253 case DISABLED: 254 sslEngine.setNeedClientAuth(false); 255 sslEngine.setWantClientAuth(false); 256 break; 257 258 case OPTIONAL: 259 default: 260 sslEngine.setNeedClientAuth(false); 261 sslEngine.setWantClientAuth(true); 262 break; 263 } 264 265 SSLSession sslSession = sslEngine.getSession(); 266 267 clearBufferSize = sslSession.getApplicationBufferSize(); 268 clearInBuffer = ByteBuffer.allocate(clearBufferSize); 269 clearOutBuffer = ByteBuffer.allocate(clearBufferSize); 270 271 sslBufferSize = sslSession.getPacketBufferSize(); 272 sslInBuffer = ByteBuffer.allocate(sslBufferSize); 273 sslOutBuffer = ByteBuffer.allocate(sslBufferSize); 274 } 275 276 277 278 /** 279 * {@inheritDoc} 280 */ 281 @Override() 282 public void initializeConnectionSecurityProvider(ConfigEntry configEntry) 283 throws ConfigException, InitializationException 284 { 285 // Initialize default values for the connection-specific variables. 286 clientConnection = null; 287 socketChannel = null; 288 289 clearInBuffer = null; 290 clearOutBuffer = null; 291 sslInBuffer = null; 292 sslOutBuffer = null; 293 clearBufferSize = -1; 294 sslBufferSize = -1; 295 296 sslEngine = null; 297 298 enabledProtocols = null; 299 enabledCipherSuites = null; 300 sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL; 301 } 302 303 304 305 /** 306 * {@inheritDoc} 307 */ 308 @Override() 309 public void finalizeConnectionSecurityProvider() 310 { 311 // No implementation is required. 312 } 313 314 315 316 /** 317 * {@inheritDoc} 318 */ 319 @Override() 320 public String getSecurityMechanismName() 321 { 322 return SSL_CONTEXT_INSTANCE_NAME; 323 } 324 325 326 327 /** 328 * {@inheritDoc} 329 */ 330 @Override() 331 public boolean isSecure() 332 { 333 // This should be considered secure. 334 return true; 335 } 336 337 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override() 343 public ConnectionSecurityProvider newInstance(ClientConnection 344 clientConnection, 345 SocketChannel socketChannel) 346 throws DirectoryException 347 { 348 return new TLSConnectionSecurityProvider(clientConnection, socketChannel, 349 this); 350 } 351 352 353 354 /** 355 * {@inheritDoc} 356 */ 357 @Override() 358 public void disconnect(boolean connectionValid) 359 { 360 if (connectionValid) 361 { 362 try 363 { 364 sslEngine.closeInbound(); 365 sslEngine.closeOutbound(); 366 367 while (true) 368 { 369 switch (sslEngine.getHandshakeStatus()) 370 { 371 case FINISHED: 372 case NOT_HANDSHAKING: 373 // We don't need to do anything else. 374 return; 375 376 case NEED_TASK: 377 // We need to process some task before continuing. 378 Runnable task = sslEngine.getDelegatedTask(); 379 task.run(); 380 break; 381 382 case NEED_WRAP: 383 // We need to send data to the client. 384 clearOutBuffer.clear(); 385 sslOutBuffer.clear(); 386 sslEngine.wrap(clearOutBuffer, sslOutBuffer); 387 sslOutBuffer.flip(); 388 while (sslOutBuffer.hasRemaining()) 389 { 390 socketChannel.write(sslOutBuffer); 391 } 392 break; 393 394 case NEED_UNWRAP: 395 // We need to read data from the client. We can do this if it's 396 // immediately available, but otherwise, ignore it because 397 // otherwise it could chew up a lot of time. 398 if (sslInBuffer.hasRemaining()) 399 { 400 clearInBuffer.clear(); 401 sslEngine.unwrap(sslInBuffer, clearInBuffer); 402 clearInBuffer.flip(); 403 } 404 else 405 { 406 sslInBuffer.clear(); 407 clearInBuffer.clear(); 408 int bytesRead = socketChannel.read(sslInBuffer); 409 if (bytesRead <= 0) 410 { 411 return; 412 } 413 sslEngine.unwrap(sslInBuffer, clearInBuffer); 414 clearInBuffer.flip(); 415 } 416 } 417 } 418 } 419 catch (Exception e) 420 { 421 if (debugEnabled()) 422 { 423 TRACER.debugCaught(DebugLogLevel.ERROR, e); 424 } 425 } 426 } 427 } 428 429 430 431 /** 432 * {@inheritDoc} 433 */ 434 @Override() 435 public int getClearBufferSize() 436 { 437 return clearBufferSize; 438 } 439 440 441 442 /** 443 * {@inheritDoc} 444 */ 445 @Override() 446 public int getEncodedBufferSize() 447 { 448 return sslBufferSize; 449 } 450 451 452 453 /** 454 * {@inheritDoc} 455 */ 456 @Override() 457 public boolean readData() 458 { 459 while (true) 460 { 461 try 462 { 463 sslInBuffer.clear(); 464 int bytesRead = socketChannel.read(sslInBuffer); 465 sslInBuffer.flip(); 466 467 if (bytesRead < 0) 468 { 469 // The client connection has been closed. Disconnect and return. 470 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, false, 471 null); 472 return false; 473 } 474 475 476 // See if there is any preliminary handshake work to do. 477 handshakeLoop: 478 while (true) 479 { 480 switch (sslEngine.getHandshakeStatus()) 481 { 482 case NEED_TASK: 483 Runnable task = sslEngine.getDelegatedTask(); 484 task.run(); 485 break; 486 487 case NEED_WRAP: 488 clearOutBuffer.clear(); 489 sslOutBuffer.clear(); 490 sslEngine.wrap(clearOutBuffer, sslOutBuffer); 491 sslOutBuffer.flip(); 492 493 while (sslOutBuffer.hasRemaining()) 494 { 495 int bytesWritten = socketChannel.write(sslOutBuffer); 496 if (bytesWritten < 0) 497 { 498 // The client connection has been closed. Disconnect and 499 // return. 500 clientConnection.disconnect( 501 DisconnectReason.CLIENT_DISCONNECT, false, null); 502 return false; 503 } 504 } 505 break; 506 507 default: 508 break handshakeLoop; 509 } 510 } 511 512 if (bytesRead == 0) 513 { 514 // We don't have any data to process, and we've already done any 515 // necessary handshaking, so we can break out and wait for more data 516 // to arrive. 517 return true; 518 } 519 520 521 // Read any SSL-encrypted data provided by the client. 522 while (sslInBuffer.hasRemaining()) 523 { 524 clearInBuffer.clear(); 525 SSLEngineResult unwrapResult = sslEngine.unwrap(sslInBuffer, 526 clearInBuffer); 527 clearInBuffer.flip(); 528 529 switch (unwrapResult.getStatus()) 530 { 531 case OK: 532 // This is fine. 533 break; 534 535 case CLOSED: 536 // The client connection (or at least the SSL side of it) has been 537 // closed. 538 // FIXME -- Allow for closing the SSL channel without closing the 539 // underlying connection. 540 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, 541 false, null); 542 return false; 543 544 default: 545 // This should not have happened. 546 clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM, 547 false, 548 ERR_TLS_SECURITY_PROVIDER_UNEXPECTED_UNWRAP_STATUS.get( 549 String.valueOf(unwrapResult.getStatus()))); 550 return false; 551 } 552 553 switch (unwrapResult.getHandshakeStatus()) 554 { 555 case NEED_TASK: 556 Runnable task = sslEngine.getDelegatedTask(); 557 task.run(); 558 break; 559 560 case NEED_WRAP: 561 clearOutBuffer.clear(); 562 sslOutBuffer.clear(); 563 sslEngine.wrap(clearOutBuffer, sslOutBuffer); 564 sslOutBuffer.flip(); 565 566 while (sslOutBuffer.hasRemaining()) 567 { 568 int bytesWritten = socketChannel.write(sslOutBuffer); 569 if (bytesWritten < 0) 570 { 571 // The client connection has been closed. Disconnect and 572 // return. 573 clientConnection.disconnect( 574 DisconnectReason.CLIENT_DISCONNECT, false, null); 575 return false; 576 } 577 } 578 break; 579 } 580 581 // If there is any clear-text data, then process it. 582 if (! clientConnection.processDataRead(clearInBuffer)) 583 { 584 // If this happens, then the client connection disconnect method 585 // should have already been called, so we don't need to do it again. 586 return false; 587 } 588 } 589 } 590 catch (IOException ioe) 591 { 592 if (debugEnabled()) 593 { 594 TRACER.debugCaught(DebugLogLevel.ERROR, ioe); 595 } 596 597 // An error occurred while trying to communicate with the client. 598 // Disconnect and return. 599 clientConnection.disconnect(DisconnectReason.IO_ERROR, false, null); 600 return false; 601 } 602 catch (Exception e) 603 { 604 if (debugEnabled()) 605 { 606 TRACER.debugCaught(DebugLogLevel.ERROR, e); 607 } 608 609 // An unexpected error occurred while trying to process the data read. 610 // Disconnect and return. 611 clientConnection.disconnect(DisconnectReason.SERVER_ERROR, true, 612 ERR_TLS_SECURITY_PROVIDER_READ_ERROR.get( 613 getExceptionMessage(e))); 614 return false; 615 } 616 } 617 } 618 619 620 621 /** 622 * {@inheritDoc} 623 */ 624 @Override() 625 public boolean writeData(ByteBuffer clearData) 626 { 627 int originalPosition = clearData.position(); 628 int originalLimit = clearData.limit(); 629 int length = originalLimit - originalPosition; 630 631 try 632 { 633 if (length > clearBufferSize) 634 { 635 // There is more data to write than we can deal with in one chunk, so 636 // break it up. 637 int pos = originalPosition; 638 int lim = originalPosition + clearBufferSize; 639 640 while (pos < originalLimit) 641 { 642 clearData.position(pos); 643 clearData.limit(lim); 644 645 if (! writeInternal(clearData)) 646 { 647 return false; 648 } 649 650 pos = lim; 651 lim = Math.min(originalLimit, pos+clearBufferSize); 652 } 653 654 return true; 655 } 656 else 657 { 658 return writeInternal(clearData); 659 } 660 } 661 finally 662 { 663 clearData.position(originalPosition); 664 clearData.limit(originalLimit); 665 } 666 } 667 668 669 670 /** 671 * Writes the data contained in the provided clear-text buffer to the client, 672 * performing any necessary encoding in the process. The amount of data in 673 * the provided buffer must be less than or equal to the value returned by the 674 * {@code getClearBufferSize} method. 675 * 676 * @param clearData The buffer containing the clear-text data to write to 677 * the client. 678 * 679 * @return {@code true} if all the data in the provided buffer was written to 680 * the client and the connection may remain established, or 681 * {@code false} if a problem occurred and the client connection is 682 * no longer valid. Note that if this method does return 683 * {@code false}, then it must have already disconnected the client. 684 */ 685 private boolean writeInternal(ByteBuffer clearData) 686 { 687 try 688 { 689 // See if there is any preliminary handshake work to be done. 690 handshakeStatusLoop: 691 while (true) 692 { 693 switch (sslEngine.getHandshakeStatus()) 694 { 695 case NEED_TASK: 696 Runnable task = sslEngine.getDelegatedTask(); 697 task.run(); 698 break; 699 700 case NEED_WRAP: 701 clearOutBuffer.clear(); 702 sslOutBuffer.clear(); 703 sslEngine.wrap(clearOutBuffer, sslOutBuffer); 704 sslOutBuffer.flip(); 705 706 while (sslOutBuffer.hasRemaining()) 707 { 708 int bytesWritten = socketChannel.write(sslOutBuffer); 709 if (bytesWritten < 0) 710 { 711 // The client connection has been closed. Disconnect and 712 // return. 713 clientConnection.disconnect( 714 DisconnectReason.CLIENT_DISCONNECT, false, null); 715 return false; 716 } 717 else if (bytesWritten == 0) 718 { 719 return NullConnectionSecurityProvider.writeWithTimeout( 720 clientConnection, socketChannel, sslOutBuffer); 721 } 722 } 723 break; 724 725 case NEED_UNWRAP: 726 // We need to read data from the client before the negotiation can 727 // continue. This is bad, because we don't know if there is data 728 // available but we do know that we can't write until we have read. 729 // See if there is something available for reading, and if not, then 730 // we can't afford to wait for it because otherwise we would be 731 // potentially blocking reads from other clients. Our only recourse 732 // is to close the connection. 733 sslInBuffer.clear(); 734 clearInBuffer.clear(); 735 int bytesRead = socketChannel.read(sslInBuffer); 736 if (bytesRead < 0) 737 { 738 // The client connection is already closed, so we don't need to 739 // worry about it. 740 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, 741 false, null); 742 return false; 743 } 744 else if (bytesRead == 0) 745 { 746 // We didn't get the data that we need. We'll have to disconnect 747 // to avoid blocking other clients. 748 clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM, 749 false, ERR_TLS_SECURITY_PROVIDER_WRITE_NEEDS_UNWRAP.get()); 750 return false; 751 } 752 else 753 { 754 // We were lucky and got the data we were looking for, so read and 755 // process it. 756 sslEngine.unwrap(sslInBuffer, clearInBuffer); 757 clearInBuffer.flip(); 758 } 759 break; 760 761 default: 762 break handshakeStatusLoop; 763 } 764 } 765 766 767 while (clearData.hasRemaining()) 768 { 769 sslOutBuffer.clear(); 770 SSLEngineResult wrapResult = sslEngine.wrap(clearData, sslOutBuffer); 771 sslOutBuffer.flip(); 772 773 switch (wrapResult.getStatus()) 774 { 775 case OK: 776 // This is fine. 777 break; 778 779 case CLOSED: 780 // The client connection (or at least the SSL side of it) has been 781 // closed. 782 // FIXME -- Allow for closing the SSL channel without closing the 783 // underlying connection. 784 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, 785 false, null); 786 return false; 787 788 default: 789 // This should not have happened. 790 clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM, 791 false, ERR_TLS_SECURITY_PROVIDER_UNEXPECTED_WRAP_STATUS.get( 792 String.valueOf(wrapResult.getStatus()))); 793 return false; 794 } 795 796 switch (wrapResult.getHandshakeStatus()) 797 { 798 case NEED_TASK: 799 Runnable task = sslEngine.getDelegatedTask(); 800 task.run(); 801 break; 802 803 case NEED_WRAP: 804 // FIXME -- Could this overwrite the SSL out that we just wrapped? 805 // FIXME -- Is this even a feasible result? 806 clearOutBuffer.clear(); 807 sslOutBuffer.clear(); 808 sslEngine.wrap(clearOutBuffer, sslOutBuffer); 809 sslOutBuffer.flip(); 810 811 while (sslOutBuffer.hasRemaining()) 812 { 813 int bytesWritten = socketChannel.write(sslOutBuffer); 814 if (bytesWritten < 0) 815 { 816 // The client connection has been closed. Disconnect and 817 // return. 818 clientConnection.disconnect( 819 DisconnectReason.CLIENT_DISCONNECT, false, null); 820 return false; 821 } 822 else if (bytesWritten == 0) 823 { 824 return NullConnectionSecurityProvider.writeWithTimeout( 825 clientConnection, socketChannel, sslOutBuffer); 826 } 827 } 828 break; 829 830 case NEED_UNWRAP: 831 // We need to read data from the client before the negotiation can 832 // continue. This is bad, because we don't know if there is data 833 // available but we do know that we can't write until we have read. 834 // See if there is something available for reading, and if not, then 835 // we can't afford to wait for it because otherwise we would be 836 // potentially blocking reads from other clients. Our only recourse 837 // is to close the connection. 838 sslInBuffer.clear(); 839 clearInBuffer.clear(); 840 int bytesRead = socketChannel.read(sslInBuffer); 841 if (bytesRead < 0) 842 { 843 // The client connection is already closed, so we don't need to 844 // worry about it. 845 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, 846 false, null); 847 return false; 848 } 849 else if (bytesRead == 0) 850 { 851 // We didn't get the data that we need. We'll have to disconnect 852 // to avoid blocking other clients. 853 clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM, 854 false, ERR_TLS_SECURITY_PROVIDER_WRITE_NEEDS_UNWRAP.get()); 855 return false; 856 } 857 else 858 { 859 // We were lucky and got the data we were looking for, so read and 860 // process it. 861 sslEngine.unwrap(sslInBuffer, clearInBuffer); 862 clearInBuffer.flip(); 863 } 864 break; 865 } 866 867 while (sslOutBuffer.hasRemaining()) 868 { 869 int bytesWritten = socketChannel.write(sslOutBuffer); 870 if (bytesWritten < 0) 871 { 872 // The client connection has been closed. 873 clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, 874 false, null); 875 return false; 876 } 877 else if (bytesWritten == 0) 878 { 879 return NullConnectionSecurityProvider.writeWithTimeout( 880 clientConnection, socketChannel, sslOutBuffer); 881 } 882 } 883 } 884 885 886 // If we've gotten here, then everything must have been written 887 // successfully. 888 return true; 889 } 890 catch (IOException ioe) 891 { 892 if (debugEnabled()) 893 { 894 TRACER.debugCaught(DebugLogLevel.ERROR, ioe); 895 } 896 897 // An error occurred while trying to communicate with the client. 898 // Disconnect and return. 899 clientConnection.disconnect(DisconnectReason.IO_ERROR, false, null); 900 return false; 901 } 902 catch (Exception e) 903 { 904 if (debugEnabled()) 905 { 906 TRACER.debugCaught(DebugLogLevel.ERROR, e); 907 } 908 909 // An unexpected error occurred while trying to process the data read. 910 // Disconnect and return. 911 clientConnection.disconnect(DisconnectReason.SERVER_ERROR, true, 912 ERR_TLS_SECURITY_PROVIDER_WRITE_ERROR.get( 913 getExceptionMessage(e))); 914 return false; 915 } 916 } 917 918 919 920 /** 921 * Retrieves the set of SSL protocols that will be allowed. 922 * 923 * @return The set of SSL protocols that will be allowed, or {@code null} if 924 * the default set will be used. 925 */ 926 public String[] getEnabledProtocols() 927 { 928 return enabledProtocols; 929 } 930 931 932 933 /** 934 * Specifies the set of SSL protocols that will be allowed. 935 * 936 * @param enabledProtocols The set of SSL protocols that will be allowed, or 937 * {@code null} if the default set will be used. 938 */ 939 public void setEnabledProtocols(String[] enabledProtocols) 940 { 941 this.enabledProtocols = enabledProtocols; 942 } 943 944 945 946 /** 947 * Retrieves the set of SSL cipher suites that will be allowed. 948 * 949 * @return The set of SSL cipher suites that will be allowed. 950 */ 951 public String[] getEnabledCipherSuites() 952 { 953 return enabledCipherSuites; 954 } 955 956 957 958 /** 959 * Specifies the set of SSL cipher suites that will be allowed. 960 * 961 * @param enabledCipherSuites The set of SSL cipher suites that will be 962 * allowed. 963 */ 964 public void setEnabledCipherSuites(String[] enabledCipherSuites) 965 { 966 this.enabledCipherSuites = enabledCipherSuites; 967 } 968 969 970 971 /** 972 * Retrieves the policy that should be used for SSL client authentication. 973 * 974 * @return The policy that should be used for SSL client authentication. 975 */ 976 public SSLClientAuthPolicy getSSLClientAuthPolicy() 977 { 978 return sslClientAuthPolicy; 979 } 980 981 982 983 /** 984 * Specifies the policy that should be used for SSL client authentication. 985 * 986 * @param sslClientAuthPolicy The policy that should be used for SSL client 987 * authentication. 988 */ 989 public void setSSLClientAuthPolicy(SSLClientAuthPolicy sslClientAuthPolicy) 990 { 991 this.sslClientAuthPolicy = sslClientAuthPolicy; 992 } 993 994 995 996 /** 997 * Retrieves the SSL session associated with this client connection. 998 * 999 * @return The SSL session associated with this client connection. 1000 */ 1001 public SSLSession getSSLSession() 1002 { 1003 return sslEngine.getSession(); 1004 } 1005 1006 1007 1008 /** 1009 * Retrieves the certificate chain that the client presented to the server 1010 * during the handshake process. The client's certificate will be the first 1011 * listed, followed by the certificates of any issuers in the chain. 1012 * 1013 * @return The certificate chain that the client presented to the server 1014 * during the handshake process, or {@code null} if the client did 1015 * not present a certificate. 1016 */ 1017 public Certificate[] getClientCertificateChain() 1018 { 1019 try 1020 { 1021 return sslEngine.getSession().getPeerCertificates(); 1022 } 1023 catch (Exception e) 1024 { 1025 if (debugEnabled()) 1026 { 1027 TRACER.debugCaught(DebugLogLevel.ERROR, e); 1028 } 1029 1030 return null; 1031 } 1032 } 1033 } 1034