1/*
2 * Copyright (c) 1996, 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
26
27package sun.security.ssl;
28
29import java.io.IOException;
30import java.net.InetAddress;
31import java.net.Socket;
32import java.net.ServerSocket;
33
34import java.security.AlgorithmConstraints;
35
36import java.util.*;
37
38import javax.net.ServerSocketFactory;
39import javax.net.ssl.SSLException;
40import javax.net.ssl.SSLServerSocket;
41import javax.net.ssl.SSLParameters;
42
43
44/**
45 * This class provides a simple way for servers to support conventional
46 * use of the Secure Sockets Layer (SSL).  Application code uses an
47 * SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
48 * difference is that the connections established are secured using SSL.
49 *
50 * <P> Also, the constructors take an explicit authentication context
51 * parameter, giving flexibility with respect to how the server socket
52 * authenticates itself.  That policy flexibility is not exposed through
53 * the standard SSLServerSocketFactory API.
54 *
55 * <P> System security defaults prevent server sockets from accepting
56 * connections if they the authentication context has not been given
57 * a certificate chain and its matching private key.  If the clients
58 * of your application support "anonymous" cipher suites, you may be
59 * able to configure a server socket to accept those suites.
60 *
61 * @see SSLSocketImpl
62 * @see SSLServerSocketFactoryImpl
63 *
64 * @author David Brownell
65 */
66final
67class SSLServerSocketImpl extends SSLServerSocket
68{
69    private SSLContextImpl      sslContext;
70
71    /* Do newly accepted connections require clients to authenticate? */
72    private byte                doClientAuth = SSLEngineImpl.clauth_none;
73
74    /* Do new connections created here use the "server" mode of SSL? */
75    private boolean             useServerMode = true;
76
77    /* Can new connections created establish new sessions? */
78    private boolean             enableSessionCreation = true;
79
80    /* what cipher suites to use by default */
81    private CipherSuiteList     enabledCipherSuites = null;
82
83    /* which protocol to use by default */
84    private ProtocolList        enabledProtocols = null;
85
86    /* could enabledCipherSuites ever complete handshaking? */
87    private boolean             checkedEnabled = false;
88
89    // the endpoint identification protocol to use by default
90    private String              identificationProtocol = null;
91
92    // The cryptographic algorithm constraints
93    private AlgorithmConstraints    algorithmConstraints = null;
94
95    /**
96     * Create an SSL server socket on a port, using a non-default
97     * authentication context and a specified connection backlog.
98     *
99     * @param port the port on which to listen
100     * @param backlog how many connections may be pending before
101     *          the system should start rejecting new requests
102     * @param context authentication context for this server
103     */
104    SSLServerSocketImpl(int port, int backlog, SSLContextImpl context)
105    throws IOException, SSLException
106    {
107        super(port, backlog);
108        initServer(context);
109    }
110
111
112    /**
113     * Create an SSL server socket on a port, using a specified
114     * authentication context and a specified backlog of connections
115     * as well as a particular specified network interface.  This
116     * constructor is used on multihomed hosts, such as those used
117     * for firewalls or as routers, to control through which interface
118     * a network service is provided.
119     *
120     * @param port the port on which to listen
121     * @param backlog how many connections may be pending before
122     *          the system should start rejecting new requests
123     * @param address the address of the network interface through
124     *          which connections will be accepted
125     * @param context authentication context for this server
126     */
127    SSLServerSocketImpl(
128        int             port,
129        int             backlog,
130        InetAddress     address,
131        SSLContextImpl  context)
132        throws IOException
133    {
134        super(port, backlog, address);
135        initServer(context);
136    }
137
138
139    /**
140     * Creates an unbound server socket.
141     */
142    SSLServerSocketImpl(SSLContextImpl context) throws IOException {
143        super();
144        initServer(context);
145    }
146
147
148    /**
149     * Initializes the server socket.
150     */
151    private void initServer(SSLContextImpl context) throws SSLException {
152        if (context == null) {
153            throw new SSLException("No Authentication context given");
154        }
155        sslContext = context;
156        enabledCipherSuites = sslContext.getDefaultCipherSuiteList(true);
157        enabledProtocols = sslContext.getDefaultProtocolList(true);
158    }
159
160    /**
161     * Returns the names of the cipher suites which could be enabled for use
162     * on an SSL connection.  Normally, only a subset of these will actually
163     * be enabled by default, since this list may include cipher suites which
164     * do not support the mutual authentication of servers and clients, or
165     * which do not protect data confidentiality.  Servers may also need
166     * certain kinds of certificates to use certain cipher suites.
167     *
168     * @return an array of cipher suite names
169     */
170    public String[] getSupportedCipherSuites() {
171        return sslContext.getSupportedCipherSuiteList().toStringArray();
172    }
173
174    /**
175     * Returns the list of cipher suites which are currently enabled
176     * for use by newly accepted connections.  A null return indicates
177     * that the system defaults are in effect.
178     */
179    synchronized public String[] getEnabledCipherSuites() {
180        return enabledCipherSuites.toStringArray();
181    }
182
183    /**
184     * Controls which particular SSL cipher suites are enabled for use
185     * by accepted connections.
186     *
187     * @param suites Names of all the cipher suites to enable; null
188     *  means to accept system defaults.
189     */
190    synchronized public void setEnabledCipherSuites(String[] suites) {
191        enabledCipherSuites = new CipherSuiteList(suites);
192        checkedEnabled = false;
193    }
194
195    public String[] getSupportedProtocols() {
196        return sslContext.getSuportedProtocolList().toStringArray();
197    }
198
199    /**
200     * Controls which protocols are enabled for use.
201     * The protocols must have been listed by
202     * getSupportedProtocols() as being supported.
203     *
204     * @param protocols protocols to enable.
205     * @exception IllegalArgumentException when one of the protocols
206     *  named by the parameter is not supported.
207     */
208    synchronized public void setEnabledProtocols(String[] protocols) {
209        enabledProtocols = new ProtocolList(protocols);
210    }
211
212    synchronized public String[] getEnabledProtocols() {
213        return enabledProtocols.toStringArray();
214    }
215
216    /**
217     * Controls whether the connections which are accepted must include
218     * client authentication.
219     */
220    public void setNeedClientAuth(boolean flag) {
221        doClientAuth = (flag ?
222            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
223    }
224
225    public boolean getNeedClientAuth() {
226        return (doClientAuth == SSLEngineImpl.clauth_required);
227    }
228
229    /**
230     * Controls whether the connections which are accepted should request
231     * client authentication.
232     */
233    public void setWantClientAuth(boolean flag) {
234        doClientAuth = (flag ?
235            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
236    }
237
238    public boolean getWantClientAuth() {
239        return (doClientAuth == SSLEngineImpl.clauth_requested);
240    }
241
242    /**
243     * Makes the returned sockets act in SSL "client" mode, not the usual
244     * server mode.  The canonical example of why this is needed is for
245     * FTP clients, which accept connections from servers and should be
246     * rejoining the already-negotiated SSL connection.
247     */
248    public void setUseClientMode(boolean flag) {
249        /*
250         * If we need to change the socket mode and the enabled
251         * protocols haven't specifically been set by the user,
252         * change them to the corresponding default ones.
253         */
254        if (useServerMode != (!flag) &&
255                sslContext.isDefaultProtocolList(enabledProtocols)) {
256            enabledProtocols = sslContext.getDefaultProtocolList(!flag);
257        }
258
259        useServerMode = !flag;
260    }
261
262    public boolean getUseClientMode() {
263        return !useServerMode;
264    }
265
266
267    /**
268     * Controls whether new connections may cause creation of new SSL
269     * sessions.
270     */
271    public void setEnableSessionCreation(boolean flag) {
272        enableSessionCreation = flag;
273    }
274
275    /**
276     * Returns true if new connections may cause creation of new SSL
277     * sessions.
278     */
279    public boolean getEnableSessionCreation() {
280        return enableSessionCreation;
281    }
282
283    /**
284     * Returns the SSLParameters in effect for newly accepted connections.
285     */
286    synchronized public SSLParameters getSSLParameters() {
287        SSLParameters params = super.getSSLParameters();
288
289        // the super implementation does not handle the following parameters
290        params.setEndpointIdentificationAlgorithm(identificationProtocol);
291        params.setAlgorithmConstraints(algorithmConstraints);
292
293        return params;
294    }
295
296    /**
297     * Applies SSLParameters to newly accepted connections.
298     */
299    synchronized public void setSSLParameters(SSLParameters params) {
300        super.setSSLParameters(params);
301
302        // the super implementation does not handle the following parameters
303        identificationProtocol = params.getEndpointIdentificationAlgorithm();
304        algorithmConstraints = params.getAlgorithmConstraints();
305    }
306
307    /**
308     * Accept a new SSL connection.  This server identifies itself with
309     * information provided in the authentication context which was
310     * presented during construction.
311     */
312    public Socket accept() throws IOException {
313        SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
314            enabledCipherSuites, doClientAuth, enableSessionCreation,
315            enabledProtocols, identificationProtocol, algorithmConstraints);
316
317        implAccept(s);
318        s.doneConnect();
319        return s;
320    }
321
322    /**
323     * Provides a brief description of this SSL socket.
324     */
325    public String toString() {
326        return "[SSL: "+ super.toString() + "]";
327    }
328}
329