[gnutls-devel] session resumption broken when tickets and db is enabled

Stefan Bühler stbuehler at lighttpd.net
Sun Aug 18 19:47:04 CEST 2013

Hi again :)

lighttpd2/mod_gnutls supports session db and tickets by default; a
nginx proxy had problems connecting:

  SSL_do_handshake() failed (SSL: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac) while SSL handshaking to upstream

The first two requests were fine, the 3rd and later failed.
Debugging wasn't easy, because...

Bug 1:
  gnutls-serv doesn't support tickets, although there is a parameter
  "--noticket". Please remove the stupid #ifdef magic ...

    gnutls-serv --http -p 5556 --x509keyfile=server.pem --x509certfile=server.pem

    echo | openssl s_client -connect -sess_out tmp.session
    echo | openssl s_client -connect -sess_in tmp.session
    echo | openssl s_client -connect -sess_in tmp.session
    140720615724712:error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac:s3_pkt.c:484:
    (Also now gnutls-serv is burning my cpu)

That shows something is broken. When --nodb or --noticket is added to gnutls-serv, everything is fine.

Testing with gnutls client requires patching again. I patched doc/examples/ex-client-resume.c
to connect 3 times and delete the session data at the end (see below).

    cd doc/examples
    gcc ex-alert.c tcp.c ex-client-resume.c -lgnutls -o client-resume
    *** Handshake failed
    GnuTLS error: An unexpected TLS packet was received.

Same as with the openssl client; broken with ticket and db, works if one is disabled.

The problem probably is in lib/gnutls_handshake.c:3193 - in the 2nd request there
is no new ticket sent, but the ticket is still used, and it will store the session
in the db (Bug 2).
Then, in the 3rd request and later, in lib/gnutls_handshake.c:516 it first tries to
restore the session from db, before knowing whether a ticket is present (if a ticket is
present this call is "wasted" and also the data shouldn't be used -> Bug 3).


diff --git a/doc/examples/ex-client-resume.c b/doc/examples/ex-client-resume.c
index 1842c5e..f0d60df 100644
--- a/doc/examples/ex-client-resume.c
+++ b/doc/examples/ex-client-resume.c
@@ -41,7 +41,7 @@ main (void)
   gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);
-  for (t = 0; t < 2; t++)
+  for (t = 0; t < 3; t++)
     {                           /* connect 2 times to the server */
       sd = tcp_connect ();
@@ -56,7 +56,6 @@ main (void)
           /* if this is not the first time we connect */
           gnutls_session_set_data (session, session_data, session_data_size);
-          free (session_data);
       gnutls_transport_set_int (session, sd);
@@ -147,6 +146,8 @@ main (void)
     }                           /* for() */
+  if (NULL != session_data) free (session_data);
   gnutls_certificate_free_credentials (xcred);
   gnutls_global_deinit ();

More information about the Gnutls-devel mailing list