Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions mysql-test/main/mdev-41008.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
create user x509_subject_user@localhost
require subject '/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB\\/CN=client';
create user x509_issuer_user@localhost
require issuer '/CN=cacert/C=FI/ST=Helsinki/L=Helsinki\\/O=MariaDB';
#
# Default old_mode: strict comparison, escaped grant does not match
#
ERROR 1045 (28000): Access denied for user 'x509_subject_user'@'localhost' (using password: NO)
ERROR 1045 (28000): Access denied for user 'x509_issuer_user'@'localhost' (using password: NO)
#
# old_mode=X509_LENIENT_COMPARE: lenient comparison, grant matches
#
set @old_mode_save= @@global.old_mode;
set global old_mode= concat(@@global.old_mode, ',X509_LENIENT_COMPARE');
1
1
1
1
set global old_mode= @old_mode_save;
drop user x509_subject_user@localhost, x509_issuer_user@localhost;
45 changes: 45 additions & 0 deletions mysql-test/main/mdev-41008.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# MDEV-41008 Parsing of forward slash '/' behaving differently between
# OpenSSL 3 vs OpenSSL 1
#
# OpenSSL 3 escapes a literal '/' or '+' inside an RDN value; OpenSSL 1.1
# and WolfSSL never do. A stored REQUIRE SUBJECT/ISSUER with such a
# backslash doesn't match a certificate rendered without one.
# old_mode=X509_LENIENT_COMPARE restores the lenient match.
#

--source include/have_ssl_communication.inc
--source include/not_embedded.inc
--source include/count_sessions.inc

let $MYSQL_CLIENT= $MYSQL --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem;

# std_data/client-cert.pem subject/issuer are from main/openssl_1.test; the
# extra backslashes below stand in for what a stricter library would escape.

create user x509_subject_user@localhost
require subject '/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB\\/CN=client';

create user x509_issuer_user@localhost
require issuer '/CN=cacert/C=FI/ST=Helsinki/L=Helsinki\\/O=MariaDB';

--echo #
--echo # Default old_mode: strict comparison, escaped grant does not match
--echo #
--error 1
--exec $MYSQL_CLIENT --user=x509_subject_user -e "select 1" 2>&1
--error 1
--exec $MYSQL_CLIENT --user=x509_issuer_user -e "select 1" 2>&1

--echo #
--echo # old_mode=X509_LENIENT_COMPARE: lenient comparison, grant matches
--echo #
set @old_mode_save= @@global.old_mode;
set global old_mode= concat(@@global.old_mode, ',X509_LENIENT_COMPARE');
--exec $MYSQL_CLIENT --user=x509_subject_user -e "select 1" 2>&1
--exec $MYSQL_CLIENT --user=x509_issuer_user -e "select 1" 2>&1
set global old_mode= @old_mode_save;

drop user x509_subject_user@localhost, x509_issuer_user@localhost;

