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 
  62     SSLServerSocketImpl(SSLContextImpl sslContext) throws IOException {
  63 
  64         super();
  65         this.sslContext = sslContext;
  66         this.sslConfig = new SSLConfiguration(sslContext, false);
  67         this.sslConfig.isClientMode = false;
  68     }
  69 
  70     SSLServerSocketImpl(SSLContextImpl sslContext,
  71             int port, int backlog) throws IOException {
  72 
  73         super(port, backlog);
  74         this.sslContext = sslContext;
  75         this.sslConfig = new SSLConfiguration(sslContext, false);
  76         this.sslConfig.isClientMode = false;
  77     }
  78 
  79     SSLServerSocketImpl(SSLContextImpl sslContext,
  80             int port, int backlog, InetAddress address) throws IOException {
  81 
  82         super(port, backlog, address);
  83         this.sslContext = sslContext;
  84         this.sslConfig = new SSLConfiguration(sslContext, false);
  85         this.sslConfig.isClientMode = false;
  86     }
  87 
  88     @Override
  89     public String[] getEnabledCipherSuites() {
  90         serverSocketLock.lock();
  91         try {
  92             return CipherSuite.namesOf(sslConfig.enabledCipherSuites);
  93         } finally {
  94             serverSocketLock.unlock();
  95         }
  96     }
  97 
  98     @Override
  99     public void setEnabledCipherSuites(String[] suites) {
 100         serverSocketLock.lock();
 101         try {
 102             sslConfig.enabledCipherSuites =
 103                     CipherSuite.validValuesOf(suites);
 104         } finally {
 105             serverSocketLock.unlock();
 106         }
 107     }
 108 
 109     @Override
 110     public String[] getSupportedCipherSuites() {
 111         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
 112     }
 113 
 114     @Override
 115     public String[] getSupportedProtocols() {
 116         return ProtocolVersion.toStringArray(
 117                 sslContext.getSupportedProtocolVersions());
 118     }
 119 
 120     @Override
 121     public String[] getEnabledProtocols() {
 122         serverSocketLock.lock();
 123         try {
 124             return ProtocolVersion.toStringArray(sslConfig.enabledProtocols);
 125         } finally {
 126             serverSocketLock.unlock();
 127         }
 128     }
 129 
 130     @Override
 131     public void setEnabledProtocols(String[] protocols) {
 132         serverSocketLock.lock();
 133         try {
 134             if (protocols == null) {
 135                 throw new IllegalArgumentException("Protocols cannot be null");
 136             }
 137 
 138             sslConfig.enabledProtocols = ProtocolVersion.namesOf(protocols);
 139         } finally {
 140             serverSocketLock.unlock();
 141         }
 142     }
 143 
 144     @Override
 145     public void setNeedClientAuth(boolean need) {
 146         serverSocketLock.lock();
 147         try {
 148             sslConfig.clientAuthType =
 149                     (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
 150                             ClientAuthType.CLIENT_AUTH_NONE);
 151         } finally {
 152             serverSocketLock.unlock();
 153         }
 154     }
 155 
 156     @Override
 157     public boolean getNeedClientAuth() {
 158         serverSocketLock.lock();
 159         try {
 160             return (sslConfig.clientAuthType ==
 161                         ClientAuthType.CLIENT_AUTH_REQUIRED);
 162         } finally {
 163             serverSocketLock.unlock();
 164         }
 165     }
 166 
 167     @Override
 168     public void setWantClientAuth(boolean want) {
 169         serverSocketLock.lock();
 170         try {
 171             sslConfig.clientAuthType =
 172                     (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
 173                             ClientAuthType.CLIENT_AUTH_NONE);
 174         } finally {
 175             serverSocketLock.unlock();
 176         }
 177     }
 178 
 179     @Override
 180     public boolean getWantClientAuth() {
 181         serverSocketLock.lock();
 182         try {
 183             return (sslConfig.clientAuthType ==
 184                         ClientAuthType.CLIENT_AUTH_REQUESTED);
 185         } finally {
 186             serverSocketLock.unlock();
 187         }
 188     }
 189 
 190     @Override
 191     public void setUseClientMode(boolean useClientMode) {
 192         serverSocketLock.lock();
 193         try {
 194             /*
 195              * If we need to change the client mode and the enabled
 196              * protocols and cipher suites haven't specifically been
 197              * set by the user, change them to the corresponding
 198              * default ones.
 199              */
 200             if (sslConfig.isClientMode != useClientMode) {
 201                 if (sslContext.isDefaultProtocolVesions(
 202                         sslConfig.enabledProtocols)) {
 203                     sslConfig.enabledProtocols =
 204                         sslContext.getDefaultProtocolVersions(!useClientMode);
 205                 }
 206 
 207                 if (sslContext.isDefaultCipherSuiteList(
 208                         sslConfig.enabledCipherSuites)) {
 209                     sslConfig.enabledCipherSuites =
 210                         sslContext.getDefaultCipherSuites(!useClientMode);
 211                 }
 212 
 213                 sslConfig.isClientMode = useClientMode;
 214             }
 215         } finally {
 216             serverSocketLock.unlock();
 217         }
 218     }
 219 
 220     @Override
 221     public boolean getUseClientMode() {
 222         serverSocketLock.lock();
 223         try {
 224             return sslConfig.isClientMode;
 225         } finally {
 226             serverSocketLock.unlock();
 227         }
 228     }
 229 
 230     @Override
 231     public void setEnableSessionCreation(boolean flag) {
 232         serverSocketLock.lock();
 233         try {
 234             sslConfig.enableSessionCreation = flag;
 235         } finally {
 236             serverSocketLock.unlock();
 237         }
 238     }
 239 
 240     @Override
 241     public boolean getEnableSessionCreation() {
 242         serverSocketLock.lock();
 243         try {
 244             return sslConfig.enableSessionCreation;
 245         } finally {
 246             serverSocketLock.unlock();
 247         }
 248     }
 249 
 250     @Override
 251     public SSLParameters getSSLParameters() {
 252         serverSocketLock.lock();
 253         try {
 254             return sslConfig.getSSLParameters();
 255         } finally {
 256             serverSocketLock.unlock();
 257         }
 258     }
 259 
 260     @Override
 261     public void setSSLParameters(SSLParameters params) {
 262         serverSocketLock.lock();
 263         try {
 264             sslConfig.setSSLParameters(params);
 265         } finally {
 266             serverSocketLock.unlock();
 267         }
 268     }
 269 
 270     @Override
 271     public Socket accept() throws IOException {
 272         SSLSocketImpl s = new SSLSocketImpl(sslContext, sslConfig);
 273 
 274         implAccept(s);
 275         s.doneConnect();
 276         return s;
 277     }
 278 
 279     @Override
 280     public String toString() {
 281         return "[SSL: "+ super.toString() + "]";
 282     }
 283 }