[473086][dstore] enableProtocols() calls setEnabledCipherSuites(), not
setEnabledProtocols()
diff --git a/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
index a301609..3acd1de 100644
--- a/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
+++ b/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.dstore.core
-Bundle-Version: 3.2.21.qualifier
+Bundle-Version: 3.2.22.qualifier
Bundle-Activator: org.eclipse.dstore.core.Activator
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
diff --git a/rse/plugins/org.eclipse.dstore.core/pom.xml b/rse/plugins/org.eclipse.dstore.core/pom.xml
index b02400d..8d23f07 100644
--- a/rse/plugins/org.eclipse.dstore.core/pom.xml
+++ b/rse/plugins/org.eclipse.dstore.core/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>org.eclipse.tm</groupId>
<artifactId>org.eclipse.dstore.core</artifactId>
- <version>3.2.21-SNAPSHOT</version>
+ <version>3.2.22-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java b/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
index db8a448..94962db 100644
--- a/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
+++ b/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
@@ -1,781 +1,782 @@
-/*******************************************************************************
- * Copyright (c) 2002, 2015 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Initial Contributors:
- * The following IBM employees contributed to the Remote System Explorer
- * component that contains this file: David McKnight, Kushal Munir,
- * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
- * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
- *
- * Contributors:
- * David McKnight (IBM) [220123][dstore] Configurable timeout on irresponsiveness
- * David McKnight (IBM) [220892][dstore] Backward compatibility: Server and Daemon should support old clients
- * Noriaki Takatsu (IBM) - [220126] [dstore][api][breaking] Single process server for multiple clients
- * David McKnight (IBM) [224906] [dstore] changes for getting properties and doing exit due to single-process capability
- * Jacob Garcowski (IBM) [225175] [dstore] error handling change for Client
- * David McKnight (IBM) - [225507][api][breaking] RSE dstore API leaks non-API types
- * Noriaki Takatsu (IBM) - [226074] process for getStatus() API
- * Noriaki Takatsu (IBM) - [226237] [dstore] Move the place where the ServerLogger instance is made
- * David McKnight (IBM) - [226561] [apidoc] Add API markup to RSE Javadocs where extend / implement is allowed
- * Noriaki Takatsu (IBM) - [242968] [multithread] serverSocket must be closed when an exception happens in Accept
- * David McKnight (IBM) - [257321] [dstore] "Error binding socket" should include port of the failed socket
- * Noriaki Takatsu (IBM) - [283656] [dstore][multithread] Serviceability issue
- * Noriaki Takatsu (IBM) - [289678][api][breaking] ServerSocket creation in multiple IP addresses
- * David McKnight (IBM) - [368072] [dstore][ssl] no exception logged upon bind error
- * David McKnight (IBM) - [371401] [dstore][multithread] avoid use of static variables - causes memory leak after disconnect
- * David McKnight (IBM) - [388472] [dstore] need alternative option for getting at server hostname
- * David McKnight (IBM) - [390681] [dstore] need to merge differences between HEAD stream and 3.2 in ConnectionEstablisher.finished()
- * David McKnight (IBM) [439545][dstore] potential deadlock on senders during shutdown
- * David McKnight (IBM) [464736][dstore] need methods to disable ciphers and protocols
- *******************************************************************************/
-
-package org.eclipse.dstore.core.server;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.net.BindException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-
-import org.eclipse.dstore.core.model.Client;
-import org.eclipse.dstore.core.model.DE;
-import org.eclipse.dstore.core.model.DataElement;
-import org.eclipse.dstore.core.model.DataStore;
-import org.eclipse.dstore.core.model.DataStoreAttributes;
-import org.eclipse.dstore.core.model.ISSLProperties;
-import org.eclipse.dstore.internal.core.server.ServerAttributes;
-import org.eclipse.dstore.internal.core.server.ServerCommandHandler;
-import org.eclipse.dstore.internal.core.server.ServerReturnCodes;
-import org.eclipse.dstore.internal.core.server.ServerSSLProperties;
-import org.eclipse.dstore.internal.core.server.ServerUpdateHandler;
-import org.eclipse.dstore.internal.core.util.ExternalLoader;
-import org.eclipse.dstore.internal.core.util.Sender;
-import org.eclipse.dstore.internal.core.util.ssl.DStoreSSLContext;
-
-/**
- * ConnectionEstablisher is responsible for managing the server DataStore and
- * facilitating the communication between client and server DataStores.
- *
- * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- *
- * @since 3.0 moved from non-API to API
- */
-public class ConnectionEstablisher
-{
-
-
- private ServerSocket _serverSocket;
- private boolean _continue;
-
- private ArrayList _receivers;
-
- private ServerCommandHandler _commandHandler;
- private ServerUpdateHandler _updateHandler;
-
- private ServerAttributes _serverAttributes = new ServerAttributes();
- private DataStore _dataStore;
-
- private int _maxConnections;
- private int _timeout;
- private String _msg;
-
-
- private String[] _disabledCipherPatterns = null;
- private String[] _disabledProtocolPatterns = null;
- private String[] _enabledCiphers = null;
- private String[] _enabledProtocols = null;
-
-
-
- /**
- * Creates the default ConnectionEstablisher. Communication occurs
- * on a default port, there is no timeout and no ticket is required
- * for a client to work with the DataStore.
- *
- */
- public ConnectionEstablisher()
- {
- String port = _serverAttributes.getAttribute(DataStoreAttributes.A_HOST_PORT);
- setup(port, null, null);
- }
-
- /**
- * Creates a ConnectionEstablisher. Communication occurs
- * on the specified port, there is no timeout and no ticket is required
- * for a client to work with the DataStore.
- *
- * @param port the number of the socket port
- */
- public ConnectionEstablisher(String port)
- {
- setup(port, null, null);
- }
-
- /**
- * Creates a ConnectionEstablisher. Communication occurs
- * on the specified port, a timeout value indicates the idle wait
- * time before shutting down, and no ticket is required
- * for a client to work with the DataStore.
- *
- * @param port the number of the socket port
- * @param timeout the idle duration to wait before shutting down
- */
- public ConnectionEstablisher(String port, String timeout)
- {
- setup(port, timeout, null);
- }
-
- /**
- * Creates a ConnectionEstablisher. Communication occurs
- * on the specified port, a timeout value indicates the idle wait
- * time before shutting down, and ticket specified the required
- * ticket for a client to present in order to work with the DataStore.
- *
- * @param port the number of the socket port
- * @param timeout the idle duration to wait before shutting down
- * @param ticket validation id required by the client to access the DataStore
- */
- public ConnectionEstablisher(String port, String timeout, String ticket)
- {
- setup(port, timeout, ticket);
- }
-
- /**
- * Creates a ConnectionEstablisher. Communication occurs
- * on the specified port and the specified IP address,
- * a timeout value indicates the idle wait time
- * before shutting down, and ticket specified the required
- * ticket for a client to present in order to work with the DataStore.
- *
- * @param port the number of the socket port
- * @param backlog listen backlog
- * @param bindAddr the local IP address to bind to
- * @param timeout the idle duration to wait before shutting down
- * @param ticket validation id required by the client to access the DataStore
- * @since 3.2
- */
- public ConnectionEstablisher(String port, int backlog, InetAddress bindAddr, String timeout, String ticket)
- {
- setup(port, backlog, bindAddr, timeout, ticket);
- }
-
-
- /**
- * Starts the run loop for the ConnectionEstablisher.
- */
- public void start()
- {
- run();
- }
-
-
-
- /**
- * Returns the DataStore.
- *
- * @return the DataStore
- */
- public DataStore getDataStore()
- {
- return _dataStore;
- }
-
- /**
- * Return the Server port opened for this client
- *
- * @return the Server port opened for this client
- */
- public int getServerPort()
- {
- if (_serverSocket != null)
- {
- return _serverSocket.getLocalPort();
- }
-
- return -1;
- }
-
- /**
- * Return the connection status for this client
- *
- * * @return the connection status for this client
- */
- public String getStatus()
- {
- return _msg;
- }
-
- /**
- * Tells the connection establisher to clean up and shutdown
- */
- public void finished(ServerReceiver receiver)
- {
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher.finished()"); //$NON-NLS-1$
- }
-
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing receiver"); //$NON-NLS-1$
- }
- _receivers.remove(receiver);
-
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing preference listener"); //$NON-NLS-1$
- }
- _dataStore.removeDataStorePreferenceListener(receiver);
- //if (_receivers.size() == 0)
- {
- _continue = false;
- _commandHandler.finish();
-
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing update handler"); //$NON-NLS-1$
- }
- _updateHandler.finish();
-
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing sender"); //$NON-NLS-1$
- }
- _updateHandler.removeSenderWith(receiver.socket());
-
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing DataStore"); //$NON-NLS-1$
- }
- _dataStore.finish();
- System.out.println(ServerReturnCodes.RC_FINISHED);
-
- if (SystemServiceManager.getInstance().getSystemService() == null)
- System.exit(0);
- }
- }
-
- private void waitForConnections()
- {
- while (_continue == true)
- {
- try
- {
- if (_dataStore.usingSSL())
- {
- SSLServerSocket sslServerSocket = (SSLServerSocket)_serverSocket;
- // for security, disable ciphers and protocols we don't want
- disableCiphers(sslServerSocket);
- disableProtocols(sslServerSocket);
-
- // for security, enable only ciphers and protocols that are common
- enableCiphers(sslServerSocket);
- enableProtocols(sslServerSocket);
-
- logAvailableCiphersAndProtocols(sslServerSocket);
- }
-
- Socket newSocket = _serverSocket.accept();
- if (_dataStore.usingSSL())
- {
-
- // wait for connection
- SSLSocket sslSocket = (SSLSocket)newSocket;
- sslSocket.setUseClientMode(false);
- sslSocket.setNeedClientAuth(false);
- SSLSession session = sslSocket.getSession();
-
- if (session == null)
- {
- System.out.println("handshake failed"); //$NON-NLS-1$
- sslSocket.close();
- return;
- }
- }
-
- doHandShake(newSocket);
- newSocket.setKeepAlive(true);
-
- ServerReceiver receiver = new ServerReceiver(newSocket, this);
- _dataStore.addDataStorePreferenceListener(receiver);
-
- if (_dataStore.getClient() != null)
- _dataStore.getClient().setServerReceiver(receiver);
-
- Sender sender = new Sender(newSocket, _dataStore);
-
- // add this connection to list of elements
- _receivers.add(receiver);
- _updateHandler.addSender(sender);
-
- receiver.start();
-
- if (_receivers.size() == 1)
- {
- _updateHandler.start();
- _commandHandler.start();
- }
-
- if (_receivers.size() == _maxConnections)
- {
- _continue = false;
- _serverSocket.close();
-
- }
- }
- catch (IOException ioe)
- {
- System.err.println(ServerReturnCodes.RC_CONNECTION_ERROR);
- System.err.println("Server: error initializing socket: " + ioe); //$NON-NLS-1$
- _msg = ioe.toString();
- try
- {
- _serverSocket.close();
- }
- catch (Throwable e)
- {
-
- }
- _continue = false;
- }
- }
- }
-
-
-
-
- private ServerSocket createSocket(String portStr, int backlog, InetAddress bindAddr) throws UnknownHostException
- {
- ServerSocket serverSocket = null;
- SSLContext sslContext = null;
- // port
- int port = 0;
-
- if (_dataStore.usingSSL())
- {
- String keyStoreFileName = _dataStore.getKeyStoreLocation();
- String keyStorePassword = _dataStore.getKeyStorePassword();
-
- try
- {
- sslContext = DStoreSSLContext.getServerSSLContext(keyStoreFileName, keyStorePassword);
- }
- catch (Exception e)
- {
-
- }
- }
-
- // determine if portStr is a port range or just a port
- String[] range = portStr.split("-"); //$NON-NLS-1$
- if (range.length == 2)
- {
- int lPort = 0;
- int hPort = 0;
- try
- {
- lPort = Integer.parseInt(range[0]);
- hPort = Integer.parseInt(range[1]);
- }
- catch (Exception e)
- {
- }
-
- for (int i = lPort; i < hPort; i++)
- {
- // create server socket from port
- try
- {
- if (_dataStore.usingSSL() && sslContext != null)
- {
- try
- {
- serverSocket = sslContext.getServerSocketFactory().createServerSocket(i, backlog, bindAddr);
- }
- catch (BindException e)
- {
- _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
- System.err.println(_msg);
- _dataStore.trace(_msg);
- }
- catch (Exception e)
- {
- }
- }
- else
- {
- try
- {
- serverSocket = new ServerSocket(i, backlog, bindAddr);
- }
- catch (BindException e)
- {
- _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
- System.err.println(_msg);
- _dataStore.trace(_msg);
- }
- catch (Exception e)
- {
- }
- }
- }
- catch (Exception e)
- {
- _dataStore.trace(e);
- }
- if (serverSocket != null && serverSocket.getLocalPort() > 0)
- {
- return serverSocket;
- }
- }
- if (serverSocket == null){
- _msg = ServerReturnCodes.RC_BIND_ERROR + " on ports " + portStr; //$NON-NLS-1$
- System.err.println(_msg);
- }
- }
- else
- {
- port = Integer.parseInt(portStr);
-
-
- // create server socket from port
- if (_dataStore.usingSSL() && sslContext != null)
- {
- try
- {
- serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, bindAddr);
- }
- catch (BindException e){
- _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
- System.err.println(_msg);
- _dataStore.trace(_msg);
- }
- catch (Exception e)
- {
- _dataStore.trace(e);
- }
- }
- else
- {
- try
- {
- serverSocket = new ServerSocket(port, backlog, bindAddr);
- }
- catch (BindException e){
- _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
- System.err.println(_msg);
- _dataStore.trace(_msg);
- }
- catch (Exception e)
- {
- _dataStore.trace(e);
- }
- }
- }
- return serverSocket;
- }
-
- /**
- * Create the DataStore and initializes it's handlers and communications.
- *
- * @param portStr the number of the socket port
- * @param timeoutStr the idle duration to wait before shutting down
- * @param ticketStr validation id required by the client to access the DataStore
- */
- private void setup(String portStr, String timeoutStr, String ticketStr)
- {
- setup(portStr, 50, null, timeoutStr, ticketStr);
- }
-
- /**
- * Create the DataStore and initializes it's handlers and communications.
- *
- * @param portStr the number of the socket port
- * @param backlog listen backlog
- * @param bindAddr the local IP address to bind to
- * @param timeoutStr the idle duration to wait before shutting down
- * @param ticketStr validation id required by the client to access the DataStore
- */
- private void setup(String portStr, int backlog, InetAddress bindAddr, String timeoutStr, String ticketStr)
- {
- _maxConnections = 1;
-
-
- ArrayList loaders = new ArrayList();
- loaders.add(new ExternalLoader(getClass().getClassLoader(), "*")); //$NON-NLS-1$
- _commandHandler = new ServerCommandHandler(loaders);
- _updateHandler = new ServerUpdateHandler();
-
- ISSLProperties sslProperties = new ServerSSLProperties();
-
- _dataStore = new DataStore(_serverAttributes, _commandHandler, _updateHandler, null);
- _dataStore.setSSLProperties(sslProperties);
-
- DataElement ticket = _dataStore.getTicket();
- ticket.setAttribute(DE.A_NAME, ticketStr);
-
- _updateHandler.setDataStore(_dataStore);
- _commandHandler.setDataStore(_dataStore);
-
- if (SystemServiceManager.getInstance().getSystemService() == null)
- {
- Client client = new Client();
- _dataStore.setClient(client);
- ServerLogger logger = new ServerLogger(_dataStore.getUserPreferencesDirectory());
- client.setLogger(logger);
- }
-
- _receivers = new ArrayList();
- _continue = true;
-
- try
- {
-
- _serverSocket = createSocket(portStr, backlog, bindAddr);
- if (_serverSocket == null)
- {
- _continue = false;
- }
- else
- {
- // timeout
- if (timeoutStr != null)
- {
- _timeout = Integer.parseInt(timeoutStr);
- }
- else
- {
- _timeout = 120000;
- }
-
- if (_timeout > 0)
- {
- _serverSocket.setSoTimeout(_timeout);
- }
-
- System.err.println(ServerReturnCodes.RC_SUCCESS);
- System.err.println(_serverSocket.getLocalPort());
- _msg = ServerReturnCodes.RC_SUCCESS;
- System.err.println("Server running on: " + ServerAttributes.getHostName()); //$NON-NLS-1$
- }
- }
- catch (UnknownHostException e)
- {
- System.err.println(ServerReturnCodes.RC_UNKNOWN_HOST_ERROR + ':' + e.getMessage());
- _msg = ServerReturnCodes.RC_UNKNOWN_HOST_ERROR;
- _continue = false;
- }
- catch (BindException e)
- {
- System.err.println(ServerReturnCodes.RC_BIND_ERROR + ':' + e.getMessage());
- _msg = ServerReturnCodes.RC_BIND_ERROR;
- _continue = false;
- }
- catch (IOException e)
- {
- System.err.println(ServerReturnCodes.RC_GENERAL_IO_ERROR + ':' + e.getMessage());
- _msg = ServerReturnCodes.RC_GENERAL_IO_ERROR;
- _continue = false;
- }
- catch (SecurityException e)
- {
- System.err.println(ServerReturnCodes.RC_SECURITY_ERROR + ':' + e.getMessage());
- _msg = ServerReturnCodes.RC_SECURITY_ERROR;
- _continue = false;
- }
- }
-
- private void run()
- {
- waitForConnections();
- }
-
- private void doHandShake(Socket socket)
- {
- try
- {
- BufferedWriter bwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), DE.ENCODING_UTF_8));
- PrintWriter writer = new PrintWriter(bwriter);
-
- String version = DataStoreAttributes.DATASTORE_VERSION;
- String preferenceVersion = System.getProperty("DSTORE_VERSION"); //$NON-NLS-1$
- if (preferenceVersion != null && preferenceVersion.length() > 0){
- version = preferenceVersion;
- }
- writer.println(version);
- writer.flush();
-
- if (socket instanceof SSLSocket){ // log the protocol and cipher suite used
- SSLSocket sslSocket = (SSLSocket)socket;
- SSLSession session = sslSocket.getSession();
- String protocol = session.getProtocol();
- String cipherSuite = session.getCipherSuite();
- IServerLogger logger = _dataStore.getClient().getLogger();
-
- String cn = getClass().toString();
-
- logger.logInfo(cn, "SSL/TLS Protocol: "+protocol); //$NON-NLS-1$
- logger.logInfo(cn, "SSL/TLS Cipher Suite: " + cipherSuite); //$NON-NLS-1$
- }
- }
- catch (IOException e)
- {
- if (_dataStore.getClient() != null) {
- _dataStore.getClient().getLogger().logError(this.getClass().toString(), e.toString(), e);
- }
- System.out.println(e);
- }
-
- }
-
-
-
- private void logAvailableCiphersAndProtocols(SSLServerSocket sslSocket){
- IServerLogger logger = _dataStore.getClient().getLogger();
-
- String cn = getClass().toString();
- // list the supported and available ciphers and protocols
- logger.logDebugMessage(cn, "SSL/TLS Enabled Cipher Suites:"); //$NON-NLS-1$
- String[] enabledSuites = sslSocket.getEnabledCipherSuites();
- for (int i = 0; i < enabledSuites.length; i++){
- String suite = enabledSuites[i];
- logger.logDebugMessage(cn, '\t' + suite);
- }
-
- String[] supportedSuites = sslSocket.getSupportedCipherSuites();
- logger.logDebugMessage(cn, "SSL/TLS Supported Cipher Suites:"); //$NON-NLS-1$
- for (int i = 0; i < supportedSuites.length; i++){
- String suite = supportedSuites[i];
- logger.logDebugMessage(cn, '\t' + suite);
- }
-
- String[] enabledProtocols = sslSocket.getEnabledProtocols();
- logger.logDebugMessage(cn, "SSL/TLS Enabled Protocols:"); //$NON-NLS-1$
- for (int i = 0; i < enabledProtocols.length; i++){
- String eprotocol = enabledProtocols[i];
- logger.logDebugMessage(cn, '\t' + eprotocol);
- }
-
- String[] supportedProtocols = sslSocket.getSupportedProtocols();
- logger.logDebugMessage(cn, "SSL/TLS Supported Protocols:"); //$NON-NLS-1$
- for (int i = 0; i < supportedProtocols.length; i++){
- String sprotocol = supportedProtocols[i];
- logger.logDebugMessage(cn, '\t' + sprotocol);
- }
- }
-
- /**
- * Specify cipher patterns to be disabled when using SSL sockets
- * @param cipherPatterns regex patterns of ciphers to disable
- */
- public void setDisabledCipherPatterns(String[] cipherPatterns){
- _disabledCipherPatterns = cipherPatterns;
- }
-
- /**
- * Specify protocol patterns to be disabled when using SSL sockets
- * @param protocolPatterns regex patterns of protocols to disable
- */
- public void setDisabledProtocolPatterns(String[] protocolPatterns){
- _disabledProtocolPatterns = protocolPatterns;
- }
-
- /**
- * Specify ciphers to be enabled when using SSL sockets
- * @param ciphers to enable
- */
- public void setEnabledCiphers(String[] ciphers){
- _enabledCiphers = ciphers;
- }
-
- /**
- * Specify protocols to be enabled when using SSL sockets
- * @param protocols to enable
- */
- public void setEnabledProtocols(String[] protocols){
- _enabledProtocols = protocols;
- }
-
- private String[] filterNames(String[] inNames, String[] filters){
- List outNames = new ArrayList();
- for (int n = 0; n < inNames.length; n++){
- String inName = inNames[n];
- boolean match = false;
- for (int i = 0; i < filters.length && !match; i++){
- String filter = filters[i];
- match = inName.matches(filter);
- }
- if (!match){
- outNames.add(inName);
- }
- else {
- String cn = getClass().toString();
- IServerLogger logger = _dataStore.getClient().getLogger();
- logger.logDebugMessage(cn, "Filtering out: " + inName); //$NON-NLS-1$
- }
- }
- return (String[])outNames.toArray(new String[outNames.size()]);
- }
-
- private void disableCiphers(SSLServerSocket socket){
- if (_disabledCipherPatterns != null){
- String[] enabledSuites = socket.getEnabledCipherSuites();
- String[] newEnabledSuites = filterNames(enabledSuites, _disabledCipherPatterns);
-
- socket.setEnabledCipherSuites(newEnabledSuites);
- }
- }
-
- private void disableProtocols(SSLServerSocket socket){
- if (_disabledProtocolPatterns != null){
- String[] enabledProtocols = socket.getEnabledProtocols();
- String[] newEnabledProtocols = filterNames(enabledProtocols, _disabledProtocolPatterns);
- socket.setEnabledProtocols(newEnabledProtocols);
- }
- }
-
- private String[] mergeCommon(String[] inNames1, String[] inNames2){
- List merged = new ArrayList();
- for (int n = 0; n < inNames1.length; n++){
- String inName1 = inNames1[n];
- boolean match = false;
- for (int i = 0; i < inNames2.length && !match; i++){
- match = inName1.equals(inNames2[i]);
- }
- if (match){
- merged.add(inName1);
- }
- }
- return (String[])merged.toArray(new String[merged.size()]);
- }
-
- private void enableCiphers(SSLServerSocket socket){
- if (_enabledCiphers != null){
- String[] enabledSuites = socket.getEnabledCipherSuites();
- String[] newEnabledSuites = mergeCommon(enabledSuites, _enabledCiphers);
- if (newEnabledSuites.length > 0){
- socket.setEnabledCipherSuites(newEnabledSuites);
- }
- }
- }
-
- private void enableProtocols(SSLServerSocket socket){
- if (_enabledProtocols != null){
- String[] enabledProtocols = socket.getEnabledProtocols();
- String[] newEnabledProtocols = mergeCommon(enabledProtocols, _enabledProtocols);
- if (newEnabledProtocols.length > 0){
- socket.setEnabledCipherSuites(newEnabledProtocols);
- }
- }
- }
-}
+/*******************************************************************************
+ * Copyright (c) 2002, 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * David McKnight (IBM) [220123][dstore] Configurable timeout on irresponsiveness
+ * David McKnight (IBM) [220892][dstore] Backward compatibility: Server and Daemon should support old clients
+ * Noriaki Takatsu (IBM) - [220126] [dstore][api][breaking] Single process server for multiple clients
+ * David McKnight (IBM) [224906] [dstore] changes for getting properties and doing exit due to single-process capability
+ * Jacob Garcowski (IBM) [225175] [dstore] error handling change for Client
+ * David McKnight (IBM) - [225507][api][breaking] RSE dstore API leaks non-API types
+ * Noriaki Takatsu (IBM) - [226074] process for getStatus() API
+ * Noriaki Takatsu (IBM) - [226237] [dstore] Move the place where the ServerLogger instance is made
+ * David McKnight (IBM) - [226561] [apidoc] Add API markup to RSE Javadocs where extend / implement is allowed
+ * Noriaki Takatsu (IBM) - [242968] [multithread] serverSocket must be closed when an exception happens in Accept
+ * David McKnight (IBM) - [257321] [dstore] "Error binding socket" should include port of the failed socket
+ * Noriaki Takatsu (IBM) - [283656] [dstore][multithread] Serviceability issue
+ * Noriaki Takatsu (IBM) - [289678][api][breaking] ServerSocket creation in multiple IP addresses
+ * David McKnight (IBM) - [368072] [dstore][ssl] no exception logged upon bind error
+ * David McKnight (IBM) - [371401] [dstore][multithread] avoid use of static variables - causes memory leak after disconnect
+ * David McKnight (IBM) - [388472] [dstore] need alternative option for getting at server hostname
+ * David McKnight (IBM) - [390681] [dstore] need to merge differences between HEAD stream and 3.2 in ConnectionEstablisher.finished()
+ * David McKnight (IBM) [439545][dstore] potential deadlock on senders during shutdown
+ * David McKnight (IBM) [464736][dstore] need methods to disable ciphers and protocols
+ * David McKnight (IBM) [473086][dstore] enableProtocols() calls setEnabledCipherSuites(), not setEnabledProtocols()
+ *******************************************************************************/
+
+package org.eclipse.dstore.core.server;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.eclipse.dstore.core.model.Client;
+import org.eclipse.dstore.core.model.DE;
+import org.eclipse.dstore.core.model.DataElement;
+import org.eclipse.dstore.core.model.DataStore;
+import org.eclipse.dstore.core.model.DataStoreAttributes;
+import org.eclipse.dstore.core.model.ISSLProperties;
+import org.eclipse.dstore.internal.core.server.ServerAttributes;
+import org.eclipse.dstore.internal.core.server.ServerCommandHandler;
+import org.eclipse.dstore.internal.core.server.ServerReturnCodes;
+import org.eclipse.dstore.internal.core.server.ServerSSLProperties;
+import org.eclipse.dstore.internal.core.server.ServerUpdateHandler;
+import org.eclipse.dstore.internal.core.util.ExternalLoader;
+import org.eclipse.dstore.internal.core.util.Sender;
+import org.eclipse.dstore.internal.core.util.ssl.DStoreSSLContext;
+
+/**
+ * ConnectionEstablisher is responsible for managing the server DataStore and
+ * facilitating the communication between client and server DataStores.
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ *
+ * @since 3.0 moved from non-API to API
+ */
+public class ConnectionEstablisher
+{
+
+
+ private ServerSocket _serverSocket;
+ private boolean _continue;
+
+ private ArrayList _receivers;
+
+ private ServerCommandHandler _commandHandler;
+ private ServerUpdateHandler _updateHandler;
+
+ private ServerAttributes _serverAttributes = new ServerAttributes();
+ private DataStore _dataStore;
+
+ private int _maxConnections;
+ private int _timeout;
+ private String _msg;
+
+
+ private String[] _disabledCipherPatterns = null;
+ private String[] _disabledProtocolPatterns = null;
+ private String[] _enabledCiphers = null;
+ private String[] _enabledProtocols = null;
+
+
+
+ /**
+ * Creates the default ConnectionEstablisher. Communication occurs
+ * on a default port, there is no timeout and no ticket is required
+ * for a client to work with the DataStore.
+ *
+ */
+ public ConnectionEstablisher()
+ {
+ String port = _serverAttributes.getAttribute(DataStoreAttributes.A_HOST_PORT);
+ setup(port, null, null);
+ }
+
+ /**
+ * Creates a ConnectionEstablisher. Communication occurs
+ * on the specified port, there is no timeout and no ticket is required
+ * for a client to work with the DataStore.
+ *
+ * @param port the number of the socket port
+ */
+ public ConnectionEstablisher(String port)
+ {
+ setup(port, null, null);
+ }
+
+ /**
+ * Creates a ConnectionEstablisher. Communication occurs
+ * on the specified port, a timeout value indicates the idle wait
+ * time before shutting down, and no ticket is required
+ * for a client to work with the DataStore.
+ *
+ * @param port the number of the socket port
+ * @param timeout the idle duration to wait before shutting down
+ */
+ public ConnectionEstablisher(String port, String timeout)
+ {
+ setup(port, timeout, null);
+ }
+
+ /**
+ * Creates a ConnectionEstablisher. Communication occurs
+ * on the specified port, a timeout value indicates the idle wait
+ * time before shutting down, and ticket specified the required
+ * ticket for a client to present in order to work with the DataStore.
+ *
+ * @param port the number of the socket port
+ * @param timeout the idle duration to wait before shutting down
+ * @param ticket validation id required by the client to access the DataStore
+ */
+ public ConnectionEstablisher(String port, String timeout, String ticket)
+ {
+ setup(port, timeout, ticket);
+ }
+
+ /**
+ * Creates a ConnectionEstablisher. Communication occurs
+ * on the specified port and the specified IP address,
+ * a timeout value indicates the idle wait time
+ * before shutting down, and ticket specified the required
+ * ticket for a client to present in order to work with the DataStore.
+ *
+ * @param port the number of the socket port
+ * @param backlog listen backlog
+ * @param bindAddr the local IP address to bind to
+ * @param timeout the idle duration to wait before shutting down
+ * @param ticket validation id required by the client to access the DataStore
+ * @since 3.2
+ */
+ public ConnectionEstablisher(String port, int backlog, InetAddress bindAddr, String timeout, String ticket)
+ {
+ setup(port, backlog, bindAddr, timeout, ticket);
+ }
+
+
+ /**
+ * Starts the run loop for the ConnectionEstablisher.
+ */
+ public void start()
+ {
+ run();
+ }
+
+
+
+ /**
+ * Returns the DataStore.
+ *
+ * @return the DataStore
+ */
+ public DataStore getDataStore()
+ {
+ return _dataStore;
+ }
+
+ /**
+ * Return the Server port opened for this client
+ *
+ * @return the Server port opened for this client
+ */
+ public int getServerPort()
+ {
+ if (_serverSocket != null)
+ {
+ return _serverSocket.getLocalPort();
+ }
+
+ return -1;
+ }
+
+ /**
+ * Return the connection status for this client
+ *
+ * * @return the connection status for this client
+ */
+ public String getStatus()
+ {
+ return _msg;
+ }
+
+ /**
+ * Tells the connection establisher to clean up and shutdown
+ */
+ public void finished(ServerReceiver receiver)
+ {
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher.finished()"); //$NON-NLS-1$
+ }
+
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing receiver"); //$NON-NLS-1$
+ }
+ _receivers.remove(receiver);
+
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing preference listener"); //$NON-NLS-1$
+ }
+ _dataStore.removeDataStorePreferenceListener(receiver);
+ //if (_receivers.size() == 0)
+ {
+ _continue = false;
+ _commandHandler.finish();
+
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing update handler"); //$NON-NLS-1$
+ }
+ _updateHandler.finish();
+
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing sender"); //$NON-NLS-1$
+ }
+ _updateHandler.removeSenderWith(receiver.socket());
+
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing DataStore"); //$NON-NLS-1$
+ }
+ _dataStore.finish();
+ System.out.println(ServerReturnCodes.RC_FINISHED);
+
+ if (SystemServiceManager.getInstance().getSystemService() == null)
+ System.exit(0);
+ }
+ }
+
+ private void waitForConnections()
+ {
+ while (_continue == true)
+ {
+ try
+ {
+ if (_dataStore.usingSSL())
+ {
+ SSLServerSocket sslServerSocket = (SSLServerSocket)_serverSocket;
+ // for security, disable ciphers and protocols we don't want
+ disableCiphers(sslServerSocket);
+ disableProtocols(sslServerSocket);
+
+ // for security, enable only ciphers and protocols that are common
+ enableCiphers(sslServerSocket);
+ enableProtocols(sslServerSocket);
+
+ logAvailableCiphersAndProtocols(sslServerSocket);
+ }
+
+ Socket newSocket = _serverSocket.accept();
+ if (_dataStore.usingSSL())
+ {
+
+ // wait for connection
+ SSLSocket sslSocket = (SSLSocket)newSocket;
+ sslSocket.setUseClientMode(false);
+ sslSocket.setNeedClientAuth(false);
+ SSLSession session = sslSocket.getSession();
+
+ if (session == null)
+ {
+ System.out.println("handshake failed"); //$NON-NLS-1$
+ sslSocket.close();
+ return;
+ }
+ }
+
+ doHandShake(newSocket);
+ newSocket.setKeepAlive(true);
+
+ ServerReceiver receiver = new ServerReceiver(newSocket, this);
+ _dataStore.addDataStorePreferenceListener(receiver);
+
+ if (_dataStore.getClient() != null)
+ _dataStore.getClient().setServerReceiver(receiver);
+
+ Sender sender = new Sender(newSocket, _dataStore);
+
+ // add this connection to list of elements
+ _receivers.add(receiver);
+ _updateHandler.addSender(sender);
+
+ receiver.start();
+
+ if (_receivers.size() == 1)
+ {
+ _updateHandler.start();
+ _commandHandler.start();
+ }
+
+ if (_receivers.size() == _maxConnections)
+ {
+ _continue = false;
+ _serverSocket.close();
+
+ }
+ }
+ catch (IOException ioe)
+ {
+ System.err.println(ServerReturnCodes.RC_CONNECTION_ERROR);
+ System.err.println("Server: error initializing socket: " + ioe); //$NON-NLS-1$
+ _msg = ioe.toString();
+ try
+ {
+ _serverSocket.close();
+ }
+ catch (Throwable e)
+ {
+
+ }
+ _continue = false;
+ }
+ }
+ }
+
+
+
+
+ private ServerSocket createSocket(String portStr, int backlog, InetAddress bindAddr) throws UnknownHostException
+ {
+ ServerSocket serverSocket = null;
+ SSLContext sslContext = null;
+ // port
+ int port = 0;
+
+ if (_dataStore.usingSSL())
+ {
+ String keyStoreFileName = _dataStore.getKeyStoreLocation();
+ String keyStorePassword = _dataStore.getKeyStorePassword();
+
+ try
+ {
+ sslContext = DStoreSSLContext.getServerSSLContext(keyStoreFileName, keyStorePassword);
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+
+ // determine if portStr is a port range or just a port
+ String[] range = portStr.split("-"); //$NON-NLS-1$
+ if (range.length == 2)
+ {
+ int lPort = 0;
+ int hPort = 0;
+ try
+ {
+ lPort = Integer.parseInt(range[0]);
+ hPort = Integer.parseInt(range[1]);
+ }
+ catch (Exception e)
+ {
+ }
+
+ for (int i = lPort; i < hPort; i++)
+ {
+ // create server socket from port
+ try
+ {
+ if (_dataStore.usingSSL() && sslContext != null)
+ {
+ try
+ {
+ serverSocket = sslContext.getServerSocketFactory().createServerSocket(i, backlog, bindAddr);
+ }
+ catch (BindException e)
+ {
+ _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+ System.err.println(_msg);
+ _dataStore.trace(_msg);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ else
+ {
+ try
+ {
+ serverSocket = new ServerSocket(i, backlog, bindAddr);
+ }
+ catch (BindException e)
+ {
+ _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+ System.err.println(_msg);
+ _dataStore.trace(_msg);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _dataStore.trace(e);
+ }
+ if (serverSocket != null && serverSocket.getLocalPort() > 0)
+ {
+ return serverSocket;
+ }
+ }
+ if (serverSocket == null){
+ _msg = ServerReturnCodes.RC_BIND_ERROR + " on ports " + portStr; //$NON-NLS-1$
+ System.err.println(_msg);
+ }
+ }
+ else
+ {
+ port = Integer.parseInt(portStr);
+
+
+ // create server socket from port
+ if (_dataStore.usingSSL() && sslContext != null)
+ {
+ try
+ {
+ serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, bindAddr);
+ }
+ catch (BindException e){
+ _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+ System.err.println(_msg);
+ _dataStore.trace(_msg);
+ }
+ catch (Exception e)
+ {
+ _dataStore.trace(e);
+ }
+ }
+ else
+ {
+ try
+ {
+ serverSocket = new ServerSocket(port, backlog, bindAddr);
+ }
+ catch (BindException e){
+ _msg = ServerReturnCodes.RC_BIND_ERROR + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+ System.err.println(_msg);
+ _dataStore.trace(_msg);
+ }
+ catch (Exception e)
+ {
+ _dataStore.trace(e);
+ }
+ }
+ }
+ return serverSocket;
+ }
+
+ /**
+ * Create the DataStore and initializes it's handlers and communications.
+ *
+ * @param portStr the number of the socket port
+ * @param timeoutStr the idle duration to wait before shutting down
+ * @param ticketStr validation id required by the client to access the DataStore
+ */
+ private void setup(String portStr, String timeoutStr, String ticketStr)
+ {
+ setup(portStr, 50, null, timeoutStr, ticketStr);
+ }
+
+ /**
+ * Create the DataStore and initializes it's handlers and communications.
+ *
+ * @param portStr the number of the socket port
+ * @param backlog listen backlog
+ * @param bindAddr the local IP address to bind to
+ * @param timeoutStr the idle duration to wait before shutting down
+ * @param ticketStr validation id required by the client to access the DataStore
+ */
+ private void setup(String portStr, int backlog, InetAddress bindAddr, String timeoutStr, String ticketStr)
+ {
+ _maxConnections = 1;
+
+
+ ArrayList loaders = new ArrayList();
+ loaders.add(new ExternalLoader(getClass().getClassLoader(), "*")); //$NON-NLS-1$
+ _commandHandler = new ServerCommandHandler(loaders);
+ _updateHandler = new ServerUpdateHandler();
+
+ ISSLProperties sslProperties = new ServerSSLProperties();
+
+ _dataStore = new DataStore(_serverAttributes, _commandHandler, _updateHandler, null);
+ _dataStore.setSSLProperties(sslProperties);
+
+ DataElement ticket = _dataStore.getTicket();
+ ticket.setAttribute(DE.A_NAME, ticketStr);
+
+ _updateHandler.setDataStore(_dataStore);
+ _commandHandler.setDataStore(_dataStore);
+
+ if (SystemServiceManager.getInstance().getSystemService() == null)
+ {
+ Client client = new Client();
+ _dataStore.setClient(client);
+ ServerLogger logger = new ServerLogger(_dataStore.getUserPreferencesDirectory());
+ client.setLogger(logger);
+ }
+
+ _receivers = new ArrayList();
+ _continue = true;
+
+ try
+ {
+
+ _serverSocket = createSocket(portStr, backlog, bindAddr);
+ if (_serverSocket == null)
+ {
+ _continue = false;
+ }
+ else
+ {
+ // timeout
+ if (timeoutStr != null)
+ {
+ _timeout = Integer.parseInt(timeoutStr);
+ }
+ else
+ {
+ _timeout = 120000;
+ }
+
+ if (_timeout > 0)
+ {
+ _serverSocket.setSoTimeout(_timeout);
+ }
+
+ System.err.println(ServerReturnCodes.RC_SUCCESS);
+ System.err.println(_serverSocket.getLocalPort());
+ _msg = ServerReturnCodes.RC_SUCCESS;
+ System.err.println("Server running on: " + ServerAttributes.getHostName()); //$NON-NLS-1$
+ }
+ }
+ catch (UnknownHostException e)
+ {
+ System.err.println(ServerReturnCodes.RC_UNKNOWN_HOST_ERROR + ':' + e.getMessage());
+ _msg = ServerReturnCodes.RC_UNKNOWN_HOST_ERROR;
+ _continue = false;
+ }
+ catch (BindException e)
+ {
+ System.err.println(ServerReturnCodes.RC_BIND_ERROR + ':' + e.getMessage());
+ _msg = ServerReturnCodes.RC_BIND_ERROR;
+ _continue = false;
+ }
+ catch (IOException e)
+ {
+ System.err.println(ServerReturnCodes.RC_GENERAL_IO_ERROR + ':' + e.getMessage());
+ _msg = ServerReturnCodes.RC_GENERAL_IO_ERROR;
+ _continue = false;
+ }
+ catch (SecurityException e)
+ {
+ System.err.println(ServerReturnCodes.RC_SECURITY_ERROR + ':' + e.getMessage());
+ _msg = ServerReturnCodes.RC_SECURITY_ERROR;
+ _continue = false;
+ }
+ }
+
+ private void run()
+ {
+ waitForConnections();
+ }
+
+ private void doHandShake(Socket socket)
+ {
+ try
+ {
+ BufferedWriter bwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), DE.ENCODING_UTF_8));
+ PrintWriter writer = new PrintWriter(bwriter);
+
+ String version = DataStoreAttributes.DATASTORE_VERSION;
+ String preferenceVersion = System.getProperty("DSTORE_VERSION"); //$NON-NLS-1$
+ if (preferenceVersion != null && preferenceVersion.length() > 0){
+ version = preferenceVersion;
+ }
+ writer.println(version);
+ writer.flush();
+
+ if (socket instanceof SSLSocket){ // log the protocol and cipher suite used
+ SSLSocket sslSocket = (SSLSocket)socket;
+ SSLSession session = sslSocket.getSession();
+ String protocol = session.getProtocol();
+ String cipherSuite = session.getCipherSuite();
+ IServerLogger logger = _dataStore.getClient().getLogger();
+
+ String cn = getClass().toString();
+
+ logger.logInfo(cn, "SSL/TLS Protocol: "+protocol); //$NON-NLS-1$
+ logger.logInfo(cn, "SSL/TLS Cipher Suite: " + cipherSuite); //$NON-NLS-1$
+ }
+ }
+ catch (IOException e)
+ {
+ if (_dataStore.getClient() != null) {
+ _dataStore.getClient().getLogger().logError(this.getClass().toString(), e.toString(), e);
+ }
+ System.out.println(e);
+ }
+
+ }
+
+
+
+ private void logAvailableCiphersAndProtocols(SSLServerSocket sslSocket){
+ IServerLogger logger = _dataStore.getClient().getLogger();
+
+ String cn = getClass().toString();
+ // list the supported and available ciphers and protocols
+ logger.logDebugMessage(cn, "SSL/TLS Enabled Cipher Suites:"); //$NON-NLS-1$
+ String[] enabledSuites = sslSocket.getEnabledCipherSuites();
+ for (int i = 0; i < enabledSuites.length; i++){
+ String suite = enabledSuites[i];
+ logger.logDebugMessage(cn, '\t' + suite);
+ }
+
+ String[] supportedSuites = sslSocket.getSupportedCipherSuites();
+ logger.logDebugMessage(cn, "SSL/TLS Supported Cipher Suites:"); //$NON-NLS-1$
+ for (int i = 0; i < supportedSuites.length; i++){
+ String suite = supportedSuites[i];
+ logger.logDebugMessage(cn, '\t' + suite);
+ }
+
+ String[] enabledProtocols = sslSocket.getEnabledProtocols();
+ logger.logDebugMessage(cn, "SSL/TLS Enabled Protocols:"); //$NON-NLS-1$
+ for (int i = 0; i < enabledProtocols.length; i++){
+ String eprotocol = enabledProtocols[i];
+ logger.logDebugMessage(cn, '\t' + eprotocol);
+ }
+
+ String[] supportedProtocols = sslSocket.getSupportedProtocols();
+ logger.logDebugMessage(cn, "SSL/TLS Supported Protocols:"); //$NON-NLS-1$
+ for (int i = 0; i < supportedProtocols.length; i++){
+ String sprotocol = supportedProtocols[i];
+ logger.logDebugMessage(cn, '\t' + sprotocol);
+ }
+ }
+
+ /**
+ * Specify cipher patterns to be disabled when using SSL sockets
+ * @param cipherPatterns regex patterns of ciphers to disable
+ */
+ public void setDisabledCipherPatterns(String[] cipherPatterns){
+ _disabledCipherPatterns = cipherPatterns;
+ }
+
+ /**
+ * Specify protocol patterns to be disabled when using SSL sockets
+ * @param protocolPatterns regex patterns of protocols to disable
+ */
+ public void setDisabledProtocolPatterns(String[] protocolPatterns){
+ _disabledProtocolPatterns = protocolPatterns;
+ }
+
+ /**
+ * Specify ciphers to be enabled when using SSL sockets
+ * @param ciphers to enable
+ */
+ public void setEnabledCiphers(String[] ciphers){
+ _enabledCiphers = ciphers;
+ }
+
+ /**
+ * Specify protocols to be enabled when using SSL sockets
+ * @param protocols to enable
+ */
+ public void setEnabledProtocols(String[] protocols){
+ _enabledProtocols = protocols;
+ }
+
+ private String[] filterNames(String[] inNames, String[] filters){
+ List outNames = new ArrayList();
+ for (int n = 0; n < inNames.length; n++){
+ String inName = inNames[n];
+ boolean match = false;
+ for (int i = 0; i < filters.length && !match; i++){
+ String filter = filters[i];
+ match = inName.matches(filter);
+ }
+ if (!match){
+ outNames.add(inName);
+ }
+ else {
+ String cn = getClass().toString();
+ IServerLogger logger = _dataStore.getClient().getLogger();
+ logger.logDebugMessage(cn, "Filtering out: " + inName); //$NON-NLS-1$
+ }
+ }
+ return (String[])outNames.toArray(new String[outNames.size()]);
+ }
+
+ private void disableCiphers(SSLServerSocket socket){
+ if (_disabledCipherPatterns != null){
+ String[] enabledSuites = socket.getEnabledCipherSuites();
+ String[] newEnabledSuites = filterNames(enabledSuites, _disabledCipherPatterns);
+
+ socket.setEnabledCipherSuites(newEnabledSuites);
+ }
+ }
+
+ private void disableProtocols(SSLServerSocket socket){
+ if (_disabledProtocolPatterns != null){
+ String[] enabledProtocols = socket.getEnabledProtocols();
+ String[] newEnabledProtocols = filterNames(enabledProtocols, _disabledProtocolPatterns);
+ socket.setEnabledProtocols(newEnabledProtocols);
+ }
+ }
+
+ private String[] mergeCommon(String[] inNames1, String[] inNames2){
+ List merged = new ArrayList();
+ for (int n = 0; n < inNames1.length; n++){
+ String inName1 = inNames1[n];
+ boolean match = false;
+ for (int i = 0; i < inNames2.length && !match; i++){
+ match = inName1.equals(inNames2[i]);
+ }
+ if (match){
+ merged.add(inName1);
+ }
+ }
+ return (String[])merged.toArray(new String[merged.size()]);
+ }
+
+ private void enableCiphers(SSLServerSocket socket){
+ if (_enabledCiphers != null){
+ String[] enabledSuites = socket.getEnabledCipherSuites();
+ String[] newEnabledSuites = mergeCommon(enabledSuites, _enabledCiphers);
+ if (newEnabledSuites.length > 0){
+ socket.setEnabledCipherSuites(newEnabledSuites);
+ }
+ }
+ }
+
+ private void enableProtocols(SSLServerSocket socket){
+ if (_enabledProtocols != null){
+ String[] enabledProtocols = socket.getEnabledProtocols();
+ String[] newEnabledProtocols = mergeCommon(enabledProtocols, _enabledProtocols);
+ if (newEnabledProtocols.length > 0){
+ socket.setEnabledProtocols(newEnabledProtocols);
+ }
+ }
+ }
+}