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
26package sun.security.ssl;
27
28import java.io.*;
29import java.nio.channels.SocketChannel;
30import java.net.*;
31import java.util.Set;
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    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}
671