Commit dd93028d authored by Sergei Golubchik's avatar Sergei Golubchik

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
parent ec494cb1
...@@ -7,9 +7,9 @@ grant proxy on pam_test to test_pam; ...@@ -7,9 +7,9 @@ grant proxy on pam_test to test_pam;
# note that current_user() differs from user() # note that current_user() differs from user()
# #
Challenge input first. Challenge input first.
Enter: not very secret challenge Enter: *************************
Now, the magic number! Now, the magic number!
PIN: **** PIN: 9225
select user(), current_user(), database(); select user(), current_user(), database();
user() current_user() database() user() current_user() database()
test_pam@localhost pam_test@% test test_pam@localhost pam_test@% test
...@@ -17,16 +17,29 @@ test_pam@localhost pam_test@% test ...@@ -17,16 +17,29 @@ test_pam@localhost pam_test@% test
# athentication is unsuccessful # athentication is unsuccessful
# #
Challenge input first. Challenge input first.
Enter: not very secret challenge Enter: *************************
Now, the magic number! Now, the magic number!
PIN: **** PIN: 9224
# #
# athentication is unsuccessful # athentication is unsuccessful
# #
Challenge input first. Challenge input first.
Enter: crash pam module Enter: ****************
Now, the magic number! 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 test_pam;
drop user pam_test; drop user pam_test;
create user PAM_TEST identified via pam using 'mariadb_mtr'; create user PAM_TEST identified via pam using 'mariadb_mtr';
...@@ -34,17 +47,17 @@ 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 # athentication is unsuccessful
# #
Challenge input first. Challenge input first.
Enter: not very secret challenge Enter: *************************
Now, the magic number! Now, the magic number!
PIN: **** PIN: 9225
set global pam_winbind_workaround=1; set global pam_winbind_workaround=1;
# #
# athentication is successful # athentication is successful
# #
Challenge input first. Challenge input first.
Enter: not very secret challenge Enter: *************************
Now, the magic number! Now, the magic number!
PIN: **** PIN: 9225
select user(), current_user(), database(); select user(), current_user(), database();
user() current_user() database() user() current_user() database()
PAM_TEST@localhost PAM_TEST@% test PAM_TEST@localhost PAM_TEST@% test
......
...@@ -15,7 +15,12 @@ EOF ...@@ -15,7 +15,12 @@ EOF
--write_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt --write_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt
crash pam module 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(); select user(), current_user(), database();
EOF EOF
...@@ -37,6 +42,18 @@ EOF ...@@ -37,6 +42,18 @@ EOF
--error 1 --error 1
--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_ugly.txt --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 test_pam;
drop user pam_test; drop user pam_test;
create user PAM_TEST identified via pam using 'mariadb_mtr'; create user PAM_TEST identified via pam using 'mariadb_mtr';
...@@ -54,6 +71,7 @@ set global pam_winbind_workaround=1; ...@@ -54,6 +71,7 @@ set global pam_winbind_workaround=1;
--exec $MYSQL_TEST -u PAM_TEST < $MYSQLTEST_VARDIR/tmp/pam_good.txt --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_good.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_good2.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt --remove_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt
--remove_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt --remove_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt
drop user PAM_TEST; drop user PAM_TEST;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <mysql/plugin_auth.h> #include <mysql/plugin_auth.h>
#include "auth_pam_tool.h" #include "auth_pam_tool.h"
#include <my_global.h> #include <my_global.h>
...@@ -101,7 +103,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) ...@@ -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 */ /* no user name yet ? read the client handshake packet with the user name */
if (info->user_name == 0) 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; return CR_ERROR;
} }
else else
...@@ -157,7 +159,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) ...@@ -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) if ((buf_len= read_string(c_to_p[0], (char *) buf, sizeof(buf))) < 0)
goto error_ret; goto error_ret;
if (!pkt || (buf[0] >> 1) != 2) if (!pkt || !*pkt || (buf[0] >> 1) != 2)
{ {
PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); PAM_DEBUG((stderr, "PAM: sending CONV string.\n"));
if (vio->write_packet(vio, buf, buf_len)) 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) ...@@ -186,6 +188,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
error_ret: error_ret:
close(p_to_c[1]); close(p_to_c[1]);
close(c_to_p[0]); close(c_to_p[0]);
waitpid(proc_id, NULL, WNOHANG);
PAM_DEBUG((stderr, "PAM: auth result %d.\n", result)); PAM_DEBUG((stderr, "PAM: auth result %d.\n", result));
return result; return result;
......
...@@ -170,8 +170,9 @@ static int pam_auth_base(struct param *param, MYSQL_SERVER_AUTH_INFO *info) ...@@ -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; info->authenticated_as[sizeof(info->authenticated_as)-1]= 0;
end: end:
PAM_DEBUG((stderr, "PAM: status = %d (%s) user = %s\n",
status, pam_strerror(pamh, status), info->authenticated_as));
pam_end(pamh, status); 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; return status == PAM_SUCCESS ? CR_OK : CR_ERROR;
} }
...@@ -70,6 +70,8 @@ int main(int argc, char **argv) ...@@ -70,6 +70,8 @@ int main(int argc, char **argv)
int res; int res;
char a_buf[MYSQL_USERNAME_LENGTH + 1 + 1024]; char a_buf[MYSQL_USERNAME_LENGTH + 1 + 1024];
setreuid(0, 0);
if (read(0, &field, 1) < 1) if (read(0, &field, 1) < 1)
return -1; return -1;
#ifndef DBUG_OFF #ifndef DBUG_OFF
......
...@@ -2072,7 +2072,7 @@ static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin) ...@@ -2072,7 +2072,7 @@ static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin)
auth->salt.length= len; auth->salt.length= len;
} }
else else
auth->salt= auth->auth_string; auth->salt= safe_lexcstrdup_root(&acl_memroot, auth->auth_string);
return 0; return 0;
} }
......
...@@ -43,7 +43,7 @@ PrivateNetwork=false ...@@ -43,7 +43,7 @@ PrivateNetwork=false
User=mysql User=mysql
Group=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 CapabilityBoundingSet=CAP_IPC_LOCK
# Prevent writes to /usr, /boot, and /etc # Prevent writes to /usr, /boot, and /etc
...@@ -52,8 +52,6 @@ ProtectSystem=full ...@@ -52,8 +52,6 @@ ProtectSystem=full
# Doesn't yet work properly with SELinux enabled # Doesn't yet work properly with SELinux enabled
# NoNewPrivileges=true # NoNewPrivileges=true
PrivateDevices=true
# Prevent accessing /home, /root and /run/user # Prevent accessing /home, /root and /run/user
ProtectHome=true ProtectHome=true
...@@ -98,6 +96,17 @@ RestartSec=5s ...@@ -98,6 +96,17 @@ RestartSec=5s
UMask=007 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 ## USERs can override
## ##
......
...@@ -164,7 +164,7 @@ PrivateNetwork=false ...@@ -164,7 +164,7 @@ PrivateNetwork=false
## Package maintainers ## 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 CapabilityBoundingSet=CAP_IPC_LOCK
# Prevent writes to /usr, /boot, and /etc # Prevent writes to /usr, /boot, and /etc
...@@ -174,8 +174,6 @@ ProtectSystem=full ...@@ -174,8 +174,6 @@ ProtectSystem=full
# (https://github.com/systemd/systemd/issues/3845) # (https://github.com/systemd/systemd/issues/3845)
# NoNewPrivileges=true # NoNewPrivileges=true
PrivateDevices=true
# Prevent accessing /home, /root and /run/user # Prevent accessing /home, /root and /run/user
ProtectHome=true ProtectHome=true
...@@ -202,6 +200,17 @@ RestartSec=5s ...@@ -202,6 +200,17 @@ RestartSec=5s
UMask=007 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 ## USERs can override
## ##
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment