From 973bbab9d0c1fa32bf3155efe121767dd8b1ed3a Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 5 Sep 2016 19:30:48 -0500 Subject: [PATCH] Add TLS SNI support to the client. --- include/violite.h | 2 +- sql-common/client.c | 6 +++--- vio/test-ssl.c | 2 +- vio/test-sslclient.c | 2 +- vio/viossl.c | 25 +++++++++++++++++++++---- vio/viotest-ssl.c | 2 +- 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/include/violite.h b/include/violite.h index ebf8c1f..9d4f1a3 100644 --- a/include/violite.h +++ b/include/violite.h @@ -208,7 +208,7 @@ struct st_VioSSLFd }; int sslaccept(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); -int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr, const char *host); struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, diff --git a/sql-common/client.c b/sql-common/client.c index 56d1a57..5f5010e 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -3411,7 +3411,7 @@ Establishes SSL if requested and supported. @retval 1 failure */ static int -cli_establish_ssl(MYSQL *mysql) +cli_establish_ssl(MYSQL *mysql, const char *host) { #ifdef HAVE_OPENSSL NET *net= &mysql->net; @@ -3501,7 +3501,7 @@ cli_establish_ssl(MYSQL *mysql) DBUG_PRINT("info", ("IO layer change in progress...")); MYSQL_TRACE(SSL_CONNECT, mysql, ()); if (sslconnect(ssl_fd, net->vio, - (long) (mysql->options.connect_timeout), &ssl_error)) + (long) (mysql->options.connect_timeout), &ssl_error, (const char *)host)) { char buf[512]; ERR_error_string_n(ssl_error, buf, 512); @@ -4679,7 +4679,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, scramble_buffer= scramble_data; } - if (cli_establish_ssl(mysql)) + if (cli_establish_ssl(mysql, host)) goto error; /* diff --git a/vio/test-ssl.c b/vio/test-ssl.c index c99f507..c2bccf4 100644 --- a/vio/test-ssl.c +++ b/vio/test-ssl.c @@ -99,7 +99,7 @@ main(int argc, char** argv) client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); client_vio->sd = sv[0]; client_vio->vioblocking(client_vio, 0, &unused); - sslconnect(ssl_connector,client_vio,60L,&ssl_error); + sslconnect(ssl_connector,client_vio,60L,&ssl_error, "the_hostname"); server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); server_vio->sd = sv[1]; server_vio->vioblocking(client_vio, 0, &unused); diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c index 93fdb06..28f7f73 100644 --- a/vio/test-sslclient.c +++ b/vio/test-sslclient.c @@ -85,7 +85,7 @@ main( int argc __attribute__((unused)), /* ----------------------------------------------- */ /* Now we have TCP conncetion. Start SSL negotiation. */ read(client_vio->sd,xbuf, sizeof(xbuf)); - sslconnect(ssl_connector,client_vio,60L,&ssl_error); + sslconnect(ssl_connector,client_vio,60L,&ssl_error, "the_hostname"); err = vio_read(client_vio,xbuf, sizeof(xbuf)); if (err<=0) { my_free(ssl_connector); diff --git a/vio/viossl.c b/vio/viossl.c index 5622cb7..5e8690e 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -20,6 +20,10 @@ the file descriptior. */ +#include + +#include + #include "vio_priv.h" #ifdef HAVE_OPENSSL @@ -376,7 +380,7 @@ static int ssl_handshake_loop(Vio *vio, SSL *ssl, static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, ssl_handshake_func_t func, - unsigned long *ssl_errno_holder) + unsigned long *ssl_errno_holder, const char *host) { int r; SSL *ssl; @@ -399,6 +403,19 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, } DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); SSL_clear(ssl); + +#if defined(HAVE_OPENSSL) + if (host) + { + if (!SSL_set_tlsext_host_name(ssl, host)) + { + DBUG_PRINT("error", ("SSL_set_tlsext_host_name failure")); + *ssl_errno_holder= ERR_get_error(); + DBUG_RETURN(1); + } + } +#endif + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, sd); #if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION) @@ -491,15 +508,15 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *ssl_errno_holder) { DBUG_ENTER("sslaccept"); - DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept, ssl_errno_holder)); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept, ssl_errno_holder, NULL)); } int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout, - unsigned long *ssl_errno_holder) + unsigned long *ssl_errno_holder, const char *host) { DBUG_ENTER("sslconnect"); - DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect, ssl_errno_holder)); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect, ssl_errno_holder, host)); } diff --git a/vio/viotest-ssl.c b/vio/viotest-ssl.c index 51d171d..a42aee0 100644 --- a/vio/viotest-ssl.c +++ b/vio/viotest-ssl.c @@ -99,7 +99,7 @@ int main(int argc, char **argv) client_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); client_vio->sd = sv[0]; - sslconnect(ssl_connector,client_vio,&ssl_error); + sslconnect(ssl_connector,client_vio,&ssl_error, "the_hostname"); server_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); server_vio->sd = sv[1]; sslaccept(ssl_acceptor,server_vio,&ssl_error);