BaseSSLSocketImpl.java revision 12745:f068a4ffddd2
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
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    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   1.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}
670