summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2019-06-30 20:41:26 +0200
committerSergei Golubchik <serg@mariadb.org>2019-07-02 14:27:31 +0200
commitdd93028dae22f00a6b23ff27d348ff1a4722ee88 (patch)
treec9a5e1fe924af4dd6cd8311c0707818cf4a12db8
parentec494cb1fadb40ae25b944bb1229fc2d6f88e8c6 (diff)
downloadmariadb-git-dd93028dae22f00a6b23ff27d348ff1a4722ee88.tar.gz
MDEV-19878 pam v2: pam password authentication doesn't work at all
* wait() for the child process to die, let it rest in peace * fix incorrect parentheses * if there was no password on the command line or in .cnf file, pkt will be "", and we need to request the user to enter the password * make sure that auth->salt is always allocated on a permanent memroot. when called from set_user_salt_if_needed(), user_copy and its auth_str are on the thd memroot, but auth_copy->salt is then copied to auth->salt * adjust service files so that systemd wouldn't interfere with our setuid executables also * print the pam error message in debug mode
-rw-r--r--mysql-test/suite/plugins/r/pam.result33
-rw-r--r--mysql-test/suite/plugins/t/pam.test20
-rw-r--r--plugin/auth_pam/auth_pam.c7
-rw-r--r--plugin/auth_pam/auth_pam_base.c3
-rw-r--r--plugin/auth_pam/auth_pam_tool.c2
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--support-files/mariadb.service.in15
-rw-r--r--support-files/mariadb@.service.in15
8 files changed, 76 insertions, 21 deletions
diff --git a/mysql-test/suite/plugins/r/pam.result b/mysql-test/suite/plugins/r/pam.result
index 1d70f530969..40075245d0c 100644
--- a/mysql-test/suite/plugins/r/pam.result
+++ b/mysql-test/suite/plugins/r/pam.result
@@ -7,9 +7,9 @@ grant proxy on pam_test to test_pam;
# note that current_user() differs from user()
#
Challenge input first.
-Enter: not very secret challenge
+Enter: *************************
Now, the magic number!
-PIN: ****
+PIN: 9225
select user(), current_user(), database();
user() current_user() database()
test_pam@localhost pam_test@% test
@@ -17,16 +17,29 @@ test_pam@localhost pam_test@% test
# athentication is unsuccessful
#
Challenge input first.
-Enter: not very secret challenge
+Enter: *************************
Now, the magic number!
-PIN: ****
+PIN: 9224
#
# athentication is unsuccessful
#
Challenge input first.
-Enter: crash pam module
+Enter: ****************
Now, the magic number!
-PIN: ***
+PIN: 616
+#
+# athentication is successful
+#
+Now, the magic number!
+PIN: 9212
+select user(), current_user(), database();
+user() current_user() database()
+test_pam@localhost pam_test@% test
+#
+# athentication is unsuccessful
+#
+Now, the magic number!
+PIN: 9212
drop user test_pam;
drop user pam_test;
create user PAM_TEST identified via pam using 'mariadb_mtr';
@@ -34,17 +47,17 @@ create user PAM_TEST identified via pam using 'mariadb_mtr';
# athentication is unsuccessful
#
Challenge input first.
-Enter: not very secret challenge
+Enter: *************************
Now, the magic number!
-PIN: ****
+PIN: 9225
set global pam_winbind_workaround=1;
#
# athentication is successful
#
Challenge input first.
-Enter: not very secret challenge
+Enter: *************************
Now, the magic number!
-PIN: ****
+PIN: 9225
select user(), current_user(), database();
user() current_user() database()
PAM_TEST@localhost PAM_TEST@% test
diff --git a/mysql-test/suite/plugins/t/pam.test b/mysql-test/suite/plugins/t/pam.test
index 040b26ef8b8..1bb1fa2c230 100644
--- a/mysql-test/suite/plugins/t/pam.test
+++ b/mysql-test/suite/plugins/t/pam.test
@@ -15,7 +15,12 @@ EOF
--write_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt
crash pam module
-666
+616
+select user(), current_user(), database();
+EOF
+
+--write_file $MYSQLTEST_VARDIR/tmp/pam_good2.txt
+9212
select user(), current_user(), database();
EOF
@@ -37,6 +42,18 @@ EOF
--error 1
--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_ugly.txt
+--echo #
+--echo # athentication is successful
+--echo #
+--error 0
+--exec $MYSQL_TEST -u test_pam -pgoodpassword --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_good2.txt
+
+--echo #
+--echo # athentication is unsuccessful
+--echo #
+--error 1
+--exec $MYSQL_TEST -u test_pam -pbadpassword --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_good2.txt
+
drop user test_pam;
drop user pam_test;
create user PAM_TEST identified via pam using 'mariadb_mtr';
@@ -54,6 +71,7 @@ set global pam_winbind_workaround=1;
--exec $MYSQL_TEST -u PAM_TEST < $MYSQLTEST_VARDIR/tmp/pam_good.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_good.txt
+--remove_file $MYSQLTEST_VARDIR/tmp/pam_good2.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt
drop user PAM_TEST;
diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c
index 45a5028429f..ec0096609ba 100644
--- a/plugin/auth_pam/auth_pam.c
+++ b/plugin/auth_pam/auth_pam.c
@@ -17,6 +17,8 @@
#include <unistd.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <mysql/plugin_auth.h>
#include "auth_pam_tool.h"
#include <my_global.h>
@@ -101,7 +103,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
/* no user name yet ? read the client handshake packet with the user name */
if (info->user_name == 0)
{
- if ((pkt_len= vio->read_packet(vio, &pkt) < 0))
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
return CR_ERROR;
}
else
@@ -157,7 +159,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
if ((buf_len= read_string(c_to_p[0], (char *) buf, sizeof(buf))) < 0)
goto error_ret;
- if (!pkt || (buf[0] >> 1) != 2)
+ if (!pkt || !*pkt || (buf[0] >> 1) != 2)
{
PAM_DEBUG((stderr, "PAM: sending CONV string.\n"));
if (vio->write_packet(vio, buf, buf_len))
@@ -186,6 +188,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
error_ret:
close(p_to_c[1]);
close(c_to_p[0]);
+ waitpid(proc_id, NULL, WNOHANG);
PAM_DEBUG((stderr, "PAM: auth result %d.\n", result));
return result;
diff --git a/plugin/auth_pam/auth_pam_base.c b/plugin/auth_pam/auth_pam_base.c
index a23cfcbfd65..cdaafa58b98 100644
--- a/plugin/auth_pam/auth_pam_base.c
+++ b/plugin/auth_pam/auth_pam_base.c
@@ -170,8 +170,9 @@ static int pam_auth_base(struct param *param, MYSQL_SERVER_AUTH_INFO *info)
info->authenticated_as[sizeof(info->authenticated_as)-1]= 0;
end:
+ PAM_DEBUG((stderr, "PAM: status = %d (%s) user = %s\n",
+ status, pam_strerror(pamh, status), info->authenticated_as));
pam_end(pamh, status);
- PAM_DEBUG((stderr, "PAM: status = %d user = %s\n", status, info->authenticated_as));
return status == PAM_SUCCESS ? CR_OK : CR_ERROR;
}
diff --git a/plugin/auth_pam/auth_pam_tool.c b/plugin/auth_pam/auth_pam_tool.c
index 6fd30b457ee..3ab2e00c142 100644
--- a/plugin/auth_pam/auth_pam_tool.c
+++ b/plugin/auth_pam/auth_pam_tool.c
@@ -70,6 +70,8 @@ int main(int argc, char **argv)
int res;
char a_buf[MYSQL_USERNAME_LENGTH + 1 + 1024];
+ setreuid(0, 0);
+
if (read(0, &field, 1) < 1)
return -1;
#ifndef DBUG_OFF
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 076b2e2994d..382275320e5 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2072,7 +2072,7 @@ static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin)
auth->salt.length= len;
}
else
- auth->salt= auth->auth_string;
+ auth->salt= safe_lexcstrdup_root(&acl_memroot, auth->auth_string);
return 0;
}
diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in
index 8d43b6db428..c31e883000d 100644
--- a/support-files/mariadb.service.in
+++ b/support-files/mariadb.service.in
@@ -43,7 +43,7 @@ PrivateNetwork=false
User=mysql
Group=mysql
-# To allow memlock to be used as non-root user if set in configuration
+# CAP_IPC_LOCK To allow memlock to be used as non-root user
CapabilityBoundingSet=CAP_IPC_LOCK
# Prevent writes to /usr, /boot, and /etc
@@ -52,8 +52,6 @@ ProtectSystem=full
# Doesn't yet work properly with SELinux enabled
# NoNewPrivileges=true
-PrivateDevices=true
-
# Prevent accessing /home, /root and /run/user
ProtectHome=true
@@ -99,6 +97,17 @@ RestartSec=5s
UMask=007
##############################################################################
+## PAM plugin section
+#
+# CAP_DAC_OVERRIDE To allow auth_pam_tool (which is SUID root) to read /etc/shadow when it's chmod 0
+# does nothing for non-root, not needed if /etc/shadow is u+r
+# CAP_AUDIT_WRITE Needed on Debian for whatever reason
+CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
+
+# PrivateDevices=true implies NoNewPrivileges=true and SUID doesn't work at all
+PrivateDevices=false
+
+##############################################################################
## USERs can override
##
##
diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in
index f0e82860aa0..fc87742e705 100644
--- a/support-files/mariadb@.service.in
+++ b/support-files/mariadb@.service.in
@@ -164,7 +164,7 @@ PrivateNetwork=false
## Package maintainers
##
-# To allow memlock to be used as non-root user if set in configuration
+# CAP_IPC_LOCK To allow memlock to be used as non-root user
CapabilityBoundingSet=CAP_IPC_LOCK
# Prevent writes to /usr, /boot, and /etc
@@ -174,8 +174,6 @@ ProtectSystem=full
# (https://github.com/systemd/systemd/issues/3845)
# NoNewPrivileges=true
-PrivateDevices=true
-
# Prevent accessing /home, /root and /run/user
ProtectHome=true
@@ -203,6 +201,17 @@ RestartSec=5s
UMask=007
##############################################################################
+## PAM plugin section
+#
+# CAP_DAC_OVERRIDE To allow auth_pam_tool (which is SUID root) to read /etc/shadow when it's chmod 0
+# does nothing for non-root, not needed if /etc/shadow is u+r
+# CAP_AUDIT_WRITE Needed on Debian for whatever reason
+CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
+
+# PrivateDevices=true implies NoNewPrivileges=true and SUID doesn't work at all
+PrivateDevices=false
+
+##############################################################################
## USERs can override
##
##