SQL Server Jdbc Error on Java 8: the Driver Could Not Establish a Secure Connection to SQL Server by Using Secure Sockets Layer (Ssl) Encryption

SQL Server JDBC Error on Java 8: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption

I turned on SSL logging in the Java 8 JVM on a Linux instance which reproduces the problem. SSL logging is turned on using -Djavax.net.debug=ssl:handshake:verbose. This revealed some useful information.

The workaround that we are using in production and has proven to work for us is to set this parameter on the JVM:

 -Djdk.tls.client.protocols=TLSv1

If you want more details, please read on.

On a server where the problem can be reproduced (again, only 5-10% of the time), I observed the following:

*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 195
main, READ: TLSv1.2 Handshake, length = 1130
*** ServerHello, TLSv1.2
--- 8<-- SNIP -----
%% Initialized: [Session-79, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256]
** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
*** Diffie-Hellman ServerKeyExchange
--- 8<-- SNIP -----
*** ServerHelloDone
*** ClientKeyExchange, DH
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 133
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 108, 116, 29, 115, 13, 26, 154, 198, 17, 125, 114, 166 }
***
main, WRITE: TLSv1.2 Handshake, length = 40
main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT: warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)
main, waiting for close_notify or alert: state 5
main, received EOFException: ignored
main, called closeInternal(false)
main, close invoked again; state = 5
main, handling exception: java.io.IOException: SQL Server returned an incomplete response. The connection has been closed. ClientConnectionId:12a722b3-d61d-4ce4-8319-af049a0a4415

Notice that TLSv1.2 is selected by the database server and used in this exchange. I've observed that, when connections fail from the problematic linux service, TLSv1.2 is ALWAYS the level which was selected. However, connections do not ALWAYS fail when TLSv1.2 is used. They only fail 5-10% of the time.

Now here is an exchange from a server that does NOT have the problem. Everything else is equal. I.e., connecting to the same database, same version of the JVM (Java 1.8.0_60), same JDBC driver, etc. Notice that, here, TLSv1 is selected by the database server instead of TLSv1.2 as in the faulty server's case.

*** ClientHello, TLSv1.2
--- 8<-- SNIP -----
main, WRITE: TLSv1.2 Handshake, length = 207
main, READ: TLSv1 Handshake, length = 604
*** ServerHello, TLSv1
--- 8<-- SNIP -----
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
%% Initialized: [Session-79, TLS_RSA_WITH_AES_128_CBC_SHA]
** TLS_RSA_WITH_AES_128_CBC_SHA
--- 8<-- SNIP -----
Algorithm: [SHA1withRSA]
--- 8<-- SNIP -----
***
*** ServerHelloDone
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
--- 8<-- SNIP -----
main, WRITE: TLSv1 Handshake, length = 134
main, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data: { 26, 155, 166, 89, 229, 193, 126, 39, 103, 206, 126, 21 }
***
main, WRITE: TLSv1 Handshake, length = 48
main, READ: TLSv1 Change Cipher Spec, length = 1
main, READ: TLSv1 Handshake, length = 48
*** Finished

So, when TLSv1 is negotiated between the Linux JVM and the SQL Server, connections are ALWAYS successful. When TLSv1.2 is negotiated, we get sporadic connection failures.

(Note: Java 7 (1.7.0_51) always negotiates TLSv1, which is why the problem never occurred for us with a Java 7 JVM.)

The open questions we still have are:

  1. WHY is that the same Java 8 JVM run from 2 different Linux servers will always negotiate TLSv1, but when connecting from another Linux server it always negotiates TLSv1.2.
  2. And also why are TLSv1.2 negotiated connections successful most, but not all, of the time on that server?

Update 6/10/2017:
This posting from Microsoft describes the problem and their proposed solution.

Resources:

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://www.infoworld.com/article/2849292/operating-systems/more-patch-problems-reported-with-the-ms14-066-kb-2992611-winshock-mess.html

