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