Update custom TLS extension and supplemental data 'generate' callbacks to support...
authorScott Deboy <sdeboy@secondstryke.com>
Thu, 12 Sep 2013 19:03:40 +0000 (12:03 -0700)
committerScott Deboy <sdeboy@secondstryke.com>
Sun, 9 Feb 2014 00:17:24 +0000 (16:17 -0800)
If multiple TLS extensions are expected but not received, the TLS extension and supplemental data 'generate' callbacks are the only chance for the receive-side to trigger a specific TLS alert during the handshake.

Removed logic which no-op'd TLS extension generate callbacks (as the generate callbacks need to always be called in order to trigger alerts), and updated the serverinfo-specific custom TLS extension callbacks to track which custom TLS extensions were received by the client, where no-ops for 'generate' callbacks are appropriate.

(cherry picked from commit ac20719d994729970eb3b775c7bffa81f0e9f960)
Conflicts:
ssl/t1_lib.c

12 files changed:
apps/s_client.c
apps/s_server.c
ssl/s23_clnt.c
ssl/s3_clnt.c
ssl/s3_lib.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_locl.h
ssl/ssl_rsa.c
ssl/ssltest.c
ssl/t1_lib.c

index e06c9486e0e83393f3e8ddef3e2c9188f9635971..b9feec73a5ddb380dbdd836ac165e876ca1ba9e3 100644 (file)
@@ -242,11 +242,11 @@ static int suppdata_cb(SSL *s, unsigned short supp_data_type,
 
 static int auth_suppdata_generate_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg);
+                                     unsigned short *outlen, int *al, void *arg);
 
 static int authz_tlsext_generate_cb(SSL *s, unsigned short ext_type,
                                    const unsigned char **out, unsigned short *outlen,
-                                   void *arg);
+                                    int *al, void *arg);
 
 static int authz_tlsext_cb(SSL *s, unsigned short ext_type,
                           const unsigned char *in,
@@ -2458,7 +2458,7 @@ static int authz_tlsext_cb(SSL *s, unsigned short ext_type,
 
 static int authz_tlsext_generate_cb(SSL *s, unsigned short ext_type,
                                    const unsigned char **out, unsigned short *outlen,
-                                   void *arg)
+                                    int *al, void *arg)
        {
        if (c_auth)
                {
@@ -2490,7 +2490,7 @@ static int suppdata_cb(SSL *s, unsigned short supp_data_type,
 
 static int auth_suppdata_generate_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (c_auth && server_provided_client_authz && server_provided_server_authz)
                {
index 576daac6963e05215f0de89440e8f2eb84400136..9bd00431bf0531186181781ad37edd87fde7a3eb 100644 (file)
@@ -336,11 +336,11 @@ static int suppdata_cb(SSL *s, unsigned short supp_data_type,
 
 static int auth_suppdata_generate_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg);
+                                     unsigned short *outlen, int *al, void *arg);
 
 static int authz_tlsext_generate_cb(SSL *s, unsigned short ext_type,
                                    const unsigned char **out, unsigned short *outlen,
-                                   void *arg);
+                                    int *al, void *arg);
 
 static int authz_tlsext_cb(SSL *s, unsigned short ext_type,
                           const unsigned char *in,
@@ -3576,7 +3576,7 @@ static int authz_tlsext_cb(SSL *s, unsigned short ext_type,
 
 static int authz_tlsext_generate_cb(SSL *s, unsigned short ext_type,
                                    const unsigned char **out, unsigned short *outlen,
-                                   void *arg)
+                                    int *al, void *arg)
        {
        if (c_auth && client_provided_client_authz && client_provided_server_authz)
                {
@@ -3609,7 +3609,7 @@ static int suppdata_cb(SSL *s, unsigned short supp_data_type,
 
 static int auth_suppdata_generate_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (c_auth && client_provided_client_authz && client_provided_server_authz)
                {
index a101bce1611afbff4301cc895dd11625afa06e3c..99d5dfe6d36133512878461de47f038268c5ddbc 100644 (file)
@@ -553,8 +553,9 @@ static int ssl23_client_hello(SSL *s)
                                SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
                                return -1;
                                }
-                       if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                        if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL)
                                {
+                                ssl3_send_alert(s,SSL3_AL_FATAL,al);
                                SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
                                return -1;
                                }
index d7178793ab3390772e3f5fb524502d4dbc2d5a4e..d39cbba49be9447eae35ca308075cf541b7e743a 100644 (file)
@@ -891,8 +891,9 @@ int ssl3_client_hello(SSL *s)
                        SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
                        goto err;
                        }
-               if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL)
                        {
+                        ssl3_send_alert(s,SSL3_AL_FATAL,al);
                        SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
                        goto err;
                        }
@@ -3617,6 +3618,7 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
 #ifndef OPENSSL_NO_TLSEXT
 int tls1_send_client_supplemental_data(SSL *s, int *skip)
        {
+        int al = 0;
        if (s->ctx->cli_supp_data_records_count)
                {
                unsigned char *p = NULL;
@@ -3636,14 +3638,14 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
                        if (!record->fn2)
                                continue;
                        cb_retval = record->fn2(s, record->supp_data_type,
-                               &out, &outlen,
+                                &out, &outlen, &al,
                                record->arg);
                        if (cb_retval == -1)
                                continue; /* skip this supp data entry */
                        if (cb_retval == 0)
                                {
                                SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
-                               return 0;
+                                goto f_err;
                                }
                        if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
                                {
@@ -3695,7 +3697,11 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip)
        s->init_num = 0;
        s->init_off = 0;
        return 1;
-       }
+
+f_err:
+        ssl3_send_alert(s,SSL3_AL_FATAL,al);
+        return 0;
+}
 
 int tls1_get_server_supplemental_data(SSL *s)
        {
index b03601d6eaa0b141ea6fd87169aa63842b9e13ac..e99b048e4c7373c7279f687572c989ff056c72e2 100644 (file)
@@ -3029,8 +3029,8 @@ void ssl3_free(SSL *s)
        SSL_SRP_CTX_free(s);
 #endif
 #ifndef OPENSSL_NO_TLSEXT
-       if (s->s3->tlsext_custom_types != NULL)
-               OPENSSL_free(s->s3->tlsext_custom_types);
+        if (s->s3->serverinfo_client_tlsext_custom_types != NULL)
+                OPENSSL_free(s->s3->serverinfo_client_tlsext_custom_types);
 #endif
        OPENSSL_cleanse(s->s3,sizeof *s->s3);
        OPENSSL_free(s->s3);
@@ -3076,12 +3076,12 @@ void ssl3_clear(SSL *s)
                }
 #endif
 #ifndef OPENSSL_NO_TLSEXT
-       if (s->s3->tlsext_custom_types != NULL)
+        if (s->s3->serverinfo_client_tlsext_custom_types != NULL)
                {
-               OPENSSL_free(s->s3->tlsext_custom_types);
-               s->s3->tlsext_custom_types = NULL;
+                OPENSSL_free(s->s3->serverinfo_client_tlsext_custom_types);
+                s->s3->serverinfo_client_tlsext_custom_types = NULL;
                }
-       s->s3->tlsext_custom_types_count = 0;   
+        s->s3->serverinfo_client_tlsext_custom_types_count = 0;
 #ifndef OPENSSL_NO_EC
        s->s3->is_probably_safari = 0;
 #endif /* !OPENSSL_NO_EC */
index 3699524eb3192bdbe2179604b2904f66cc685537..15061aef30e99ddc4df5d69efac6dc8c576e3f3c 100644 (file)
@@ -1500,7 +1500,7 @@ int ssl3_send_server_hello(SSL *s)
        {
        unsigned char *buf;
        unsigned char *p,*d;
-       int i,sl;
+        int i,sl,al;
        unsigned long l;
 
        if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
@@ -1569,8 +1569,9 @@ int ssl3_send_server_hello(SSL *s)
                        SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
                        return -1;
                        }
-               if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL)
                        {
+                        ssl3_send_alert(s, SSL3_AL_FATAL, al);
                        SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
                        return -1;
                        }
@@ -3654,6 +3655,7 @@ int ssl3_get_next_proto(SSL *s)
 
 int tls1_send_server_supplemental_data(SSL *s, int *skip)
        {
+        int al = 0;
        if (s->ctx->srv_supp_data_records_count)
                {
                unsigned char *p = NULL;
@@ -3673,14 +3675,14 @@ int tls1_send_server_supplemental_data(SSL *s, int *skip)
                        if (!record->fn1)
                                continue;
                        cb_retval = record->fn1(s, record->supp_data_type,
-                       &out, &outlen,
+                        &out, &outlen, &al,
                        record->arg);
                        if (cb_retval == -1)
                                continue; /* skip this supp data entry */
                        if (cb_retval == 0)
                                {
                                SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
-                               return 0;
+                                goto f_err;
                                }
                        if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
                                {
@@ -3738,6 +3740,9 @@ int tls1_send_server_supplemental_data(SSL *s, int *skip)
        s->init_num = 0;
        s->init_off = 0;
        return 1;
+f_err:
+        ssl3_send_alert(s,SSL3_AL_FATAL,al);
+        return 0;
        }
 
 int tls1_get_client_supplemental_data(SSL *s)
index 2f590fe5deba10cd8b4b2526826e5aff44607885..7b6af00ff2cf6f298e8795e8947f0dbad67cebb9 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -406,7 +406,7 @@ typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, S
  */
 typedef int (*custom_cli_ext_first_cb_fn)(SSL *s, unsigned short ext_type,
                                          const unsigned char **out,
-                                         unsigned short *outlen, void *arg);
+                                          unsigned short *outlen, int *al, void *arg);
 typedef int (*custom_cli_ext_second_cb_fn)(SSL *s, unsigned short ext_type,
                                           const unsigned char *in,
                                           unsigned short inlen, int *al,
@@ -418,7 +418,7 @@ typedef int (*custom_srv_ext_first_cb_fn)(SSL *s, unsigned short ext_type,
                                          void *arg);
 typedef int (*custom_srv_ext_second_cb_fn)(SSL *s, unsigned short ext_type,
                                           const unsigned char **out,
-                                          unsigned short *outlen, void *arg); 
+                                           unsigned short *outlen, int *al, void *arg);
 
 typedef struct {
        unsigned short ext_type;
@@ -457,7 +457,7 @@ typedef struct {
  */
 typedef int (*srv_supp_data_first_cb_fn)(SSL *s, unsigned short supp_data_type,
             const unsigned char **out,
-            unsigned short *outlen, void *arg);
+             unsigned short *outlen, int *al, void *arg);
 typedef int (*srv_supp_data_second_cb_fn)(SSL *s, unsigned short supp_data_type,
             const unsigned char *in,
             unsigned short inlen, int *al,
@@ -469,7 +469,7 @@ typedef int (*cli_supp_data_first_cb_fn)(SSL *s, unsigned short supp_data_type,
             void *arg);
 typedef int (*cli_supp_data_second_cb_fn)(SSL *s, unsigned short supp_data_type,
             const unsigned char **out,
-            unsigned short *outlen, void *arg);
+             unsigned short *outlen, int *al, void *arg);
 
 typedef struct {
        unsigned short supp_data_type;
index 6e7bd0f62c2236a17a675f38e414713a4abd3d19..2e46410fd37ab01f4e50edc43594e8d16895c29f 100644 (file)
@@ -560,14 +560,12 @@ typedef struct ssl3_state_st
 #endif
 
 #ifndef OPENSSL_NO_TLSEXT
-       /* tlsext_custom_types contains an array of TLS Extension types which 
-        * were advertised by the client in its ClientHello, which were not 
-        * otherwise handled by OpenSSL, and which the server has registered
-        * a custom_srv_ext_record to handle.
+        /* serverinfo_client_tlsext_custom_types contains an array of TLS Extension types which
+         * were advertised by the client in its ClientHello and leveraged by ServerInfo TLS extension callbacks.
         * The array does not contain any duplicates, and is in the same order
         * as the types were received in the client hello. */
-       unsigned short *tlsext_custom_types;
-       size_t tlsext_custom_types_count; /* how many tlsext_custom_types */
+        unsigned short *serverinfo_client_tlsext_custom_types;
+        size_t serverinfo_client_tlsext_custom_types_count; /* how many serverinfo_client_tlsext_custom_types */
 
 #ifndef OPENSSL_NO_EC
        /* This is set to true if we believe that this is a version of Safari
index 6f1209cbbbd659c571af4c0edf7e3aaeaad55223..1e67a5629575114dc52549ef33f816cacfbede23 100644 (file)
@@ -1263,8 +1263,8 @@ int tls1_shared_list(SSL *s,
                        const unsigned char *l1, size_t l1len,
                        const unsigned char *l2, size_t l2len,
                        int nmatch);
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al);
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al);
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
 int ssl_check_clienthello_tlsext_late(SSL *s);
 int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n);
index 7fcd8460a3e5832c385e264f033b154b4f77225b..063eea5ecb9ed9e4344914f88794d929fad1aa45 100644 (file)
@@ -848,20 +848,59 @@ static int serverinfo_srv_first_cb(SSL *s, unsigned short ext_type,
                                   unsigned short inlen, int *al,
                                   void *arg)
        {
+        size_t i = 0;
        if (inlen != 0)
                {
                *al = SSL_AD_DECODE_ERROR;
                return 0;
                }
+        //if already in list, error out
+        for (i = 0; i < s->s3->serverinfo_client_tlsext_custom_types_count; i++)
+                {
+                if (s->s3->serverinfo_client_tlsext_custom_types[i] == ext_type)
+                        {
+                        *al = SSL_AD_DECODE_ERROR;
+                        return 0;
+                        }
+                }
+        s->s3->serverinfo_client_tlsext_custom_types_count++;
+        s->s3->serverinfo_client_tlsext_custom_types = OPENSSL_realloc(
+        s->s3->serverinfo_client_tlsext_custom_types,
+        s->s3->serverinfo_client_tlsext_custom_types_count * 2);
+        if (s->s3->serverinfo_client_tlsext_custom_types == NULL)
+                {
+                s->s3->serverinfo_client_tlsext_custom_types_count = 0;
+                *al = TLS1_AD_INTERNAL_ERROR;
+                return 0;
+                }
+        s->s3->serverinfo_client_tlsext_custom_types[
+        s->s3->serverinfo_client_tlsext_custom_types_count - 1] = ext_type;
+
        return 1;
        }
 
 static int serverinfo_srv_second_cb(SSL *s, unsigned short ext_type,
                                    const unsigned char **out, unsigned short *outlen, 
-                                   void *arg)
+                                    int *al, void *arg)
        {
        const unsigned char *serverinfo = NULL;
        size_t serverinfo_length = 0;
+        size_t i = 0;
+        unsigned int match = 0;
+        /* Did the client send a TLS extension for this type? */
+        for (i = 0; i < s->s3->serverinfo_client_tlsext_custom_types_count; i++)
+                {
+                if (s->s3->serverinfo_client_tlsext_custom_types[i] == ext_type)
+                        {
+                        match = 1;
+                        break;
+                        }
+                }
+        if (!match)
+        {
+                //extension not sent by client...don't send extension
+                return -1;
+        }
 
        /* Is there serverinfo data for the chosen server cert? */
        if ((ssl_get_server_cert_serverinfo(s, &serverinfo,
index 3755e06905549cbf486d9724f974589f872ef757..2af5710f90193eb861e028a20d978e9ad2459b8e 100644 (file)
@@ -489,7 +489,7 @@ static int verify_serverinfo()
 
 static int custom_ext_0_cli_first_cb(SSL *s, unsigned short ext_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (ext_type != CUSTOM_EXT_TYPE_0)
                custom_ext_error = 1;
@@ -507,7 +507,7 @@ static int custom_ext_0_cli_second_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_1_cli_first_cb(SSL *s, unsigned short ext_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (ext_type != CUSTOM_EXT_TYPE_1)
                custom_ext_error = 1;
@@ -527,7 +527,7 @@ static int custom_ext_1_cli_second_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_2_cli_first_cb(SSL *s, unsigned short ext_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (ext_type != CUSTOM_EXT_TYPE_2)
                custom_ext_error = 1;
@@ -550,7 +550,7 @@ static int custom_ext_2_cli_second_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_3_cli_first_cb(SSL *s, unsigned short ext_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        if (ext_type != CUSTOM_EXT_TYPE_3)
                custom_ext_error = 1;
@@ -573,7 +573,7 @@ static int custom_ext_3_cli_second_cb(SSL *s, unsigned short ext_type,
        return 1;
        }
 
-
+//custom_ext_0_cli_first_cb returns -1 - the server won't receive a callback for this extension
 static int custom_ext_0_srv_first_cb(SSL *s, unsigned short ext_type,
                                     const unsigned char *in,
                                     unsigned short inlen, int *al,
@@ -583,12 +583,12 @@ static int custom_ext_0_srv_first_cb(SSL *s, unsigned short ext_type,
        return 0; /* Shouldn't be called */
        }
 
+//'generate' callbacks are always called, even if the 'receive' callback isn't called
 static int custom_ext_0_srv_second_cb(SSL *s, unsigned short ext_type,
                                      const unsigned char **out,
-                                     unsigned short *outlen, void *arg)
+                                      unsigned short *outlen, int *al, void *arg)
        {
-       custom_ext_error = 1;
-       return 0; /* Shouldn't be called */
+        return -1; /* Don't send an extension */
        }
 
 static int custom_ext_1_srv_first_cb(SSL *s, unsigned short ext_type,
@@ -608,7 +608,7 @@ static int custom_ext_1_srv_first_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_1_srv_second_cb(SSL *s, unsigned short ext_type,
                                      const unsigned char **out,
-                                     unsigned short *outlen, void *arg)
+                                      unsigned short *outlen, int *al, void *arg)
        {
        return -1; /* Don't send an extension */
        }
@@ -630,7 +630,7 @@ static int custom_ext_2_srv_first_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_2_srv_second_cb(SSL *s, unsigned short ext_type,
                                      const unsigned char **out,
-                                     unsigned short *outlen, void *arg)
+                                      unsigned short *outlen, int *al, void *arg)
        {
        *out = NULL;
        *outlen = 0;
@@ -654,7 +654,7 @@ static int custom_ext_3_srv_first_cb(SSL *s, unsigned short ext_type,
 
 static int custom_ext_3_srv_second_cb(SSL *s, unsigned short ext_type,
                                      const unsigned char **out,
-                                     unsigned short *outlen, void *arg)
+                                      unsigned short *outlen, int *al, void *arg)
        {
        *out = (const unsigned char*)custom_ext_srv_string;
        *outlen = strlen(custom_ext_srv_string);
@@ -663,7 +663,7 @@ static int custom_ext_3_srv_second_cb(SSL *s, unsigned short ext_type,
 
 static int supp_data_0_srv_first_cb(SSL *s, unsigned short supp_data_type,
                                    const unsigned char **out,
-                                   unsigned short *outlen, void *arg)
+                                    unsigned short *outlen, int *al, void *arg)
        {
        *out = (const unsigned char*)supp_data_0_string;
        *outlen = strlen(supp_data_0_string);
@@ -690,7 +690,7 @@ static int supp_data_0_srv_second_cb(SSL *s, unsigned short supp_data_type,
 
 static int supp_data_1_srv_first_cb(SSL *s, unsigned short supp_data_type,
                                    const unsigned char **out,
-                                   unsigned short *outlen, void *arg)
+                                    unsigned short *outlen, int *al, void *arg)
        {
        return -1;
        }
@@ -731,7 +731,7 @@ static int supp_data_0_cli_first_cb(SSL *s, unsigned short supp_data_type,
 
 static int supp_data_0_cli_second_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        *out = (const unsigned char*)supp_data_0_string;
        *outlen = strlen(supp_data_0_string);
@@ -751,7 +751,7 @@ static int supp_data_1_cli_first_cb(SSL *s, unsigned short supp_data_type,
 
 static int supp_data_1_cli_second_cb(SSL *s, unsigned short supp_data_type,
                                     const unsigned char **out,
-                                    unsigned short *outlen, void *arg)
+                                     unsigned short *outlen, int *al, void *arg)
        {
        return -1;
        }
index 291f4ab00f0fd89c2e98d451c3d29969ee15a92b..f3f6f8218458787c7a535a946df38d5a8c21b174 100644 (file)
@@ -1102,7 +1102,7 @@ static int byte_compare(const void *in_a, const void *in_b)
        return 0;
 }
 
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
        {
        int extdatalen=0;
        unsigned char *ret = p;
@@ -1466,7 +1466,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                                {
                                int cb_retval = 0;
                                cb_retval = record->fn1(s, record->ext_type,
-                                                       &out, &outlen,
+                                                        &out, &outlen, al,
                                                        record->arg);
                                if (cb_retval == 0)
                                        return NULL; /* error */
@@ -1519,10 +1519,12 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
        return ret;
        }
 
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
        {
        int extdatalen=0;
        unsigned char *ret = p;
+        size_t i;
+        custom_srv_ext_record *record;
 #ifndef OPENSSL_NO_NEXTPROTONEG
        int next_proto_neg_seen;
 #endif
@@ -1706,45 +1708,29 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 #endif
 
-       /* If custom types were sent in ClientHello, add ServerHello responses */
-       if (s->s3->tlsext_custom_types_count)
+        for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++)
                {
-               size_t i;
-
-               for (i = 0; i < s->s3->tlsext_custom_types_count; i++)
-                       {
-                       size_t j;
-                       custom_srv_ext_record *record;
-
-                       for (j = 0; j < s->ctx->custom_srv_ext_records_count; j++)
-                               {
-                               record = &s->ctx->custom_srv_ext_records[j];
-                               if (s->s3->tlsext_custom_types[i] == record->ext_type)
-                                       {
-                                       const unsigned char *out = NULL;
-                                       unsigned short outlen = 0;
-                                       int cb_retval = 0;
-
-                                       /* NULL callback or -1 omits extension */
-                                       if (!record->fn2)
-                                               break;
-                                       cb_retval = record->fn2(s, record->ext_type,
-                                                               &out, &outlen,
-                                                               record->arg);
-                                       if (cb_retval == 0)
-                                               return NULL; /* error */
-                                       if (cb_retval == -1)
-                                               break; /* skip this extension */
-                                       if (limit < ret + 4 + outlen)
-                                               return NULL;
-                                       s2n(record->ext_type, ret);
-                                       s2n(outlen, ret);
-                                       memcpy(ret, out, outlen);
-                                       ret += outlen;
-                                       break;
-                                       }
-                               }
-                       }
+                record = &s->ctx->custom_srv_ext_records[i];
+                const unsigned char *out = NULL;
+                unsigned short outlen = 0;
+                int cb_retval = 0;
+
+                /* NULL callback or -1 omits extension */
+                if (!record->fn2)
+                        break;
+                cb_retval = record->fn2(s, record->ext_type,
+                &out, &outlen, al,
+                record->arg);
+                if (cb_retval == 0)
+                        return NULL; /* error */
+                if (cb_retval == -1)
+                        break; /* skip this extension */
+                if (limit < ret + 4 + outlen)
+                        return NULL;
+                s2n(record->ext_type, ret);
+                s2n(outlen, ret);
+                memcpy(ret, out, outlen);
+                ret += outlen;
                }
 
        if (s->s3->alpn_selected)
@@ -1938,11 +1924,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 #endif
 
        /* Clear observed custom extensions */
-       s->s3->tlsext_custom_types_count = 0;
-       if (s->s3->tlsext_custom_types != NULL)
+        s->s3->serverinfo_client_tlsext_custom_types_count = 0;
+        if (s->s3->serverinfo_client_tlsext_custom_types != NULL)
                {
-               OPENSSL_free(s->s3->tlsext_custom_types);
-               s->s3->tlsext_custom_types = NULL;
+                OPENSSL_free(s->s3->serverinfo_client_tlsext_custom_types);
+                s->s3->serverinfo_client_tlsext_custom_types = NULL;
                }               
 
        if (s->s3->alpn_selected)
@@ -2467,35 +2453,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                record = &s->ctx->custom_srv_ext_records[i];
                                if (type == record->ext_type)
                                        {
-                                       size_t j;
-
-                                       /* Error on duplicate TLS Extensions */
-                                       for (j = 0; j < s->s3->tlsext_custom_types_count; j++)
-                                               {
-                                               if (type == s->s3->tlsext_custom_types[j])
-                                                       {
-                                                       *al = TLS1_AD_DECODE_ERROR;
-                                                       return 0;
-                                                       }
-                                               }
-
-                                       /* NULL callback still notes the extension */ 
                                        if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
                                                return 0;
-                                               
-                                       /* Add the (non-duplicated) entry */
-                                       s->s3->tlsext_custom_types_count++;
-                                       s->s3->tlsext_custom_types = OPENSSL_realloc(
-                                                       s->s3->tlsext_custom_types,
-                                                       s->s3->tlsext_custom_types_count * 2);
-                                       if (s->s3->tlsext_custom_types == NULL)
-                                               {
-                                               s->s3->tlsext_custom_types = 0;
-                                               *al = TLS1_AD_INTERNAL_ERROR;
-                                               return 0;
-                                               }
-                                       s->s3->tlsext_custom_types[
-                                                       s->s3->tlsext_custom_types_count - 1] = type;
                                        }                                               
                                }
                        }