Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-19880

pam v1: pam password authentication doesn't work at all in MariaDB 10.4

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 10.4.6
    • Fix Version/s: 10.4.7
    • Component/s: Plugin - pam
    • Labels:
      None

      Description

      In MariaDB 10.4, version 2 of the pam plugin is provided. Unfortunately, password authentication seems to be completely broken in version 2. See MDEV-19878 about that.

      Luckily, version 1 of the pam plugin is also included. It is possible to install that version by doing the following:

      UNINSTALL SONAME 'auth_pam';
      INSTALL SONAME 'auth_pam_v1';
      

      Unfortunately, password authentication also seems to be completely broken in version 2 in MariaDB 10.4.

      To reproduce, simply do the following:

      Create a Unix user account and set a password for the user:

      sudo useradd alice
      sudo passwd alice
      

      Create the PAM service configuration:

      sudo tee /etc/pam.d/mariadb <<EOF
      auth required pam_unix.so audit
      account required pam_unix.so audit
      EOF
      

      Then in MariaDB, install the plugin:

      INSTALL SONAME 'auth_pam_v1';
      

      And then create the user account:

      CREATE USER 'alice'@'localhost' IDENTIFIED VIA pam USING 'mariadb';
      

      And then you need to do the /etc/shadow workaround for pam_unix:

      sudo groupadd shadow
      sudo usermod -a -G shadow mysql
      sudo chown root:shadow /etc/shadow
      sudo chmod g+r /etc/shadow
      

      And then restart MariaDB:

      sudo systemctl restart mariadb
      

      And then, try to authenticate as the Unix account (while using the workaround for MDEV-19807):

      $ mysql -u alice --plugin-dir=/usr/lib64/mysql/plugin
      ERROR 1045 (28000): Access denied for user 'alice'@'localhost' (using password: NO)
      

      The client does not even seem to be prompting for a password.

      The pam v1 plugin should properly pass the password to pam_unix, but the syslog shows that the password doesn't work, even though it is correct:

      Jun 28 01:58:14 ip-172-30-0-123 unix_chkpwd[7504]: password check failed for user (alice)
      Jun 28 01:58:14 ip-172-30-0-123 mysqld: pam_unix(mariadb:auth): authentication failure; logname= uid=997 euid=997 tty= ruser= rhost=  user=alice
      

      The strace output of the client connection/PAM plugin thread seems to show that the plugin is passing an empty string to the unix_chkpwd process:

      pipe([48, 49])                          = 0
      rt_sigaction(SIGCHLD, {SIG_DFL, [], SA_RESTORER, 0x7f523423e5d0}, {SIG_DFL, [], 0}, 8) = 0
      clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f521c0d29d0) = 7504
      write(49, "", 0)                        = 0
      write(49, "\0", 1)                      = 1
      close(48)                               = 0
      close(49)                               = 0
      wait4(7504, [{WIFEXITED(s) && WEXITSTATUS(s) == 7}], 0, NULL) = 7504
      --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=7504, si_uid=997, si_status=7, si_utime=1, si_stime=1} ---
      rt_sigaction(SIGCHLD, {SIG_DFL, [], SA_RESTORER, 0x7f523423e5d0}, NULL, 8) = 0
      ioctl(0, TCGETS, 0x7f521c0cddb0)        = -1 ENOTTY (Inappropriate ioctl for device)
      getuid()                                = 997
      geteuid()                               = 997
      socket(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 48
      connect(48, {sa_family=AF_LOCAL, sun_path="/dev/log"}, 110) = 0
      sendto(48, "<85>Jun 28 01:58:14 mysqld: pam_unix(mariadb:auth): authentication failure; logname= uid=997 euid=997 tty= ruser= rhost=  user=alice", 132, MSG_NOSIGNAL, NULL, 0) = 132
      

      The strace output of the unix_chkpwd process confirms that it received the empty string as the password from stdin:

      getuid()                                = 997
      setuid(997)                             = 0
      read(0, "\0", 513)                      = 1
      open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
      

      I wanted to try testing how it worked if I provided the password on the command line. Even that fails:

      $ mysql -u alice --plugin-dir=/usr/lib64/mysql/plugin -palicemariadb
      ERROR 1045 (28000): Access denied for user 'alice'@'localhost' (using password: NO)
      

      And the strace output for that does show that the client connection received the proper password:

      recvfrom(47, "\270\0\0\1", 4, MSG_DONTWAIT, NULL, NULL) = 4
      recvfrom(47, "\204\246\337 \0\0\0\1!\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\0\0\0alice\0\24\206\212\215\1*\252\262H\27K\256,\201\376\236B{\3279pmysql_native_password\0f\3_os\5Linux\f_client_name\nlibmariadb\4_pid\0047576\17_client_version\0053.1.2\t_platform\6x86_64\fprogram_name\5mysql", 184, MSG_DONTWAIT, NULL, NULL) = 184
      sendto(47, "\10\0\0\2\376dialog\0", 12, MSG_DONTWAIT, NULL, 0) = 12
      recvfrom(47, "\r\0\0\3", 4, MSG_DONTWAIT, NULL, NULL) = 4
      recvfrom(47, "alicemariadb\0", 13, MSG_DONTWAIT, NULL, NULL) = 13
      

      But it looks to me like it's still passing the empty string as the password to the unix_chkpwd process:

      pipe([48, 49])                          = 0
      rt_sigaction(SIGCHLD, {SIG_DFL, [], SA_RESTORER, 0x7fbd8d65b5d0}, {SIG_DFL, [], 0}, 8) = 0
      clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbd740c29d0) = 7578
      write(49, "", 0)                        = 0
      write(49, "\0", 1)                      = 1
      close(48)                               = 0
      close(49)                               = 0
      wait4(7578, [{WIFEXITED(s) && WEXITSTATUS(s) == 7}], 0, NULL) = 7578
      --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=7578, si_uid=997, si_status=7, si_utime=1, si_stime=2} ---
      rt_sigaction(SIGCHLD, {SIG_DFL, [], SA_RESTORER, 0x7fbd8d65b5d0}, NULL, 8) = 0
      ioctl(0, TCGETS, 0x7fbd740bddb0)        = -1 ENOTTY (Inappropriate ioctl for device)
      getuid()                                = 997
      geteuid()                               = 997
      socket(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 48
      connect(48, {sa_family=AF_LOCAL, sun_path="/dev/log"}, 110) = 0
      sendto(48, "<85>Jun 28 02:13:59 mysqld: pam_unix(mariadb:auth): authentication failure; logname= uid=997 euid=997 tty= ruser= rhost=  user=alice", 132, MSG_NOSIGNAL, NULL, 0) = 132
      

      And the strace output of the unix_chkpwd process seems to confirm that it is still reading the empty string from stdin:

      getuid()                                = 997
      setuid(997)                             = 0
      read(0, "\0", 513)                      = 1
      open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                serg Sergei Golubchik
                Reporter:
                GeoffMontee Geoff Montee
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: