Bug #36948 Trying to use trustCertificateKeyStoreUrl causes an IllegalStateException.
Submitted: 26 May 2008 8:41 Modified: 19 Apr 2012 21:16
Reporter: Robert Fitzsimons Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:5.1.6 OS:Any
Assigned to: CPU Architecture:Any

[26 May 2008 8:41] Robert Fitzsimons
Description:
If you try to use trustCertificateKeyStoreUrl or clientCertificateKeyStoreUrl an IllegalStateException is caused by an uninitialized TrustManagerFactoryImpl object.

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
     
Last packet sent to the server was 49 ms ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1074)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2103)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:718)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:302)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:282)
    at java.sql.DriverManager.getConnection(DriverManager.java:582)
    at java.sql.DriverManager.getConnection(DriverManager.java:185)
    at Test.main(Test.java:19)
Caused by: java.lang.IllegalStateException: TrustManagerFactoryImpl is not initialized 
    at com.sun.net.ssl.internal.ssl.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:79)
    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:263)
    at com.mysql.jdbc.ExportControlled.getSSLSocketFactoryDefaultOrConfigured(ExportControlled.java:237)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:79)
    at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4472)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1319)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2031)
    ... 12 more 

How to repeat:
Just running with the follow Test will cause the exception.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public final class Test {
        private Test() {}

        public static void main(final String[] args) throws SQLException {
                final String username = "username";
                final String password = "password";
                final String url = "jdbc:mysql://localhost/test?"
                        + "useSSL=true"
                        + "&requireSSL=true"
                        + "&verifyServerCertificate=true"
                        + "&trustCertificateKeyStoreUrl=file:root.jks"
                        + "&trustCertificateKeyStoreType=JKS"
                        + "&trustCertificateKeyStorePassword=password"
                        ;
                Connection connection = DriverManager.getConnection(url, username, password);
                connection.close();
        }
}

Suggested fix:
Applying the following change and recompiling fixed the problem for me.

Index: src/com/mysql/jdbc/ExportControlled.java
===================================================================
--- src/com/mysql/jdbc/ExportControlled.java    (revision 6773)
+++ src/com/mysql/jdbc/ExportControlled.java    (working copy)
@@ -148,7 +148,7 @@
                                                        SQL_STATE_BAD_SSL_PARAMS, 0, false);
                }
 
-               if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)) {
+               if (!StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)) {
                        try {
                                if (!StringUtils.isNullOrEmpty(clientCertificateKeyStoreType)) {
                                        KeyStore clientKeyStore = KeyStore
@@ -190,7 +190,7 @@
                        }
                }
 
-               if (StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
+               if (!StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
 
                        try {
                                if (!StringUtils.isNullOrEmpty(trustCertificateKeyStoreType)) {
[28 May 2008 8:39] Tonci Grgin
Test case, ExportControlled.java rev.6774

Attachment: TestBug36948.java (text/java), 2.78 KiB.

[28 May 2008 8:42] Tonci Grgin
Hi Robert and thanks for your report.

Verified just as described with test case attached (find all details inside) even though Mark made new revision yesterday after we discussed this.

Workaround is rather simple; remove &trustCertificateKeyStoreUrl=c:\jvms\jdk1.5.0\bin\bug36948&trustCertificateKeyStorePassword=****** (and for client too) and put it into code:
	System.setProperty("javax.net.ssl.keyStore","c://jvms//jdk1.5.0//bin//bug36948");
    	System.setProperty("javax.net.ssl.keyStorePassword","*****");
    	System.setProperty("javax.net.ssl.trustStore","c://jvms//jdk1.5.0//bin//bug36948");
    	System.setProperty("javax.net.ssl.trustStorePassword","******");
[23 Jul 2008 8:49] Tonci Grgin
Bug#38192 was marked as duplicate of this report.
[19 Apr 2012 21:16] John Russell
Added to changelog for 5.1.7: 

When using trustCertificateKeyStoreUrl or
clientCertificateKeyStoreUrl, an IllegalStateException was caused by
an uninitialized TrustManagerFactoryImpl object.
[6 Jul 2016 10:36] Richard Bradley
Related to this, I have found that if I specify "clientCertificateKeyStoreUrl" but not "trustCertificateKeyStoreUrl" as connection URL parameters I get the "TrustManagerFactoryImpl is not initialized" IllegalStateException.

It would be more helpful if the connector failed with a message like "'trustCertificateKeyStoreUrl' is required if 'clientCertificateKeyStoreUrl' is specified"