Skip to content

Commit b241f89

Browse files
committed
MDEV-14101: tls-version
Client part of MDEV-14101: Add support for tls-version, via mysql_options(mysql, MARIADB_OPT_TLS_VERSION, value) Accepted values are "TLSv1.1", "TLSv1.2" and "TLSv1.3". Fixed testcase openssl_1 for schannel
1 parent a095106 commit b241f89

File tree

10 files changed

+186
-77
lines changed

10 files changed

+186
-77
lines changed

include/ma_tls.h

+13-11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ enum enum_pvio_tls_type {
1010
SSL_TYPE_GNUTLS
1111
};
1212

13+
#define PROTOCOL_SSLV3 0
14+
#define PROTOCOL_TLS_1_0 1
15+
#define PROTOCOL_TLS_1_1 2
16+
#define PROTOCOL_TLS_1_2 3
17+
#define PROTOCOL_TLS_1_3 4
18+
#define PROTOCOL_UNKNOWN 5
19+
#define PROTOCOL_MAX PROTOCOL_TLS_1_3
20+
1321
#define TLS_VERSION_LENGTH 64
1422
extern char tls_library_version[TLS_VERSION_LENGTH];
1523

@@ -19,11 +27,6 @@ typedef struct st_ma_pvio_tls {
1927
void *ssl;
2028
} MARIADB_TLS;
2129

22-
struct st_ssl_version {
23-
unsigned int iversion;
24-
char *cversion;
25-
};
26-
2730
/* Function prototypes */
2831

2932
/* ma_tls_start
@@ -133,15 +136,15 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ssl);
133136
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int fp_len);
134137

135138
/* ma_tls_get_protocol_version
136-
returns protocol version in use
139+
returns protocol version number in use
137140
Parameter:
138141
MARIADB_TLS MariaDB SSL container
139-
version pointer to ssl version info
140142
Returns:
141-
0 success
142-
1 error
143+
protocol number
143144
*/
144-
my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version);
145+
int ma_tls_get_protocol_version(MARIADB_TLS *ctls);
146+
const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls);
147+
int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls);
145148

146149
/* Function prototypes */
147150
MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql);
@@ -153,7 +156,6 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls);
153156
const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls);
154157
my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list);
155158
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
156-
my_bool ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version);
157159
void ma_pvio_tls_end();
158160

159161
#endif /* _ma_tls_h_ */

include/mysql.h

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ extern const char *SQLSTATE_UNKNOWN;
204204
MYSQL_OPT_SSL_ENFORCE,
205205
MYSQL_OPT_MAX_ALLOWED_PACKET,
206206
MYSQL_OPT_NET_BUFFER_LENGTH,
207+
MYSQL_OPT_TLS_VERSION,
207208

208209
/* MariaDB specific */
209210
MYSQL_PROGRESS_CALLBACK=5999,

libmariadb/ma_tls.c

+14-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
my_bool ma_tls_initialized= FALSE;
5252
unsigned int mariadb_deinitialize_ssl= 1;
5353

54-
const char *ssl_protocol_version[5]= {"TLS1.0", "TLS1.1", "TLS1.2"};
54+
const char *tls_protocol_version[]=
55+
{"SSLv3", "TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3", "Unknown"};
5556

5657
MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql)
5758
{
@@ -114,9 +115,19 @@ void ma_pvio_tls_end()
114115
ma_tls_end();
115116
}
116117

117-
my_bool ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version)
118+
int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls)
118119
{
119-
return ma_tls_get_protocol_version(ctls, version);
120+
return ma_tls_get_protocol_version(ctls);
121+
}
122+
123+
const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls)
124+
{
125+
int version;
126+
127+
version= ma_tls_get_protocol_version(ctls);
128+
if (version < 0 || version > PROTOCOL_MAX)
129+
return tls_protocol_version[PROTOCOL_UNKNOWN];
130+
return tls_protocol_version[version];
120131
}
121132

122133
static char ma_hex2int(char c)

libmariadb/mariadb_lib.c

+9-12
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ struct st_mariadb_methods MARIADB_DEFAULT_METHODS;
135135
#define native_password_plugin_name "mysql_native_password"
136136

137137
#define IS_CONNHDLR_ACTIVE(mysql)\
138-
(((mysql)->extension->conn_hdlr))
138+
((mysql)->extension && (mysql)->extension->conn_hdlr)
139139

