If a server is not acknowledging SNI then don't reject early_data
[openssl.git] / ssl / statem / extensions.c
index e16b75f683dcd3ee259dcca94fe5f627b1c8445c..a72859c873da4f1caf393c25eb9d4b3bf678e6b9 100644 (file)
@@ -55,6 +55,7 @@ static int init_srtp(SSL *s, unsigned int context);
 #endif
 static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al);
 static int final_early_data(SSL *s, unsigned int context, int sent, int *al);
+static int final_maxfragmentlen(SSL *s, unsigned int context, int sent, int *al);
 
 /* Structure to define a built-in extension */
 typedef struct extensions_definition_st {
@@ -135,6 +136,14 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         tls_construct_stoc_server_name, tls_construct_ctos_server_name,
         final_server_name
     },
+    {
+        TLSEXT_TYPE_max_fragment_length,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+        | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+        NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
+        tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
+        final_maxfragmentlen
+    },
 #ifndef OPENSSL_NO_SRP
     {
         TLSEXT_TYPE_srp,
@@ -832,7 +841,7 @@ static int init_server_name(SSL *s, unsigned int context)
 static int final_server_name(SSL *s, unsigned int context, int sent,
                                      int *al)
 {
-    int ret = SSL_TLSEXT_ERR_NOACK;
+    int ret = SSL_TLSEXT_ERR_NOACK, discard;
     int altmp = SSL_AD_UNRECOGNIZED_NAME;
     int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
 
@@ -849,6 +858,19 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
         s->session->ext.hostname = NULL;
     }
 
+    /*
+     * If we switched contexts (whether here or in the client_hello callback),
+     * move the sess_accept increment from the session_ctx to the new
+     * context, to avoid the confusing situation of having sess_accept_good
+     * exceed sess_accept (zero) for the new context.
+     */
+    if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) {
+        CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &discard,
+                          s->ctx->lock);
+        CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, -1, &discard,
+                          s->session_ctx->lock);
+    }
+
     /*
      * If we're expecting to send a ticket, and tickets were previously enabled,
      * and now tickets are disabled, then turn off expected ticket.
@@ -889,8 +911,6 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
 
     case SSL_TLSEXT_ERR_NOACK:
         s->servername_done = 0;
-        if (s->server && s->session->ext.hostname != NULL)
-            s->ext.early_data_ok = 0;
         return 1;
 
     default:
@@ -1462,3 +1482,25 @@ static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
 
     return 1;
 }
+
+static int final_maxfragmentlen(SSL *ssl, unsigned int context, int sent, int *al)
+{
+    /*
+     * Session resumption on server-side with MFL extension active
+     *  BUT MFL extension packet was not resent (i.e. sent == 0)
+     */
+    if (ssl->server && ssl->hit && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
+            && !sent ) {
+        *al = SSL_AD_MISSING_EXTENSION;
+        return 0;
+    }
+
+    /* Current SSL buffer is lower than requested MFL */
+    if (ssl->session && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
+            && ssl->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(ssl->session))
+        /* trigger a larger buffer reallocation */
+        if (!ssl3_setup_buffers(ssl))   
+            return 0;
+
+    return 1;
+}