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