140140
static void end_server(MYSQL *mysql);
141141
static void mysql_close_memory(MYSQL *mysql);
@@ -644,7 +644,8 @@ struct st_default_options mariadb_defaults[] =
644644
{MARIADB_OPT_SSL_FP, MARIADB_OPTION_STR, "ssl-fp"},
645645
{MARIADB_OPT_SSL_FP_LIST, MARIADB_OPTION_STR, "ssl-fp-list"},
646646
{MARIADB_OPT_SSL_FP_LIST, MARIADB_OPTION_STR, "ssl-fplist"},
647-
{MARIADB_OPT_TLS_PASSPHRASE, MARIADB_OPTION_STR, "ssl_passphrase"},
647+
{MARIADB_OPT_TLS_PASSPHRASE, MARIADB_OPTION_STR, "ssl-passphrase"},
648+
{MARIADB_OPT_TLS_VERSION, MARIADB_OPTION_STR, "tls_version"},
648649
{MYSQL_OPT_BIND, MARIADB_OPTION_STR, "bind-address"},
649650
{0, 0, NULL}
650651
};
@@ -3003,6 +3004,10 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
30033004
OPT_SET_EXTENDED_VALUE(&mysql->options, proxy_header_len, arg2);
30043005
}
30053006
break;
3007+
case MARIADB_OPT_TLS_VERSION:
3008+
case MYSQL_OPT_TLS_VERSION:
3009+
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, tls_version, (char *)arg1);
3010+
break;
30063011
default:
30073012
va_end(ap);
30083013
return(-1);
@@ -3685,23 +3690,15 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *
36853690
case MARIADB_CONNECTION_TLS_VERSION:
36863691
#ifdef HAVE_TLS
36873692
if (mysql && mysql->net.pvio && mysql->net.pvio->ctls)
3688-
{
3689-
struct st_ssl_version version;
3690-
if (!ma_pvio_tls_get_protocol_version(mysql->net.pvio->ctls, &version))
3691-
*((char **)arg)= version.cversion;
3692-
}
3693+
*((char **)arg)= (char *)ma_pvio_tls_get_protocol_version(mysql->net.pvio->ctls);
36933694
else
36943695
#endif
36953696
goto error;
36963697
break;
36973698
case MARIADB_CONNECTION_TLS_VERSION_ID:
36983699
#ifdef HAVE_TLS
36993700
if (mysql && mysql->net.pvio && mysql->net.pvio->ctls)
3700-
{
3701-
struct st_ssl_version version;
3702-
if (!ma_pvio_tls_get_protocol_version(mysql->net.pvio->ctls, &version))
3703-
*((unsigned int *)arg)= version.iversion;
3704-
}
3701+
*((unsigned int *)arg)= ma_pvio_tls_get_protocol_version_id(mysql->net.pvio->ctls);
37053702
else
37063703
#endif
37073704
goto error;

libmariadb/secure/gnutls.c

+37-10
Original file line numberDiff line numberDiff line change
@@ -1006,17 +1006,46 @@ void ma_tls_end()
10061006
return;
10071007
}
10081008

1009-
static int ma_gnutls_set_ciphers(gnutls_session_t ssl, char *cipher_str)
1009+
static size_t ma_gnutls_get_protocol_version(const char *tls_version_option,
1010+
char *priority_string,
1011+
size_t prio_len)
1012+
{
1013+
char tls_versions[128];
1014+
1015+
tls_versions[0]= 0;
1016+
if (!tls_version_option || !tls_version_option[0])
1017+
goto end;
1018+
1019+
1020+
if (strstr(tls_version_option, "TLSv1.0"))
1021+
strcat(tls_versions, ":+VERS-TLS1.0");
1022+
if (strstr(tls_version_option, "TLSv1.1"))
1023+
strcat(tls_versions, ":+VERS-TLS1.1");
1024+
if (strstr(tls_version_option, "TLSv1.2"))
1025+
strcat(tls_versions, ":+VERS-TLS1.2");
1026+
end:
1027+
if (tls_versions[0])
1028+
snprintf(priority_string, prio_len - 1, "NORMAL:-VERS-TLS-ALL%s", tls_versions);
1029+
else
1030+
strncpy(priority_string, "NORMAL", prio_len - 1);
1031+
return strlen(priority_string);
1032+
}
1033+
1034+
static int ma_gnutls_set_ciphers(gnutls_session_t ssl,
1035+
const char *cipher_str,
1036+
const char *tls_version)
10101037
{
10111038
const char *err;
10121039
char *token;
1013-
#define PRIO_SIZE 1024
1040+
#define PRIO_SIZE 1024
10141041
char prio[PRIO_SIZE];
10151042

1043+
ma_gnutls_get_protocol_version(tls_version, prio, PRIO_SIZE);
1044+
10161045
if (!cipher_str)
1017-
return gnutls_priority_set_direct(ssl, "NORMAL", &err);
1046+
return gnutls_priority_set_direct(ssl, prio, &err);
10181047

1019-
token= strtok(cipher_str, ":");
1048+
token= strtok((char *)cipher_str, ":");
10201049

10211050
strcpy(prio, "NONE:+VERS-TLS-ALL:+SIGN-ALL:+COMP-NULL");
10221051

@@ -1180,7 +1209,7 @@ void *ma_tls_init(MYSQL *mysql)
11801209
/*
11811210
gnutls_certificate_set_retrieve_function2(GNUTLS_xcred, client_cert_callback);
11821211
*/
1183-
ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher);
1212+
ssl_error= ma_gnutls_set_ciphers(ssl, mysql->options.ssl_cipher, mysql->options.extension ? mysql->options.extension->tls_version : NULL);
11841213
if (ssl_error < 0)
11851214
goto error;
11861215

