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 }