mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Extend Unix socket authentication to support authentication_string
Before this change the unix socket auth plugin returned true only when the OS socket user id matches the MariaDB user name. The authentication string was ignored. Now if an authentication string is defined with in `unix_socket` authentication rule, then the authentication string will be used to compare with the socket's user name, and the plugin will return a positive if matching. Make the plugin to fill in the @@external_user variable. This change is similar to MySQL commit of https://github.com/mysql/mysql-server/commit/6ddbc58e. However there's one difference with above commit: - For MySQL, both Unix user matches DB user name and Unix user matches the authentication string will be allowed to connect. - For MariaDB, we only allows the Unix user matches the authentication string to connect, if the authentication string is defined. This is because allowing both Unix user names has risks and couldn't handle the case that a customer only wants to allow one single Unix user to connect which doesn't matches the DB user name. If DB user is created with multiple unix_socket options for example: `create user A identified via unix_socket as 'B' or unix_socket as 'C';` Then both Unix user of B and C are accepted. Existing MTR test of `plugins.unix_socket` is not impacted. Also add a new MTR test to verify authentication with authentication string. See the MTR test cases for supported/unsupported cases. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
This commit is contained in:
parent
25b5c63905
commit
9e1923ca23
3 changed files with 311 additions and 5 deletions
|
@ -0,0 +1,139 @@
|
|||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
# - connect as database user A using unix user of B
|
||||
# Expected result:
|
||||
# - connection succeed
|
||||
########################################################################
|
||||
create user 'DB_USER1' identified via unix_socket as 'OS_USER' or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
grant select on test.* to 'DB_USER1';
|
||||
#
|
||||
# Auth succeed with OS user matches the first authentication string.
|
||||
# @@external_user is set to OS_USER name.
|
||||
#
|
||||
select user(), current_user(), database();
|
||||
user() current_user() database()
|
||||
DB_USER1@localhost DB_USER1@% test
|
||||
select @@external_user;
|
||||
@@external_user
|
||||
OS_USER
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
host user authentication_string optional_authentication_string
|
||||
% DB_USER1 -Cannot-Match-Any-Legal-Unix-User-Name OS_USER
|
||||
|
||||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
# - connect as database user A using unix user of C
|
||||
# Expected result:
|
||||
# - connection succeed
|
||||
########################################################################
|
||||
create user 'DB_USER2' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name' or unix_socket as 'OS_USER';
|
||||
grant select on test.* to 'DB_USER2';
|
||||
#
|
||||
# Auth succeed with OS user matches the optional authentication string.
|
||||
# @@external_user is set to OS_USER name.
|
||||
#
|
||||
select user(), current_user(), database();
|
||||
user() current_user() database()
|
||||
DB_USER2@localhost DB_USER2@% test
|
||||
select @@external_user;
|
||||
@@external_user
|
||||
OS_USER
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
host user authentication_string optional_authentication_string
|
||||
% DB_USER1 -Cannot-Match-Any-Legal-Unix-User-Name OS_USER
|
||||
|
||||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B';
|
||||
# - connect as database user A using unix user of D
|
||||
# Expected result:
|
||||
# - connection is refused
|
||||
########################################################################
|
||||
create user 'DB_USER3' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
grant select on test.* to 'DB_USER3';
|
||||
#
|
||||
# Auth fail with OS user that does not match the authentication string.
|
||||
#
|
||||
#
|
||||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
# - connect as database user A using unix user of D
|
||||
# Expected result:
|
||||
# - connection is refused
|
||||
########################################################################
|
||||
create user 'DB_USER4' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-1'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-2';
|
||||
grant select on test.* to 'DB_USER4';
|
||||
#
|
||||
# Auth fail with OS user that does not match the authentication string.
|
||||
#
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
host user authentication_string optional_authentication_string
|
||||
% DB_USER1 -Cannot-Match-Any-Legal-Unix-User-Name OS_USER
|
||||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B' or unix_socket as 'C' or unix_socket as 'D' or unix_socket as 'E' or unix_socket as 'F';
|
||||
# - connect as database user A using unix user of 'D'
|
||||
# Expected result:
|
||||
# - connection succeed
|
||||
########################################################################
|
||||
create user 'DB_USER5' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-B'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-C'
|
||||
or unix_socket as 'OS_USER'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-E'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-F';
|
||||
grant select on test.* to 'DB_USER5';
|
||||
#
|
||||
# Auth succeed with OS user matches the first authentication string.
|
||||
# @@external_user is set to OS_USER name.
|
||||
#
|
||||
select user(), current_user(), database();
|
||||
user() current_user() database()
|
||||
DB_USER5@localhost DB_USER5@% test
|
||||
select @@external_user;
|
||||
@@external_user
|
||||
OS_USER
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string_0,
|
||||
json_value(priv, '$.auth_or[1].authentication_string') as optional_authentication_string_1,
|
||||
json_value(priv, '$.auth_or[2].authentication_string') as optional_authentication_string_2,
|
||||
json_value(priv, '$.auth_or[3].authentication_string') as optional_authentication_string_3
|
||||
from mysql.global_priv where user='DB_USER5';
|
||||
host user authentication_string optional_authentication_string_0 optional_authentication_string_1 optional_authentication_string_2 optional_authentication_string_3
|
||||
% DB_USER5 -Cannot-Match-Any-Legal-Unix-User-Name-F -Cannot-Match-Any-Legal-Unix-User-Name-B -Cannot-Match-Any-Legal-Unix-User-Name-C OS_USER -Cannot-Match-Any-Legal-Unix-User-Name-E
|
||||
|
||||
########################################################################
|
||||
# Test for case:
|
||||
# - create user A identified via unix_socket as 'B';
|
||||
# - connect as database user A using unix user of A
|
||||
# Expected result:
|
||||
# - connection is rejected
|
||||
########################################################################
|
||||
#
|
||||
# Create DB user different with the OS user name, but using OS user name as the authentication string.
|
||||
#
|
||||
create user 'OS_USER' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
grant select on test.* to 'OS_USER';
|
||||
#
|
||||
# Auth fail with OS user that does not match the authentication string.
|
||||
#
|
||||
|
||||
########################################################################
|
||||
# Removing the test user.
|
||||
########################################################################
|
||||
drop user 'DB_USER1';
|
||||
drop user 'DB_USER2';
|
||||
drop user 'DB_USER3';
|
||||
drop user 'DB_USER4';
|
||||
drop user 'DB_USER5';
|
||||
drop user 'OS_USER';
|
||||
FLUSH PRIVILEGES;
|
||||
########################################################################
|
||||
# Removing the test file.
|
||||
########################################################################
|
|
@ -0,0 +1,160 @@
|
|||
--source include/have_unix_socket.inc
|
||||
|
||||
--let $OS_USER=$USER
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
select user(), current_user(), database();
|
||||
select @@external_user;
|
||||
EOF
|
||||
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
--echo # - connect as database user A using unix user of B
|
||||
--echo # Expected result:
|
||||
--echo # - connection succeed
|
||||
--echo ########################################################################
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval create user 'DB_USER1' identified via unix_socket as '$OS_USER' or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval grant select on test.* to 'DB_USER1';
|
||||
--echo #
|
||||
--echo # Auth succeed with OS user matches the first authentication string.
|
||||
--echo # @@external_user is set to OS_USER name.
|
||||
--echo #
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
--exec $MYSQL_TEST -u DB_USER1 < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
|
||||
|
||||
--echo
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
--echo # - connect as database user A using unix user of C
|
||||
--echo # Expected result:
|
||||
--echo # - connection succeed
|
||||
--echo ########################################################################
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval create user 'DB_USER2' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name' or unix_socket as '$OS_USER';
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval grant select on test.* to 'DB_USER2';
|
||||
--echo #
|
||||
--echo # Auth succeed with OS user matches the optional authentication string.
|
||||
--echo # @@external_user is set to OS_USER name.
|
||||
--echo #
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
--exec $MYSQL_TEST -u DB_USER2 < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
|
||||
|
||||
--echo
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B';
|
||||
--echo # - connect as database user A using unix user of D
|
||||
--echo # Expected result:
|
||||
--echo # - connection is refused
|
||||
--echo ########################################################################
|
||||
eval create user 'DB_USER3' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
eval grant select on test.* to 'DB_USER3';
|
||||
--echo #
|
||||
--echo # Auth fail with OS user that does not match the authentication string.
|
||||
--echo #
|
||||
--error 1
|
||||
--exec $MYSQL_TEST -u DB_USER3 < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
|
||||
|
||||
--echo #
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B' or unix_socket as 'C';
|
||||
--echo # - connect as database user A using unix user of D
|
||||
--echo # Expected result:
|
||||
--echo # - connection is refused
|
||||
--echo ########################################################################
|
||||
eval create user 'DB_USER4' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-1'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-2';
|
||||
eval grant select on test.* to 'DB_USER4';
|
||||
--echo #
|
||||
--echo # Auth fail with OS user that does not match the authentication string.
|
||||
--echo #
|
||||
--error 1
|
||||
--exec $MYSQL_TEST -u DB_USER4 < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string from mysql.global_priv where user='DB_USER1';
|
||||
|
||||
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B' or unix_socket as 'C' or unix_socket as 'D' or unix_socket as 'E' or unix_socket as 'F';
|
||||
--echo # - connect as database user A using unix user of 'D'
|
||||
--echo # Expected result:
|
||||
--echo # - connection succeed
|
||||
--echo ########################################################################
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval create user 'DB_USER5' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-B'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-C'
|
||||
or unix_socket as '$OS_USER'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-E'
|
||||
or unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name-F';
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval grant select on test.* to 'DB_USER5';
|
||||
--echo #
|
||||
--echo # Auth succeed with OS user matches the first authentication string.
|
||||
--echo # @@external_user is set to OS_USER name.
|
||||
--echo #
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
--exec $MYSQL_TEST -u DB_USER5 < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
select host, user, json_value(priv, '$.authentication_string') as authentication_string,
|
||||
json_value(priv, '$.auth_or[0].authentication_string') as optional_authentication_string_0,
|
||||
json_value(priv, '$.auth_or[1].authentication_string') as optional_authentication_string_1,
|
||||
json_value(priv, '$.auth_or[2].authentication_string') as optional_authentication_string_2,
|
||||
json_value(priv, '$.auth_or[3].authentication_string') as optional_authentication_string_3
|
||||
from mysql.global_priv where user='DB_USER5';
|
||||
|
||||
|
||||
--echo
|
||||
--echo ########################################################################
|
||||
--echo # Test for case:
|
||||
--echo # - create user A identified via unix_socket as 'B';
|
||||
--echo # - connect as database user A using unix user of A
|
||||
--echo # Expected result:
|
||||
--echo # - connection is rejected
|
||||
--echo ########################################################################
|
||||
--echo #
|
||||
--echo # Create DB user different with the OS user name, but using OS user name as the authentication string.
|
||||
--echo #
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval create user '$OS_USER' identified via unix_socket as '-Cannot-Match-Any-Legal-Unix-User-Name';
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval grant select on test.* to '$OS_USER';
|
||||
--echo #
|
||||
--echo # Auth fail with OS user that does not match the authentication string.
|
||||
--echo #
|
||||
--error 1
|
||||
--exec $MYSQL_TEST -u $OS_USER < $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
||||
|
||||
|
||||
--echo
|
||||
--echo ########################################################################
|
||||
--echo # Removing the test user.
|
||||
--echo ########################################################################
|
||||
eval drop user 'DB_USER1';
|
||||
eval drop user 'DB_USER2';
|
||||
eval drop user 'DB_USER3';
|
||||
eval drop user 'DB_USER4';
|
||||
eval drop user 'DB_USER5';
|
||||
--replace_result $OS_USER "OS_USER"
|
||||
eval drop user '$OS_USER';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--echo ########################################################################
|
||||
--echo # Removing the test file.
|
||||
--echo ########################################################################
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt
|
|
@ -119,13 +119,20 @@ static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
|
|||
u = cred.uid;
|
||||
#endif
|
||||
|
||||
/* and find the username for this uid */
|
||||
/* and find the socket user name for this uid */
|
||||
getpwuid_r(u, &pwd_buf, buf, sizeof(buf), &pwd);
|
||||
if (pwd == NULL)
|
||||
return CR_ERROR;
|
||||
|
||||
/* now it's simple as that */
|
||||
return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK;
|
||||
/* fill in the external user name used */
|
||||
strncpy(info->external_user, pwd->pw_name, sizeof(info->external_user) - 1);
|
||||
info->external_user[sizeof(info->external_user) - 1]= '\0';
|
||||
|
||||
/* compare with auth_string if it's defined, otherwise compare with DB user name*/
|
||||
if (info->auth_string && info->auth_string[0])
|
||||
return !strcmp(pwd->pw_name, info->auth_string) ? CR_OK : CR_ERROR;
|
||||
else
|
||||
return !strcmp(pwd->pw_name, info->user_name) ? CR_OK : CR_ERROR;
|
||||
}
|
||||
|
||||
static struct st_mysql_auth socket_auth_handler=
|
||||
|
@ -146,10 +153,10 @@ maria_declare_plugin(auth_socket)
|
|||
PLUGIN_LICENSE_GPL,
|
||||
NULL,
|
||||
NULL,
|
||||
0x0100,
|
||||
0x0101,
|
||||
NULL,
|
||||
NULL,
|
||||
"1.0",
|
||||
"1.1",
|
||||
MariaDB_PLUGIN_MATURITY_STABLE
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
|
Loading…
Add table
Reference in a new issue