JDBC Connections fails with "The driver could not establish a secure connection to SQL Server...."
Published Apr 08 2019 11:52 PM 83.9K Views

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.

 

Java VersionJava 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.

 

Network Trace SampleNetwork 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.

SupportSupport

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

2 Comments
Version history
Last update:
‎Apr 08 2019 11:55 PM