1/* 2 * Copyright (c) 2002, 2008, 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 27package sun.security.ssl; 28 29import java.io.*; 30import java.nio.channels.SocketChannel; 31import java.net.*; 32 33import 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 */ 48abstract 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 Socket self; 59 60 BaseSSLSocketImpl() { 61 super(); 62 this.self = this; 63 } 64 65 BaseSSLSocketImpl(Socket socket) { 66 super(); 67 this.self = socket; 68 } 69 70 // 71 // CONSTANTS AND STATIC METHODS 72 // 73 74 /** 75 * TLS requires that a close_notify warning alert is sent before the 76 * connection is closed in order to avoid truncation attacks. Some 77 * implementations (MS IIS and others) don't do that. The property 78 * below controls whether we accept that or treat it as an error. 79 * 80 * The default is "false", i.e. tolerate the broken behavior. 81 */ 82 private final static String PROP_NAME = 83 "com.sun.net.ssl.requireCloseNotify"; 84 85 final static boolean requireCloseNotify = 86 Debug.getBooleanProperty(PROP_NAME, false); 87 88 // 89 // MISC SOCKET METHODS 90 // 91 92 /** 93 * Returns the unique {@link java.nio.SocketChannel SocketChannel} object 94 * associated with this socket, if any. 95 * @see java.net.Socket#getChannel 96 */ 97 public final SocketChannel getChannel() { 98 if (self == this) { 99 return super.getChannel(); 100 } else { 101 return self.getChannel(); 102 } 103 } 104 105 /** 106 * Binds the address to the socket. 107 * @see java.net.Socket#bind 108 */ 109 public void bind(SocketAddress bindpoint) throws IOException { 110 /* 111 * Bind to this socket 112 */ 113 if (self == this) { 114 super.bind(bindpoint); 115 } else { 116 // If we're binding on a layered socket... 117 throw new IOException( 118 "Underlying socket should already be connected"); 119 } 120 } 121 122 /** 123 * Returns the address of the endpoint this socket is connected to 124 * @see java.net.Socket#getLocalSocketAddress 125 */ 126 public SocketAddress getLocalSocketAddress() { 127 if (self == this) { 128 return super.getLocalSocketAddress(); 129 } else { 130 return self.getLocalSocketAddress(); 131 } 132 } 133 134 /** 135 * Returns the address of the endpoint this socket is connected to 136 * @see java.net.Socket#getRemoteSocketAddress 137 */ 138 public SocketAddress getRemoteSocketAddress() { 139 if (self == this) { 140 return super.getRemoteSocketAddress(); 141 } else { 142 return self.getRemoteSocketAddress(); 143 } 144 } 145 146 /** 147 * Connects this socket to the server. 148 * 149 * This method is either called on an unconnected SSLSocketImpl by the 150 * application, or it is called in the constructor of a regular 151 * SSLSocketImpl. If we are layering on top on another socket, then 152 * this method should not be called, because we assume that the 153 * underlying socket is already connected by the time it is passed to 154 * us. 155 * 156 * @param endpoint the <code>SocketAddress</code> 157 * @throws IOException if an error occurs during the connection 158 */ 159 public final void connect(SocketAddress endpoint) throws IOException { 160 connect(endpoint, 0); 161 } 162 163 /** 164 * Returns the connection state of the socket. 165 * @see java.net.Socket#isConnected 166 */ 167 public final boolean isConnected() { 168 if (self == this) { 169 return super.isConnected(); 170 } else { 171 return self.isConnected(); 172 } 173 } 174 175 /** 176 * Returns the binding state of the socket. 177 * @see java.net.Socket#isBound 178 */ 179 public final boolean isBound() { 180 if (self == this) { 181 return super.isBound(); 182 } else { 183 return self.isBound(); 184 } 185 } 186 187 // 188 // CLOSE RELATED METHODS 189 // 190 191 /** 192 * The semantics of shutdownInput is not supported in TLS 1.0 193 * spec. Thus when the method is called on an SSL socket, an 194 * UnsupportedOperationException will be thrown. 195 * 196 * @throws UnsupportedOperationException 197 */ 198 public final void shutdownInput() throws IOException { 199 throw new UnsupportedOperationException("The method shutdownInput()" + 200 " is not supported in SSLSocket"); 201 } 202 203 /** 204 * The semantics of shutdownOutput is not supported in TLS 1.0 205 * spec. Thus when the method is called on an SSL socket, an 206 * UnsupportedOperationException will be thrown. 207 * 208 * @throws UnsupportedOperationException 209 */ 210 public final void shutdownOutput() throws IOException { 211 throw new UnsupportedOperationException("The method shutdownOutput()" + 212 " is not supported in SSLSocket"); 213 214 } 215 216 /** 217 * Returns the input state of the socket 218 * @see java.net.Socket#isInputShutdown 219 */ 220 public final boolean isInputShutdown() { 221 if (self == this) { 222 return super.isInputShutdown(); 223 } else { 224 return self.isInputShutdown(); 225 } 226 } 227 228 /** 229 * Returns the output state of the socket 230 * @see java.net.Socket#isOutputShutdown 231 */ 232 public final boolean isOutputShutdown() { 233 if (self == this) { 234 return super.isOutputShutdown(); 235 } else { 236 return self.isOutputShutdown(); 237 } 238 } 239 240 /** 241 * Ensures that the SSL connection is closed down as cleanly 242 * as possible, in case the application forgets to do so. 243 * This allows SSL connections to be implicitly reclaimed, 244 * rather than forcing them to be explicitly reclaimed at 245 * the penalty of prematurly killing SSL sessions. 246 */ 247 protected final void finalize() throws Throwable { 248 try { 249 close(); 250 } catch (IOException e1) { 251 try { 252 if (self == this) { 253 super.close(); 254 } 255 } catch (IOException e2) { 256 // ignore 257 } 258 } finally { 259 // We called close on the underlying socket above to 260 // make doubly sure all resources got released. We 261 // don't finalize self in the case of overlain sockets, 262 // that's a different object which the GC will finalize 263 // separately. 264 265 super.finalize(); 266 } 267 } 268 269 // 270 // GET ADDRESS METHODS 271 // 272 273 /** 274 * Returns the address of the remote peer for this connection. 275 */ 276 public final InetAddress getInetAddress() { 277 if (self == this) { 278 return super.getInetAddress(); 279 } else { 280 return self.getInetAddress(); 281 } 282 } 283 284 /** 285 * Gets the local address to which the socket is bound. 286 * 287 * @return the local address to which the socket is bound. 288 * @since JDK1.1 289 */ 290 public final InetAddress getLocalAddress() { 291 if (self == this) { 292 return super.getLocalAddress(); 293 } else { 294 return self.getLocalAddress(); 295 } 296 } 297 298 /** 299 * Returns the number of the remote port that this connection uses. 300 */ 301 public final int getPort() { 302 if (self == this) { 303 return super.getPort(); 304 } else { 305 return self.getPort(); 306 } 307 } 308 309 /** 310 * Returns the number of the local port that this connection uses. 311 */ 312 public final int getLocalPort() { 313 if (self == this) { 314 return super.getLocalPort(); 315 } else { 316 return self.getLocalPort(); 317 } 318 } 319 320 // 321 // SOCKET OPTION METHODS 322 // 323 324 /** 325 * Enables or disables the Nagle optimization. 326 * @see java.net.Socket#setTcpNoDelay 327 */ 328 public final void setTcpNoDelay(boolean value) throws SocketException { 329 if (self == this) { 330 super.setTcpNoDelay(value); 331 } else { 332 self.setTcpNoDelay(value); 333 } 334 } 335 336 /** 337 * Returns true if the Nagle optimization is disabled. This 338 * relates to low-level buffering of TCP traffic, delaying the 339 * traffic to promote better throughput. 340 * 341 * @see java.net.Socket#getTcpNoDelay 342 */ 343 public final boolean getTcpNoDelay() throws SocketException { 344 if (self == this) { 345 return super.getTcpNoDelay(); 346 } else { 347 return self.getTcpNoDelay(); 348 } 349 } 350 351 /** 352 * Assigns the socket's linger timeout. 353 * @see java.net.Socket#setSoLinger 354 */ 355 public final void setSoLinger(boolean flag, int linger) 356 throws SocketException { 357 if (self == this) { 358 super.setSoLinger(flag, linger); 359 } else { 360 self.setSoLinger(flag, linger); 361 } 362 } 363 364 /** 365 * Returns the socket's linger timeout. 366 * @see java.net.Socket#getSoLinger 367 */ 368 public final int getSoLinger() throws SocketException { 369 if (self == this) { 370 return super.getSoLinger(); 371 } else { 372 return self.getSoLinger(); 373 } 374 } 375 376 /** 377 * Send one byte of urgent data on the socket. 378 * @see java.net.Socket#sendUrgentData 379 * At this point, there seems to be no specific requirement to support 380 * this for an SSLSocket. An implementation can be provided if a need 381 * arises in future. 382 */ 383 public final void sendUrgentData(int data) throws SocketException { 384 throw new SocketException("This method is not supported " 385 + "by SSLSockets"); 386 } 387 388 /** 389 * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this 390 * option is disabled and TCP urgent data received on a socket is silently 391 * discarded. 392 * @see java.net.Socket#setOOBInline 393 * Setting OOBInline does not have any effect on SSLSocket, 394 * since currently we don't support sending urgent data. 395 */ 396 public final void setOOBInline(boolean on) throws SocketException { 397 throw new SocketException("This method is ineffective, since" 398 + " sending urgent data is not supported by SSLSockets"); 399 } 400 401 /** 402 * Tests if OOBINLINE is enabled. 403 * @see java.net.Socket#getOOBInline 404 */ 405 public final boolean getOOBInline() throws SocketException { 406 throw new SocketException("This method is ineffective, since" 407 + " sending urgent data is not supported by SSLSockets"); 408 } 409 410 /** 411 * Returns the socket timeout. 412 * @see java.net.Socket#getSoTimeout 413 */ 414 public final int getSoTimeout() throws SocketException { 415 if (self == this) { 416 return super.getSoTimeout(); 417 } else { 418 return self.getSoTimeout(); 419 } 420 } 421 422 public final void setSendBufferSize(int size) throws SocketException { 423 if (self == this) { 424 super.setSendBufferSize(size); 425 } else { 426 self.setSendBufferSize(size); 427 } 428 } 429 430 public final int getSendBufferSize() throws SocketException { 431 if (self == this) { 432 return super.getSendBufferSize(); 433 } else { 434 return self.getSendBufferSize(); 435 } 436 } 437 438 public final void setReceiveBufferSize(int size) throws SocketException { 439 if (self == this) { 440 super.setReceiveBufferSize(size); 441 } else { 442 self.setReceiveBufferSize(size); 443 } 444 } 445 446 public final int getReceiveBufferSize() throws SocketException { 447 if (self == this) { 448 return super.getReceiveBufferSize(); 449 } else { 450 return self.getReceiveBufferSize(); 451 } 452 } 453 454 /** 455 * Enable/disable SO_KEEPALIVE. 456 * @see java.net.Socket#setKeepAlive 457 */ 458 public final void setKeepAlive(boolean on) throws SocketException { 459 if (self == this) { 460 super.setKeepAlive(on); 461 } else { 462 self.setKeepAlive(on); 463 } 464 } 465 466 /** 467 * Tests if SO_KEEPALIVE is enabled. 468 * @see java.net.Socket#getKeepAlive 469 */ 470 public final boolean getKeepAlive() throws SocketException { 471 if (self == this) { 472 return super.getKeepAlive(); 473 } else { 474 return self.getKeepAlive(); 475 } 476 } 477 478 /** 479 * Sets traffic class or type-of-service octet in the IP header for 480 * packets sent from this Socket. 481 * @see java.net.Socket#setTrafficClass 482 */ 483 public final void setTrafficClass(int tc) throws SocketException { 484 if (self == this) { 485 super.setTrafficClass(tc); 486 } else { 487 self.setTrafficClass(tc); 488 } 489 } 490 491 /** 492 * Gets traffic class or type-of-service in the IP header for packets 493 * sent from this Socket. 494 * @see java.net.Socket#getTrafficClass 495 */ 496 public final int getTrafficClass() throws SocketException { 497 if (self == this) { 498 return super.getTrafficClass(); 499 } else { 500 return self.getTrafficClass(); 501 } 502 } 503 504 /** 505 * Enable/disable SO_REUSEADDR. 506 * @see java.net.Socket#setReuseAddress 507 */ 508 public final void setReuseAddress(boolean on) throws SocketException { 509 if (self == this) { 510 super.setReuseAddress(on); 511 } else { 512 self.setReuseAddress(on); 513 } 514 } 515 516 /** 517 * Tests if SO_REUSEADDR is enabled. 518 * @see java.net.Socket#getReuseAddress 519 */ 520 public final boolean getReuseAddress() throws SocketException { 521 if (self == this) { 522 return super.getReuseAddress(); 523 } else { 524 return self.getReuseAddress(); 525 } 526 } 527 528 /** 529 * Sets performance preferences for this socket. 530 * 531 * @see java.net.Socket#setPerformancePreferences(int, int, int) 532 */ 533 public void setPerformancePreferences(int connectionTime, 534 int latency, int bandwidth) { 535 if (self == this) { 536 super.setPerformancePreferences( 537 connectionTime, latency, bandwidth); 538 } else { 539 self.setPerformancePreferences( 540 connectionTime, latency, bandwidth); 541 } 542 } 543 544} 545