Skip to content

Commit ef0183c

Browse files
davidbenCQ bot account: commit-bot@chromium.org
authored andcommitted
Make SSL_get_servername work in the early callback.
This avoids early callback users writing their own SNI parser and gives us a place to surface the server name from ESNI in the future. Update-Note: This isn't a breaking change, but users of SSL_CTX_set_select_certificate_cb can likely drop a bit of code after this CL. Bug: 275 Change-Id: I9685ae5cca8e0483de76229d12dac45ff8e9ec32 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/36784 Reviewed-by: Steven Valdez <[email protected]> Commit-Queue: David Benjamin <[email protected]>
1 parent 4dfd5af commit ef0183c

File tree

4 files changed

+64
-66
lines changed

4 files changed

+64
-66
lines changed

include/openssl/ssl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,6 +3714,8 @@ OPENSSL_EXPORT int SSL_early_callback_ctx_extension_get(
37143714
// high-level operation on |ssl| to be retried at a later time, which will
37153715
// result in another call to |cb|.
37163716
//
3717+
// |SSL_get_servername| may be used during this callback.
3718+
//
37173719
// Note: The |SSL_CLIENT_HELLO| is only valid for the duration of the callback
37183720
// and is not valid while the handshake is paused.
37193721
OPENSSL_EXPORT void SSL_CTX_set_select_certificate_cb(

ssl/handshake_server.cc

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,54 @@ static bool is_probably_jdk11_with_tls13(const SSL_CLIENT_HELLO *client_hello) {
503503
return true;
504504
}
505505

506+
static bool extract_sni(SSL_HANDSHAKE *hs, uint8_t *out_alert,
507+
const SSL_CLIENT_HELLO *client_hello) {
508+
SSL *const ssl = hs->ssl;
509+
CBS sni;
510+
if (!ssl_client_hello_get_extension(client_hello, &sni,
511+
TLSEXT_TYPE_server_name)) {
512+
// No SNI extension to parse.
513+
return true;
514+
}
515+
516+
CBS server_name_list, host_name;
517+
uint8_t name_type;
518+
if (!CBS_get_u16_length_prefixed(&sni, &server_name_list) ||
519+
!CBS_get_u8(&server_name_list, &name_type) ||
520+
// Although the server_name extension was intended to be extensible to
521+
// new name types and multiple names, OpenSSL 1.0.x had a bug which meant
522+
// different name types will cause an error. Further, RFC 4366 originally
523+
// defined syntax inextensibly. RFC 6066 corrected this mistake, but
524+
// adding new name types is no longer feasible.
525+
//
526+
// Act as if the extensibility does not exist to simplify parsing.
527+
!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
528+
CBS_len(&server_name_list) != 0 ||
529+
CBS_len(&sni) != 0) {
530+
*out_alert = SSL_AD_DECODE_ERROR;
531+
return false;
532+
}
533+
534+
if (name_type != TLSEXT_NAMETYPE_host_name ||
535+
CBS_len(&host_name) == 0 ||
536+
CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
537+
CBS_contains_zero_byte(&host_name)) {
538+
*out_alert = SSL_AD_UNRECOGNIZED_NAME;
539+
return false;
540+
}
541+
542+
// Copy the hostname as a string.
543+
char *raw = nullptr;
544+
if (!CBS_strdup(&host_name, &raw)) {
545+
*out_alert = SSL_AD_INTERNAL_ERROR;
546+
return false;
547+
}
548+
ssl->s3->hostname.reset(raw);
549+
550+
hs->should_ack_sni = true;
551+
return true;
552+
}
553+
506554
static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
507555
SSL *const ssl = hs->ssl;
508556

@@ -526,6 +574,12 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
526574
return ssl_hs_handoff;
527575
}
528576

577+
uint8_t alert = SSL_AD_DECODE_ERROR;
578+
if (!extract_sni(hs, &alert, &client_hello)) {
579+
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
580+
return ssl_hs_error;
581+
}
582+
529583
// Run the early callback.
530584
if (ssl->ctx->select_certificate_cb != NULL) {
531585
switch (ssl->ctx->select_certificate_cb(&client_hello)) {
@@ -553,7 +607,6 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) {
553607
hs->apply_jdk11_workaround = true;
554608
}
555609

556-
uint8_t alert = SSL_AD_DECODE_ERROR;
557610
if (!negotiate_version(hs, &alert, &client_hello)) {
558611
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
559612
return ssl_hs_error;

ssl/t1_lib.cc

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -633,45 +633,7 @@ static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
633633

634634
static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
635635
CBS *contents) {
636-
SSL *const ssl = hs->ssl;
637-
if (contents == NULL) {
638-
return true;
639-
}
640-
641-
CBS server_name_list, host_name;
642-
uint8_t name_type;
643-
if (!CBS_get_u16_length_prefixed(contents, &server_name_list) ||
644-
!CBS_get_u8(&server_name_list, &name_type) ||
645-
// Although the server_name extension was intended to be extensible to
646-
// new name types and multiple names, OpenSSL 1.0.x had a bug which meant
647-
// different name types will cause an error. Further, RFC 4366 originally
648-
// defined syntax inextensibly. RFC 6066 corrected this mistake, but
649-
// adding new name types is no longer feasible.
650-
//
651-
// Act as if the extensibility does not exist to simplify parsing.
652-
!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
653-
CBS_len(&server_name_list) != 0 ||
654-
CBS_len(contents) != 0) {
655-
return false;
656-
}
657-
658-
if (name_type != TLSEXT_NAMETYPE_host_name ||
659-
CBS_len(&host_name) == 0 ||
660-
CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
661-
CBS_contains_zero_byte(&host_name)) {
662-
*out_alert = SSL_AD_UNRECOGNIZED_NAME;
663-
return false;
664-
}
665-
666-
// Copy the hostname as a string.
667-
char *raw = nullptr;
668-
if (!CBS_strdup(&host_name, &raw)) {
669-
*out_alert = SSL_AD_INTERNAL_ERROR;
670-
return false;
671-
}
672-
ssl->s3->hostname.reset(raw);
673-
674-
hs->should_ack_sni = true;
636+
// SNI has already been parsed earlier in the handshake. See |extract_sni|.
675637
return true;
676638
}
677639

ssl/test/test_config.cc

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,34 +1102,15 @@ static enum ssl_select_cert_result_t SelectCertificateCallback(
11021102
GetTestState(client_hello->ssl)->early_callback_called = true;
11031103

11041104
if (!config->expect_server_name.empty()) {
1105-
const uint8_t *extension_data;
1106-
size_t extension_len;
1107-
CBS extension, server_name_list, host_name;
1108-
uint8_t name_type;
1109-
1110-
if (!SSL_early_callback_ctx_extension_get(
1111-
client_hello, TLSEXT_TYPE_server_name, &extension_data,
1112-
&extension_len)) {
1113-
fprintf(stderr, "Could not find server_name extension.\n");
1114-
return ssl_select_cert_error;
1115-
}
1116-
1117-
CBS_init(&extension, extension_data, extension_len);
1118-
if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
1119-
CBS_len(&extension) != 0 ||
1120-
!CBS_get_u8(&server_name_list, &name_type) ||
1121-
name_type != TLSEXT_NAMETYPE_host_name ||
1122-
!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
1123-
CBS_len(&server_name_list) != 0) {
1124-
fprintf(stderr, "Could not decode server_name extension.\n");
1105+
const char *server_name =
1106+
SSL_get_servername(client_hello->ssl, TLSEXT_NAMETYPE_host_name);
1107+
if (server_name == nullptr ||
1108+
std::string(server_name) != config->expect_server_name) {
1109+
fprintf(stderr,
1110+
"Server name mismatch in early callback (got %s; want %s).\n",
1111+
server_name, config->expect_server_name.c_str());
11251112
return ssl_select_cert_error;
11261113
}
1127-
1128-
if (!CBS_mem_equal(&host_name,
1129-
(const uint8_t *)config->expect_server_name.data(),
1130-
config->expect_server_name.size())) {
1131-
fprintf(stderr, "Server name mismatch.\n");
1132-
}
11331114
}
11341115

11351116
if (config->fail_early_callback) {

0 commit comments

Comments
 (0)