@@ -1427,19 +1456,17 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int l
14271456
else
14281457
{
14291458
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
1430-
ER(CR_SSL_CONNECTION_ERROR),
1459+
ER(CR_SSL_CONNECTION_ERROR),
14311460
"Finger print buffer too small");
14321461
return 0;
14331462
}
14341463
}
14351464

1436-
my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version)
1465+
int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
14371466
{
14381467
if (!ctls || !ctls->ssl)
14391468
return 1;
14401469

1441-
version->iversion= gnutls_protocol_get_version(ctls->ssl);
1442-
version->cversion= (char *)gnutls_protocol_get_name(version->iversion);
1443-
return 0;
1470+
return gnutls_protocol_get_version(ctls->ssl) - 1;
14441471
}
14451472
#endif /* HAVE_GNUTLS */

libmariadb/secure/ma_schannel.c

+9-16
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls)
851851

852852
if (crl_file && !(crl_ctx= (CRL_CONTEXT *)ma_schannel_create_crl_context(pvio, mysql->options.extension->ssl_crl)))
853853
goto end;
854-
854+
855855
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
856856
{
857857
ma_schannel_set_sec_error(pvio, sRet);
@@ -978,8 +978,8 @@ ssize_t ma_schannel_write_encrypt(MARIADB_PVIO *pvio,
978978

979979
extern char *ssl_protocol_version[5];
980980

981-
/* {{{ ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version) */
982-
my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version)
981+
/* {{{ ma_tls_get_protocol_version(MARIADB_TLS *ctls) */
982+
int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
983983
{
984984
SC_CTX *sctx;
985985
SecPkgContext_ConnectionInfo ConnectionInfo;
@@ -989,27 +989,20 @@ my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *ve
989989
sctx= (SC_CTX *)ctls->ssl;
990990

991991
if (QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_CONNECTION_INFO, &ConnectionInfo) != SEC_E_OK)
992-
return 1;
992+
return -1;
993993

994994
switch(ConnectionInfo.dwProtocol)
995995
{
996996
case SP_PROT_SSL3_CLIENT:
997-
version->iversion= 1;
998-
break;
997+
return PROTOCOL_SSLV3;
999998
case SP_PROT_TLS1_CLIENT:
1000-
version->iversion= 2;
1001-
break;
999+
return PROTOCOL_TLS_1_0;
10021000
case SP_PROT_TLS1_1_CLIENT:
1003-
version->iversion= 3;
1004-
break;
1001+
return PROTOCOL_TLS_1_1;
10051002
case SP_PROT_TLS1_2_CLIENT:
1006-
version->iversion= 4;
1007-
break;
1003+
return PROTOCOL_TLS_1_2;
10081004
default:
1009-
version->iversion= 0;
1010-
break;
1005+
return -1;
10111006
}
1012-
version->cversion= ssl_protocol_version[version->iversion];
1013-
return 0;
10141007
}
10151008
/* }}} */

libmariadb/secure/openssl.c

+31-11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,30 @@ static int ma_bio_write(BIO *h, const char *buf, int size);
7272
static BIO_METHOD ma_BIO_method;
7373
#endif
7474

