1 /*
   2  * Copyright (c) 2002, 2012, 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     final private Socket self;
  59     final private 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 final static String PROP_NAME =
  92                                 "com.sun.net.ssl.requireCloseNotify";
  93 
  94     final static 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     protected final void finalize() throws Throwable {
 269         try {
 270             close();
 271         } catch (IOException e1) {
 272             try {
 273                 if (self == this) {
 274                     super.close();
 275                 }
 276             } catch (IOException e2) {
 277                 // ignore
 278             }
 279         } finally {
 280             // We called close on the underlying socket above to
 281             // make doubly sure all resources got released.  We
 282             // don't finalize self in the case of overlain sockets,
 283             // that's a different object which the GC will finalize
 284             // separately.
 285 
 286             super.finalize();
 287         }
 288     }
 289 
 290     //
 291     // GET ADDRESS METHODS
 292     //
 293 
 294     /**
 295      * Returns the address of the remote peer for this connection.
 296      */
 297     @Override
 298     public final InetAddress getInetAddress() {
 299         if (self == this) {
 300             return super.getInetAddress();
 301         } else {
 302             return self.getInetAddress();
 303         }
 304     }
 305 
 306     /**
 307      * Gets the local address to which the socket is bound.
 308      *
 309      * @return the local address to which the socket is bound.
 310      * @since   JDK1.1
 311      */
 312     @Override
 313     public final InetAddress getLocalAddress() {
 314         if (self == this) {
 315             return super.getLocalAddress();
 316         } else {
 317             return self.getLocalAddress();
 318         }
 319     }
 320 
 321     /**
 322      * Returns the number of the remote port that this connection uses.
 323      */
 324     @Override
 325     public final int getPort() {
 326         if (self == this) {
 327             return super.getPort();
 328         } else {
 329             return self.getPort();
 330         }
 331     }
 332 
 333     /**
 334      * Returns the number of the local port that this connection uses.
 335      */
 336     @Override
 337     public final int getLocalPort() {
 338         if (self == this) {
 339             return super.getLocalPort();
 340         } else {
 341             return self.getLocalPort();
 342         }
 343     }
 344 
 345     //
 346     // SOCKET OPTION METHODS
 347     //
 348 
 349     /**
 350      * Enables or disables the Nagle optimization.
 351      * @see java.net.Socket#setTcpNoDelay
 352      */
 353     @Override
 354     public final void setTcpNoDelay(boolean value) throws SocketException {
 355         if (self == this) {
 356             super.setTcpNoDelay(value);
 357         } else {
 358             self.setTcpNoDelay(value);
 359         }
 360     }
 361 
 362     /**
 363      * Returns true if the Nagle optimization is disabled.  This
 364      * relates to low-level buffering of TCP traffic, delaying the
 365      * traffic to promote better throughput.
 366      *
 367      * @see java.net.Socket#getTcpNoDelay
 368      */
 369     @Override
 370     public final boolean getTcpNoDelay() throws SocketException {
 371         if (self == this) {
 372             return super.getTcpNoDelay();
 373         } else {
 374             return self.getTcpNoDelay();
 375         }
 376     }
 377 
 378     /**
 379      * Assigns the socket's linger timeout.
 380      * @see java.net.Socket#setSoLinger
 381      */
 382     @Override
 383     public final void setSoLinger(boolean flag, int linger)
 384             throws SocketException {
 385         if (self == this) {
 386             super.setSoLinger(flag, linger);
 387         } else {
 388             self.setSoLinger(flag, linger);
 389         }
 390     }
 391 
 392     /**
 393      * Returns the socket's linger timeout.
 394      * @see java.net.Socket#getSoLinger
 395      */
 396     @Override
 397     public final int getSoLinger() throws SocketException {
 398         if (self == this) {
 399             return super.getSoLinger();
 400         } else {
 401             return self.getSoLinger();
 402         }
 403     }
 404 
 405     /**
 406      * Send one byte of urgent data on the socket.
 407      * @see java.net.Socket#sendUrgentData
 408      * At this point, there seems to be no specific requirement to support
 409      * this for an SSLSocket. An implementation can be provided if a need
 410      * arises in future.
 411      */
 412     @Override
 413     public final void sendUrgentData(int data) throws SocketException {
 414         throw new SocketException("This method is not supported "
 415                         + "by SSLSockets");
 416     }
 417 
 418     /**
 419      * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
 420      * option is disabled and TCP urgent data received on a socket is silently
 421      * discarded.
 422      * @see java.net.Socket#setOOBInline
 423      * Setting OOBInline does not have any effect on SSLSocket,
 424      * since currently we don't support sending urgent data.
 425      */
 426     @Override
 427     public final void setOOBInline(boolean on) throws SocketException {
 428         throw new SocketException("This method is ineffective, since"
 429                 + " sending urgent data is not supported by SSLSockets");
 430     }
 431 
 432     /**
 433      * Tests if OOBINLINE is enabled.
 434      * @see java.net.Socket#getOOBInline
 435      */
 436     @Override
 437     public final boolean getOOBInline() throws SocketException {
 438         throw new SocketException("This method is ineffective, since"
 439                 + " sending urgent data is not supported by SSLSockets");
 440     }
 441 
 442     /**
 443      * Returns the socket timeout.
 444      * @see java.net.Socket#getSoTimeout
 445      */
 446     @Override
 447     public final int getSoTimeout() throws SocketException {
 448         if (self == this) {
 449             return super.getSoTimeout();
 450         } else {
 451             return self.getSoTimeout();
 452         }
 453     }
 454 
 455     @Override
 456     public final void setSendBufferSize(int size) throws SocketException {
 457         if (self == this) {
 458             super.setSendBufferSize(size);
 459         } else {
 460             self.setSendBufferSize(size);
 461         }
 462     }
 463 
 464     @Override
 465     public final int getSendBufferSize() throws SocketException {
 466         if (self == this) {
 467             return super.getSendBufferSize();
 468         } else {
 469             return self.getSendBufferSize();
 470         }
 471     }
 472 
 473     @Override
 474     public final void setReceiveBufferSize(int size) throws SocketException {
 475         if (self == this) {
 476             super.setReceiveBufferSize(size);
 477         } else {
 478             self.setReceiveBufferSize(size);
 479         }
 480     }
 481 
 482     @Override
 483     public final int getReceiveBufferSize() throws SocketException {
 484         if (self == this) {
 485             return super.getReceiveBufferSize();
 486         } else {
 487             return self.getReceiveBufferSize();
 488         }
 489     }
 490 
 491     /**
 492      * Enable/disable SO_KEEPALIVE.
 493      * @see java.net.Socket#setKeepAlive
 494      */
 495     @Override
 496     public final void setKeepAlive(boolean on) throws SocketException {
 497         if (self == this) {
 498             super.setKeepAlive(on);
 499         } else {
 500             self.setKeepAlive(on);
 501         }
 502     }
 503 
 504     /**
 505      * Tests if SO_KEEPALIVE is enabled.
 506      * @see java.net.Socket#getKeepAlive
 507      */
 508     @Override
 509     public final boolean getKeepAlive() throws SocketException {
 510         if (self == this) {
 511             return super.getKeepAlive();
 512         } else {
 513             return self.getKeepAlive();
 514         }
 515     }
 516 
 517     /**
 518      * Sets traffic class or type-of-service octet in the IP header for
 519      * packets sent from this Socket.
 520      * @see java.net.Socket#setTrafficClass
 521      */
 522     @Override
 523     public final void setTrafficClass(int tc) throws SocketException {
 524         if (self == this) {
 525             super.setTrafficClass(tc);
 526         } else {
 527             self.setTrafficClass(tc);
 528         }
 529     }
 530 
 531     /**
 532      * Gets traffic class or type-of-service in the IP header for packets
 533      * sent from this Socket.
 534      * @see java.net.Socket#getTrafficClass
 535      */
 536     @Override
 537     public final int getTrafficClass() throws SocketException {
 538         if (self == this) {
 539             return super.getTrafficClass();
 540         } else {
 541             return self.getTrafficClass();
 542         }
 543     }
 544 
 545     /**
 546      * Enable/disable SO_REUSEADDR.
 547      * @see java.net.Socket#setReuseAddress
 548      */
 549     @Override
 550     public final void setReuseAddress(boolean on) throws SocketException {
 551         if (self == this) {
 552             super.setReuseAddress(on);
 553         } else {
 554             self.setReuseAddress(on);
 555         }
 556     }
 557 
 558     /**
 559      * Tests if SO_REUSEADDR is enabled.
 560      * @see java.net.Socket#getReuseAddress
 561      */
 562     @Override
 563     public final boolean getReuseAddress() throws SocketException {
 564         if (self == this) {
 565             return super.getReuseAddress();
 566         } else {
 567             return self.getReuseAddress();
 568         }
 569     }
 570 
 571     /**
 572      * Sets performance preferences for this socket.
 573      *
 574      * @see java.net.Socket#setPerformancePreferences(int, int, int)
 575      */
 576     @Override
 577     public void setPerformancePreferences(int connectionTime,
 578             int latency, int bandwidth) {
 579         if (self == this) {
 580             super.setPerformancePreferences(
 581                 connectionTime, latency, bandwidth);
 582         } else {
 583             self.setPerformancePreferences(
 584                 connectionTime, latency, bandwidth);
 585         }
 586     }
 587 
 588     @Override
 589     public String toString() {
 590         if (self == this) {
 591             return super.toString();
 592         }
 593 
 594         return self.toString();
 595     }
 596 
 597     @Override
 598     public InputStream getInputStream() throws IOException {
 599         if (self == this) {
 600             return super.getInputStream();
 601         }
 602 
 603         if (consumedInput != null) {
 604             return new SequenceInputStream(consumedInput,
 605                                                 self.getInputStream());
 606         }
 607 
 608         return self.getInputStream();
 609     }
 610 
 611     @Override
 612     public OutputStream getOutputStream() throws IOException {
 613         if (self == this) {
 614             return super.getOutputStream();
 615         }
 616 
 617         return self.getOutputStream();
 618     }
 619 
 620     @Override
 621     public synchronized void close() throws IOException {
 622         if (self == this) {
 623             super.close();
 624         } else {
 625             self.close();
 626         }
 627     }
 628 
 629     @Override
 630     public synchronized void setSoTimeout(int timeout) throws SocketException {
 631         if (self == this) {
 632             super.setSoTimeout(timeout);
 633         } else {
 634             self.setSoTimeout(timeout);
 635         }
 636     }
 637 
 638     @Override
 639     public <T> Socket setOption(SocketOption<T> name,
 640             T value) throws IOException {
 641         if (self == this) {
 642             return super.setOption(name, value);
 643         } else {
 644             return self.setOption(name, value);
 645         }
 646     }
 647 
 648     @Override
 649     public <T> T getOption(SocketOption<T> name) throws IOException {
 650         if (self == this) {
 651             return super.getOption(name);
 652         } else {
 653             return self.getOption(name);
 654         }
 655     }
 656 
 657     @Override
 658     public Set<SocketOption<?>> supportedOptions() {
 659         if (self == this) {
 660             return super.supportedOptions();
 661         } else {
 662             return self.supportedOptions();
 663         }
 664     }
 665 
 666     boolean isLayered() {
 667         return (self != this);
 668     }
 669 }