All Downloads are FREE. Search and download functionalities are using the official Maven repository.

Alachisoft.NCache.Common.Communication.Secure.SecureStream Maven / Gradle / Ivy

There is a newer version: 5.3.3
Show newest version
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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy