1 /*
2  * Copyright (c) 1996, 2019, 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.IOException;
29 import java.net.InetAddress;
30 import java.net.Socket;
31 import java.util.concurrent.locks.ReentrantLock;
32 import javax.net.ssl.SSLParameters;
33 import javax.net.ssl.SSLServerSocket;
34 
35 /**
36  * This class provides a simple way for servers to support conventional
37  * use of the Secure Sockets Layer (SSL).  Application code uses an
38  * SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
39  * difference is that the connections established are secured using SSL.
40  *
41  * <P> Also, the constructors take an explicit authentication context
42  * parameter, giving flexibility with respect to how the server socket
43  * authenticates itself.  That policy flexibility is not exposed through
44  * the standard SSLServerSocketFactory API.
45  *
46  * <P> System security defaults prevent server sockets from accepting
47  * connections if they the authentication context has not been given
48  * a certificate chain and its matching private key.  If the clients
49  * of your application support "anonymous" cipher suites, you may be
50  * able to configure a server socket to accept those suites.
51  *
52  * @see SSLSocketImpl
53  * @see SSLServerSocketFactoryImpl
54  *
55  * @author David Brownell
56  */
57 final class SSLServerSocketImpl extends SSLServerSocket {
58     private final SSLContextImpl        sslContext;
59     private final SSLConfiguration      sslConfig;
60     private final ReentrantLock         serverSocketLock = new ReentrantLock();
61 
SSLServerSocketImpl(SSLContextImpl sslContext)62     SSLServerSocketImpl(SSLContextImpl sslContext) throws IOException {
63 
64         super();
65         this.sslContext = sslContext;
66         this.sslConfig = new SSLConfiguration(sslContext, false);
67     }
68 
SSLServerSocketImpl(SSLContextImpl sslContext, int port, int backlog)69     SSLServerSocketImpl(SSLContextImpl sslContext,
70             int port, int backlog) throws IOException {
71 
72         super(port, backlog);
73         this.sslContext = sslContext;
74         this.sslConfig = new SSLConfiguration(sslContext, false);
75     }
76 
SSLServerSocketImpl(SSLContextImpl sslContext, int port, int backlog, InetAddress address)77     SSLServerSocketImpl(SSLContextImpl sslContext,
78             int port, int backlog, InetAddress address) throws IOException {
79 
80         super(port, backlog, address);
81         this.sslContext = sslContext;
82         this.sslConfig = new SSLConfiguration(sslContext, false);
83     }
84 
85     @Override
getEnabledCipherSuites()86     public String[] getEnabledCipherSuites() {
87         serverSocketLock.lock();
88         try {
89             return CipherSuite.namesOf(sslConfig.enabledCipherSuites);
90         } finally {
91             serverSocketLock.unlock();
92         }
93     }
94 
95     @Override
setEnabledCipherSuites(String[] suites)96     public void setEnabledCipherSuites(String[] suites) {
97         serverSocketLock.lock();
98         try {
99             sslConfig.enabledCipherSuites =
100                     CipherSuite.validValuesOf(suites);
101         } finally {
102             serverSocketLock.unlock();
103         }
104     }
105 
106     @Override
getSupportedCipherSuites()107     public String[] getSupportedCipherSuites() {
108         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
109     }
110 
111     @Override
getSupportedProtocols()112     public String[] getSupportedProtocols() {
113         return ProtocolVersion.toStringArray(
114                 sslContext.getSupportedProtocolVersions());
115     }
116 
117     @Override
getEnabledProtocols()118     public String[] getEnabledProtocols() {
119         serverSocketLock.lock();
120         try {
121             return ProtocolVersion.toStringArray(sslConfig.enabledProtocols);
122         } finally {
123             serverSocketLock.unlock();
124         }
125     }
126 
127     @Override
setEnabledProtocols(String[] protocols)128     public void setEnabledProtocols(String[] protocols) {
129         serverSocketLock.lock();
130         try {
131             if (protocols == null) {
132                 throw new IllegalArgumentException("Protocols cannot be null");
133             }
134 
135             sslConfig.enabledProtocols = ProtocolVersion.namesOf(protocols);
136         } finally {
137             serverSocketLock.unlock();
138         }
139     }
140 
141     @Override
setNeedClientAuth(boolean need)142     public void setNeedClientAuth(boolean need) {
143         serverSocketLock.lock();
144         try {
145             sslConfig.clientAuthType =
146                     (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
147                             ClientAuthType.CLIENT_AUTH_NONE);
148         } finally {
149             serverSocketLock.unlock();
150         }
151     }
152 
153     @Override
getNeedClientAuth()154     public boolean getNeedClientAuth() {
155         serverSocketLock.lock();
156         try {
157             return (sslConfig.clientAuthType ==
158                         ClientAuthType.CLIENT_AUTH_REQUIRED);
159         } finally {
160             serverSocketLock.unlock();
161         }
162     }
163 
164     @Override
setWantClientAuth(boolean want)165     public void setWantClientAuth(boolean want) {
166         serverSocketLock.lock();
167         try {
168             sslConfig.clientAuthType =
169                     (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
170                             ClientAuthType.CLIENT_AUTH_NONE);
171         } finally {
172             serverSocketLock.unlock();
173         }
174     }
175 
176     @Override
getWantClientAuth()177     public boolean getWantClientAuth() {
178         serverSocketLock.lock();
179         try {
180             return (sslConfig.clientAuthType ==
181                         ClientAuthType.CLIENT_AUTH_REQUESTED);
182         } finally {
183             serverSocketLock.unlock();
184         }
185     }
186 
187     @Override
setUseClientMode(boolean useClientMode)188     public void setUseClientMode(boolean useClientMode) {
189         serverSocketLock.lock();
190         try {
191             /*
192              * If we need to change the client mode and the enabled
193              * protocols and cipher suites haven't specifically been
194              * set by the user, change them to the corresponding
195              * default ones.
196              */
197             if (sslConfig.isClientMode != useClientMode) {
198                 if (sslContext.isDefaultProtocolVesions(
199                         sslConfig.enabledProtocols)) {
200                     sslConfig.enabledProtocols =
201                         sslContext.getDefaultProtocolVersions(!useClientMode);
202                 }
203 
204                 if (sslContext.isDefaultCipherSuiteList(
205                         sslConfig.enabledCipherSuites)) {
206                     sslConfig.enabledCipherSuites =
207                         sslContext.getDefaultCipherSuites(!useClientMode);
208                 }
209 
210                 sslConfig.toggleClientMode();
211             }
212         } finally {
213             serverSocketLock.unlock();
214         }
215     }
216 
217     @Override
getUseClientMode()218     public boolean getUseClientMode() {
219         serverSocketLock.lock();
220         try {
221             return sslConfig.isClientMode;
222         } finally {
223             serverSocketLock.unlock();
224         }
225     }
226 
227     @Override
setEnableSessionCreation(boolean flag)228     public void setEnableSessionCreation(boolean flag) {
229         serverSocketLock.lock();
230         try {
231             sslConfig.enableSessionCreation = flag;
232         } finally {
233             serverSocketLock.unlock();
234         }
235     }
236 
237     @Override
getEnableSessionCreation()238     public boolean getEnableSessionCreation() {
239         serverSocketLock.lock();
240         try {
241             return sslConfig.enableSessionCreation;
242         } finally {
243             serverSocketLock.unlock();
244         }
245     }
246 
247     @Override
getSSLParameters()248     public SSLParameters getSSLParameters() {
249         serverSocketLock.lock();
250         try {
251             return sslConfig.getSSLParameters();
252         } finally {
253             serverSocketLock.unlock();
254         }
255     }
256 
257     @Override
setSSLParameters(SSLParameters params)258     public void setSSLParameters(SSLParameters params) {
259         serverSocketLock.lock();
260         try {
261             sslConfig.setSSLParameters(params);
262         } finally {
263             serverSocketLock.unlock();
264         }
265     }
266 
267     @Override
accept()268     public Socket accept() throws IOException {
269         SSLSocketImpl s = new SSLSocketImpl(sslContext, sslConfig);
270 
271         implAccept(s);
272         s.doneConnect();
273         return s;
274     }
275 
276     @Override
toString()277     public String toString() {
278         return "[SSL: "+ super.toString() + "]";
279     }
280 }
281