/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.ssl;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.concurrent.locks.ReentrantLock;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
This class provides a simple way for servers to support conventional
use of the Secure Sockets Layer (SSL). Application code uses an
SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
difference is that the connections established are secured using SSL.
Also, the constructors take an explicit authentication context
parameter, giving flexibility with respect to how the server socket
authenticates itself. That policy flexibility is not exposed through
the standard SSLServerSocketFactory API.
System security defaults prevent server sockets from accepting
connections if they the authentication context has not been given
a certificate chain and its matching private key. If the clients
of your application support "anonymous" cipher suites, you may be
able to configure a server socket to accept those suites.
Author: David Brownell See Also: - SSLSocketImpl
- SSLServerSocketFactoryImpl
/**
* This class provides a simple way for servers to support conventional
* use of the Secure Sockets Layer (SSL). Application code uses an
* SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
* difference is that the connections established are secured using SSL.
*
* <P> Also, the constructors take an explicit authentication context
* parameter, giving flexibility with respect to how the server socket
* authenticates itself. That policy flexibility is not exposed through
* the standard SSLServerSocketFactory API.
*
* <P> System security defaults prevent server sockets from accepting
* connections if they the authentication context has not been given
* a certificate chain and its matching private key. If the clients
* of your application support "anonymous" cipher suites, you may be
* able to configure a server socket to accept those suites.
*
* @see SSLSocketImpl
* @see SSLServerSocketFactoryImpl
*
* @author David Brownell
*/
final class SSLServerSocketImpl extends SSLServerSocket {
private final SSLContextImpl sslContext;
private final SSLConfiguration sslConfig;
private final ReentrantLock serverSocketLock = new ReentrantLock();
SSLServerSocketImpl(SSLContextImpl sslContext) throws IOException {
super();
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
SSLServerSocketImpl(SSLContextImpl sslContext,
int port, int backlog) throws IOException {
super(port, backlog);
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
SSLServerSocketImpl(SSLContextImpl sslContext,
int port, int backlog, InetAddress address) throws IOException {
super(port, backlog, address);
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
@Override
public String[] getEnabledCipherSuites() {
serverSocketLock.lock();
try {
return CipherSuite.namesOf(sslConfig.enabledCipherSuites);
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setEnabledCipherSuites(String[] suites) {
serverSocketLock.lock();
try {
sslConfig.enabledCipherSuites =
CipherSuite.validValuesOf(suites);
} finally {
serverSocketLock.unlock();
}
}
@Override
public String[] getSupportedCipherSuites() {
return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
}
@Override
public String[] getSupportedProtocols() {
return ProtocolVersion.toStringArray(
sslContext.getSupportedProtocolVersions());
}
@Override
public String[] getEnabledProtocols() {
serverSocketLock.lock();
try {
return ProtocolVersion.toStringArray(sslConfig.enabledProtocols);
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setEnabledProtocols(String[] protocols) {
serverSocketLock.lock();
try {
if (protocols == null) {
throw new IllegalArgumentException("Protocols cannot be null");
}
sslConfig.enabledProtocols = ProtocolVersion.namesOf(protocols);
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setNeedClientAuth(boolean need) {
serverSocketLock.lock();
try {
sslConfig.clientAuthType =
(need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
ClientAuthType.CLIENT_AUTH_NONE);
} finally {
serverSocketLock.unlock();
}
}
@Override
public boolean getNeedClientAuth() {
serverSocketLock.lock();
try {
return (sslConfig.clientAuthType ==
ClientAuthType.CLIENT_AUTH_REQUIRED);
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setWantClientAuth(boolean want) {
serverSocketLock.lock();
try {
sslConfig.clientAuthType =
(want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
ClientAuthType.CLIENT_AUTH_NONE);
} finally {
serverSocketLock.unlock();
}
}
@Override
public boolean getWantClientAuth() {
serverSocketLock.lock();
try {
return (sslConfig.clientAuthType ==
ClientAuthType.CLIENT_AUTH_REQUESTED);
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setUseClientMode(boolean useClientMode) {
serverSocketLock.lock();
try {
/*
* If we need to change the client mode and the enabled
* protocols and cipher suites haven't specifically been
* set by the user, change them to the corresponding
* default ones.
*/
if (sslConfig.isClientMode != useClientMode) {
if (sslContext.isDefaultProtocolVesions(
sslConfig.enabledProtocols)) {
sslConfig.enabledProtocols =
sslContext.getDefaultProtocolVersions(!useClientMode);
}
if (sslContext.isDefaultCipherSuiteList(
sslConfig.enabledCipherSuites)) {
sslConfig.enabledCipherSuites =
sslContext.getDefaultCipherSuites(!useClientMode);
}
sslConfig.isClientMode = useClientMode;
}
} finally {
serverSocketLock.unlock();
}
}
@Override
public boolean getUseClientMode() {
serverSocketLock.lock();
try {
return sslConfig.isClientMode;
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setEnableSessionCreation(boolean flag) {
serverSocketLock.lock();
try {
sslConfig.enableSessionCreation = flag;
} finally {
serverSocketLock.unlock();
}
}
@Override
public boolean getEnableSessionCreation() {
serverSocketLock.lock();
try {
return sslConfig.enableSessionCreation;
} finally {
serverSocketLock.unlock();
}
}
@Override
public SSLParameters getSSLParameters() {
serverSocketLock.lock();
try {
return sslConfig.getSSLParameters();
} finally {
serverSocketLock.unlock();
}
}
@Override
public void setSSLParameters(SSLParameters params) {
serverSocketLock.lock();
try {
sslConfig.setSSLParameters(params);
} finally {
serverSocketLock.unlock();
}
}
@Override
public Socket accept() throws IOException {
SSLSocketImpl s = new SSLSocketImpl(sslContext, sslConfig);
implAccept(s);
s.doneConnect();
return s;
}
@Override
public String toString() {
return "[SSL: "+ super.toString() + "]";
}
}