JDBC Connections fails with “The driver could not establish a secure connection to SQL Server….”

This post has been republished via RSS; it originally appeared at: SQL Server Support articles.

Issue:

 

While working on customer issue recently, I came across following scenario where there was a problem in connecting to the SQL Server from the IBM Java application (JDK 1.7) if we enable only TLS 1.2 protocol on both SQL and Application servers.

Let's say we have a simple java program build using the IBM JDK 1.7(pwa6470sr9fp50-20160720_02(SR9fp50)) to test the connectivity to the SQL Server by only enabling the TLS 1.2 protocol on both Application and SQL Server.

Java version as shown below.

 

1.pngJava Version

If we do a test connection to the SQL Server from the application server using the simple java program from the command prompt, it fails with the below error stack.

 

C:\JDK1.7\IBMJava70\bin>java -jar C:\DBConnTest\DBConnTest.jar

Using DB vendor -> MSSQL

Using the following properties:

Type:   MSSQL

 Host:   XXXXXXXX

 Port:   1433

 Name:   master

 User:   sa

 Pass:   XXXXXXXX

 Driver Path:    C:\DBConnTest\Drivers\jdbc41\sqljdbc_4.1\enu\jre7\sqljdbc41.jar

com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server did not return a response. The connection has been closed. ClientConnectionId:7436e46e-1210-4052-92d2-0f2688b1e461".

        at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1669)

        at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1668)  at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1325)

        at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:993)

        at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:829)

        at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1012)

        at DriverShim.connect(DriverShim.java:14)

        at java.sql.DriverManager.getConnection(DriverManager.java:583)

        at java.sql.DriverManager.getConnection(DriverManager.java:227)

        at DBConnTest.main(DBConnTest.java:136)

Caused by: java.io.IOException: SQL Server did not return a response. The connection has been closed. ClientConnectionId:7436e46e-1210-4052-92d2-0f2688b1e461

        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.ensureSSLPayload(IOBuffer.java:651)

        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.readInternal(IOBuffer.java:708)

        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.read(IOBuffer.java:700)

        at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:895)

        at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.read(IOBuffer.java:883)

        at com.ibm.jsse2.a.a(a.java:227)

        at com.ibm.jsse2.a.a(a.java:269)

        at com.ibm.jsse2.qc.a(qc.java:459)

        at com.ibm.jsse2.qc.h(qc.java:275)

        at com.ibm.jsse2.qc.a(qc.java:541)

        at com.ibm.jsse2.qc.startHandshake(qc.java:89)

        at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1618)

        ... 8 more

 

All done

 

Note: In the above case we are using the IBM JDK 1.7 with Microsoft JDBC driver 4.1 and you will experience the same issue for latest JDBC drivers (4.2,6.0,6.2) as well.

 

In the network trace analysis, we see that client initiates TLS handshake with a TLS1.0 Client Hello as shown below screen shot.

 

2.pngNetwork Trace Sample

Cause:

 

IBM JDK 1.7 supports the TLS 1.2 but still by default it uses the TLS 1.0 and for that reason we see that client application initiates TLS 3-way handshake with a TLS 1.0 client hello and connections are failing. 

The System property com.ibm.jsse2.overrideDefaultTLS is used to match the behavior of SSLContext.getInstance("TLS") in the IBM SDK.

com.ibm.jsse2.overrideDefaultTLS =[true|false]

To match the behavior of SSLContext.getInstance("TLS"), set this property to true. The default value is false.

3.pngSupport

Solution:

 

We need to set the property com.ibm.jsse2.overrideDefaultTLS to True to enable the TLS 1.1 and TLS 1.2 in the IBM JDK.

To make a successful connection to the SQL Server from the application over TLS 1.2, we need to set the property com.ibm.jsse2.overrideDefaultTLS =true and pass it during run time as shown below.

 

C:\JDK1.7\IBMJava70\bin>java -jar -Dcom.ibm.jsse2.overrideDefaultTLS=true C:\DBConnTest\DBConnTest.jar

Using DB vendor -> MSSQL

Using the following properties:

 Type:   MSSQL

 Host:   XXXX

 Port:   1433

 Name:   master

 User:   sa

 Pass:   XXXXXXX

 Driver Path:    C:\DBConnTest\Drivers\jdbc41\sqljdbc_4.1\enu\jre7\sqljdbc41.jar

 Connection successful.

 

 

Author:  SatyaSai K – Support Engineer, SQL Server BI Developer team, Microsoft 
Reviewer: Krishnakumar Rukmangathan - Support Escalation Engineer, SQL Server BI Developer team, Microsoft

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.