1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.net.ssl;
19
20import java.io.IOException;
21import java.net.InetAddress;
22import java.net.Socket;
23import java.net.UnknownHostException;
24
25/**
26 * The extension of {@code Socket} providing secure protocols like SSL (Secure
27 * Sockets Layer) or TLS (Transport Layer Security).
28 */
29public abstract class SSLSocket extends Socket {
30
31    /**
32     * Only to be used by subclasses.
33     * <p>
34     * Creates a TCP socket.
35     */
36    protected SSLSocket() {
37    }
38
39    /**
40     * Only to be used by subclasses.
41     * <p>
42     * Creates a TCP socket connection to the specified host at the specified
43     * port.
44     *
45     * @param host
46     *            the host name to connect to.
47     * @param port
48     *            the port number to connect to.
49     * @throws IOException
50     *             if creating the socket fails.
51     * @throws UnknownHostException
52     *             if the specified host is not known.
53     */
54    protected SSLSocket(String host, int port) throws IOException, UnknownHostException {
55        super(host, port);
56    }
57
58    /**
59     * Only to be used by subclasses.
60     * <p>
61     * Creates a TCP socket connection to the specified address at the specified
62     * port.
63     *
64     * @param address
65     *            the address to connect to.
66     * @param port
67     *            the port number to connect to.
68     * @throws IOException
69     *             if creating the socket fails.
70     */
71    protected SSLSocket(InetAddress address, int port) throws IOException {
72        super(address, port);
73    }
74
75    /**
76     * Only to be used by subclasses.
77     * <p>
78     * Creates a TCP socket connection to the specified host at the specified
79     * port with the client side bound to the specified address and port.
80     *
81     * @param host
82     *            the host name to connect to.
83     * @param port
84     *            the port number to connect to.
85     * @param clientAddress
86     *            the client address to bind to
87     * @param clientPort
88     *            the client port number to bind to.
89     * @throws IOException
90     *             if creating the socket fails.
91     * @throws UnknownHostException
92     *             if the specified host is not known.
93     */
94    protected SSLSocket(String host, int port, InetAddress clientAddress, int clientPort)
95            throws IOException, UnknownHostException {
96        super(host, port, clientAddress, clientPort);
97    }
98
99    /**
100     * Only to be used by subclasses.
101     * <p>
102     * Creates a TCP socket connection to the specified address at the specified
103     * port with the client side bound to the specified address and port.
104     *
105     * @param address
106     *            the address to connect to.
107     * @param port
108     *            the port number to connect to.
109     * @param clientAddress
110     *            the client address to bind to.
111     * @param clientPort
112     *            the client port number to bind to.
113     * @throws IOException
114     *             if creating the socket fails.
115     */
116    protected SSLSocket(InetAddress address, int port, InetAddress clientAddress, int clientPort)
117            throws IOException {
118        super(address, port, clientAddress, clientPort);
119    }
120
121    /**
122     * Unsupported for SSL because reading from an SSL socket may require
123     * writing to the network.
124     */
125    @Override public void shutdownInput() throws IOException {
126        throw new UnsupportedOperationException();
127    }
128
129    /**
130     * Unsupported for SSL because writing to an SSL socket may require reading
131     * from the network.
132     */
133    @Override public void shutdownOutput() throws IOException {
134        throw new UnsupportedOperationException();
135    }
136
137    /**
138     * Returns the names of the supported cipher suites.
139     */
140    public abstract String[] getSupportedCipherSuites();
141
142    /**
143     * Returns the names of the enabled cipher suites.
144     */
145    public abstract String[] getEnabledCipherSuites();
146
147    /**
148     * Sets the names of the cipher suites to be enabled.
149     * Only cipher suites returned by {@link #getSupportedCipherSuites()} are
150     * allowed.
151     *
152     * @param suites
153     *            the names of the to be enabled cipher suites.
154     * @throws IllegalArgumentException
155     *             if one of the cipher suite names is not supported.
156     */
157    public abstract void setEnabledCipherSuites(String[] suites);
158
159    /**
160     * Returns the names of the supported protocols.
161     */
162    public abstract String[] getSupportedProtocols();
163
164    /**
165     * Returns the names of the enabled protocols.
166     */
167    public abstract String[] getEnabledProtocols();
168
169    /**
170     * Sets the names of the protocols to be enabled. Only
171     * protocols returned by {@link #getSupportedProtocols()} are allowed.
172     *
173     * @param protocols
174     *            the names of the to be enabled protocols.
175     * @throws IllegalArgumentException
176     *             if one of the protocols is not supported.
177     */
178    public abstract void setEnabledProtocols(String[] protocols);
179
180    /**
181     * Returns the {@code SSLSession} for this connection. If necessary, a
182     * handshake will be initiated, in which case this method will block until the handshake
183     * has been established. If the handshake fails, an invalid session object
184     * will be returned.
185     *
186     * @return the session object.
187     */
188    public abstract SSLSession getSession();
189
190    /**
191     * Registers the specified listener to receive notification on completion of a
192     * handshake on this connection.
193     *
194     * @param listener
195     *            the listener to register.
196     * @throws IllegalArgumentException
197     *             if {@code listener} is {@code null}.
198     */
199    public abstract void addHandshakeCompletedListener(HandshakeCompletedListener listener);
200
201    /**
202     * Removes the specified handshake completion listener.
203     *
204     * @param listener
205     *            the listener to remove.
206     * @throws IllegalArgumentException
207     *             if the specified listener is not registered or {@code null}.
208     */
209    public abstract void removeHandshakeCompletedListener(HandshakeCompletedListener listener);
210
211    /**
212     * Starts a new SSL handshake on this connection.
213     *
214     * @throws IOException
215     *             if an error occurs.
216     */
217    public abstract void startHandshake() throws IOException;
218
219    /**
220     * Sets whether this connection should act in client mode when handshaking.
221     *
222     * @param mode
223     *            {@code true} if this connection should act in client mode,
224     *            {@code false} if not.
225     */
226    public abstract void setUseClientMode(boolean mode);
227
228    /**
229     * Returns true if this connection will act in client mode when handshaking.
230     */
231    public abstract boolean getUseClientMode();
232
233    /**
234     * Sets whether the server should require client authentication. This
235     * does not apply to sockets in {@link #getUseClientMode() client mode}.
236     * Client authentication is one of the following:
237     * <ul>
238     * <li>authentication required</li>
239     * <li>authentication requested</li>
240     * <li>no authentication needed</li>
241     * </ul>
242     * This method overrides the setting of {@link #setWantClientAuth(boolean)}.
243     */
244    public abstract void setNeedClientAuth(boolean need);
245
246    /**
247     * Sets whether the server should request client authentication. Unlike
248     * {@link #setNeedClientAuth} this won't stop the negotiation if the client
249     * doesn't authenticate. This does not apply to sockets in {@link
250     * #getUseClientMode() client mode}.The client authentication is one of:
251     * <ul>
252     * <li>authentication required</li>
253     * <li>authentication requested</li>
254     * <li>no authentication needed</li>
255     * </ul>
256     * This method overrides the setting of {@link #setNeedClientAuth(boolean)}.
257     */
258    public abstract void setWantClientAuth(boolean want);
259
260    /**
261     * Returns true if the server socket should require client authentication.
262     * This does not apply to sockets in {@link #getUseClientMode() client
263     * mode}.
264     */
265    public abstract boolean getNeedClientAuth();
266
267    /**
268     * Returns true if the server should request client authentication. This
269     * does not apply to sockets in {@link #getUseClientMode() client mode}.
270     */
271    public abstract boolean getWantClientAuth();
272
273    /**
274     * Sets whether new SSL sessions may be created by this socket or if
275     * existing sessions must be reused. If {@code flag} is false and there are
276     * no sessions to resume, handshaking will fail.
277     *
278     * @param flag {@code true} if new sessions may be created.
279     */
280    public abstract void setEnableSessionCreation(boolean flag);
281
282    /**
283     * Returns whether new SSL sessions may be created by this socket or if
284     * existing sessions must be reused.
285     *
286     * @return {@code true} if new sessions may be created, otherwise
287     *         {@code false}.
288     */
289    public abstract boolean getEnableSessionCreation();
290
291    /**
292     * Returns a new SSLParameters based on this SSLSocket's current
293     * cipher suites, protocols, and client authentication settings.
294     *
295     * @since 1.6
296     */
297    public SSLParameters getSSLParameters() {
298        SSLParameters p = new SSLParameters();
299        p.setCipherSuites(getEnabledCipherSuites());
300        p.setProtocols(getEnabledProtocols());
301        p.setNeedClientAuth(getNeedClientAuth());
302        p.setWantClientAuth(getWantClientAuth());
303        return p;
304    }
305
306    /**
307     * Sets various SSL handshake parameters based on the SSLParameter
308     * argument. Specifically, sets the SSLSocket's enabled cipher
309     * suites if the parameter's cipher suites are non-null. Similarly
310     * sets the enabled protocols. If the parameters specify the want
311     * or need for client authentication, those requirements are set
312     * on the SSLSocket, otherwise both are set to false.
313     * @since 1.6
314     */
315    public void setSSLParameters(SSLParameters p) {
316        String[] cipherSuites = p.getCipherSuites();
317        if (cipherSuites != null) {
318            setEnabledCipherSuites(cipherSuites);
319        }
320        String[] protocols = p.getProtocols();
321        if (protocols != null) {
322            setEnabledProtocols(protocols);
323        }
324        if (p.getNeedClientAuth()) {
325            setNeedClientAuth(true);
326        } else if (p.getWantClientAuth()) {
327            setWantClientAuth(true);
328        } else {
329            setWantClientAuth(false);
330        }
331    }
332}
333