JanetM
JanetM

Reputation: 53

Failing to establish an Java SSLSocket connection to a secure mysql open socket

Note: I am a novice SSLSocket person...

I have a secure connection between a mysql database (Version 5.7.9) and a java application (Java 1.8.0_U73) both running on localhost. The database connection is created using the SpringFramework 4.2.4 API. I am attempting to open a Java SSLSocket on the same socket the database and the java application are communicating over via the SpringFramework API with no success. The printstack error I am getting when I initiate the ssl socket startHandshake() method is (note path to replaced the actual installation folder I am running from):

[*path to*\db\mysql\bin\mysqld, "--basedir=*path to*\db\mysql", "--datadir=*path to*\db\mysql\data", "--secure-file-priv=*path to*\db\mysql\data", --port=3355, "--ssl-ca=*path to*\db\mysql\data\cacert.pem", "--ssl-cert=*path to*\db\mysql\data\server-cert.pem", "--ssl-key=*path to*\db\mysql\data\server-key.pem"]
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at sun.security.ssl.InputRecord.handleUnknownRecord(Unknown Source)
    at sun.security.ssl.InputRecord.read(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at TestSSL.testSocket(TestSSL.java:209)
    at TestSSL.main(TestSSL.java:253)

The mysql database is started with the sample cacert.pem, server-cert.pem, and server-key.pem files that can be found in the mysql-5.7.11-winx64-debug-test.zip I downloaded from the mysql website using the --ssl-ca, --ssl-cert, and --ssl-key startup options.

The Mysql log file shows the following for the mysqld startup:

2016-02-24T19:37:06.710628Z 0 [Note] InnoDB: Loading buffer pool(s) from path to\db\mysql\data\ib_buffer_pool
2016-02-24T19:37:06.808638Z 0 [Warning] CA certificate path to\db\mysql\data\cacert.pem is self signed.
2016-02-24T19:37:06.819639Z 0 [Note] Server hostname (bind-address): '*'; port: 3355
2016-02-24T19:37:06.821639Z 0 [Note] IPv6 is available.
2016-02-24T19:37:06.822639Z 0 [Note] - '::' resolves to '::';
2016-02-24T19:37:06.823639Z 0 [Note] Server socket created on IP: '::'.
2016-02-24T19:37:06.977655Z 0 [Note] InnoDB: Buffer pool(s) load completed at 160224 12:37:06
2016-02-24T19:37:07.107668Z 0 [Note] Event Scheduler: Loaded 0 events
2016-02-24T19:37:07.108668Z 0 [Note] path to\db\mysql\bin\mysqld: ready for connections.
Version: '5.7.9' socket: '' port: 3355 MySQL Community Server (GPL)

Also, a quick connection to the mysql database using MySQL Workbench shows:

Connection:
Name: MyConnection64
Host: localhost
Port: 3355
Server: MySQL Community Server (GPL)
Version: 5.7.9
Login User: root
Current User: root@localhost
SSL: Using DHE-RSA-AES256-SHA

The URL for creating the Java SpringFramework database connection is (from my SpringFramework dbaccess.xml file):

entry key="db.jdbcurl" value="jdbc:mysql://localhost:3355/imom?useServerPrepStmts=false&rewriteBatchedStatements=true&server.basedir=path to\db\mysql&server.datadir=path to\db\mysql\data&createDatabaseIfNotExist=true&autoReconnect=true&useSSL=true"

The VM arguments I am using to start my java app are:
-Djavax.net.ssl.keyStore="path to\db\mysql\data\keystore" -Djavax.net.ssl.keyStorePassword="changeme" -Djavax.net.ssl.trustStore="path to\db\mysql\data\truststore" -Djavax.net.ssl.trustStorePassword="changeme"

The code I am using (successfully) to create the SpringFramework connection is:

private static void testSpring() {

    try {
        Connection conn = DataSourceUtils.getConnection(m_dataSource);
        conn.close();
    } catch (Exception ex) {
        System.out.println(ex.getMessage());
        ex.printStackTrace();
    }
}

The code I am using to create the SSLSocket (Unsuccessfully) is:

private static void testSocket() {
//      System.setProperty("jsse.enableSNIExtension", "false");
//      System.setProperty("jsse.enabledSSLCipherSuites", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA");

    try {
        Socket socket = new Socket(m_hostnameString, Integer.parseInt(m_portString));
        InputStream keyStoreResource = new FileInputStream(m_baseDir
                + File.separator + "data" + File.separator + "keystore");
        char[] keyStorePassphrase = "changeme".toCharArray();
        KeyStore ksKeys = KeyStore.getInstance("JKS");
        ksKeys.load(keyStoreResource, keyStorePassphrase);

        // KeyManager decides which key material to use.
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ksKeys, keyStorePassphrase);

        InputStream trustStoreIS = new FileInputStream(m_baseDir
                + File.separator + "data" + File.separator + "truststore");
        char[] trustStorePassphrase = "changeme".toCharArray();
        KeyStore ksTrust = KeyStore.getInstance("JKS");
        ksTrust.load(trustStoreIS, trustStorePassphrase);

        // TrustManager decides which certificate authorities to use.
        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance("SunX509");
        tmf.init(ksTrust);

//          SSLSocketFactoryEx factory = new SSLSocketFactoryEx(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, m_hostnameString, Integer.parseInt(m_portString),true);

        // and go!
        sslSocket.startHandshake();
    }
    catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Upvotes: 1

Views: 595

Answers (1)

stdunbar
stdunbar

Reputation: 17455

I'm a bit confused as to why you're directly connecting to the MySQL instance with your own SSL socket. In general, you'd still want to use the JDBC library through whatever mechanism (Spring, JPA, etc.) and tell it to use SSL. Just as you wouldn't want to connect directly to the MySQL server with a "normal" socket, you wouldn't want to with SSL either. See this page for more info.

Upvotes: 1

Related Questions