Commit 70fa3aa1 authored by Ionut Mihalcea's avatar Ionut Mihalcea Committed by Matt Caswell
Browse files

Don't set SNI by default if hostname is not dNS name



Reviewed-by: default avatarBen Kaduk <kaduk@mit.edu>
Reviewed-by: default avatarViktor Dukhovni <viktor@openssl.org>
Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8175)

(cherry picked from commit 8e981051)
parent 663dc8c1
Loading
Loading
Loading
Loading
+72 −4
Original line number Diff line number Diff line
/*
 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright 2005 Nokia. All rights reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
@@ -74,6 +74,7 @@ static void print_stuff(BIO *berr, SSL *con, int full);
static int ocsp_resp_cb(SSL *s, void *arg);
#endif
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
static int is_dNS_name(const char *host);

static int saved_errno;

@@ -1991,9 +1992,11 @@ int s_client_main(int argc, char **argv)
        SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV);

    if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
        if (servername == NULL)
        if (servername == NULL) {
            if(host == NULL || is_dNS_name(host)) 
                servername = (host == NULL) ? "localhost" : host;
        if (!SSL_set_tlsext_host_name(con, servername)) {
        }
        if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) {
            BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
            ERR_print_errors(bio_err);
            goto end;
@@ -3473,4 +3476,69 @@ static int ldap_ExtendedResponse_parse(const char *buf, long rem)
    return ret;
}

/*
 * Host dNS Name verifier: used for checking that the hostname is in dNS format 
 * before setting it as SNI
 */
static int is_dNS_name(const char *host)
{
    const size_t MAX_LABEL_LENGTH = 63;
    size_t i;
    int isdnsname = 0;
    size_t length = strlen(host);
    size_t label_length = 0;
    int all_numeric = 1;

    /*
     * Deviation from strict DNS name syntax, also check names with '_'
     * Check DNS name syntax, any '-' or '.' must be internal,
     * and on either side of each '.' we can't have a '-' or '.'.
     *
     * If the name has just one label, we don't consider it a DNS name.
     */
    for (i = 0; i < length && label_length < MAX_LABEL_LENGTH; ++i) {
        char c = host[i];

        if ((c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '_') {
            label_length += 1;
            all_numeric = 0;
            continue;
        }

        if (c >= '0' && c <= '9') {
            label_length += 1;
            continue;
        }

        /* Dot and hyphen cannot be first or last. */
        if (i > 0 && i < length - 1) {
            if (c == '-') {
                label_length += 1;
                continue;
            }
            /*
             * Next to a dot the preceding and following characters must not be
             * another dot or a hyphen.  Otherwise, record that the name is
             * plausible, since it has two or more labels.
             */
            if (c == '.'
                && host[i + 1] != '.'
                && host[i - 1] != '-'
                && host[i + 1] != '-') {
                label_length = 0;
                isdnsname = 1;
                continue;
            }
        }
        isdnsname = 0;
        break;
    }

    /* dNS name must not be all numeric and labels must be shorter than 64 characters. */
    isdnsname &= !all_numeric && !(label_length == MAX_LABEL_LENGTH);

    return isdnsname;
}
#endif                          /* OPENSSL_NO_SOCK */
+11 −8
Original line number Diff line number Diff line
@@ -191,14 +191,17 @@ Use IPv6 only.
=item B<-servername name>

Set the TLS SNI (Server Name Indication) extension in the ClientHello message to
the given value. If both this option and the B<-noservername> are not given, the
TLS SNI extension is still set to the hostname provided to the B<-connect> option,
or "localhost" if B<-connect> has not been supplied. This is default since OpenSSL
1.1.1.

Even though SNI name should normally be a DNS name and not an IP address, this
option will not make the distinction when parsing B<-connect> and will send
IP address if one passed.
the given value. 
If B<-servername> is not provided, the TLS SNI extension will be populated with 
the name given to B<-connect> if it follows a DNS name format. If B<-connect> is 
not provided either, the SNI is set to "localhost".
This is the default since OpenSSL 1.1.1.

Even though SNI should normally be a DNS name and not an IP address, if 
B<-servername> is provided then that name will be sent, regardless of whether 
it is a DNS name or not.

This option cannot be used in conjuction with B<-noservername>.

=item B<-noservername>