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 }