Ошибка рукопожатия с ReloadableX509TrustManager в Java - PullRequest
0 голосов
/ 24 января 2019

У меня следующая проблема. Я реализовал динамический обмен файлами trustore.jks на моем сервере с помощью ReloadableX509TrustManager. Проблема в том, что когда я перезагружаю сервер и пытаюсь подключить большое количество клиентов к моему серверу, не все клиенты подключаются сразу. Некоторые из них через некоторое время подключатся к серверу, и до этого я получаю такую ​​ошибку:

2019-01-24 10: 03: 16,908 ОШИБКА c.s.Server [Тема-26] javax.net.ssl.SSLException: получен close_notify во время рукопожатия javax.net.ssl.SSLException: получено close_notify во время рукопожатия
at sun.security.ssl.Alerts.getSSLException (Alerts.java:208) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1946) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1898) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.recvAlert (SSLSocketImpl.java:1999) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:1127) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1367) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:750) ~ [?: 1.8.0_191] в sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream $ BlockDataOutputStream.drain (ObjectOutputStream.java:1877) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream $ BlockDataOutputStream.setBlockDataMode (ObjectOutputStream.java:1786) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream. (ObjectOutputStream.java:247) ~ [?: 1.8.0_191] в api.server.Server $ ConnectionClientRepresentation.run (Server.java:254) [Serwer_szy_res_adr.jar:]

И иногда я тоже получаю следующую ошибку:

2019-01-24 12: 56: 43,715 ОШИБКА c.s.Server [Thread-429066] javax.net.ssl.SSLException: нераспознанное сообщение SSL, открытый текст связь? javax.net.ssl.SSLException: нераспознанное сообщение SSL, текстовое соединение? в sun.security.ssl.InputRecord.handleUnknownRecord (InputRecord.java:710) ~ [?: 1.8.0_191] в sun.security.ssl.InputRecord.read (InputRecord.java:527) ~ [?: 1.8.0_191] at sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:975) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1367) ~ [?: 1.8.0_191] в sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:750) ~ [?: 1.8.0_191] в sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream $ BlockDataOutputStream.drain (ObjectOutputStream.java:1877) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream $ BlockDataOutputStream.setBlockDataMode (ObjectOutputStream.java:1786) ~ [?: 1.8.0_191] в java.io.ObjectOutputStream. (ObjectOutputStream.java:247) ~ [?: 1.8.0_191] в api.server.Server $ ConnectionClientRepresentation.run (Server.java:254) [Serwer_szyf_res_adr.jar:]

Моя реализация сервера:

class ReloadableX509TrustManager implements X509TrustManager {
    private final String trustStorePath;
    private X509TrustManager trustManager;

    public ReloadableX509TrustManager(String pathToTrustStore) throws Exception {
        this.trustStorePath = pathToTrustStore;
        reloadTrustManager();
    }

    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        try {
            reloadTrustManager();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String username = x509Certificates[0].getSubjectDN().getName().split("CN=")[1].split(",")[0];
        x509Certificates[0].checkValidity();
        System.out.println("Trying to connect : " + username);
        trustManager.checkClientTrusted(x509Certificates, s);
        x509Certificates[0].checkValidity();
        System.out.println("User " + username + " signed in, you are authenticated!");
    }


    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//            trustManager.checkServerTrusted(x509Certificates, s);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        X509Certificate[] issuers = trustManager.getAcceptedIssuers();
        return issuers;
    }

    private void reloadTrustManager() throws Exception {
        KeyStore trustStore = KeyStore.getInstance("JKS");
        InputStream in = new FileInputStream(trustStorePath);
        try {
            trustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray());
        } finally {
            in.close();
        }

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
        trustManagerFactory.init(trustStore);

        TrustManager trustManagers[] = trustManagerFactory.getTrustManagers();
        for (int i = 0; i < trustManagers.length; i++) {
            if (trustManagers[i] instanceof X509TrustManager) {
                trustManager = (X509TrustManager) trustManagers[i];
                return;
            }
        }
        throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory");
    }
}



public void run() {
    try {
        createSSLServerSocketFactory();
        SSLServerSocket ss = (SSLServerSocket) factory.createServerSocket(port);
        while (true) {
            SSLSocket s = (SSLSocket) ss.accept();
            s.setNeedClientAuth(true);
            try {
                ConnectionClientRepresentation connection = new ConnectionClientRepresentation(s);
                connection.start();
            } catch (Exception e) {
                try {
                    s.close();
                } catch (IOException e1) {
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
private void createSSLServerSocketFactory() {
    try {
        factory = getSSLContext(TRUSTSTORE_PATH).getServerSocketFactory();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public SSLContext getSSLContext(String pathToTrustStore) throws Exception {
    InputStream keyStoreInputStream = new FileInputStream(KEYSTORE_PATH);
    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(keyStoreInputStream, KEYSTORE_PASSWORD.toCharArray());
    keyStoreInputStream.close();

    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());

    TrustManager[] trustManagers = new TrustManager[]{
            new ReloadableX509TrustManager(pathToTrustStore)
    };
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom());
    return sslContext;
}

И реализация на стороне клиента:

private void createSSSLSocketFactory() {
    try {
        InputStream keyStoreInputStream = new FileInputStream(KEYSTORE_PATH);
        InputStream trustStoreInputStream = new FileInputStream(TRUSTSTORE_PATH);

        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(keyStoreInputStream, KEYSTORE_PASSWORD.toCharArray());
        keyStoreInputStream.close();

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
        keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());

        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(trustStoreInputStream, TRUSTSTORE_PASSWORD.toCharArray());
        trustStoreInputStream.close();

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
        trustManagerFactory.init(trustStore);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

        factory = sslContext.getSocketFactory();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}



public void run() {
        while (true) {
            try {
                s = (SSLSocket) factory.createSocket(serverIP, serverPort);
                s.startHandshake();
                oos = new ObjectOutputStream(s.getOutputStream());
                ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
...
}
}
}
...