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