RT2772: accept empty SessionTicket
authorEmilia Kasper <emilia@openssl.org>
Thu, 10 Sep 2015 14:32:51 +0000 (16:32 +0200)
committerEmilia Kasper <emilia@openssl.org>
Mon, 28 Sep 2015 14:00:25 +0000 (16:00 +0200)
RFC 5077 section 3.3 says:
If the server determines that it does not want to include a
ticket after it has included the SessionTicket extension in the
ServerHello, then it sends a zero-length ticket in the
NewSessionTicket handshake message.

Previously the client would fail upon attempting to allocate a
zero-length buffer. Now, we have the client ignore the empty ticket and
keep the existing session.

Reviewed-by: Matt Caswell <matt@openssl.org>
ssl/s3_clnt.c

index 036a531d7c996f9d43ae92b7fd8b19b8f54be7d4..2c93bd0dff9a08e526594803a414d729113eca94 100644 (file)
@@ -2195,6 +2195,7 @@ int ssl3_get_new_session_ticket(SSL *s)
 {
     int ok, al, ret = 0;
     unsigned int ticklen;
+    unsigned long ticket_lifetime_hint;
     long n;
     PACKET pkt;
 
@@ -2212,6 +2213,18 @@ int ssl3_get_new_session_ticket(SSL *s)
         goto f_err;
     }
 
+    if (!PACKET_get_net_4(&pkt, &ticket_lifetime_hint)
+            || !PACKET_get_net_2(&pkt, &ticklen)
+            || PACKET_remaining(&pkt) != ticklen) {
+        al = SSL_AD_DECODE_ERROR;
+        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+        goto f_err;
+    }
+
+    /* Server is allowed to change its mind and send an empty ticket. */
+    if (ticklen == 0)
+        return 1;
+
     if (s->session->session_id_length > 0) {
         int i = s->session_ctx->session_cache_mode;
         SSL_SESSION *new_sess;
@@ -2243,15 +2256,9 @@ int ssl3_get_new_session_ticket(SSL *s)
         s->session = new_sess;
     }
 
-    if (!PACKET_get_net_4(&pkt, &s->session->tlsext_tick_lifetime_hint)
-            || !PACKET_get_net_2(&pkt, &ticklen)
-            || PACKET_remaining(&pkt) != ticklen) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
-    }
     OPENSSL_free(s->session->tlsext_tick);
     s->session->tlsext_ticklen = 0;
+
     s->session->tlsext_tick = OPENSSL_malloc(ticklen);
     if (!s->session->tlsext_tick) {
         SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
@@ -2262,6 +2269,8 @@ int ssl3_get_new_session_ticket(SSL *s)
         SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
+
+    s->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
     s->session->tlsext_ticklen = ticklen;
     /*
      * There are two ways to detect a resumed ticket session. One is to set