http://blogs.msdn.com/b/jdbcteam/archive/2008/09/09/the-driver-could-not-establish-a-secure-connection-to-sql-server-by-using-secure-sockets-layer-ssl-encryption.aspx

Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLS

http://blogs.msdn.com/b/saponsqlserver/archive/2013/05/10/analyzing-jdbc-connection-issues.aspx

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2

https://blogs.oracle.com/java-platform-group/entry/java_8_will_use_tls

SQL Server JDBC Error: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption

Ok, so we worked with Microsoft Support on this issue and this is the understanding that we came to.

Microsoft added/enabled TLS 1.0 and TLS 1.1 to the Database Server for testing purposes only since Microsoft does not support TLS 1.0 anymore. This lowered the security protocol to a lower state but were able to establish SQL Connectivity between the Application server and the Database Server, but still the Application initially couldn't connect. Microsoft thinks that it is because of the current connection provider/driver that is being used by the application and they wouldn't support that part of it since that is Java/Oracle's JDBC driver.

In our case, the application did connect after enabling the TLS 1.0 and TLS 1.1 after sometime.
This may or may not work in your case.

So the recommended solutions if you have the resources to modify the application, are to update the drivers for the application, test and redeploy.

If you don't have the resources to the application then the options are these:
1.Rollback to older Servers for SQL Server. This could work but there is no guarantee.
Also another thing to note is that SQL Server 2008 and 2008R2 are out of support, so the oldest we could go (and still stay supported) would be SQL Server 2012 which may not resolve the issue.

2.Open the security wide open. This will very likely solve the issue, but is most definitely not recommended. It is likely that the issue has to do with extremely outdated security providers, that are no longer supported. So, opening your security wide open will likely resolve the issue, but this is not recommended.

3.Rewrite the application which is not the easiest option, but is the only one that is fully recommended by Microsoft.

See this https://serverfault.com/questions/649052/do-i-have-to-enable-tls-1-0-in-windows-2008-r2 and this https://www.youtube.com/watch?v=vUuR_M3biDU if you'd like to enable TLS by yourself. The server will require reboot after you make this change.

The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: Unexpected rethrowing

add this property to application entry point

Security.setProperty("jdk.tls.disabledAlgorithms","SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,EC keySize < 224, 3DES_EDE_CBC, anon, NULL");

if you use spring boot

you can use like this

import java.security.Security;

public class Application {

public static void main(String[] args) {
Security.setProperty("jdk.tls.disabledAlgorithms","SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,EC keySize < 224, 3DES_EDE_CBC, anon, NULL");
SpringApplication.run(Application.class, args);
}

}

Cannot connect to SQL Server server with MS JDBC Driver from CentOS 8 server: SSL error but not using secure connection

So, the way I was able to get this to work after much trial and error was to copy the java.security file from the windows 10 install to the CentOS 8 install. The ONLY thing I can see as different between the two was in this section:

'# List of comma-separated packages that start with or equal this string

'# will cause a security exception to be thrown when

'# passed to checkPackageDefinition unless the

'# corresponding RuntimePermission ("defineClassInPackage."+package) has

'# been granted.

'#

'# by default, none of the class loaders supplied with the JDK call

'# checkPackageDefinition.

'#

The entries in CentOS included at the end of the list:

           org.GNOME.Accessibility.,\
org.GNOME.Bonobo.

The entries in the Windows version had only one entry at the end:

           com.sun.java.accessibility.

That was the only difference I could find. And, I don't understand why that made a difference.. But it DOES connect without error now and that is all I wanted....

The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption in liquibase

That version is too old to support TLS 1.2. If your client won't support older cypher suites, and you need to use an encrypted connection, then you'll need to patch the SQL Server to support TLS 1.2.

In your case you would apply Service Pack 3 and then ths update SQL Server 2008 R2 SP3 – KB4057113.

As outlined here: KB3135244 - TLS 1.2 support for Microsoft SQL Server



Related Topics



Leave a reply



Submit