--source include/wait_until_count_sessions.inc
2 changes: 1 addition & 1 deletion mysql-test/main/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ The following specify which files/extra groups are read (specified before remain
--old-mode=name Used to emulate old behavior from earlier MariaDB or
MySQL versions. Any combination of: NO_DUP_KEY_WARNINGS_WITH_IGNORE,
NO_PROGRESS_INFO, ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3, IGNORE_INDEX_ONLY_FOR_JOIN,
COMPAT_5_1_CHECKSUM, NO_NULL_COLLATION_IDS
COMPAT_5_1_CHECKSUM, NO_NULL_COLLATION_IDS, X509_LENIENT_COMPARE
Use 'ALL' to set all combinations.
--old-passwords Use old password encryption method (needed for 4.0 and
older clients)
Expand Down
18 changes: 15 additions & 3 deletions mysql-test/suite/sys_vars/r/old_mode_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ SET @@global.old_mode = NO_DUP_KEY_WARNINGS_WITH_IGNORE;
SELECT @@global.old_mode;
@@global.old_mode
NO_DUP_KEY_WARNINGS_WITH_IGNORE
SET @@global.old_mode = X509_LENIENT_COMPARE;
SELECT @@global.old_mode;
@@global.old_mode
X509_LENIENT_COMPARE
SET @@global.old_mode = OFF;
ERROR 42000: Variable 'old_mode' can't be set to the value of 'OFF'
SET @@session.old_mode = NO_PROGRESS_INFO;
Expand All @@ -57,13 +61,17 @@ SET @@session.old_mode = NO_DUP_KEY_WARNINGS_WITH_IGNORE;
SELECT @@session.old_mode;
@@session.old_mode
NO_DUP_KEY_WARNINGS_WITH_IGNORE
SET @@session.old_mode = X509_LENIENT_COMPARE;
SELECT @@session.old_mode;
@@session.old_mode
X509_LENIENT_COMPARE
SET @@session.old_mode = OFF;
ERROR 42000: Variable 'old_mode' can't be set to the value of 'OFF'
SET @@global.old_mode = '?';
ERROR 42000: Variable 'old_mode' can't be set to the value of '?'
SELECT @@global.old_mode;
@@global.old_mode
NO_DUP_KEY_WARNINGS_WITH_IGNORE
X509_LENIENT_COMPARE
'#--------------------FN_DYNVARS_152_04-------------------------#'
SET @@global.old_mode = -1;
ERROR 42000: Variable 'old_mode' can't be set to the value of '-1'
Expand Down Expand Up @@ -115,10 +123,14 @@ SELECT @@global.old_mode;
@@global.old_mode
ZERO_DATE_TIME_CAST
SET @@global.old_mode = 128;
ERROR 42000: Variable 'old_mode' can't be set to the value of '128'
SELECT @@global.old_mode;
@@global.old_mode
ZERO_DATE_TIME_CAST
X509_LENIENT_COMPARE
SET @@global.old_mode = 256;
ERROR 42000: Variable 'old_mode' can't be set to the value of '256'
SELECT @@global.old_mode;
@@global.old_mode
X509_LENIENT_COMPARE
SET @@global.old_mode = 0.4;
ERROR 42000: Incorrect argument type to variable 'old_mode'
'#---------------------FN_DYNVARS_152_08----------------------#'
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -2309,7 +2309,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,X509_LENIENT_COMPARE
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OLD_PASSWORDS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2479,7 +2479,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS
ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,X509_LENIENT_COMPARE
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OLD_PASSWORDS
Expand Down
9 changes: 8 additions & 1 deletion mysql-test/suite/sys_vars/t/old_mode_basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ SET @@global.old_mode = NO_PROGRESS_INFO;
SELECT @@global.old_mode;
SET @@global.old_mode = NO_DUP_KEY_WARNINGS_WITH_IGNORE;
SELECT @@global.old_mode;
SET @@global.old_mode = X509_LENIENT_COMPARE;
SELECT @@global.old_mode;

--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.old_mode = OFF;
Expand All @@ -95,6 +97,8 @@ SET @@session.old_mode = NO_PROGRESS_INFO;
SELECT @@session.old_mode;
SET @@session.old_mode = NO_DUP_KEY_WARNINGS_WITH_IGNORE;
SELECT @@session.old_mode;
SET @@session.old_mode = X509_LENIENT_COMPARE;
SELECT @@session.old_mode;

--Error ER_WRONG_VALUE_FOR_VAR
SET @@session.old_mode = OFF;
Expand Down Expand Up @@ -171,10 +175,13 @@ SELECT @@global.old_mode;
SET @@global.old_mode = 4;
SELECT @@global.old_mode;

--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.old_mode = 128;
SELECT @@global.old_mode;

--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.old_mode = 256;
SELECT @@global.old_mode;

# use of decimal values

--Error ER_WRONG_TYPE_FOR_VAR
Expand Down
34 changes: 32 additions & 2 deletions sql/sql_acl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14447,6 +14447,36 @@ static void server_mpvio_info(MYSQL_PLUGIN_VIO *vio,
mpvio_info(mpvio->auth_info.thd->net.vio, info);
}

#ifdef HAVE_OPENSSL
/*
strcmp(), unless old_mode=X509_LENIENT_COMPARE: then ignore a backslash
before '/' or '+' on either side, so a name escaped by OpenSSL 3 still
matches the unescaped rendering from OpenSSL 1.1 or WolfSSL. Opt-in:
it reintroduces ambiguity between an escaped literal '/' or '+' and a
real RDN separator.
*/
static int my_x509_oneline_cmp(THD *thd, const char *a, const char *b)
{
if (!a || !b)
return a != b;
if (!(thd->variables.old_behavior & OLD_MODE_X509_LENIENT_COMPARE))
return strcmp(a, b);
for (;;)
{
if (*a == '\\' && (a[1] == '/' || a[1] == '+'))
a++;
if (*b == '\\' && (b[1] == '/' || b[1] == '+'))
b++;
Comment on lines +14466 to +14469
if (*a != *b)
return (unsigned char) *a - (unsigned char) *b;
if (*a == '\0')
return 0;
a++;
b++;
}
}
#endif /* HAVE_OPENSSL */

static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
{
Vio *vio= thd->net.vio;
Expand Down Expand Up @@ -14532,7 +14562,7 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
char *ptr= X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
DBUG_PRINT("info", ("comparing issuers: '%s' and '%s'",
acl_user->x509_issuer, ptr));
if (strcmp(acl_user->x509_issuer, ptr))
if (my_x509_oneline_cmp(thd, acl_user->x509_issuer, ptr))
{
Comment thread
vaintroub marked this conversation as resolved.
if (global_system_variables.log_warnings)
sql_print_information("X509 issuer mismatch: should be '%s' "
Expand All @@ -14549,7 +14579,7 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
DBUG_PRINT("info", ("comparing subjects: '%s' and '%s'",
acl_user->x509_subject, ptr));
if (strcmp(acl_user->x509_subject, ptr))
if (my_x509_oneline_cmp(thd, acl_user->x509_subject, ptr))
{
if (global_system_variables.log_warnings)
sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
Expand Down
1 change: 1 addition & 0 deletions sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ enum enum_binlog_row_image {
#define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4)
#define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5)
#define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6)
#define OLD_MODE_X509_LENIENT_COMPARE (1 << 7)

extern char internal_table_name[2];
extern char empty_c_string[1];
Expand Down
1 change: 1 addition & 0 deletions sql/sys_vars.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3981,6 +3981,7 @@ static const char *old_mode_names[]=
"IGNORE_INDEX_ONLY_FOR_JOIN",
"COMPAT_5_1_CHECKSUM",
"NO_NULL_COLLATION_IDS",
"X509_LENIENT_COMPARE",
0
};

Expand Down