1 /*
   2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.io.EOFException;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.InterruptedIOException;
  32 import java.io.OutputStream;
  33 import java.net.InetAddress;
  34 import java.net.InetSocketAddress;
  35 import java.net.Socket;
  36 import java.net.SocketAddress;
  37 import java.net.SocketException;
  38 import java.net.UnknownHostException;
  39 import java.nio.ByteBuffer;
  40 import java.util.List;
  41 import java.util.function.BiFunction;
  42 import javax.net.ssl.HandshakeCompletedListener;
  43 import javax.net.ssl.SSLException;
  44 import javax.net.ssl.SSLHandshakeException;
  45 import javax.net.ssl.SSLParameters;
  46 import javax.net.ssl.SSLProtocolException;
  47 import javax.net.ssl.SSLServerSocket;
  48 import javax.net.ssl.SSLSession;
  49 import javax.net.ssl.SSLSocket;
  50 import jdk.internal.access.JavaNetInetAddressAccess;
  51 import jdk.internal.access.SharedSecrets;
  52 
  53 /**
  54  * Implementation of an SSL socket.
  55  * <P>
  56  * This is a normal connection type socket, implementing SSL over some lower
  57  * level socket, such as TCP.  Because it is layered over some lower level
  58  * socket, it MUST override all default socket methods.
  59  * <P>
  60  * This API offers a non-traditional option for establishing SSL
  61  * connections.  You may first establish the connection directly, then pass
  62  * that connection to the SSL socket constructor with a flag saying which
  63  * role should be taken in the handshake protocol.  (The two ends of the
  64  * connection must not choose the same role!)  This allows setup of SSL
  65  * proxying or tunneling, and also allows the kind of "role reversal"
  66  * that is required for most FTP data transfers.
  67  *
  68  * @see javax.net.ssl.SSLSocket
  69  * @see SSLServerSocket
  70  *
  71  * @author David Brownell
  72  */
  73 public final class SSLSocketImpl
  74         extends BaseSSLSocketImpl implements SSLTransport {
  75 
  76     final SSLContextImpl            sslContext;
  77     final TransportContext          conContext;
  78 
  79     private final AppInputStream    appInput = new AppInputStream();
  80     private final AppOutputStream   appOutput = new AppOutputStream();
  81 
  82     private String                  peerHost;
  83     private boolean                 autoClose;
  84     private boolean                 isConnected = false;
  85     private volatile boolean        tlsIsClosed = false;
  86 
  87     /*
  88      * Is the local name service trustworthy?
  89      *
  90      * If the local name service is not trustworthy, reverse host name
  91      * resolution should not be performed for endpoint identification.
  92      */
  93     private static final boolean trustNameService =
  94             Utilities.getBooleanProperty("jdk.tls.trustNameService", false);
  95 
  96     /**
  97      * Package-private constructor used to instantiate an unconnected
  98      * socket.
  99      *
 100      * This instance is meant to set handshake state to use "client mode".
 101      */
 102     SSLSocketImpl(SSLContextImpl sslContext) {
 103         super();
 104         this.sslContext = sslContext;
 105         HandshakeHash handshakeHash = new HandshakeHash();
 106         this.conContext = new TransportContext(sslContext, this,
 107                 new SSLSocketInputRecord(handshakeHash),
 108                 new SSLSocketOutputRecord(handshakeHash), true);
 109     }
 110 
 111     /**
 112      * Package-private constructor used to instantiate a server socket.
 113      *
 114      * This instance is meant to set handshake state to use "server mode".
 115      */
 116     SSLSocketImpl(SSLContextImpl sslContext, SSLConfiguration sslConfig) {
 117         super();
 118         this.sslContext = sslContext;
 119         HandshakeHash handshakeHash = new HandshakeHash();
 120         this.conContext = new TransportContext(sslContext, this, sslConfig,
 121                 new SSLSocketInputRecord(handshakeHash),
 122                 new SSLSocketOutputRecord(handshakeHash));
 123     }
 124 
 125     /**
 126      * Constructs an SSL connection to a named host at a specified
 127      * port, using the authentication context provided.
 128      *
 129      * This endpoint acts as the client, and may rejoin an existing SSL session
 130      * if appropriate.
 131      */
 132     SSLSocketImpl(SSLContextImpl sslContext, String peerHost,
 133             int peerPort) throws IOException, UnknownHostException {
 134         super();
 135         this.sslContext = sslContext;
 136         HandshakeHash handshakeHash = new HandshakeHash();
 137         this.conContext = new TransportContext(sslContext, this,
 138                 new SSLSocketInputRecord(handshakeHash),
 139                 new SSLSocketOutputRecord(handshakeHash), true);
 140         this.peerHost = peerHost;
 141         SocketAddress socketAddress =
 142                peerHost != null ? new InetSocketAddress(peerHost, peerPort) :
 143                new InetSocketAddress(InetAddress.getByName(null), peerPort);
 144         connect(socketAddress, 0);
 145     }
 146 
 147     /**
 148      * Constructs an SSL connection to a server at a specified
 149      * address, and TCP port, using the authentication context
 150      * provided.
 151      *
 152      * This endpoint acts as the client, and may rejoin an existing SSL
 153      * session if appropriate.
 154      */
 155     SSLSocketImpl(SSLContextImpl sslContext,
 156             InetAddress address, int peerPort) throws IOException {
 157         super();
 158         this.sslContext = sslContext;
 159         HandshakeHash handshakeHash = new HandshakeHash();
 160         this.conContext = new TransportContext(sslContext, this,
 161                 new SSLSocketInputRecord(handshakeHash),
 162                 new SSLSocketOutputRecord(handshakeHash), true);
 163 
 164         SocketAddress socketAddress = new InetSocketAddress(address, peerPort);
 165         connect(socketAddress, 0);
 166     }
 167 
 168     /**
 169      * Constructs an SSL connection to a named host at a specified
 170      * port, using the authentication context provided.
 171      *
 172      * This endpoint acts as the client, and may rejoin an existing SSL
 173      * session if appropriate.
 174      */
 175     SSLSocketImpl(SSLContextImpl sslContext,
 176             String peerHost, int peerPort, InetAddress localAddr,
 177             int localPort) throws IOException, UnknownHostException {
 178         super();
 179         this.sslContext = sslContext;
 180         HandshakeHash handshakeHash = new HandshakeHash();
 181         this.conContext = new TransportContext(sslContext, this,
 182                 new SSLSocketInputRecord(handshakeHash),
 183                 new SSLSocketOutputRecord(handshakeHash), true);
 184         this.peerHost = peerHost;
 185 
 186         bind(new InetSocketAddress(localAddr, localPort));
 187         SocketAddress socketAddress =
 188                peerHost != null ? new InetSocketAddress(peerHost, peerPort) :
 189                new InetSocketAddress(InetAddress.getByName(null), peerPort);
 190         connect(socketAddress, 0);
 191     }
 192 
 193     /**
 194      * Constructs an SSL connection to a server at a specified
 195      * address, and TCP port, using the authentication context
 196      * provided.
 197      *
 198      * This endpoint acts as the client, and may rejoin an existing SSL
 199      * session if appropriate.
 200      */
 201     SSLSocketImpl(SSLContextImpl sslContext,
 202             InetAddress peerAddr, int peerPort,
 203             InetAddress localAddr, int localPort) throws IOException {
 204         super();
 205         this.sslContext = sslContext;
 206         HandshakeHash handshakeHash = new HandshakeHash();
 207         this.conContext = new TransportContext(sslContext, this,
 208                 new SSLSocketInputRecord(handshakeHash),
 209                 new SSLSocketOutputRecord(handshakeHash), true);
 210 
 211         bind(new InetSocketAddress(localAddr, localPort));
 212         SocketAddress socketAddress = new InetSocketAddress(peerAddr, peerPort);
 213         connect(socketAddress, 0);
 214     }
 215 
 216     /**
 217      * Creates a server mode {@link Socket} layered over an
 218      * existing connected socket, and is able to read data which has
 219      * already been consumed/removed from the {@link Socket}'s
 220      * underlying {@link InputStream}.
 221      */
 222     SSLSocketImpl(SSLContextImpl sslContext, Socket sock,
 223             InputStream consumed, boolean autoClose) throws IOException {
 224         super(sock, consumed);
 225         // We always layer over a connected socket
 226         if (!sock.isConnected()) {
 227             throw new SocketException("Underlying socket is not connected");
 228         }
 229 
 230         this.sslContext = sslContext;
 231         HandshakeHash handshakeHash = new HandshakeHash();
 232         this.conContext = new TransportContext(sslContext, this,
 233                 new SSLSocketInputRecord(handshakeHash),
 234                 new SSLSocketOutputRecord(handshakeHash), false);
 235         this.autoClose = autoClose;
 236         doneConnect();
 237     }
 238 
 239     /**
 240      * Layer SSL traffic over an existing connection, rather than
 241      * creating a new connection.
 242      *
 243      * The existing connection may be used only for SSL traffic (using this
 244      * SSLSocket) until the SSLSocket.close() call returns. However, if a
 245      * protocol error is detected, that existing connection is automatically
 246      * closed.
 247      * <p>
 248      * This particular constructor always uses the socket in the
 249      * role of an SSL client. It may be useful in cases which start
 250      * using SSL after some initial data transfers, for example in some
 251      * SSL tunneling applications or as part of some kinds of application
 252      * protocols which negotiate use of a SSL based security.
 253      */
 254     SSLSocketImpl(SSLContextImpl sslContext, Socket sock,
 255             String peerHost, int port, boolean autoClose) throws IOException {
 256         super(sock);
 257         // We always layer over a connected socket
 258         if (!sock.isConnected()) {
 259             throw new SocketException("Underlying socket is not connected");
 260         }
 261 
 262         this.sslContext = sslContext;
 263         HandshakeHash handshakeHash = new HandshakeHash();
 264         this.conContext = new TransportContext(sslContext, this,
 265                 new SSLSocketInputRecord(handshakeHash),
 266                 new SSLSocketOutputRecord(handshakeHash), true);
 267         this.peerHost = peerHost;
 268         this.autoClose = autoClose;
 269         doneConnect();
 270     }
 271 
 272     @Override
 273     public void connect(SocketAddress endpoint,
 274             int timeout) throws IOException {
 275 
 276         if (isLayered()) {
 277             throw new SocketException("Already connected");
 278         }
 279 
 280         if (!(endpoint instanceof InetSocketAddress)) {
 281             throw new SocketException(
 282                     "Cannot handle non-Inet socket addresses.");
 283         }
 284 
 285         super.connect(endpoint, timeout);
 286         doneConnect();
 287     }
 288 
 289     @Override
 290     public String[] getSupportedCipherSuites() {
 291         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
 292     }
 293 
 294     @Override
 295     public synchronized String[] getEnabledCipherSuites() {
 296         return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
 297     }
 298 
 299     @Override
 300     public synchronized void setEnabledCipherSuites(String[] suites) {
 301         conContext.sslConfig.enabledCipherSuites =
 302                 CipherSuite.validValuesOf(suites);
 303     }
 304 
 305     @Override
 306     public String[] getSupportedProtocols() {
 307         return ProtocolVersion.toStringArray(
 308                 sslContext.getSupportedProtocolVersions());
 309     }
 310 
 311     @Override
 312     public synchronized String[] getEnabledProtocols() {
 313         return ProtocolVersion.toStringArray(
 314                 conContext.sslConfig.enabledProtocols);
 315     }
 316 
 317     @Override
 318     public synchronized void setEnabledProtocols(String[] protocols) {
 319         if (protocols == null) {
 320             throw new IllegalArgumentException("Protocols cannot be null");
 321         }
 322 
 323         conContext.sslConfig.enabledProtocols =
 324                 ProtocolVersion.namesOf(protocols);
 325     }
 326 
 327     @Override
 328     public SSLSession getSession() {
 329         try {
 330             // start handshaking, if failed, the connection will be closed.
 331             ensureNegotiated();
 332         } catch (IOException ioe) {
 333             if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
 334                 SSLLogger.severe("handshake failed", ioe);
 335             }
 336 
 337             return SSLSessionImpl.nullSession;
 338         }
 339 
 340         return conContext.conSession;
 341     }
 342 
 343     @Override
 344     public synchronized SSLSession getHandshakeSession() {
 345         return conContext.handshakeContext == null ?
 346                 null : conContext.handshakeContext.handshakeSession;
 347     }
 348 
 349     @Override
 350     public synchronized void addHandshakeCompletedListener(
 351             HandshakeCompletedListener listener) {
 352         if (listener == null) {
 353             throw new IllegalArgumentException("listener is null");
 354         }
 355 
 356         conContext.sslConfig.addHandshakeCompletedListener(listener);
 357     }
 358 
 359     @Override
 360     public synchronized void removeHandshakeCompletedListener(
 361             HandshakeCompletedListener listener) {
 362         if (listener == null) {
 363             throw new IllegalArgumentException("listener is null");
 364         }
 365 
 366         conContext.sslConfig.removeHandshakeCompletedListener(listener);
 367     }
 368 
 369     @Override
 370     public void startHandshake() throws IOException {
 371         if (!isConnected) {
 372             throw new SocketException("Socket is not connected");
 373         }
 374 
 375         if (conContext.isBroken || conContext.isInboundClosed() ||
 376                 conContext.isOutboundClosed()) {
 377             throw new SocketException("Socket has been closed or broken");
 378         }
 379 
 380         synchronized (conContext) {     // handshake lock
 381             // double check the context status
 382             if (conContext.isBroken || conContext.isInboundClosed() ||
 383                     conContext.isOutboundClosed()) {
 384                 throw new SocketException("Socket has been closed or broken");
 385             }
 386 
 387             try {
 388                 conContext.kickstart();
 389 
 390                 // All initial handshaking goes through this operation until we
 391                 // have a valid SSL connection.
 392                 //
 393                 // Handle handshake messages only, need no application data.
 394                 if (!conContext.isNegotiated) {
 395                     readHandshakeRecord();
 396                 }
 397             } catch (IOException ioe) {
 398                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
 399                     "Couldn't kickstart handshaking", ioe);
 400             } catch (Exception oe) {    // including RuntimeException
 401                 handleException(oe);
 402             }
 403         }
 404     }
 405 
 406     @Override
 407     public synchronized void setUseClientMode(boolean mode) {
 408         conContext.setUseClientMode(mode);
 409     }
 410 
 411     @Override
 412     public synchronized boolean getUseClientMode() {
 413         return conContext.sslConfig.isClientMode;
 414     }
 415 
 416     @Override
 417     public synchronized void setNeedClientAuth(boolean need) {
 418         conContext.sslConfig.clientAuthType =
 419                 (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
 420                         ClientAuthType.CLIENT_AUTH_NONE);
 421     }
 422 
 423     @Override
 424     public synchronized boolean getNeedClientAuth() {
 425         return (conContext.sslConfig.clientAuthType ==
 426                         ClientAuthType.CLIENT_AUTH_REQUIRED);
 427     }
 428 
 429     @Override
 430     public synchronized void setWantClientAuth(boolean want) {
 431         conContext.sslConfig.clientAuthType =
 432                 (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
 433                         ClientAuthType.CLIENT_AUTH_NONE);
 434     }
 435 
 436     @Override
 437     public synchronized boolean getWantClientAuth() {
 438         return (conContext.sslConfig.clientAuthType ==
 439                         ClientAuthType.CLIENT_AUTH_REQUESTED);
 440     }
 441 
 442     @Override
 443     public synchronized void setEnableSessionCreation(boolean flag) {
 444         conContext.sslConfig.enableSessionCreation = flag;
 445     }
 446 
 447     @Override
 448     public synchronized boolean getEnableSessionCreation() {
 449         return conContext.sslConfig.enableSessionCreation;
 450     }
 451 
 452     @Override
 453     public boolean isClosed() {
 454         return tlsIsClosed;
 455     }
 456 
 457     // Please don't synchronized this method.  Otherwise, the read and close
 458     // locks may be deadlocked.
 459     @Override
 460     public void close() throws IOException {
 461         if (tlsIsClosed) {
 462             return;
 463         }
 464 
 465         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 466             SSLLogger.fine("duplex close of SSLSocket");
 467         }
 468 
 469         try {
 470             // shutdown output bound, which may have been closed previously.
 471             if (!isOutputShutdown()) {
 472                 duplexCloseOutput();
 473             }
 474 
 475             // shutdown input bound, which may have been closed previously.
 476             if (!isInputShutdown()) {
 477                 duplexCloseInput();
 478             }
 479 
 480             if (!isClosed()) {
 481                 // close the connection directly
 482                 closeSocket(false);
 483             }
 484         } catch (IOException ioe) {
 485             // ignore the exception
 486             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 487                 SSLLogger.warning("SSLSocket duplex close failed", ioe);
 488             }
 489         } finally {
 490             tlsIsClosed = true;
 491         }
 492     }
 493 
 494     /**
 495      * Duplex close, start from closing outbound.
 496      *
 497      * For TLS 1.2 [RFC 5246], unless some other fatal alert has been
 498      * transmitted, each party is required to send a close_notify alert
 499      * before closing the write side of the connection.  The other party
 500      * MUST respond with a close_notify alert of its own and close down
 501      * the connection immediately, discarding any pending writes.  It is
 502      * not required for the initiator of the close to wait for the responding
 503      * close_notify alert before closing the read side of the connection.
 504      *
 505      * For TLS 1.3, Each party MUST send a close_notify alert before
 506      * closing its write side of the connection, unless it has already sent
 507      * some error alert.  This does not have any effect on its read side of
 508      * the connection.  Both parties need not wait to receive a close_notify
 509      * alert before closing their read side of the connection, though doing
 510      * so would introduce the possibility of truncation.
 511      *
 512      * In order to support user initiated duplex-close for TLS 1.3 connections,
 513      * the user_canceled alert is used together with the close_notify alert.
 514      */
 515     private void duplexCloseOutput() throws IOException {
 516         boolean useUserCanceled = false;
 517         boolean hasCloseReceipt = false;
 518         if (conContext.isNegotiated) {
 519             if (!conContext.protocolVersion.useTLS13PlusSpec()) {
 520                 hasCloseReceipt = true;
 521             } else {
 522                 // Use a user_canceled alert for TLS 1.3 duplex close.
 523                 useUserCanceled = true;
 524             }
 525         } else if (conContext.handshakeContext != null) {   // initial handshake
 526             // Use user_canceled alert regardless the protocol versions.
 527             useUserCanceled = true;
 528 
 529             // The protocol version may have been negotiated.
 530             ProtocolVersion pv = conContext.handshakeContext.negotiatedProtocol;
 531             if (pv == null || (!pv.useTLS13PlusSpec())) {
 532                 hasCloseReceipt = true;
 533             }
 534         }
 535 
 536         // Need a lock here so that the user_canceled alert and the
 537         // close_notify alert can be delivered together.
 538         try {
 539             synchronized (conContext.outputRecord) {
 540                 // send a user_canceled alert if needed.
 541                 if (useUserCanceled) {
 542                     conContext.warning(Alert.USER_CANCELED);
 543                 }
 544 
 545                 // send a close_notify alert
 546                 conContext.warning(Alert.CLOSE_NOTIFY);
 547             }
 548         } finally {
 549             if (!conContext.isOutboundClosed()) {
 550                 conContext.outputRecord.close();
 551             }
 552 
 553             if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 554                 super.shutdownOutput();
 555             }
 556         }
 557 
 558         if (!isInputShutdown()) {
 559             bruteForceCloseInput(hasCloseReceipt);
 560         }
 561     }
 562 
 563     /**
 564      * Duplex close, start from closing inbound.
 565      *
 566      * This method should only be called when the outbound has been closed,
 567      * but the inbound is still open.
 568      */
 569     private void duplexCloseInput() throws IOException {
 570         boolean hasCloseReceipt = false;
 571         if (conContext.isNegotiated &&
 572                 !conContext.protocolVersion.useTLS13PlusSpec()) {
 573             hasCloseReceipt = true;
 574         }   // No close receipt if handshake has no completed.
 575 
 576         bruteForceCloseInput(hasCloseReceipt);
 577     }
 578 
 579     /**
 580      * Brute force close the input bound.
 581      *
 582      * This method should only be called when the outbound has been closed,
 583      * but the inbound is still open.
 584      */
 585     private void bruteForceCloseInput(
 586             boolean hasCloseReceipt) throws IOException {
 587         if (hasCloseReceipt) {
 588             // It is not required for the initiator of the close to wait for
 589             // the responding close_notify alert before closing the read side
 590             // of the connection.  However, if the application protocol using
 591             // TLS provides that any data may be carried over the underlying
 592             // transport after the TLS connection is closed, the TLS
 593             // implementation MUST receive a "close_notify" alert before
 594             // indicating end-of-data to the application-layer.
 595             try {
 596                 this.shutdown();
 597             } finally {
 598                 if (!isInputShutdown()) {
 599                     shutdownInput(false);
 600                 }
 601             }
 602         } else {
 603             if (!conContext.isInboundClosed()) {
 604                 try (conContext.inputRecord) {
 605                     // Try the best to use up the input records and close the
 606                     // socket gracefully, without impact the performance too
 607                     // much.
 608                     appInput.deplete();
 609                 }
 610             }
 611 
 612             if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 613                 super.shutdownInput();
 614             }
 615         }
 616     }
 617 
 618     // Please don't synchronized this method.  Otherwise, the read and close
 619     // locks may be deadlocked.
 620     @Override
 621     public void shutdownInput() throws IOException {
 622         shutdownInput(true);
 623     }
 624 
 625     // It is not required to check the close_notify receipt unless an
 626     // application call shutdownInput() explicitly.
 627     private void shutdownInput(
 628             boolean checkCloseNotify) throws IOException {
 629         if (isInputShutdown()) {
 630             return;
 631         }
 632 
 633         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 634             SSLLogger.fine("close inbound of SSLSocket");
 635         }
 636 
 637         // Is it ready to close inbound?
 638         //
 639         // No need to throw exception if the initial handshake is not started.
 640         if (checkCloseNotify && !conContext.isInputCloseNotified &&
 641             (conContext.isNegotiated || conContext.handshakeContext != null)) {
 642 
 643             throw conContext.fatal(Alert.INTERNAL_ERROR,
 644                     "closing inbound before receiving peer's close_notify");
 645         }
 646 
 647         conContext.closeInbound();
 648         if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 649             super.shutdownInput();
 650         }
 651     }
 652 
 653     @Override
 654     public boolean isInputShutdown() {
 655         return conContext.isInboundClosed() &&
 656                 ((autoClose || !isLayered()) ? super.isInputShutdown(): true);
 657     }
 658 
 659     // Please don't synchronized this method.  Otherwise, the read and close
 660     // locks may be deadlocked.
 661     @Override
 662     public void shutdownOutput() throws IOException {
 663         if (isOutputShutdown()) {
 664             return;
 665         }
 666 
 667         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 668             SSLLogger.fine("close outbound of SSLSocket");
 669         }
 670         conContext.closeOutbound();
 671 
 672         if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 673             super.shutdownOutput();
 674         }
 675     }
 676 
 677     @Override
 678     public boolean isOutputShutdown() {
 679         return conContext.isOutboundClosed() &&
 680                 ((autoClose || !isLayered()) ? super.isOutputShutdown(): true);
 681     }
 682 
 683     @Override
 684     public synchronized InputStream getInputStream() throws IOException {
 685         if (isClosed()) {
 686             throw new SocketException("Socket is closed");
 687         }
 688 
 689         if (!isConnected) {
 690             throw new SocketException("Socket is not connected");
 691         }
 692 
 693         if (conContext.isInboundClosed() || isInputShutdown()) {
 694             throw new SocketException("Socket input is already shutdown");
 695         }
 696 
 697         return appInput;
 698     }
 699 
 700     private void ensureNegotiated() throws IOException {
 701         if (conContext.isNegotiated || conContext.isBroken ||
 702                 conContext.isInboundClosed() || conContext.isOutboundClosed()) {
 703             return;
 704         }
 705 
 706         synchronized (conContext) {     // handshake lock
 707             // double check the context status
 708             if (conContext.isNegotiated || conContext.isBroken ||
 709                     conContext.isInboundClosed() ||
 710                     conContext.isOutboundClosed()) {
 711                 return;
 712             }
 713 
 714             startHandshake();
 715         }
 716     }
 717 
 718     /**
 719      * InputStream for application data as returned by
 720      * SSLSocket.getInputStream().
 721      */
 722     private class AppInputStream extends InputStream {
 723         // One element array used to implement the single byte read() method
 724         private final byte[] oneByte = new byte[1];
 725 
 726         // the temporary buffer used to read network
 727         private ByteBuffer buffer;
 728 
 729         // Is application data available in the stream?
 730         private volatile boolean appDataIsAvailable;
 731 
 732         AppInputStream() {
 733             this.appDataIsAvailable = false;
 734             this.buffer = ByteBuffer.allocate(4096);
 735         }
 736 
 737         /**
 738          * Return the minimum number of bytes that can be read
 739          * without blocking.
 740          */
 741         @Override
 742         public int available() throws IOException {
 743             // Currently not synchronized.
 744             if ((!appDataIsAvailable) || checkEOF()) {
 745                 return 0;
 746             }
 747 
 748             return buffer.remaining();
 749         }
 750 
 751         /**
 752          * Read a single byte, returning -1 on non-fault EOF status.
 753          */
 754         @Override
 755         public int read() throws IOException {
 756             int n = read(oneByte, 0, 1);
 757             if (n <= 0) {   // EOF
 758                 return -1;
 759             }
 760 
 761             return oneByte[0] & 0xFF;
 762         }
 763 
 764         /**
 765          * Reads up to {@code len} bytes of data from the input stream
 766          * into an array of bytes.
 767          *
 768          * An attempt is made to read as many as {@code len} bytes, but a
 769          * smaller number may be read. The number of bytes actually read
 770          * is returned as an integer.
 771          *
 772          * If the layer above needs more data, it asks for more, so we
 773          * are responsible only for blocking to fill at most one buffer,
 774          * and returning "-1" on non-fault EOF status.
 775          */
 776         @Override
 777         public int read(byte[] b, int off, int len)
 778                 throws IOException {
 779             if (b == null) {
 780                 throw new NullPointerException("the target buffer is null");
 781             } else if (off < 0 || len < 0 || len > b.length - off) {
 782                 throw new IndexOutOfBoundsException(
 783                         "buffer length: " + b.length + ", offset; " + off +
 784                         ", bytes to read:" + len);
 785             } else if (len == 0) {
 786                 return 0;
 787             }
 788 
 789             if (checkEOF()) {
 790                 return -1;
 791             }
 792 
 793             // start handshaking if the connection has not been negotiated.
 794             if (!conContext.isNegotiated && !conContext.isBroken &&
 795                     !conContext.isInboundClosed() &&
 796                     !conContext.isOutboundClosed()) {
 797                 ensureNegotiated();
 798             }
 799 
 800             // Check if the Socket is invalid (error or closed).
 801             if (!conContext.isNegotiated ||
 802                     conContext.isBroken || conContext.isInboundClosed()) {
 803                 throw new SocketException("Connection or inbound has closed");
 804             }
 805 
 806             // Read the available bytes at first.
 807             //
 808             // Note that the receiving and processing of post-handshake message
 809             // are also synchronized with the read lock.
 810             synchronized (this) {
 811                 int remains = available();
 812                 if (remains > 0) {
 813                     int howmany = Math.min(remains, len);
 814                     buffer.get(b, off, howmany);
 815 
 816                     return howmany;
 817                 }
 818 
 819                 appDataIsAvailable = false;
 820                 try {
 821                     ByteBuffer bb = readApplicationRecord(buffer);
 822                     if (bb == null) {   // EOF
 823                         return -1;
 824                     } else {
 825                         // The buffer may be reallocated for bigger capacity.
 826                         buffer = bb;
 827                     }
 828 
 829                     bb.flip();
 830                     int volume = Math.min(len, bb.remaining());
 831                     buffer.get(b, off, volume);
 832                     appDataIsAvailable = true;
 833 
 834                     return volume;
 835                 } catch (Exception e) {   // including RuntimeException
 836                     // shutdown and rethrow (wrapped) exception as appropriate
 837                     handleException(e);
 838 
 839                     // dummy for compiler
 840                     return -1;
 841                 }
 842             }
 843         }
 844 
 845         /**
 846          * Skip n bytes.
 847          *
 848          * This implementation is somewhat less efficient than possible, but
 849          * not badly so (redundant copy).  We reuse the read() code to keep
 850          * things simpler.
 851          */
 852         @Override
 853         public synchronized long skip(long n) throws IOException {
 854             // dummy array used to implement skip()
 855             byte[] skipArray = new byte[256];
 856 
 857             long skipped = 0;
 858             while (n > 0) {
 859                 int len = (int)Math.min(n, skipArray.length);
 860                 int r = read(skipArray, 0, len);
 861                 if (r <= 0) {
 862                     break;
 863                 }
 864                 n -= r;
 865                 skipped += r;
 866             }
 867 
 868             return skipped;
 869         }
 870 
 871         @Override
 872         public void close() throws IOException {
 873             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 874                 SSLLogger.finest("Closing input stream");
 875             }
 876 
 877             try {
 878                 shutdownInput(false);
 879             } catch (IOException ioe) {
 880                 // ignore the exception
 881                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 882                     SSLLogger.warning("input stream close failed", ioe);
 883                 }
 884             }
 885         }
 886 
 887         /**
 888          * Return whether we have reached end-of-file.
 889          *
 890          * If the socket is not connected, has been shutdown because of an error
 891          * or has been closed, throw an Exception.
 892          */
 893         private boolean checkEOF() throws IOException {
 894             if (conContext.isInboundClosed()) {
 895                 return true;
 896             } else if (conContext.isInputCloseNotified || conContext.isBroken) {
 897                 if (conContext.closeReason == null) {
 898                     return true;
 899                 } else {
 900                     throw new SSLException(
 901                         "Connection has closed: " + conContext.closeReason,
 902                         conContext.closeReason);
 903                 }
 904             }
 905 
 906             return false;
 907         }
 908 
 909         /**
 910          * Try the best to use up the input records so as to close the
 911          * socket gracefully, without impact the performance too much.
 912          */
 913         private synchronized void deplete() {
 914             if (!conContext.isInboundClosed()) {
 915                 if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
 916                     return;
 917                 }
 918 
 919                 SSLSocketInputRecord socketInputRecord =
 920                         (SSLSocketInputRecord)conContext.inputRecord;
 921                 try {
 922                     socketInputRecord.deplete(
 923                         conContext.isNegotiated && (getSoTimeout() > 0));
 924                 } catch (IOException ioe) {
 925                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 926                         SSLLogger.warning(
 927                             "input stream close depletion failed", ioe);
 928                     }
 929                 }
 930             }
 931         }
 932     }
 933 
 934     @Override
 935     public synchronized OutputStream getOutputStream() throws IOException {
 936         if (isClosed()) {
 937             throw new SocketException("Socket is closed");
 938         }
 939 
 940         if (!isConnected) {
 941             throw new SocketException("Socket is not connected");
 942         }
 943 
 944         if (conContext.isOutboundDone() || isOutputShutdown()) {
 945             throw new SocketException("Socket output is already shutdown");
 946         }
 947 
 948         return appOutput;
 949     }
 950 
 951 
 952     /**
 953      * OutputStream for application data as returned by
 954      * SSLSocket.getOutputStream().
 955      */
 956     private class AppOutputStream extends OutputStream {
 957         // One element array used to implement the write(byte) method
 958         private final byte[] oneByte = new byte[1];
 959 
 960         @Override
 961         public void write(int i) throws IOException {
 962             oneByte[0] = (byte)i;
 963             write(oneByte, 0, 1);
 964         }
 965 
 966         @Override
 967         public void write(byte[] b,
 968                 int off, int len) throws IOException {
 969             if (b == null) {
 970                 throw new NullPointerException("the source buffer is null");
 971             } else if (off < 0 || len < 0 || len > b.length - off) {
 972                 throw new IndexOutOfBoundsException(
 973                         "buffer length: " + b.length + ", offset; " + off +
 974                         ", bytes to read:" + len);
 975             } else if (len == 0) {
 976                 //
 977                 // Don't bother to really write empty records.  We went this
 978                 // far to drive the handshake machinery, for correctness; not
 979                 // writing empty records improves performance by cutting CPU
 980                 // time and network resource usage.  However, some protocol
 981                 // implementations are fragile and don't like to see empty
 982                 // records, so this also increases robustness.
 983                 //
 984                 return;
 985             }
 986 
 987             // Start handshaking if the connection has not been negotiated.
 988             if (!conContext.isNegotiated && !conContext.isBroken &&
 989                     !conContext.isInboundClosed() &&
 990                     !conContext.isOutboundClosed()) {
 991                 ensureNegotiated();
 992             }
 993 
 994             // Check if the Socket is invalid (error or closed).
 995             if (!conContext.isNegotiated ||
 996                     conContext.isBroken || conContext.isOutboundClosed()) {
 997                 throw new SocketException("Connection or outbound has closed");
 998             }
 999 
1000             //
1001 
1002             // Delegate the writing to the underlying socket.
1003             try {
1004                 conContext.outputRecord.deliver(b, off, len);
1005             } catch (SSLHandshakeException she) {
1006                 // may be record sequence number overflow
1007                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
1008             } catch (IOException e) {
1009                 throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
1010             }
1011 
1012             // Is the sequence number is nearly overflow, or has the key usage
1013             // limit been reached?
1014             if (conContext.outputRecord.seqNumIsHuge() ||
1015                     conContext.outputRecord.writeCipher.atKeyLimit()) {
1016                 tryKeyUpdate();
1017             }
1018         }
1019 
1020         @Override
1021         public void close() throws IOException {
1022             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1023                 SSLLogger.finest("Closing output stream");
1024             }
1025 
1026             try {
1027                 shutdownOutput();
1028             } catch (IOException ioe) {
1029                 // ignore the exception
1030                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1031                     SSLLogger.warning("output stream close failed", ioe);
1032                 }
1033             }
1034         }
1035     }
1036 
1037     @Override
1038     public synchronized SSLParameters getSSLParameters() {
1039         return conContext.sslConfig.getSSLParameters();
1040     }
1041 
1042     @Override
1043     public synchronized void setSSLParameters(SSLParameters params) {
1044         conContext.sslConfig.setSSLParameters(params);
1045 
1046         if (conContext.sslConfig.maximumPacketSize != 0) {
1047             conContext.outputRecord.changePacketSize(
1048                     conContext.sslConfig.maximumPacketSize);
1049         }
1050     }
1051 
1052     @Override
1053     public synchronized String getApplicationProtocol() {
1054         return conContext.applicationProtocol;
1055     }
1056 
1057     @Override
1058     public synchronized String getHandshakeApplicationProtocol() {
1059         if (conContext.handshakeContext != null) {
1060             return conContext.handshakeContext.applicationProtocol;
1061         }
1062 
1063         return null;
1064     }
1065 
1066     @Override
1067     public synchronized void setHandshakeApplicationProtocolSelector(
1068             BiFunction<SSLSocket, List<String>, String> selector) {
1069         conContext.sslConfig.socketAPSelector = selector;
1070     }
1071 
1072     @Override
1073     public synchronized BiFunction<SSLSocket, List<String>, String>
1074             getHandshakeApplicationProtocolSelector() {
1075         return conContext.sslConfig.socketAPSelector;
1076     }
1077 
1078     /**
1079      * Read the initial handshake records.
1080      */
1081     private int readHandshakeRecord() throws IOException {
1082         while (!conContext.isInboundClosed()) {
1083             try {
1084                 Plaintext plainText = decode(null);
1085                 if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
1086                         conContext.isNegotiated) {
1087                     return 0;
1088                 }
1089             } catch (SSLException ssle) {
1090                 throw ssle;
1091             } catch (IOException ioe) {
1092                 if (!(ioe instanceof SSLException)) {
1093                     throw new SSLException("readHandshakeRecord", ioe);
1094                 } else {
1095                     throw ioe;
1096                 }
1097             }
1098         }
1099 
1100         return -1;
1101     }
1102 
1103     /**
1104      * Read application data record. Used by AppInputStream only, but defined
1105      * here so as to use the socket level synchronization.
1106      *
1107      * Note that the connection guarantees that handshake, alert, and change
1108      * cipher spec data streams are handled as they arrive, so we never see
1109      * them here.
1110      *
1111      * Note: Please be careful about the synchronization, and don't use this
1112      * method other than in the AppInputStream class!
1113      */
1114     private ByteBuffer readApplicationRecord(
1115             ByteBuffer buffer) throws IOException {
1116         while (!conContext.isInboundClosed()) {
1117             /*
1118              * clean the buffer and check if it is too small, e.g. because
1119              * the AppInputStream did not have the chance to see the
1120              * current packet length but rather something like that of the
1121              * handshake before. In that case we return 0 at this point to
1122              * give the caller the chance to adjust the buffer.
1123              */
1124             buffer.clear();
1125             int inLen = conContext.inputRecord.bytesInCompletePacket();
1126             if (inLen < 0) {    // EOF
1127                 handleEOF(null);
1128 
1129                 // if no exception thrown
1130                 return null;
1131             }
1132 
1133             // Is this packet bigger than SSL/TLS normally allows?
1134             if (inLen > SSLRecord.maxLargeRecordSize) {
1135                 throw new SSLProtocolException(
1136                         "Illegal packet size: " + inLen);
1137             }
1138 
1139             if (inLen > buffer.remaining()) {
1140                 buffer = ByteBuffer.allocate(inLen);
1141             }
1142 
1143             try {
1144                 Plaintext plainText;
1145                 synchronized (this) {
1146                     plainText = decode(buffer);
1147                 }
1148                 if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
1149                         buffer.position() > 0) {
1150                     return buffer;
1151                 }
1152             } catch (SSLException ssle) {
1153                 throw ssle;
1154             } catch (IOException ioe) {
1155                 if (!(ioe instanceof SSLException)) {
1156                     throw new SSLException("readApplicationRecord", ioe);
1157                 } else {
1158                     throw ioe;
1159                 }
1160             }
1161         }
1162 
1163         //
1164         // couldn't read, due to some kind of error
1165         //
1166         return null;
1167     }
1168 
1169     private Plaintext decode(ByteBuffer destination) throws IOException {
1170         Plaintext plainText;
1171         try {
1172             if (destination == null) {
1173                 plainText = SSLTransport.decode(conContext,
1174                         null, 0, 0, null, 0, 0);
1175             } else {
1176                 plainText = SSLTransport.decode(conContext,
1177                         null, 0, 0, new ByteBuffer[]{destination}, 0, 1);
1178             }
1179         } catch (EOFException eofe) {
1180             // EOFException is special as it is related to close_notify.
1181             plainText = handleEOF(eofe);
1182         }
1183 
1184         // Is the sequence number is nearly overflow?
1185         if (plainText != Plaintext.PLAINTEXT_NULL &&
1186                 (conContext.inputRecord.seqNumIsHuge() ||
1187                 conContext.inputRecord.readCipher.atKeyLimit())) {
1188             tryKeyUpdate();
1189         }
1190 
1191         return plainText;
1192     }
1193 
1194     /**
1195      * Try key update for sequence number wrap or key usage limit.
1196      *
1197      * Note that in order to maintain the handshake status properly, we check
1198      * the sequence number and key usage limit after the last record
1199      * reading/writing process.
1200      *
1201      * As we request renegotiation or close the connection for wrapped sequence
1202      * number when there is enough sequence number space left to handle a few
1203      * more records, so the sequence number of the last record cannot be
1204      * wrapped.
1205      */
1206     private void tryKeyUpdate() throws IOException {
1207         // Don't bother to kickstart if handshaking is in progress, or if the
1208         // connection is not duplex-open.
1209         if ((conContext.handshakeContext == null) &&
1210                 !conContext.isOutboundClosed() &&
1211                 !conContext.isInboundClosed() &&
1212                 !conContext.isBroken) {
1213             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1214                 SSLLogger.finest("trigger key update");
1215             }
1216             startHandshake();
1217         }
1218     }
1219 
1220     /**
1221      * Initialize the handshaker and socket streams.
1222      *
1223      * Called by connect, the layered constructor, and SSLServerSocket.
1224      */
1225     synchronized void doneConnect() throws IOException {
1226         // In server mode, it is not necessary to set host and serverNames.
1227         // Otherwise, would require a reverse DNS lookup to get the hostname.
1228         if (peerHost == null || peerHost.isEmpty()) {
1229             boolean useNameService =
1230                     trustNameService && conContext.sslConfig.isClientMode;
1231             useImplicitHost(useNameService);
1232         } else {
1233             conContext.sslConfig.serverNames =
1234                     Utilities.addToSNIServerNameList(
1235                             conContext.sslConfig.serverNames, peerHost);
1236         }
1237 
1238         InputStream sockInput = super.getInputStream();
1239         conContext.inputRecord.setReceiverStream(sockInput);
1240 
1241         OutputStream sockOutput = super.getOutputStream();
1242         conContext.inputRecord.setDeliverStream(sockOutput);
1243         conContext.outputRecord.setDeliverStream(sockOutput);
1244 
1245         this.isConnected = true;
1246     }
1247 
1248     private void useImplicitHost(boolean useNameService) {
1249         // Note: If the local name service is not trustworthy, reverse
1250         // host name resolution should not be performed for endpoint
1251         // identification.  Use the application original specified
1252         // hostname or IP address instead.
1253 
1254         // Get the original hostname via jdk.internal.access.SharedSecrets
1255         InetAddress inetAddress = getInetAddress();
1256         if (inetAddress == null) {      // not connected
1257             return;
1258         }
1259 
1260         JavaNetInetAddressAccess jna =
1261                 SharedSecrets.getJavaNetInetAddressAccess();
1262         String originalHostname = jna.getOriginalHostName(inetAddress);
1263         if (originalHostname != null && !originalHostname.isEmpty()) {
1264 
1265             this.peerHost = originalHostname;
1266             if (conContext.sslConfig.serverNames.isEmpty() &&
1267                     !conContext.sslConfig.noSniExtension) {
1268                 conContext.sslConfig.serverNames =
1269                         Utilities.addToSNIServerNameList(
1270                                 conContext.sslConfig.serverNames, peerHost);
1271             }
1272 
1273             return;
1274         }
1275 
1276         // No explicitly specified hostname, no server name indication.
1277         if (!useNameService) {
1278             // The local name service is not trustworthy, use IP address.
1279             this.peerHost = inetAddress.getHostAddress();
1280         } else {
1281             // Use the underlying reverse host name resolution service.
1282             this.peerHost = getInetAddress().getHostName();
1283         }
1284     }
1285 
1286     // ONLY used by HttpsClient to setup the URI specified hostname
1287     //
1288     // Please NOTE that this method MUST be called before calling to
1289     // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
1290     // may override SNIHostName in the customized server name indication.
1291     public synchronized void setHost(String host) {
1292         this.peerHost = host;
1293         this.conContext.sslConfig.serverNames =
1294                 Utilities.addToSNIServerNameList(
1295                         conContext.sslConfig.serverNames, host);
1296     }
1297 
1298     /**
1299      * Handle an exception.
1300      *
1301      * This method is called by top level exception handlers (in read(),
1302      * write()) to make sure we always shutdown the connection correctly
1303      * and do not pass runtime exception to the application.
1304      *
1305      * This method never returns normally, it always throws an IOException.
1306      */
1307     private void handleException(Exception cause) throws IOException {
1308         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1309             SSLLogger.warning("handling exception", cause);
1310         }
1311 
1312         // Don't close the Socket in case of timeouts or interrupts.
1313         if (cause instanceof InterruptedIOException) {
1314             throw (IOException)cause;
1315         }
1316 
1317         // need to perform error shutdown
1318         boolean isSSLException = (cause instanceof SSLException);
1319         Alert alert;
1320         if (isSSLException) {
1321             if (cause instanceof SSLHandshakeException) {
1322                 alert = Alert.HANDSHAKE_FAILURE;
1323             } else {
1324                 alert = Alert.UNEXPECTED_MESSAGE;
1325             }
1326         } else {
1327             if (cause instanceof IOException) {
1328                 alert = Alert.UNEXPECTED_MESSAGE;
1329             } else {
1330                 // RuntimeException
1331                 alert = Alert.INTERNAL_ERROR;
1332             }
1333         }
1334 
1335         throw conContext.fatal(alert, cause);
1336     }
1337 
1338     private Plaintext handleEOF(EOFException eofe) throws IOException {
1339         if (requireCloseNotify || conContext.handshakeContext != null) {
1340             SSLException ssle;
1341             if (conContext.handshakeContext != null) {
1342                 ssle = new SSLHandshakeException(
1343                         "Remote host terminated the handshake");
1344             } else {
1345                 ssle = new SSLProtocolException(
1346                         "Remote host terminated the connection");
1347             }
1348 
1349             if (eofe != null) {
1350                 ssle.initCause(eofe);
1351             }
1352             throw ssle;
1353         } else {
1354             // treat as if we had received a close_notify
1355             conContext.isInputCloseNotified = true;
1356             shutdownInput();
1357 
1358             return Plaintext.PLAINTEXT_NULL;
1359         }
1360     }
1361 
1362 
1363     @Override
1364     public String getPeerHost() {
1365         return peerHost;
1366     }
1367 
1368     @Override
1369     public int getPeerPort() {
1370         return getPort();
1371     }
1372 
1373     @Override
1374     public boolean useDelegatedTask() {
1375         return false;
1376     }
1377 
1378     @Override
1379     public void shutdown() throws IOException {
1380         if (!isClosed()) {
1381             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1382                 SSLLogger.fine("close the underlying socket");
1383             }
1384 
1385             try {
1386                 if (conContext.isInputCloseNotified) {
1387                     // Close the connection, no wait for more peer response.
1388                     closeSocket(false);
1389                 } else {
1390                     // Close the connection, may wait for peer close_notify.
1391                     closeSocket(true);
1392                 }
1393             } finally {
1394                 tlsIsClosed = true;
1395             }
1396         }
1397     }
1398 
1399     private void closeSocket(boolean selfInitiated) throws IOException {
1400         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1401             SSLLogger.fine("close the SSL connection " +
1402                 (selfInitiated ? "(initiative)" : "(passive)"));
1403         }
1404 
1405         if (autoClose || !isLayered()) {
1406             super.close();
1407         } else if (selfInitiated) {
1408             if (!conContext.isInboundClosed() && !isInputShutdown()) {
1409                 // wait for close_notify alert to clear input stream.
1410                 waitForClose();
1411             }
1412         }
1413     }
1414 
1415    /**
1416     * Wait for close_notify alert for a graceful closure.
1417     *
1418     * [RFC 5246] If the application protocol using TLS provides that any
1419     * data may be carried over the underlying transport after the TLS
1420     * connection is closed, the TLS implementation must receive the responding
1421     * close_notify alert before indicating to the application layer that
1422     * the TLS connection has ended.  If the application protocol will not
1423     * transfer any additional data, but will only close the underlying
1424     * transport connection, then the implementation MAY choose to close the
1425     * transport without waiting for the responding close_notify.
1426     */
1427     private void waitForClose() throws IOException {
1428         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1429             SSLLogger.fine("wait for close_notify or alert");
1430         }
1431 
1432         while (!conContext.isInboundClosed()) {
1433             try {
1434                 Plaintext plainText = decode(null);
1435                 // discard and continue
1436                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1437                     SSLLogger.finest(
1438                         "discard plaintext while waiting for close", plainText);
1439                 }
1440             } catch (Exception e) {   // including RuntimeException
1441                 handleException(e);
1442             }
1443         }
1444     }
1445 }