Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8014272

jTDS JDBC SSL connections hang with JRE 6u34 and 7u6

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Not an Issue
    • Affects Version/s: 6u34, 7u13, 8
    • Fix Version/s: None
    • Component/s: security-libs
    • Labels:

      Description

      FULL PRODUCT VERSION :
      java -version
      java version " 1.7.0_13 "
      Java(TM) SE Runtime Environment (build 1.7.0_13-b20)
      Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux 3.6.11-1-ARCH #1 SMP PREEMPT Tue Dec 18 08:57:15 CET 2012 x86_64 GNU/Linux

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      IPv4 only, SQL Server installed on a remote system, firewalls disabled

      A DESCRIPTION OF THE PROBLEM :
      With recent versions of JRE 1.6 and 1.7, the jTDS driver is hanging after login when SSL is used. We have reproduced this using Java 1.6.0_39 and 1.7.0_13, with and without the JCE applied (we normally use the JCE for our application). Note that when we use earlier versions of the JREs, such as 1.6.0_27 or 1.7.0_5, this problem does not occur. In order to make sure the problem did not lie with our application, we wrote a small Groovy app that reproduces it without any extra stuff.

      Note that we have tried using jTDS versions 1.2.7 (with Java 1.6), and 1.3.0 (with Java 1.7), and experience the same behavior of a hanging connection.

      If we set -Djsse.enableCBCProtection=false, then the connection works as expected without hanging. However, that is not a workaround that we can use moving forward, due to the security risk.

      Is this a problem with the JRE, or a problem with jTDS?

      REGRESSION. Last worked in version 7

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Attempt to open a JDBC connect to SQL Server using jTDS. It hangs. Although the example code below is written using Groovy, we have also seen this bug in our pure Java application.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      jTDS should function normally, where SQL queries can be sent to the database, and return a response.
      ACTUAL -
      When we enable -Djavax.net.debug=all, the last few packets exchanged are:

      Set collation to 0x0904E00000/Cp1252
      Language changed from to us_english
      SQLWarning: reason(Changed language setting to us_english.) SQLState(01000) vendor code(5703)
      Changed blocksize to 4096
      ----- Stream #2 send last Request packet

         0: 01 01 01 38 00 00 01 00 53 00 45 00 4C 00 45 00 | 8 S E L E |
        16: 43 00 54 00 20 00 40 00 40 00 4D 00 41 00 58 00 |C T @ @ M A X |
        32: 5F 00 50 00 52 00 45 00 43 00 49 00 53 00 49 00 |_ P R E C I S I |
        48: 4F 00 4E 00 0D 00 0A 00 53 00 45 00 54 00 20 00 |O N S E T |
        64: 54 00 52 00 41 00 4E 00 53 00 41 00 43 00 54 00 |T R A N S A C T |
        80: 49 00 4F 00 4E 00 20 00 49 00 53 00 4F 00 4C 00 |I O N I S O L |
        96: 41 00 54 00 49 00 4F 00 4E 00 20 00 4C 00 45 00 |A T I O N L E |
       112: 56 00 45 00 4C 00 20 00 52 00 45 00 41 00 44 00 |V E L R E A D |
       128: 20 00 43 00 4F 00 4D 00 4D 00 49 00 54 00 54 00 | C O M M I T T |
       144: 45 00 44 00 0D 00 0A 00 53 00 45 00 54 00 20 00 |E D S E T |
       160: 49 00 4D 00 50 00 4C 00 49 00 43 00 49 00 54 00 |I M P L I C I T |
       176: 5F 00 54 00 52 00 41 00 4E 00 53 00 41 00 43 00 |_ T R A N S A C |
       192: 54 00 49 00 4F 00 4E 00 53 00 20 00 4F 00 46 00 |T I O N S O F |
       208: 46 00 0D 00 0A 00 53 00 45 00 54 00 20 00 51 00 |F S E T Q |
       224: 55 00 4F 00 54 00 45 00 44 00 5F 00 49 00 44 00 |U O T E D _ I D |
       240: 45 00 4E 00 54 00 49 00 46 00 49 00 45 00 52 00 |E N T I F I E R |
       256: 20 00 4F 00 4E 00 0D 00 0A 00 53 00 45 00 54 00 | O N S E T |
       272: 20 00 54 00 45 00 58 00 54 00 53 00 49 00 5A 00 | T E X T S I Z |
       288: 45 00 20 00 32 00 31 00 34 00 37 00 34 00 38 00 |E 2 1 4 7 4 8 |
       304: 33 00 36 00 34 00 37 00 |3 6 4 7 |

      Padded plaintext before ENCRYPTION: len = 32
      0000: 01 DD FA 88 D0 7C 40 44 7F EA 49 E1 A2 AD D6 AF ......@D..I.....
      0010: 1E 01 4B 24 5E 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ..K$^...........
      main, WRITE: TLSv1 Application Data, length = 32
      [Raw write]: length = 37
      0000: 17 03 01 00 20 63 05 9C 6C 21 C6 BE F6 4C FC 17 .... c..l!...L..
      0010: C1 C0 F3 6A 3E 6F 5A DF A6 78 B5 91 85 AE E2 F6 ...j>oZ..x......
      0020: D9 65 1D A8 2A .e..*
      Padded plaintext before ENCRYPTION: len = 336
      0000: 01 01 38 00 00 01 00 53 00 45 00 4C 00 45 00 43 ..8....S.E.L.E.C
      0010: 00 54 00 20 00 40 00 40 00 4D 00 41 00 58 00 5F .T. .@.@.M.A.X._
      0020: 00 50 00 52 00 45 00 43 00 49 00 53 00 49 00 4F .P.R.E.C.I.S.I.O
      0030: 00 4E 00 0D 00 0A 00 53 00 45 00 54 00 20 00 54 .N.....S.E.T. .T
      0040: 00 52 00 41 00 4E 00 53 00 41 00 43 00 54 00 49 .R.A.N.S.A.C.T.I
      0050: 00 4F 00 4E 00 20 00 49 00 53 00 4F 00 4C 00 41 .O.N. .I.S.O.L.A
      0060: 00 54 00 49 00 4F 00 4E 00 20 00 4C 00 45 00 56 .T.I.O.N. .L.E.V
      0070: 00 45 00 4C 00 20 00 52 00 45 00 41 00 44 00 20 .E.L. .R.E.A.D.
      0080: 00 43 00 4F 00 4D 00 4D 00 49 00 54 00 54 00 45 .C.O.M.M.I.T.T.E
      0090: 00 44 00 0D 00 0A 00 53 00 45 00 54 00 20 00 49 .D.....S.E.T. .I
      00A0: 00 4D 00 50 00 4C 00 49 00 43 00 49 00 54 00 5F .M.P.L.I.C.I.T._
      00B0: 00 54 00 52 00 41 00 4E 00 53 00 41 00 43 00 54 .T.R.A.N.S.A.C.T
      00C0: 00 49 00 4F 00 4E 00 53 00 20 00 4F 00 46 00 46 .I.O.N.S. .O.F.F
      00D0: 00 0D 00 0A 00 53 00 45 00 54 00 20 00 51 00 55 .....S.E.T. .Q.U
      00E0: 00 4F 00 54 00 45 00 44 00 5F 00 49 00 44 00 45 .O.T.E.D._.I.D.E
      00F0: 00 4E 00 54 00 49 00 46 00 49 00 45 00 52 00 20 .N.T.I.F.I.E.R.
      0100: 00 4F 00 4E 00 0D 00 0A 00 53 00 45 00 54 00 20 .O.N.....S.E.T.
      0110: 00 54 00 45 00 58 00 54 00 53 00 49 00 5A 00 45 .T.E.X.T.S.I.Z.E
      0120: 00 20 00 32 00 31 00 34 00 37 00 34 00 38 00 33 . .2.1.4.7.4.8.3
      0130: 00 36 00 34 00 37 00 CC 2B 17 A6 64 92 C0 4C 55 .6.4.7..+..d..LU
      0140: C9 B0 2B 15 C5 22 A6 B9 AA 19 58 04 04 04 04 04 ..+.. " ....X.....
      main, WRITE: TLSv1 Application Data, length = 336
      [Raw write]: length = 341
      0000: 17 03 01 01 50 FE ED 12 F7 DE 64 3E A0 F4 CA CC ....P.....d>....
      0010: DE BC 31 A2 2C E1 5B 9C 91 07 7F DB A4 D9 4E CC ..1.,.[.......N.
      0020: 43 9E 42 E1 6B 1E 29 C9 35 39 D0 C9 CA 55 92 B7 C.B.k.).59...U..
      0030: D8 78 C9 15 A6 7F 2C 33 9B C4 B7 78 B3 AD E6 04 .x....,3...x....
      0040: EE 00 F4 22 88 9B D1 9A 61 83 3D 16 72 DF A7 DE ... " ....a.=.r...
      0050: 88 D8 8B A1 96 33 4A F4 8B 79 CD 94 21 AF 4F FA .....3J..y..!.O.
      0060: BB 5C E7 8B 7A 75 E5 26 0E B3 1A 21 AE AC B6 D4 .\..zu.&...!....
      0070: 05 D4 C4 9A 51 FC 21 5A 29 FE 72 CD 99 8B 8E 30 ....Q.!Z).r....0
      0080: EB 4F 60 4C 76 9C 3D D7 E2 69 3E AC 52 42 E3 C2 .O`Lv.=..i>.RB..
      0090: EB A2 21 D0 6A C7 C6 84 54 59 82 B1 9C FE 55 27 ..!.j...TY....U'
      00A0: 60 7C A7 25 CD FC C1 5A C9 D3 5A 47 56 FB 55 C7 `..%...Z..ZGV.U.
      00B0: 6F EA DC 84 56 7E 48 E9 F5 7E AE 25 19 5F CF 3F o...V.H....%._.?
      00C0: 11 DC AD 0B EE 46 74 5F D7 08 9D 04 D3 5F 56 71 .....Ft_....._Vq
      00D0: DF 7B FA AE ED 36 22 F8 FA 15 3A A9 DF 59 8D DE .....6 " ...:..Y..
      00E0: 66 D7 D2 6A 57 DC CA 33 14 39 35 96 16 DF 98 25 f..jW..3.95....%
      00F0: E1 DD A4 EF B9 CA 78 E6 79 0D 4F 72 80 2C F3 8D ......x.y.Or.,..
      0100: 02 A6 F4 34 8F 98 59 63 D8 9B 51 A1 39 D9 26 00 ...4..Yc..Q.9.&.
      0110: DC 1C BF 51 EA B1 E9 8C 35 5F 5D 91 1A E5 D4 50 ...Q....5_]....P
      0120: 83 AC FE 92 E5 4D B8 40 0F 08 2E 71 DC D9 51 78 .....M.@...q..Qx
      0130: F9 51 6C 83 5F CF 9E 75 E1 60 DF C2 8D BC 0D 33 .Ql._..u.`.....3
      0140: 65 79 9B FF 71 F2 9F FE B3 B9 DA B7 8E 17 4F 1B ey..q.........O.
      0150: 83 76 52 3F 85 .vR?.

      The precision check is the very first SQL query issued by jTDS after logging in (which happens after the SSL handshake).

      Note that this looks very similar to the BEAST SSL issue, however this is reproduced using Java versions that include the fix, and affect SQL Server database that have been patched (2008 R2 and 2012).

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      If we take a thread dump when the connection is hanging, we can see the following:

      2013-02-07 16:04:07
      Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.7-b01 mixed mode):

       " Monitor Ctrl-Break " daemon prio=10 tid=0x00007fc9a8181800 nid=0x735c runnable [0x00007fc997541000]
         java.lang.Thread.State: RUNNABLE
      at java.net.SocketInputStream.socketRead0(Native Method)
      at java.net.SocketInputStream.read(SocketInputStream.java:150)
      at java.net.SocketInputStream.read(SocketInputStream.java:121)
      at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
      at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
      at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
      - locked <0x00000000d71516a0> (a java.io.InputStreamReader)
      at java.io.InputStreamReader.read(InputStreamReader.java:184)
      at java.io.BufferedReader.fill(BufferedReader.java:154)
      at java.io.BufferedReader.readLine(BufferedReader.java:317)
      - locked <0x00000000d71516a0> (a java.io.InputStreamReader)
      at java.io.BufferedReader.readLine(BufferedReader.java:382)
      at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:85)
      at java.lang.Thread.run(Thread.java:722)

       " Service Thread " daemon prio=10 tid=0x00007fc9a80ef800 nid=0x735a runnable [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

       " C2 CompilerThread1 " daemon prio=10 tid=0x00007fc9a80ed800 nid=0x7359 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

       " C2 CompilerThread0 " daemon prio=10 tid=0x00007fc9a80ea800 nid=0x7358 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

       " Signal Dispatcher " daemon prio=10 tid=0x00007fc9a80e8000 nid=0x7357 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

       " Finalizer " daemon prio=10 tid=0x00007fc9a809b000 nid=0x7356 in Object.wait() [0x00007fc997ffe000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000000d70b5798> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
      - locked <0x00000000d70b5798> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
      at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)

       " Reference Handler " daemon prio=10 tid=0x00007fc9a8099000 nid=0x7355 in Object.wait() [0x00007fc9a414b000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000000d70b5320> (a java.lang.ref.Reference$Lock)
      at java.lang.Object.wait(Object.java:503)
      at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
      - locked <0x00000000d70b5320> (a java.lang.ref.Reference$Lock)

       " main " prio=10 tid=0x00007fc9a8008800 nid=0x734f runnable [0x00007fc9b0601000]
         java.lang.Thread.State: RUNNABLE
      at java.net.SocketInputStream.socketRead0(Native Method)
      at java.net.SocketInputStream.read(SocketInputStream.java:150)
      at java.net.SocketInputStream.read(SocketInputStream.java:121)
      at net.sourceforge.jtds.ssl.TdsTlsInputStream.read(TdsTlsInputStream.java:72)
      at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
      at sun.security.ssl.InputRecord.read(InputRecord.java:350)
      at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
      - locked <0x00000000d849f9b0> (a java.lang.Object)
      at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
      at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
      - locked <0x00000000d8915910> (a sun.security.ssl.AppInputStream)
      at java.io.DataInputStream.readFully(DataInputStream.java:195)
      at java.io.DataInputStream.readFully(DataInputStream.java:169)
      at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:881)
      at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:762)
      - locked <0x00000000d8330338> (a java.util.concurrent.ConcurrentHashMap)
      at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:477)
      at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:114)
      at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:99)
      at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3999)
      at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1052)
      - locked <0x00000000d8a1f308> (a net.sourceforge.jtds.jdbc.TdsCore)
      at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:493)
      at net.sourceforge.jtds.jdbc.JtdsStatement.executeQuery(JtdsStatement.java:1427)
      at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:414)
      at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:183)
      at java.sql.DriverManager.getConnection(DriverManager.java:579)
      at java.sql.DriverManager.getConnection(DriverManager.java:190)
      at groovy.sql.Sql.newInstance(Sql.java:312)
      at groovy.sql.Sql.newInstance(Sql.java:356)
      at groovy.sql.Sql$newInstance.call(Unknown Source)
      at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
      at com.broken.jdbc.BugMain.main(BugMain.groovy:27)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

       " VM Thread " prio=10 tid=0x00007fc9a8091800 nid=0x7354 runnable

       " GC task thread#0 (ParallelGC) " prio=10 tid=0x00007fc9a8016000 nid=0x7350 runnable

       " GC task thread#1 (ParallelGC) " prio=10 tid=0x00007fc9a8018000 nid=0x7351 runnable

       " GC task thread#2 (ParallelGC) " prio=10 tid=0x00007fc9a8019800 nid=0x7352 runnable

       " GC task thread#3 (ParallelGC) " prio=10 tid=0x00007fc9a801b800 nid=0x7353 runnable

       " VM Periodic Task Thread " prio=10 tid=0x00007fc9a8102800 nid=0x735b waiting on condition

      JNI global references: 155

      Heap
       PSYoungGen total 36736K, used 26475K [0x00000000d70b0000, 0x00000000d99a0000, 0x0000000100000000)
        eden space 31552K, 83% used [0x00000000d70b0000,0x00000000d8a8ac60,0x00000000d8f80000)
        from space 5184K, 0% used [0x00000000d9490000,0x00000000d9490000,0x00000000d99a0000)
        to space 5184K, 0% used [0x00000000d8f80000,0x00000000d8f80000,0x00000000d9490000)
       ParOldGen total 83904K, used 0K [0x0000000085200000, 0x000000008a3f0000, 0x00000000d70b0000)
        object space 83904K, 0% used [0x0000000085200000,0x0000000085200000,0x000000008a3f0000)
       PSPermGen total 21248K, used 11660K [0x0000000080000000, 0x00000000814c0000, 0x0000000085200000)
        object space 21248K, 54% used [0x0000000080000000,0x0000000080b633d0,0x00000000814c0000)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.broken.jdbc

      import groovy.sql.Sql

      class BugMain {
          public static void main(String[] args) {

              def properties = new Properties()
              properties.setProperty( " ssl " , " require " )
              properties.setProperty( " password " , " <mypassword> " )
              properties.setProperty( " user " , " <myuser> " )

              Sql sql = Sql.newInstance( " jdbc:jtds:sqlserver://&lt;myhost&gt;/&lt;mydbname> " , properties, " net.sourceforge.jtds.jdbc.Driver " )
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      If we set -Djsse.enableCBCProtection=false, then the connection works as expected without hanging. However, that is not a workaround that we can use moving forward, due to the security risk.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              wetmore Bradford Wetmore
              Reporter:
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: