diff options
-rw-r--r-- | ssl/statem/extensions.c | 41 | ||||
-rw-r--r-- | ssl/statem/statem_srvr.c | 48 |
2 files changed, 49 insertions, 40 deletions
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 2268b271ce..a5dda45a96 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -28,7 +28,6 @@ static int init_status_request(SSL *s, unsigned int context); static int init_npn(SSL *s, unsigned int context); #endif static int init_alpn(SSL *s, unsigned int context); -static int final_alpn(SSL *s, unsigned int context, int sent, int *al); static int init_sig_algs(SSL *s, unsigned int context); static int init_certificate_authorities(SSL *s, unsigned int context); static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, @@ -207,7 +206,7 @@ static const EXTENSION_DEFINITION ext_defs[] = { SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn, - tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn + tls_construct_stoc_alpn, tls_construct_ctos_alpn, NULL }, #ifndef OPENSSL_NO_SRTP { @@ -937,44 +936,6 @@ static int init_alpn(SSL *s, unsigned int context) return 1; } -static int final_alpn(SSL *s, unsigned int context, int sent, int *al) -{ - const unsigned char *selected = NULL; - unsigned char selected_len = 0; - - if (!s->server) - return 1; - - if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { - int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len, - s->s3->alpn_proposed, - (unsigned int)s->s3->alpn_proposed_len, - s->ctx->ext.alpn_select_cb_arg); - - if (r == SSL_TLSEXT_ERR_OK) { - OPENSSL_free(s->s3->alpn_selected); - s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); - if (s->s3->alpn_selected == NULL) { - *al = SSL_AD_INTERNAL_ERROR; - return 0; - } - s->s3->alpn_selected_len = selected_len; -#ifndef OPENSSL_NO_NEXTPROTONEG - /* ALPN takes precedence over NPN. */ - s->s3->npn_seen = 0; -#endif - } else if (r == SSL_TLSEXT_ERR_NOACK) { - /* Behave as if no callback was present. */ - return 1; - } else { - *al = SSL_AD_NO_APPLICATION_PROTOCOL; - return 0; - } - } - - return 1; -} - static int init_sig_algs(SSL *s, unsigned int context) { /* Clear any signature algorithms extension received */ diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index fad339adb2..8c5f77bce5 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1934,6 +1934,45 @@ static int tls_handle_status_request(SSL *s, int *al) return 1; } +/* + * Call the alpn_select callback if needed. Upon success, returns 1. + * Upon failure, returns 0 and sets |*al| to the appropriate fatal alert. + */ +static int tls_handle_alpn(SSL *s, int *al) +{ + const unsigned char *selected = NULL; + unsigned char selected_len = 0; + + if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { + int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len, + s->s3->alpn_proposed, + (unsigned int)s->s3->alpn_proposed_len, + s->ctx->ext.alpn_select_cb_arg); + + if (r == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); + if (s->s3->alpn_selected == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + return 0; + } + s->s3->alpn_selected_len = selected_len; +#ifndef OPENSSL_NO_NEXTPROTONEG + /* ALPN takes precedence over NPN. */ + s->s3->npn_seen = 0; +#endif + } else if (r == SSL_TLSEXT_ERR_NOACK) { + /* Behave as if no callback was present. */ + return 1; + } else { + *al = SSL_AD_NO_APPLICATION_PROTOCOL; + return 0; + } + } + + return 1; +} + WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) { int al = SSL_AD_HANDSHAKE_FAILURE; @@ -2018,6 +2057,15 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) SSL_R_CLIENTHELLO_TLSEXT); goto f_err; } + /* + * Call alpn_select callback if needed. Has to be done after SNI and + * cipher negotiation (HTTP/2 restricts permitted ciphers). + */ + if (!tls_handle_alpn(s, &al)) { + SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, + SSL_R_CLIENTHELLO_TLSEXT); + goto f_err; + } wst = WORK_MORE_C; } |