You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
CONC-724: Added TLS verification callback support
For testing purposes (the python3 dummy server can't handle further communication after TLS handshake succeeded) support for verification callback was added. my_bool callback(MYSQL *mysql, unsigned int *flags, my_bool verified) Parameter: - mysql connection handle for current connection - flags verification flags - verified true if callback was called after verification, otherwise false Return value: - False (0) to continue - True (1) to abort tls connection The callback function can be registered via mysql_optionsv(mysql, MARIADB_OPT_TLS_VERIFICATION_CALLBACK, callback);
This commit is contained in:
@@ -88,6 +88,7 @@ struct st_mysql_options_extension {
|
|||||||
void (*status_callback)(void *ptr, enum enum_mariadb_status_info type, ...);
|
void (*status_callback)(void *ptr, enum enum_mariadb_status_info type, ...);
|
||||||
void *status_data;
|
void *status_data;
|
||||||
my_bool tls_allow_invalid_server_cert;
|
my_bool tls_allow_invalid_server_cert;
|
||||||
|
my_bool (*tls_verification_callback)(MYSQL *mysql, unsigned int *verification_flags, my_bool verified);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_connection_handler
|
typedef struct st_connection_handler
|
||||||
|
@@ -297,7 +297,7 @@ typedef struct st_net {
|
|||||||
unsigned char reading_or_writing;
|
unsigned char reading_or_writing;
|
||||||
char save_char;
|
char save_char;
|
||||||
char unused_1;
|
char unused_1;
|
||||||
my_bool tls_verify_status;
|
unsigned char tls_verify_status;
|
||||||
my_bool compress;
|
my_bool compress;
|
||||||
my_bool unused_2;
|
my_bool unused_2;
|
||||||
char *unused_3;
|
char *unused_3;
|
||||||
|
@@ -259,7 +259,8 @@ extern const char *SQLSTATE_UNKNOWN;
|
|||||||
MARIADB_OPT_RPL_REGISTER_REPLICA,
|
MARIADB_OPT_RPL_REGISTER_REPLICA,
|
||||||
MARIADB_OPT_STATUS_CALLBACK,
|
MARIADB_OPT_STATUS_CALLBACK,
|
||||||
MARIADB_OPT_SERVER_PLUGINS,
|
MARIADB_OPT_SERVER_PLUGINS,
|
||||||
MARIADB_OPT_BULK_UNIT_RESULTS
|
MARIADB_OPT_BULK_UNIT_RESULTS,
|
||||||
|
MARIADB_OPT_TLS_VERIFICATION_CALLBACK
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mariadb_value {
|
enum mariadb_value {
|
||||||
|
@@ -119,7 +119,17 @@ int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mysql->options.extension->tls_verification_callback &&
|
||||||
|
mysql->options.extension->tls_verification_callback(mysql, &flags, 0))
|
||||||
|
rc= 1;
|
||||||
|
else {
|
||||||
rc= ma_tls_verify_server_cert(ctls, flags);
|
rc= ma_tls_verify_server_cert(ctls, flags);
|
||||||
|
if (mysql->options.extension->tls_verification_callback &&
|
||||||
|
mysql->options.extension->tls_verification_callback(mysql, &flags, 1))
|
||||||
|
{
|
||||||
|
rc= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Set error messages */
|
/* Set error messages */
|
||||||
if (!mysql->net.last_errno)
|
if (!mysql->net.last_errno)
|
||||||
|
@@ -3853,6 +3853,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
|||||||
case MARIADB_OPT_BULK_UNIT_RESULTS:
|
case MARIADB_OPT_BULK_UNIT_RESULTS:
|
||||||
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, bulk_unit_results, *(my_bool *)arg1);
|
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, bulk_unit_results, *(my_bool *)arg1);
|
||||||
break;
|
break;
|
||||||
|
case MARIADB_OPT_TLS_VERIFICATION_CALLBACK:
|
||||||
|
OPT_SET_EXTENDED_VALUE(&mysql->options, tls_verification_callback, arg1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
|
SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
|
||||||
|
@@ -42,11 +42,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
FAIL_IF(!(status & (flag)), (text));\
|
FAIL_IF(!(status & (flag)), (text));\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_NO_TLS_FLAGS(m)\
|
#define CHECK_NO_TLS_FLAG(m, flag, text)\
|
||||||
{\
|
{\
|
||||||
unsigned int status;\
|
unsigned int status;\
|
||||||
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);\
|
mariadb_get_infov(mysql, MARIADB_TLS_VERIFY_STATUS, &status);\
|
||||||
FAIL_IF(status), "Expected MARIADB_TLS_VERIFY_OK");\
|
FAIL_IF((status & (flag)), (text));\
|
||||||
}
|
}
|
||||||
|
|
||||||
my_bool auto_generated_cert= 0;
|
my_bool auto_generated_cert= 0;
|
||||||
@@ -141,7 +141,7 @@ static int test_start_tls_server(MYSQL *my __attribute__((unused)))
|
|||||||
|
|
||||||
snprintf(hostname, sizeof(hostname), "--host=%s", tls_dummy_host);
|
snprintf(hostname, sizeof(hostname), "--host=%s", tls_dummy_host);
|
||||||
snprintf(port, sizeof(port), "--port=%d", tls_dummy_port);
|
snprintf(port, sizeof(port), "--port=%d", tls_dummy_port);
|
||||||
execlp("@Python3_EXECUTABLE@", "@Python3_EXECUTABLE@", "tls_server.py", hostname, port, NULL);
|
execlp("@Python3_EXECUTABLE@", "@Python3_EXECUTABLE@", "@CC_SOURCE_DIR@/unittest/libmariadb/tls_server.py", hostname, port, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -658,11 +658,72 @@ static int stop_tls_server(MYSQL *my __attribute__((unused)))
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my_bool tls_wildcard_callback(MYSQL *mysql, unsigned int *flags, my_bool verified)
|
||||||
|
{
|
||||||
|
if (!verified)
|
||||||
|
{
|
||||||
|
free(mysql->host);
|
||||||
|
mysql->host= strdup("test.example.com");
|
||||||
|
*flags= MARIADB_TLS_VERIFY_HOST;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Indicate error, since the dummy server can't handle further client server
|
||||||
|
communication after TLS handshake */
|
||||||
|
mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_ERROR;
|
||||||
|
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
|
||||||
|
ER(CR_SSL_CONNECTION_ERROR),
|
||||||
|
"Certificate verification aborted by callback");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cert_wildcard(MYSQL *my __attribute((unused)))
|
||||||
|
{
|
||||||
|
MYSQL *mysql= mysql_init(NULL);
|
||||||
|
if (set_tls_dummy_options("CMD:create_new=True commonName='*.example.com'"))
|
||||||
|
{
|
||||||
|
diag("Error when setting TLS options");
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
mysql_optionsv(mysql, MARIADB_OPT_TLS_VERIFICATION_CALLBACK, tls_wildcard_callback);
|
||||||
|
|
||||||
|
if (!my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
CHECK_NO_TLS_FLAG(mysql, MARIADB_TLS_VERIFY_HOST, "Hostname verification didn't pass");
|
||||||
|
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_TRUST, "Self signed certificate expected");
|
||||||
|
mysql_close(mysql);
|
||||||
|
} else {
|
||||||
|
mysql_close(mysql);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql= mysql_init(NULL);
|
||||||
|
if (set_tls_dummy_options("CMD:create_new=True commonName='*.noexample.com'"))
|
||||||
|
{
|
||||||
|
diag("Error when setting TLS options");
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
mysql_optionsv(mysql, MARIADB_OPT_TLS_VERIFICATION_CALLBACK, tls_wildcard_callback);
|
||||||
|
|
||||||
|
if (!my_test_connect(mysql, tls_dummy_host, "tlsuser", "foo", NULL, tls_dummy_port, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
CHECK_TLS_FLAGS(mysql, MARIADB_TLS_VERIFY_HOST, "Hostname verification passed with wrong wildcard");
|
||||||
|
mysql_close(mysql);
|
||||||
|
} else {
|
||||||
|
mysql_close(mysql);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct my_tests_st my_tests[] = {
|
struct my_tests_st my_tests[] = {
|
||||||
/* Don't add test above, test_init needs to be run first */
|
/* Don't add test above, test_init needs to be run first */
|
||||||
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
{"test_start_tls_server", test_start_tls_server, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||||
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
{"test_init", test_init, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||||
/* Here you can add more tests */
|
/* Here you can add more tests */
|
||||||
|
{"test_cert_wildcard", test_cert_wildcard, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
{"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
{"test_cert_expired", test_cert_expired, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
{"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
{"test_pw_check", test_pw_check, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
{"test_ca_cert_check", test_ca_cert_check, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
{"test_ca_cert_check", test_ca_cert_check, TEST_CONNECTION_NONE, 0, NULL, NULL},
|
||||||
|
Reference in New Issue
Block a user