Uploaded image for project: 'Undertow'
  1. Undertow
  2. UNDERTOW-2236

SslConduit client hangs on TLS handshake with single multi-record TLS message from server.

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • 2.2.20.Final
    • SSL
    • None

      I am using Undertow's WebSocketClient to interface with a server configured for HTTPS. I am seeing the TLS handshake process stall under certain scenarios. In my tests, if the HTTPS server is configured with a relatively simple certificate and a Custom Certificate Authority is provided, I see the TLS handshake stall after a single multi-record TLS message is received from the server (refer to the attach Wireshark capture).

      Note that in the Wireshark capture the server responds with a TLS message that contains the following TLS records:

      • Server Hello
      • Change Cipher Spec
      • Encrypted Extensions
      • Certificate
      • Certificate Verify
      • Finished

      The server completes the TLS interaction in a single TLS message, which may be an uncommon scenario, and it appears that the client (Undertow) is unaware that the server is finished and that it is responsible for completing the TLS interaction. I imagine this scenario doesn't happen with traditional certificate chains since these tend to be longer and servers will likely split the TLS records across multiple TLS messages.

      In debugging this scenario, I've seen the following interaction between SslConduit and SSLEngine:

      >> SslConduit calls SSLEngine.wrap()
         << SSLEngine generates the ClientHello message - returns NEED_UNWRAP
      >> SslConduit sends ClientHello, then listens on the IO channel.
      >> SslConduit receives the multi-record TLS message, calls SSLEngine.unwrap()
         << SSLEngine processes just the ServerHello message - returns NEED_TASK
      >> SslConduit executes the task delegated by SSLEngine.
      >> SslConduit completes the task and calls the doHandshake() method
      >> SslConduit calls SSLEngine.unwrap()
         << SSLEngine doesn't process any data - returns NEED_WRAP
      >> SslConduit calls SSLEngine.wrap()
         << SSLEngine produces data - returns NEED_UNWRAP
      >> SslConduit calls resumeWrites() method that waits for data from IO channel.
      >> SSL Handshake stands still since the server will not send any more info.

      In this scenario, it seems like the SSLEngine task is resulting in the SSLEngine state being changed to NEED_WRAP and the SslConduit.doHandshake() method should call the doUnwrap/doWrap methods in reverse order. I am able to get this TLS interaction completing by adding an additional doUnwrap() call just after the doHandshake() call when the delegated task is completed - here. However, I am unsure of any side-effects that will happen from this change and would like feedback on how to best resolve this.

        1. bad-handshake.pcapng
          3 kB
        2. dev-sandbox-jake-home-https.crt
          1 kB
        3. dev-sandbox-jake-home-https.key
          2 kB
        4. fusion-cloud-ca.crt
          1 kB
        5. undertow-test.tar.gz
          2 kB
        6. ws-test.conf
          0.7 kB

              flaviarnn Flavia Rainone
              jfoytik Jacob Foytik (Inactive)
              Votes:
              4 Vote for this issue
              Watchers:
              11 Start watching this issue

                Created:
                Updated: