Search code examples
c++sslopenssltls1.2sni

Cannot retrieve Server Name (SNI) from ClientHello using OpenSSL 1.1.1


On my running server (using OpenSSL 1.1.1d) I tried extracting the Server Name (SNI) extension from ClientHello messages using the following callback API by:

  • Calling SSL_client_hello_get0_ext with the TLSEXT_TYPE_server_name type as done in the repo.
  • Calling SSL_get_servername with TLSEXT_NAMETYPE_host_name as documented.

Yet nothing seems to work, the SNI is either NULL or garbage.

One thing that I noticed was that only after finishing the ClientHello callback I was able to extract it, but at that point it's too late. Has someone encountered a similar issue?

Attaching below a minimal code sample demonstrating how I retrieve the SNI:

int
my_server::client_hello_cb(SSL *ssl, int *al, void *arg)
{
    my_server* server = static_cast<my_server*>(SSL_get_app_data(ssl));
    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);

    server->set_client_sni(sni);
    return 0;
}

void
my_server::create()
{
    SSL* ssl = SSL_new(ctx_);
    SSL_set_app_data(ssl, this);

    BIO* rbio = BIO_new(BIO_s_mem());
    BIO* wbio = BIO_new(BIO_s_mem());
    SSL_set_bio(ssl, rbio, wbio);

    SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());

    SSL_CTX_set_ecdh_auto(ctx, 1);
    SSL_CTX_set_client_hello_cb(ctx, client_hello_cb, nullptr);
}

Solution

  • Special thanks to Steffen for clearing stuff out.

    The SSL_get_servername must be called directly from the server name callback, therfore not solving the original issue.

    Instead, the server name extension can be parsed manually (as done here) using SSL_client_hello_get0_ext directly from the client hello callback.