I'm trying to connect to a mysql database via ssl using java. I have a certificate file called rds-combined-ca-bundle.pem (downloaded from here) for a remote server hosting a mysql database.
If I run the following ( on Red Hat Enterprise Linux Server release 5.7 (Tikanga)):
mysql -u a_user -D db_name \
-h some.server.com \
--ssl_ca=/path/to/cert/rds-combined-ca-bundle.pem -p"the_password"
Then it works:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1076
Server version: 5.6.27-log MySQL Community Server (GPL)
However, what doesn't work is when I try to do it in java using the mysql driver (mysql-connector-java-5.1.38-bin.jar), and I'm not sure of the cause. I followed the steps as indicated here.
First, I made my truststore and keystore:
keytool -import -alias fnblCert -file rds-combined-ca-bundle.pem -keystore fdcertstore
Then I made my client key
keytool -genkey -keyalg rsa -alias fnblclient -keystore fdkeystore
My java code (at least, the part that handles the db connection) handles it thusly :
System.setProperty("javax.net.ssl.trustStore", "/srv/dw/apps/FileDownloader/config/fdcertstore");
System.setProperty("javax.net.ssl.trustStorePassword", "the_password");
System.setProperty("javax.net.ssl.keyStore", "/srv/dw/apps/FileDownloader/config/fdkeystore");
System.setProperty("javax.net.ssl.keyStorePassword", "the_password");
System.setProperty("javax.net.debug", "all");
String url = "jdbc:mysql://some.server.com/db_name?"
+ "user=a_user&password=the_password"
+ "&useSSL=true";
Connection conn = DriverManager.getConnection(url);
The java version : java version "1.7.0_85" OpenJDK Runtime Environment (rhel-2.6.1.3.el5_11-x86_64 u85-b01) OpenJDK 64-Bit Server VM (build 24.85-b03, mixed mode)
So when the above code runs, I get a bunch of nasty exceptions (not going to paste all of the stack trace):
An exception has occured while connecting to the remote machine: Communications link failure
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
The exception message doesn't really explain itself too well. I initially thought that it just couldn't find the trust store, or validate it, but then I saw the handshake debug output, and noticed that it found both the client:
<snip>
found key for : fnblclient
<snip>
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
Key: Sun RSA public key, 2048 bits
And also the server certification:
<snip>
trustStore is: /srv/dw/apps/FileDownloader/config/fdcertstore
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: CN=aws.amazon.com/rds/, OU=RDS, O=Amazon.com, L=Seattle, ST=Washington, C=US
Issuer: CN=aws.amazon.com/rds/, OU=RDS, O=Amazon.com, L=Seattle, ST=Washington, C=US
Algorithm: RSA; Serial number: 0xe775b657e21a8128
Valid from Tue Apr 06 01:44:31 EEST 2010 until Sun Apr 05 01:44:31 EEST 2015
Yes, I notice that it is past its expiration date, but keep in mind that the sql command works. Besides, I tried using all other certificates (some that expired in 2020) that were made available in that amazon page, but the mysql command failed with ERROR 2026 (HY000): SSL connection error
Anyway, looking forward into the log, there's some handshaking going on back and forth, and then this:
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_256_CBC_SHA]
Thread-12, SEND TLSv1 ALERT: fatal, description = certificate_unknown
Thread-12, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E
Thread-12, called closeSocket()
Thread-12, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Apparently, that means that it doesn't like the certificate I gave it. At this point, I've ran out of ideas. I thought that maybe the mysql command does a less strict checking than java. The code works if I specify the &verifyServerCertificate=false property, but I shouldn't have to do that since the --ssl-ca parameter does do server certificate authentication (as explained in the mysql 5.5 reference manual), and it works.
I'd appreciate immensely if someone could at least point me in the right direction.
PS: The server isn't mine, so I can't mess with the settings, I only have access to the user
PPS: I also can't mess with the default cacert file, since the sysadmins didn't give me privileges.