1 /* 2 * Copyright (c) 2002, 2018, 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 BaseSSLSocketImpl()60 BaseSSLSocketImpl() { 61 super(); 62 this.self = this; 63 this.consumedInput = null; 64 } 65 BaseSSLSocketImpl(Socket socket)66 BaseSSLSocketImpl(Socket socket) { 67 super(); 68 this.self = socket; 69 this.consumedInput = null; 70 } 71 BaseSSLSocketImpl(Socket socket, InputStream consumed)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 getChannel()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 bind(SocketAddress bindpoint)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 getLocalSocketAddress()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 getRemoteSocketAddress()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 connect(SocketAddress endpoint)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 isConnected()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 isBound()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 shutdownInput()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 shutdownOutput()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 isInputShutdown()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 isOutputShutdown()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") finalize()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 getInetAddress()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 getLocalAddress()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 getPort()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 getLocalPort()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 setTcpNoDelay(boolean value)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 getTcpNoDelay()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 setSoLinger(boolean flag, int linger)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 getSoLinger()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 sendUrgentData(int data)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 setOOBInline(boolean on)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 getOOBInline()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 getSoTimeout()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 setSendBufferSize(int size)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 getSendBufferSize()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 setReceiveBufferSize(int size)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 getReceiveBufferSize()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 setKeepAlive(boolean on)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 getKeepAlive()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 setTrafficClass(int tc)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 getTrafficClass()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 setReuseAddress(boolean on)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 getReuseAddress()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 setPerformancePreferences(int connectionTime, int latency, int bandwidth)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 toString()594 public String toString() { 595 if (self == this) { 596 return super.toString(); 597 } 598 599 return self.toString(); 600 } 601 602 @Override getInputStream()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 getOutputStream()617 public OutputStream getOutputStream() throws IOException { 618 if (self == this) { 619 return super.getOutputStream(); 620 } 621 622 return self.getOutputStream(); 623 } 624 625 @Override close()626 public void close() throws IOException { 627 if (self == this) { 628 super.close(); 629 } else { 630 self.close(); 631 } 632 } 633 634 @Override setSoTimeout(int timeout)635 public synchronized 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 setOption(SocketOption<T> name, T value)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 getOption(SocketOption<T> name)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 supportedOptions()663 public Set<SocketOption<?>> supportedOptions() { 664 if (self == this) { 665 return super.supportedOptions(); 666 } else { 667 return self.supportedOptions(); 668 } 669 } 670 isLayered()671 boolean isLayered() { 672 return (self != this); 673 } 674 } 675