Skip to content

Commit bd4100b

Browse files
committed
CONC-795: Implementation of client side SNI support
1 parent 4bb84c4 commit bd4100b

File tree

7 files changed

+81
-4
lines changed

7 files changed

+81
-4
lines changed

include/ma_tls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enum enum_pvio_tls_type {
2828
((m)->options.extension->tls_fp_list && (m)->options.extension->tls_fp_list[0]))
2929

3030
extern char tls_library_version[TLS_VERSION_LENGTH];
31+
extern my_bool ma_is_ip_address(const char *s);
3132

3233
typedef struct st_ma_pvio_tls {
3334
void *data;

libmariadb/ma_net.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
8080

8181
int ma_net_write_buff(NET *net,const char *packet, size_t len);
8282

83-
8483
/* Init with packet info */
8584

8685
int ma_net_init(NET *net, MARIADB_PVIO* pvio)

libmariadb/mariadb_lib.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ my_bool ma_check_buffer_boundaries(MYSQL *mysql, uchar *current_pos,
168168
return 0;
169169
}
170170

171+
my_bool ma_is_ip_address(const char *s)
172+
{
173+
struct in_addr v4;
174+
struct in6_addr v6;
175+
176+
if (inet_pton(AF_INET, s, &v4) == 1 ||
177+
inet_pton(AF_INET6, s, &v6) == 1)
178+
return 1;
179+
180+
return 0;
181+
}
182+
171183
/* net_get_error */
172184
void net_get_error(char *buf, size_t buf_len,
173185
char *error, size_t error_len,

libmariadb/secure/gnutls.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,11 @@ void *ma_tls_init(MYSQL *mysql)
11621162
a client certificate we will send it via callback function */
11631163
if ((ssl_error= gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, ctx)) < 0)
11641164
goto error;
1165-
1165+
1166+
if (mysql->host && !ma_is_ip_address(mysql->host))
1167+
if ((ssl_error = gnutls_server_name_set(ssl, GNUTLS_NAME_DNS, mysql->host, strlen(mysql->host))) < 0)
1168+
goto error;
1169+
11661170
pthread_mutex_unlock(&LOCK_gnutls_config);
11671171
return (void *)ssl;
11681172
error:

libmariadb/secure/ma_schannel.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,20 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe
8484
PUCHAR IoBuffer;
8585
BOOL fDoRead;
8686
MARIADB_TLS *ctls= pvio->ctls;
87+
MYSQL *mysql= pvio->mysql;
8788
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
89+
char *sni_host= NULL;
8890

8991

9092
dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
9193
ISC_REQ_REPLAY_DETECT |
9294
ISC_REQ_CONFIDENTIALITY |
9395
ISC_RET_EXTENDED_ERROR |
94-
ISC_REQ_ALLOCATE_MEMORY |
96+
ISC_REQ_ALLOCATE_MEMORY |
9597
ISC_REQ_STREAM;
9698

99+
if (mysql->host && !ma_is_ip_address(mysql->host))
100+
sni_host= mysql->host;
97101

98102
/* Allocate data buffer */
99103
if (!(IoBuffer = malloc(SC_IO_BUFFER_SIZE)))
@@ -166,7 +170,7 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe
166170

167171
rc = InitializeSecurityContextA(&sctx->CredHdl,
168172
&sctx->hCtxt,
169-
NULL,
173+
sni_host,
170174
dwSSPIFlags,
171175
0,
172176
SECURITY_NATIVE_DREP,

libmariadb/secure/openssl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,12 @@ void *ma_tls_init(MYSQL *mysql)
447447
if (!(ssl= SSL_new(ctx)))
448448
goto error;
449449

450+
#if !defined(OPENSSL_NO_TLSEXT)
451+
if (mysql->host && !ma_is_ip_address(mysql->host))
452+
if (!SSL_set_tlsext_host_name(ssl, mysql->host))
453+
goto error;
454+
#endif
455+
450456
if (!SSL_set_app_data(ssl, mysql))
451457
goto error;
452458

unittest/libmariadb/tls.c.in

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,9 +827,60 @@ static int test_cert_ip(MYSQL *my __attribute((unused)))
827827
return OK;
828828
}
829829

830+
static int test_conc795(MYSQL *my __attribute__((unused)))
831+
{
832+
MYSQL *mysql= mysql_init(NULL);
833+
MYSQL_RES *res= NULL;
834+
int rc, ret= FAIL;
835+
MYSQL_ROW row;
836+
837+
set_verify(mysql, 0);
838+
839+
if (ma_is_ip_address(hostname))
840+
{
841+
diag("SNI test skipped (hostname = ip address");
842+
ret = SKIP;
843+
goto end;
844+
}
845+
846+
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
847+
848+
if (!my_test_connect(mysql, hostname, username, password, schema,
849+
port, socketname, 0, 0))
850+
{
851+
diag("error: %s", mysql_error(mysql));
852+
goto end;
853+
}
854+
855+
rc= mysql_query(mysql, "SHOW STATUS LIKE 'Tls_sni_server_name'");
856+
check_mysql_rc(rc, mysql);
857+
858+
if (!(res = mysql_store_result(mysql)) || !(row = mysql_fetch_row(res)))
859+
{
860+
diag("Server doesn't support tls_sni_server_name");
861+
ret= SKIP;
862+
goto end;
863+
}
864+
865+
if (strcmp(row[1], hostname))
866+
{
867+
diag("SNI mismatch: %s != %s", hostname, row[1]);
868+
goto end;
869+
}
870+
871+
diag("SNI match: %s == %s", hostname, row[1]);
872+
ret= OK;
873+
end:
874+
if (res)
875+
mysql_free_result(res);
876+
mysql_close(mysql);
877+
return ret;
878+
}
879+
830880

831881
struct my_tests_st my_tests[] = {
832882
/* Don't add test above, test_init needs to be run first */
883+
{"test_conc795", test_conc795, TEST_CONNECTION_NEW, 0, NULL, NULL},
833884
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
834885
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
835886
/* Here you can add more tests */

0 commit comments

Comments
 (0)