1 /*
   2  * Copyright (c) 2002, 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.*;
  29 import java.net.*;
  30 import java.nio.channels.SocketChannel;
  31 import java.util.Set;
  32 import javax.net.ssl.*;
  33 
  34 /**
  35  * Abstract base class for SSLSocketImpl.
  36  *
  37  * Its purpose is to house code with no SSL related logic (or no logic at all).
  38  * This makes SSLSocketImpl shorter and easier to read. It contains a few
  39  * constants and static methods plus overridden java.net.Socket methods.
  40  *
  41  * Methods are defined final to ensure that they are not accidentally
  42  * overridden in SSLSocketImpl.
  43  *
  44  * @see javax.net.ssl.SSLSocket
  45  * @see SSLSocketImpl
  46  */
  47 abstract class BaseSSLSocketImpl extends SSLSocket {
  48 
  49     /*
  50      * Normally "self" is "this" ... but not when this connection is
  51      * layered over a preexisting socket.  If we're using an existing
  52      * socket, we delegate some actions to it.  Else, we delegate
  53      * instead to "super".  This is important to ensure that we don't
  54      * recurse infinitely ... e.g. close() calling itself, or doing
  55      * I/O in terms of our own streams.
  56      */
  57     private final Socket self;
  58     private final InputStream consumedInput;
  59 
  60     BaseSSLSocketImpl() {
  61         super();
  62         this.self = this;
  63         this.consumedInput = null;
  64     }
  65 
  66     BaseSSLSocketImpl(Socket socket) {
  67         super();
  68         this.self = socket;
  69         this.consumedInput = null;
  70     }
  71 
  72     BaseSSLSocketImpl(Socket socket, InputStream consumed) {
  73         super();
  74         this.self = socket;
  75         this.consumedInput = consumed;
  76     }
  77 
  78     //
  79     // CONSTANTS AND STATIC METHODS
  80     //
  81 
  82     /**
  83      * TLS requires that a close_notify warning alert is sent before the
  84      * connection is closed in order to avoid truncation attacks. Some
  85      * implementations (MS IIS and others) don't do that. The property
  86      * below controls whether we accept that or treat it as an error.
  87      *
  88      * The default is "false", i.e. tolerate the broken behavior.
  89      */
  90     private static final String PROP_NAME =
  91                                 "com.sun.net.ssl.requireCloseNotify";
  92 
  93     static final boolean requireCloseNotify =
  94                                 Utilities.getBooleanProperty(PROP_NAME, false);
  95 
  96     //
  97     // MISC SOCKET METHODS
  98     //
  99 
 100     /**
 101      * Returns the unique {@link java.nio.SocketChannel SocketChannel} object
 102      * associated with this socket, if any.
 103      * @see java.net.Socket#getChannel
 104      */
 105     @Override
 106     public final SocketChannel getChannel() {
 107         if (self == this) {
 108             return super.getChannel();
 109         } else {
 110             return self.getChannel();
 111         }
 112     }
 113 
 114     /**
 115      * Binds the address to the socket.
 116      * @see java.net.Socket#bind
 117      */
 118     @Override
 119     public void bind(SocketAddress bindpoint) throws IOException {
 120         /*
 121          * Bind to this socket
 122          */
 123         if (self == this) {
 124             super.bind(bindpoint);
 125         } else {
 126             // If we're binding on a layered socket...
 127             throw new IOException(
 128                 "Underlying socket should already be connected");
 129         }
 130     }
 131 
 132     /**
 133      * Returns the address of the endpoint this socket is connected to
 134      * @see java.net.Socket#getLocalSocketAddress
 135      */
 136     @Override
 137     public SocketAddress getLocalSocketAddress() {
 138         if (self == this) {
 139             return super.getLocalSocketAddress();
 140         } else {
 141             return self.getLocalSocketAddress();
 142         }
 143     }
 144 
 145     /**
 146      * Returns the address of the endpoint this socket is connected to
 147      * @see java.net.Socket#getRemoteSocketAddress
 148      */
 149     @Override
 150     public SocketAddress getRemoteSocketAddress() {
 151         if (self == this) {
 152             return super.getRemoteSocketAddress();
 153         } else {
 154             return self.getRemoteSocketAddress();
 155         }
 156     }
 157 
 158     /**
 159      * Connects this socket to the server.
 160      *
 161      * This method is either called on an unconnected SSLSocketImpl by the
 162      * application, or it is called in the constructor of a regular
 163      * SSLSocketImpl. If we are layering on top on another socket, then
 164      * this method should not be called, because we assume that the
 165      * underlying socket is already connected by the time it is passed to
 166      * us.
 167      *
 168      * @param   endpoint the <code>SocketAddress</code>
 169      * @throws  IOException if an error occurs during the connection
 170      */
 171     @Override
 172     public final void connect(SocketAddress endpoint) throws IOException {
 173         connect(endpoint, 0);
 174     }
 175 
 176     /**
 177      * Returns the connection state of the socket.
 178      * @see java.net.Socket#isConnected
 179      */
 180     @Override
 181     public final boolean isConnected() {
 182         if (self == this) {
 183             return super.isConnected();
 184         } else {
 185             return self.isConnected();
 186         }
 187     }
 188 
 189     /**
 190      * Returns the binding state of the socket.
 191      * @see java.net.Socket#isBound
 192      */
 193     @Override
 194     public final boolean isBound() {
 195         if (self == this) {
 196             return super.isBound();
 197         } else {
 198             return self.isBound();
 199         }
 200     }
 201 
 202     //
 203     // CLOSE RELATED METHODS
 204     //
 205 
 206     /**
 207      * Places the input stream for this socket at "end of stream".  Any data
 208      * sent to the input stream side of the socket is acknowledged and then
 209      * silently discarded.
 210      *
 211      * @see java.net.Socket#shutdownInput
 212      */
 213     @Override
 214     public void shutdownInput() throws IOException {
 215         if (self == this) {
 216             super.shutdownInput();
 217         } else {
 218             self.shutdownInput();
 219         }
 220     }
 221 
 222     /**
 223      * Disables the output stream for this socket.  For a TCP socket, any
 224      * previously written data will be sent followed by TCP's normal
 225      * connection termination sequence.
 226      *
 227      * @see java.net.Socket#shutdownOutput
 228      */
 229     @Override
 230     public void shutdownOutput() throws IOException {
 231         if (self == this) {
 232             super.shutdownOutput();
 233         } else {
 234             self.shutdownOutput();
 235         }
 236     }
 237 
 238     /**
 239      * Returns the input state of the socket
 240      * @see java.net.Socket#isInputShutdown
 241      */
 242     @Override
 243     public boolean isInputShutdown() {
 244         if (self == this) {
 245             return super.isInputShutdown();
 246         } else {
 247             return self.isInputShutdown();
 248         }
 249     }
 250 
 251     /**
 252      * Returns the output state of the socket
 253      * @see java.net.Socket#isOutputShutdown
 254      */
 255     @Override
 256     public boolean isOutputShutdown() {
 257         if (self == this) {
 258             return super.isOutputShutdown();
 259         } else {
 260             return self.isOutputShutdown();
 261         }
 262     }
 263 
 264     /**
 265      * Ensures that the SSL connection is closed down as cleanly
 266      * as possible, in case the application forgets to do so.
 267      * This allows SSL connections to be implicitly reclaimed,
 268      * rather than forcing them to be explicitly reclaimed at
 269      * the penalty of prematurly killing SSL sessions.
 270      */
 271     @Override
 272     @SuppressWarnings("deprecation")
 273     protected final void finalize() throws Throwable {
 274         try {
 275             close();
 276         } catch (IOException e1) {
 277             try {
 278                 if (self == this) {
 279                     super.close();
 280                 }
 281             } catch (IOException e2) {
 282                 // ignore
 283             }
 284         } finally {
 285             // We called close on the underlying socket above to
 286             // make doubly sure all resources got released.  We
 287             // don't finalize self in the case of overlain sockets,
 288             // that's a different object which the GC will finalize
 289             // separately.
 290 
 291             super.finalize();
 292         }
 293     }
 294 
 295     //
 296     // GET ADDRESS METHODS
 297     //
 298 
 299     /**
 300      * Returns the address of the remote peer for this connection.
 301      */
 302     @Override
 303     public final InetAddress getInetAddress() {
 304         if (self == this) {
 305             return super.getInetAddress();
 306         } else {
 307             return self.getInetAddress();
 308         }
 309     }
 310 
 311     /**
 312      * Gets the local address to which the socket is bound.
 313      *
 314      * @return the local address to which the socket is bound.
 315      * @since   1.1
 316      */
 317     @Override
 318     public final InetAddress getLocalAddress() {
 319         if (self == this) {
 320             return super.getLocalAddress();
 321         } else {
 322             return self.getLocalAddress();
 323         }
 324     }
 325 
 326     /**
 327      * Returns the number of the remote port that this connection uses.
 328      */
 329     @Override
 330     public final int getPort() {
 331         if (self == this) {
 332             return super.getPort();
 333         } else {
 334             return self.getPort();
 335         }
 336     }
 337 
 338     /**
 339      * Returns the number of the local port that this connection uses.
 340      */
 341     @Override
 342     public final int getLocalPort() {
 343         if (self == this) {
 344             return super.getLocalPort();
 345         } else {
 346             return self.getLocalPort();
 347         }
 348     }
 349 
 350     //
 351     // SOCKET OPTION METHODS
 352     //
 353 
 354     /**
 355      * Enables or disables the Nagle optimization.
 356      * @see java.net.Socket#setTcpNoDelay
 357      */
 358     @Override
 359     public final void setTcpNoDelay(boolean value) throws SocketException {
 360         if (self == this) {
 361             super.setTcpNoDelay(value);
 362         } else {
 363             self.setTcpNoDelay(value);
 364         }
 365     }
 366 
 367     /**
 368      * Returns true if the Nagle optimization is disabled.  This
 369      * relates to low-level buffering of TCP traffic, delaying the
 370      * traffic to promote better throughput.
 371      *
 372      * @see java.net.Socket#getTcpNoDelay
 373      */
 374     @Override
 375     public final boolean getTcpNoDelay() throws SocketException {
 376         if (self == this) {
 377             return super.getTcpNoDelay();
 378         } else {
 379             return self.getTcpNoDelay();
 380         }
 381     }
 382 
 383     /**
 384      * Assigns the socket's linger timeout.
 385      * @see java.net.Socket#setSoLinger
 386      */
 387     @Override
 388     public final void setSoLinger(boolean flag, int linger)
 389             throws SocketException {
 390         if (self == this) {
 391             super.setSoLinger(flag, linger);
 392         } else {
 393             self.setSoLinger(flag, linger);
 394         }
 395     }
 396 
 397     /**
 398      * Returns the socket's linger timeout.
 399      * @see java.net.Socket#getSoLinger
 400      */
 401     @Override
 402     public final int getSoLinger() throws SocketException {
 403         if (self == this) {
 404             return super.getSoLinger();
 405         } else {
 406             return self.getSoLinger();
 407         }
 408     }
 409 
 410     /**
 411      * Send one byte of urgent data on the socket.
 412      * @see java.net.Socket#sendUrgentData
 413      * At this point, there seems to be no specific requirement to support
 414      * this for an SSLSocket. An implementation can be provided if a need
 415      * arises in future.
 416      */
 417     @Override
 418     public final void sendUrgentData(int data) throws SocketException {
 419         throw new SocketException("This method is not supported "
 420                         + "by SSLSockets");
 421     }
 422 
 423     /**
 424      * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
 425      * option is disabled and TCP urgent data received on a socket is silently
 426      * discarded.
 427      * @see java.net.Socket#setOOBInline
 428      * Setting OOBInline does not have any effect on SSLSocket,
 429      * since currently we don't support sending urgent data.
 430      */
 431     @Override
 432     public final void setOOBInline(boolean on) throws SocketException {
 433         throw new SocketException("This method is ineffective, since"
 434                 + " sending urgent data is not supported by SSLSockets");
 435     }
 436 
 437     /**
 438      * Tests if OOBINLINE is enabled.
 439      * @see java.net.Socket#getOOBInline
 440      */
 441     @Override
 442     public final boolean getOOBInline() throws SocketException {
 443         throw new SocketException("This method is ineffective, since"
 444                 + " sending urgent data is not supported by SSLSockets");
 445     }
 446 
 447     /**
 448      * Returns the socket timeout.
 449      * @see java.net.Socket#getSoTimeout
 450      */
 451     @Override
 452     public final int getSoTimeout() throws SocketException {
 453         if (self == this) {
 454             return super.getSoTimeout();
 455         } else {
 456             return self.getSoTimeout();
 457         }
 458     }
 459 
 460     @Override
 461     public final void setSendBufferSize(int size) throws SocketException {
 462         if (self == this) {
 463             super.setSendBufferSize(size);
 464         } else {
 465             self.setSendBufferSize(size);
 466         }
 467     }
 468 
 469     @Override
 470     public final int getSendBufferSize() throws SocketException {
 471         if (self == this) {
 472             return super.getSendBufferSize();
 473         } else {
 474             return self.getSendBufferSize();
 475         }
 476     }
 477 
 478     @Override
 479     public final void setReceiveBufferSize(int size) throws SocketException {
 480         if (self == this) {
 481             super.setReceiveBufferSize(size);
 482         } else {
 483             self.setReceiveBufferSize(size);
 484         }
 485     }
 486 
 487     @Override
 488     public final int getReceiveBufferSize() throws SocketException {
 489         if (self == this) {
 490             return super.getReceiveBufferSize();
 491         } else {
 492             return self.getReceiveBufferSize();
 493         }
 494     }
 495 
 496     /**
 497      * Enable/disable SO_KEEPALIVE.
 498      * @see java.net.Socket#setKeepAlive
 499      */
 500     @Override
 501     public final void setKeepAlive(boolean on) throws SocketException {
 502         if (self == this) {
 503             super.setKeepAlive(on);
 504         } else {
 505             self.setKeepAlive(on);
 506         }
 507     }
 508 
 509     /**
 510      * Tests if SO_KEEPALIVE is enabled.
 511      * @see java.net.Socket#getKeepAlive
 512      */
 513     @Override
 514     public final boolean getKeepAlive() throws SocketException {
 515         if (self == this) {
 516             return super.getKeepAlive();
 517         } else {
 518             return self.getKeepAlive();
 519         }
 520     }
 521 
 522     /**
 523      * Sets traffic class or type-of-service octet in the IP header for
 524      * packets sent from this Socket.
 525      * @see java.net.Socket#setTrafficClass
 526      */
 527     @Override
 528     public final void setTrafficClass(int tc) throws SocketException {
 529         if (self == this) {
 530             super.setTrafficClass(tc);
 531         } else {
 532             self.setTrafficClass(tc);
 533         }
 534     }
 535 
 536     /**
 537      * Gets traffic class or type-of-service in the IP header for packets
 538      * sent from this Socket.
 539      * @see java.net.Socket#getTrafficClass
 540      */
 541     @Override
 542     public final int getTrafficClass() throws SocketException {
 543         if (self == this) {
 544             return super.getTrafficClass();
 545         } else {
 546             return self.getTrafficClass();
 547         }
 548     }
 549 
 550     /**
 551      * Enable/disable SO_REUSEADDR.
 552      * @see java.net.Socket#setReuseAddress
 553      */
 554     @Override
 555     public final void setReuseAddress(boolean on) throws SocketException {
 556         if (self == this) {
 557             super.setReuseAddress(on);
 558         } else {
 559             self.setReuseAddress(on);
 560         }
 561     }
 562 
 563     /**
 564      * Tests if SO_REUSEADDR is enabled.
 565      * @see java.net.Socket#getReuseAddress
 566      */
 567     @Override
 568     public final boolean getReuseAddress() throws SocketException {
 569         if (self == this) {
 570             return super.getReuseAddress();
 571         } else {
 572             return self.getReuseAddress();
 573         }
 574     }
 575 
 576     /**
 577      * Sets performance preferences for this socket.
 578      *
 579      * @see java.net.Socket#setPerformancePreferences(int, int, int)
 580      */
 581     @Override
 582     public void setPerformancePreferences(int connectionTime,
 583             int latency, int bandwidth) {
 584         if (self == this) {
 585             super.setPerformancePreferences(
 586                 connectionTime, latency, bandwidth);
 587         } else {
 588             self.setPerformancePreferences(
 589                 connectionTime, latency, bandwidth);
 590         }
 591     }
 592 
 593     @Override
 594     public String toString() {
 595         if (self == this) {
 596             return super.toString();
 597         }
 598 
 599         return self.toString();
 600     }
 601 
 602     @Override
 603     public InputStream getInputStream() throws IOException {
 604         if (self == this) {
 605             return super.getInputStream();
 606         }
 607 
 608         if (consumedInput != null) {
 609             return new SequenceInputStream(consumedInput,
 610                                                 self.getInputStream());
 611         }
 612 
 613         return self.getInputStream();
 614     }
 615 
 616     @Override
 617     public OutputStream getOutputStream() throws IOException {
 618         if (self == this) {
 619             return super.getOutputStream();
 620         }
 621 
 622         return self.getOutputStream();
 623     }
 624 
 625     @Override
 626     public void close() throws IOException {
 627         if (self == this) {
 628             super.close();
 629         } else {
 630             self.close();
 631         }
 632     }
 633 
 634     @Override
 635     public void setSoTimeout(int timeout) throws SocketException {
 636         if (self == this) {
 637             super.setSoTimeout(timeout);
 638         } else {
 639             self.setSoTimeout(timeout);
 640         }
 641     }
 642 
 643     @Override
 644     public <T> Socket setOption(SocketOption<T> name,
 645             T value) throws IOException {
 646         if (self == this) {
 647             return super.setOption(name, value);
 648         } else {
 649             return self.setOption(name, value);
 650         }
 651     }
 652 
 653     @Override
 654     public <T> T getOption(SocketOption<T> name) throws IOException {
 655         if (self == this) {
 656             return super.getOption(name);
 657         } else {
 658             return self.getOption(name);
 659         }
 660     }
 661 
 662     @Override
 663     public Set<SocketOption<?>> supportedOptions() {
 664         if (self == this) {
 665             return super.supportedOptions();
 666         } else {
 667             return self.supportedOptions();
 668         }
 669     }
 670 
 671     boolean isLayered() {
 672         return (self != this);
 673     }
 674 }