75+
76+
static long ma_tls_version_options(const char *version)
77+
{
78+
long protocol_options,
79+
disable_all_protocols;
80+
81+
protocol_options= disable_all_protocols=
82+
SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
83+
84+
if (!version)
85+
return 0;
86+
87+
if (strstr(version, "TLSv1.0"))
88+
protocol_options&= ~SSL_OP_NO_TLSv1;
89+
if (strstr(version, "TLSv1.1"))
90+
protocol_options&= ~SSL_OP_NO_TLSv1_1;
91+
if (strstr(version, "TLSv1.2"))
92+
protocol_options&= ~SSL_OP_NO_TLSv1_2;
93+
94+
if (protocol_options != disable_all_protocols)
95+
return protocol_options;
96+
return 0;
97+
}
98+
7599
static void ma_tls_set_error(MYSQL *mysql)
76100
{
77101
ulong ssl_errno= ERR_get_error();
@@ -488,6 +512,7 @@ void *ma_tls_init(MYSQL *mysql)
488512
{
489513
SSL *ssl= NULL;
490514
SSL_CTX *ctx= NULL;
515+
long options= SSL_OP_ALL;
491516
#ifdef HAVE_TLS_SESSION_CACHE
492517
MA_SSL_SESSION *session= ma_tls_get_session(mysql);
493518
#endif
@@ -499,7 +524,9 @@ void *ma_tls_init(MYSQL *mysql)
499524
if (!(ctx= SSL_CTX_new(SSLv23_client_method())))
500525
#endif
501526
goto error;
502-
SSL_CTX_set_options(ctx, SSL_OP_ALL);
527+
if (mysql->options.extension)
528+
options|= ma_tls_version_options(mysql->options.extension->tls_version);
529+
SSL_CTX_set_options(ctx, options);
503530
#ifdef HAVE_TLS_SESSION_CACHE
504531
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);
505532
ma_tls_sessions= (MA_SSL_SESSION *)calloc(1, sizeof(struct st_ma_tls_session) * ma_tls_session_cache_size);
@@ -762,18 +789,11 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int l
762789
}
763790

764791

765-
extern char *ssl_protocol_version[5];
766-
767-
my_bool ma_tls_get_protocol_version(MARIADB_TLS *ctls, struct st_ssl_version *version)
792+
int ma_tls_get_protocol_version(MARIADB_TLS *ctls)
768793
{
769-
SSL *ssl;
770-
771794
if (!ctls || !ctls->ssl)
772-
return 1;
795+
return -1;
773796

774-
ssl = (SSL *)ctls->ssl;
775-
version->iversion= SSL_version(ssl) - TLS1_VERSION;
776-
version->cversion= ssl_protocol_version[version->iversion];
777-
return 0;
797+
return SSL_version(ctls->ssl) & 0xFF;
778798
}
779799

libmariadb/secure/schannel.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -372,11 +372,11 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
372372
}
373373
if (mysql->options.extension && mysql->options.extension->tls_version)
374374
{
375-
if (strstr("TLSv1.0", mysql->options.extension->tls_version))
375+
if (strstr(mysql->options.extension->tls_version, "TLSv1.0"))
376376
Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0_CLIENT;
377-
if (strstr("TLSv1.1", mysql->options.extension->tls_version))
377+
if (strstr(mysql->options.extension->tls_version, "TLSv1.1"))
378378
Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1_CLIENT;
379-
if (strstr("TLSv1.2", mysql->options.extension->tls_version))
379+
if (strstr(mysql->options.extension->tls_version, "TLSv1.2"))
380380
Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2_CLIENT;
381381
}
382382
if (!Cred.grbitEnabledProtocols)

unittest/libmariadb/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ IF(WITH_SSL)
4141
FILE(READ ${CERT_PATH}/server-cert.sha1 CERT_FINGER_PRINT)
4242
STRING(REPLACE "\n" "" CERT_FINGER_PRINT "${CERT_FINGER_PRINT}")
4343
SET(API_TESTS ${API_TESTS} "ssl")
44+
IF(WIN32)
45+
STRING(REPLACE "\\" "\\\\" CERT_PATH ${CERT_PATH})
46+
ENDIF()
4447
CONFIGURE_FILE(${CC_SOURCE_DIR}/unittest/libmariadb/ssl.c.in
4548
${CC_BINARY_DIR}/unittest/libmariadb/ssl.c)
4649
ADD_EXECUTABLE(ssl ${CC_BINARY_DIR}/unittest/libmariadb/ssl.c)

0 commit comments

Comments
 (0)