New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnutls backend doesn't reuse sessions #1109

Closed
kroeckx opened this Issue Nov 5, 2016 · 2 comments

Comments

Projects
None yet
3 participants
@kroeckx

kroeckx commented Nov 5, 2016

Hi,

It seems that curl has support for session IDs but not for session tickets. When linked with gnutls client hello indicates support for TLS tickets so the server sends a TLS ticket back and does not send a session id back. But curl doesn't seem to handle the TLS tickets.

In case of OpenSSL it doesn't send a TLS ticket extension in the client hello and so gets a session id back, and then it properly reuses the session.

@bagder bagder added the SSL/TLS label Nov 5, 2016

@bagder

This comment has been minimized.

Show comment
Hide comment
@bagder

bagder Nov 9, 2016

Member

We'll welcome help and patches to fix this. This seems to be the GnuTLS docs for how it works: https://www.gnutls.org/manual/html_node/Session-resumption.html

Member

bagder commented Nov 9, 2016

We'll welcome help and patches to fix this. This seems to be the GnuTLS docs for how it works: https://www.gnutls.org/manual/html_node/Session-resumption.html

@mkauf

This comment has been minimized.

Show comment
Hide comment
@mkauf

mkauf Jan 22, 2017

Contributor

Probably TLS session tickets don't work because curl does not use the same SSL context for multiple requests. See TODO: Cache/share OpenSSL contexts

I have tested this: After disabling TLS session tickets, reusing the SSL sessions works properly. TLS session tickets are already disabled for OpenSSL.

For GnuTLS 3.5.6 and newer versions, this can be fixed with this patch:

diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index a992f99..faa70ac 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -380,6 +380,7 @@ gtls_connect_step1(struct connectdata *conn,
                    int sockindex)
 {
   struct Curl_easy *data = conn->data;
+  unsigned int init_flags;
   gnutls_session_t session;
   int rc;
   bool sni = TRUE; /* default is SNI enabled */
@@ -526,7 +527,14 @@ gtls_connect_step1(struct connectdata *conn,
   }

   /* Initialize TLS session as a client */
-  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+  init_flags = GNUTLS_CLIENT;
+
+#if defined(GNUTLS_NO_TICKETS)
+  /* Disable TLS session tickets */
+  init_flags |= GNUTLS_NO_TICKETS;
+#endif
+
+  rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
   if(rc != GNUTLS_E_SUCCESS) {
     failf(data, "gnutls_init() failed: %d", rc);
     return CURLE_SSL_CONNECT_ERROR;

The same problem also exists for mbed TLS. Patch:

diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 8bcaddd..213a58f 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -373,6 +373,11 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_ssl_conf_ciphersuites(&connssl->config,
                                 mbedtls_ssl_list_ciphersuites());

+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+  mbedtls_ssl_conf_session_tickets(&connssl->config,
+                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
+#endif
+
   /* Check if there's a cached ID we can/should use here! */
   if(data->set.general_ssl.sessionid) {
     void *old_session = NULL;

What do you think?

Contributor

mkauf commented Jan 22, 2017

Probably TLS session tickets don't work because curl does not use the same SSL context for multiple requests. See TODO: Cache/share OpenSSL contexts

I have tested this: After disabling TLS session tickets, reusing the SSL sessions works properly. TLS session tickets are already disabled for OpenSSL.

For GnuTLS 3.5.6 and newer versions, this can be fixed with this patch:

diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index a992f99..faa70ac 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -380,6 +380,7 @@ gtls_connect_step1(struct connectdata *conn,
                    int sockindex)
 {
   struct Curl_easy *data = conn->data;
+  unsigned int init_flags;
   gnutls_session_t session;
   int rc;
   bool sni = TRUE; /* default is SNI enabled */
@@ -526,7 +527,14 @@ gtls_connect_step1(struct connectdata *conn,
   }

   /* Initialize TLS session as a client */
-  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+  init_flags = GNUTLS_CLIENT;
+
+#if defined(GNUTLS_NO_TICKETS)
+  /* Disable TLS session tickets */
+  init_flags |= GNUTLS_NO_TICKETS;
+#endif
+
+  rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
   if(rc != GNUTLS_E_SUCCESS) {
     failf(data, "gnutls_init() failed: %d", rc);
     return CURLE_SSL_CONNECT_ERROR;

The same problem also exists for mbed TLS. Patch:

diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 8bcaddd..213a58f 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -373,6 +373,11 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_ssl_conf_ciphersuites(&connssl->config,
                                 mbedtls_ssl_list_ciphersuites());

+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+  mbedtls_ssl_conf_session_tickets(&connssl->config,
+                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
+#endif
+
   /* Check if there's a cached ID we can/should use here! */
   if(data->set.general_ssl.sessionid) {
     void *old_session = NULL;

What do you think?

@mkauf mkauf closed this in 511674a Jan 28, 2017

mkauf added a commit that referenced this issue Jan 28, 2017

mbedtls: disable TLS session tickets
SSL session reuse with TLS session tickets is not supported yet.
Use SSL session IDs instead.

See #1109

@lock lock bot locked as resolved and limited conversation to collaborators May 6, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.