If a server is not acknowledging SNI then don't reject early_data
[openssl.git] / ssl / statem / extensions.c
index 8b88b215841f208def3db16cf8ef64395085b168..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,
@@ -408,13 +417,23 @@ static int verify_extension(SSL *s, unsigned int context, unsigned int type,
  */
 int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
 {
+    int is_tls13;
+
+    /*
+     * For HRR we haven't selected the version yet but we know it will be
+     * TLSv1.3
+     */
+    if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
+        is_tls13 = 1;
+    else
+        is_tls13 = SSL_IS_TLS13(s);
+
     if ((SSL_IS_DTLS(s)
                 && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
             || (s->version == SSL3_VERSION
                     && (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
-            || (SSL_IS_TLS13(s)
-                && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
-            || (!SSL_IS_TLS13(s) && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
+            || (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
+            || (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
             || (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0))
         return 0;
 
@@ -822,8 +841,9 @@ 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;
 
     if (s->ctx != NULL && s->ctx->ext.servername_cb != 0)
         ret = s->ctx->ext.servername_cb(s, &altmp,
@@ -833,6 +853,53 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
         ret = s->session_ctx->ext.servername_cb(s, &altmp,
                                        s->session_ctx->ext.servername_arg);
 
+    if (!sent) {
+        OPENSSL_free(s->session->ext.hostname);
+        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.
+     * Also, if this is not a resumption, create a new session ID
+     */
+    if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
+            && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
+        s->ext.ticket_expected = 0;
+        if (!s->hit) {
+            SSL_SESSION* ss = SSL_get_session(s);
+
+            if (ss != NULL) {
+                OPENSSL_free(ss->ext.tick);
+                ss->ext.tick = NULL;
+                ss->ext.ticklen = 0;
+                ss->ext.tick_lifetime_hint = 0;
+                ss->ext.tick_age_add = 0;
+                ss->ext.tick_identity = 0;
+                if (!ssl_generate_session_id(s, ss)) {
+                    ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                    altmp = SSL_AD_INTERNAL_ERROR;
+                }
+            } else {
+                ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                altmp = SSL_AD_INTERNAL_ERROR;
+            }
+        }
+    }
+
     switch (ret) {
     case SSL_TLSEXT_ERR_ALERT_FATAL:
         *al = altmp;
@@ -844,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:
@@ -1137,35 +1202,25 @@ static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
                 && (!s->hit
                     || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
                        != 0)) {
-            const uint16_t *pcurves, *clntcurves;
-            size_t num_curves, clnt_num_curves, i;
+            const uint16_t *pgroups, *clntgroups;
+            size_t num_groups, clnt_num_groups, i;
             unsigned int group_id = 0;
 
             /* Check if a shared group exists */
 
             /* Get the clients list of supported groups. */
-            if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) {
-                *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
-                return 0;
-            }
-
-            /* Get our list of available groups */
-            if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
-                *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
-                return 0;
-            }
+            tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
+            tls1_get_supported_groups(s, &pgroups, &num_groups);
 
             /* Find the first group we allow that is also in client's list */
-            for (i = 0; i < num_curves; i++) {
-                group_id = pcurves[i];
+            for (i = 0; i < num_groups; i++) {
+                group_id = pgroups[i];
 
-                if (check_in_list(s, group_id, clntcurves, clnt_num_curves, 1))
+                if (check_in_list(s, group_id, clntgroups, clnt_num_groups, 1))
                     break;
             }
 
-            if (i < num_curves) {
+            if (i < num_groups) {
                 /* A shared group exists so send a HelloRetryRequest */
                 s->s3->group_id = group_id;
                 s->hello_retry_request = 1;
@@ -1427,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;
+}