Alachisoft.NCache.Common.Communication.Secure.SecureStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nc-common Show documentation
Show all versions of nc-common Show documentation
Internal package of Alachisoft.
package Alachisoft.NCache.Common.Communication.Secure;
import javax.net.ssl.*;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
public class SecureStream extends Socket {
private final LinkedHashMap authorizedNodeCertificates =
new LinkedHashMap();
String keyStoreType;
private boolean tlsNeedClientAuth = true;
private String[] tlsCipherSuites = {};
private String[] tlsProtocols = {"TLSv1", "SSLv3"};
private transient volatile SSLContext sslContext;
private String keyStoreURL;
private transient volatile KeyManager km;
private transient volatile TrustManager tm;
private String keyStorePin;
private String keyStorePinProperty;
private String keyStoreKeyPin;
private String keyStoreKeyPinProperty;
private String trustStoreURL;
private String trustStoreType;
private String trustStorePin;
private String trustStorePinProperty;
private boolean rebindNeeded;
public SecureStream(Socket secondaryClient) {
}
private static SSLContext createSSLContext(KeyManager km, TrustManager tm)
throws GeneralSecurityException {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(km != null ? new KeyManager[]{km} : null,
tm != null ? new TrustManager[]{tm} : null, null);
return ctx;
}
private static X509Certificate[] toArray(Collection c) {
int size = 0;
for (X509Certificate[] certs : c)
size += certs.length;
X509Certificate[] dest = new X509Certificate[size];
int destPos = 0;
for (X509Certificate[] certs : c) {
System.arraycopy(certs, 0, dest, destPos, certs.length);
destPos += certs.length;
}
return dest;
}
private static String[] intersect(String[] ss1, String[] ss2) {
String[] ss = new String[Math.min(ss1.length, ss2.length)];
int len = 0;
for (String s1 : ss1)
for (String s2 : ss2)
if (s1.equals(s2)) {
ss[len++] = s1;
break;
}
if (len == ss.length)
return ss;
String[] dest = new String[len];
System.arraycopy(ss, 0, dest, 0, len);
return dest;
}
/**
* The TLS CipherSuites that are supported on this particular connection.
* TLS CipherSuites shall be described using an RFC-2246 string
* representation (e.g. 'SSL_RSA_WITH_3DES_EDE_CBC_SHA')
*
* @return A String array containing the supported cipher suites
*/
public String[] getTlsCipherSuites() {
return tlsCipherSuites;
}
/**
* The TLS CipherSuites that are supported on this particular connection.
* TLS CipherSuites shall be described using an RFC-2246 string
* representation (e.g. 'SSL_RSA_WITH_3DES_EDE_CBC_SHA')
*
* @param tlsCipherSuites A String array containing the supported cipher suites
*/
public void setTlsCipherSuites(String... tlsCipherSuites) {
if (Arrays.equals(this.tlsCipherSuites, tlsCipherSuites))
return;
this.tlsCipherSuites = tlsCipherSuites;
needRebind();
}
public final boolean isTls() {
return tlsCipherSuites.length > 0;
}
public final String[] getTlsProtocols() {
return tlsProtocols;
}
public final void setTlsProtocols(String... tlsProtocols) {
if (Arrays.equals(this.tlsProtocols, tlsProtocols))
return;
this.tlsProtocols = tlsProtocols;
needRebind();
}
public final boolean isTlsNeedClientAuth() {
return tlsNeedClientAuth;
}
public final void setTlsNeedClientAuth(boolean tlsNeedClientAuth) {
if (this.tlsNeedClientAuth == tlsNeedClientAuth)
return;
this.tlsNeedClientAuth = tlsNeedClientAuth;
needRebind();
}
void needRebind() {
this.rebindNeeded = true;
}
private ServerSocket createTLSServerSocket() throws IOException, GeneralSecurityException {
SSLContext sslContext = sslContext();
SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
SSLServerSocket ss = (SSLServerSocket) ssf.createServerSocket();
ss.setEnabledProtocols(tlsProtocols);
ss.setEnabledCipherSuites(tlsCipherSuites);
ss.setNeedClientAuth(tlsNeedClientAuth);
return ss;
}
private SSLSocket createTLSSocket(Socket s, String hostName, int port)
throws GeneralSecurityException, IOException {
SSLContext sslContext = sslContext();
SSLSocketFactory sf = sslContext.getSocketFactory();
SSLSocket ssl = (SSLSocket) sf.createSocket(s, hostName, port, true);
ssl.setEnabledProtocols(intersect(tlsProtocols, tlsProtocols));
ssl.setEnabledCipherSuites(intersect(tlsCipherSuites, tlsCipherSuites));
ssl.startHandshake();
return ssl;
}
SSLContext sslContext() throws GeneralSecurityException, IOException {
SSLContext ctx = sslContext;
if (ctx != null)
return ctx;
sslContext = ctx = createSSLContext(km(), tm());
return ctx;
}
private KeyManager km() throws GeneralSecurityException, IOException {
KeyManager ret = km;
if (ret != null || keyStoreURL == null)
return ret;
String keyStorePin = keyStorePin();
km = ret = SSLManagerFactory.createKeyManager(keyStoreType(),
keyStoreURL, keyStorePin(), keyPin(keyStorePin));
return ret;
}
private TrustManager tm() throws GeneralSecurityException, IOException {
TrustManager ret = tm;
if (ret != null
|| trustStoreURL == null && authorizedNodeCertificates.isEmpty())
return ret;
tm = ret = trustStoreURL != null
? SSLManagerFactory.createTrustManager(trustStoreType(),
trustStoreURL, trustStorePin())
: SSLManagerFactory.createTrustManager(
getAllAuthorizedNodeCertificates());
return ret;
}
private String keyStoreType() {
if (keyStoreType == null)
throw new IllegalStateException("keyStoreURL requires keyStoreType");
return keyStoreType;
}
public final String getKeyStorePin() {
return keyStorePin;
}
public final void setKeyStorePin(String keyStorePin) {
checkNotEmpty("keyStorePin", keyStorePin);
this.keyStorePin = keyStorePin;
}
private String keyStorePin() {
if (keyStorePin != null)
return keyStorePin;
if (keyStorePinProperty == null)
throw new IllegalStateException(
"keyStoreURL requires keyStorePin or keyStorePinProperty");
String pin = System.getProperty(keyStorePinProperty);
if (pin == null)
throw new IllegalStateException(
"No such keyStorePinProperty: " + keyStorePinProperty);
return pin;
}
private void checkNotEmpty(String name, String val) {
if (val != null && val.isEmpty())
throw new IllegalArgumentException(name + " cannot be empty");
}
private String keyPin(String keyStorePin) {
if (keyStoreKeyPin != null)
return keyStoreKeyPin;
if (keyStoreKeyPinProperty == null)
return keyStorePin;
String pin = System.getProperty(keyStoreKeyPinProperty);
if (pin == null)
throw new IllegalStateException(
"No such keyPinProperty: " + keyStoreKeyPinProperty);
return pin;
}
private String trustStoreType() {
if (trustStoreType == null)
throw new IllegalStateException("trustStoreURL requires trustStoreType");
return trustStoreType;
}
private String trustStorePin() {
if (trustStorePin != null)
return trustStorePin;
if (trustStorePinProperty == null)
throw new IllegalStateException(
"trustStoreURL requires trustStorePin or trustStorePinProperty");
String pin = System.getProperty(trustStorePinProperty);
if (pin == null)
throw new IllegalStateException(
"No such trustStorePinProperty: " + trustStorePinProperty);
return pin;
}
public X509Certificate[] getAllAuthorizedNodeCertificates() {
return toArray(authorizedNodeCertificates.values());
}
public void InitializeAsClient(String targetHost, boolean provideCert) {
}
public void write(byte[] buffer) throws IOException {
}
public int read(byte[] argvalue, int totalBytesRecieved, int i) throws IOException {
return 0;
}
}