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

pam_auth_v2 still doesn't work in 10.4.8

Details

    Description

      Per https://mariadb.com/kb/en/library/authentication-plugin-pam/

      modified to echo the password

      tee /tmp/pam_log_script.sh <<EOF
      #!/bin/bash
      PASS=$(cat -)
      echo $PASS
      echo "\${PAM_SERVICE}:\${PAM_TYPE} - \${PAM_RUSER}@\${PAM_RHOST} is authenticating as \${PAM_USER}" 
      EOF
      chmod 0775 /tmp/pam_log_script.sh
      

      Added the following into /etc/pam.d/mysql so it will send password too

      auth optional pam_exec.so debug expose_authtok log=/tmp/pam_output.txt /tmp/pam_log_script.sh
      

      V1 test:

      INSTALL SONAME 'auth_pam_v1'
      <authenticate from PHP with mysqli_connect("mariadb-alpine", "test_account", "uGBXHxID3dJRALw2", "test_account")>
      # cat /tmp/pam_output.txt
      *** Thu Sep 12 13:16:11 2019
      /tmp/pam_log_script.sh: line 2: warning: command substitution: ignored null byte in input
      uGBXHxID3dJRALw2
      mysql:auth - @ is authenticating as test_account
      

      V2 test:

      UNINSTALL SONAME 'auth_pam_v1'
      INSTALL SONAME 'auth_pam'
      <authenticate from PHP with mysqli_connect("mariadb-alpine", "test_account", "uGBXHxID3dJRALw2", "test_account")>
      # cat /tmp/pam_output.txt
      *** Thu Sep 12 13:16:35 2019
      /tmp/pam_log_script.sh: line 2: warning: command substitution: ignored null byte in input
      uGBXHxID3dJRALw  <<<< LAST CHARACTER MISSING
      mysql:auth - @ is authenticating as test_account
      

      Auth fails ofc. Where did the last character from the password go?

      Please fix. Thanks

      Attachments

        Issue Links

          Activity

            GeoffMontee Geoff Montee (Inactive) added a comment - - edited

            Hi laca,

            I was able to reproduce that. It seems to be the exact same problem as MDEV-19882.

            I reproduced this by setting up a docker instance on my RHEL 7 system that runs the database:

            sudo systemctl start docker
            sudo docker run -it --rm --network=host --security-opt seccomp:unconfined php:7.3-fpm-alpine /bin/sh
            apk add --no-cache strace
            apk add --no-cache mysql-client
            apk add --no-cache mariadb-connector-c
            docker-php-ext-install mysqli
            tee pamtest.php << EOF
            <?php
            \$link = mysqli_connect("127.0.0.1", "alice", "uGBXHxID3dJRALw2", "test");
             
            if (!\$link) {
                echo "Error: Unable to connect to MySQL." . PHP_EOL;
                echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL;
                echo "Debugging error: " . mysqli_connect_error() . PHP_EOL;
                exit;
            }
             
            echo "Success: A proper connection to MySQL was made! The my_db database is great." . PHP_EOL;
            echo "Host information: " . mysqli_get_host_info(\$link) . PHP_EOL;
             
            mysqli_close(\$link);
            ?>
            EOF
            

            On the database server, I had to configure pam_use_cleartext_plugin:

            $ sudo mysql -u root --execute="SHOW GLOBAL VARIABLES LIKE 'pam%'"
            +--------------------------+-------+
            | Variable_name            | Value |
            +--------------------------+-------+
            | pam_use_cleartext_plugin | ON    |
            | pam_winbind_workaround   | OFF   |
            +--------------------------+-------+
            

            Next, I attached strace to the mysqld process:

            sudo mkdir strace/
            cd strace/
            sudo strace -o strace.out -f -ff -p $(pidof mysqld)
            

            And then back on the docker instance, I ran the PHP script while also attaching strace to the process:

            strace -o strace.out -f -ff php -f pamtest.php
            

            The strace output from the PHP script shows that the password is being transmitted properly:

            recvfrom(3, "\26\0\0\2\376mysql_clear_password\0", 32768, MSG_DONTWAIT, NULL, NULL) = 26
            sendto(3, "\20\0\0\3uGBXHxID3dJRALw2", 20, MSG_DONTWAIT, NULL, 0) = 20
            

            The strace output from mysqld shows that auth_pam_tool receives the correct password, but it truncates the password when it sends it to the PAM service:

            read(0, "\0", 1)                        = 1
            read(0, "\0\5", 2)                      = 2
            read(0, "alice", 5)                     = 5
            read(0, "\0\7", 2)                      = 2
            read(0, "mariadb", 7)                   = 7
            ...
            write(1, "C", 1)                        = 1
            write(1, "\0\v", 2)                     = 2
            write(1, "\4Password: ", 11)            = 11
            read(0, "\0\20", 2)                     = 2
            read(0, "uGBXHxID3dJRALw2", 16)         = 16
            ...
            write(4, "uGBXHxID3dJRALw", 15)         = 15
            write(4, "\0", 1)                       = 1
            

            This is the same behavior reported in MDEV-19882.

            When I compare these to the strace from a working client, I see that the password is NULL-terminated, and the length is one character longer:

            read(0, "\0", 1)                        = 1
            read(0, "\0\5", 2)                      = 2
            read(0, "alice", 5)                     = 5
            read(0, "\0\7", 2)                      = 2
            read(0, "mariadb", 7)                   = 7
            ...
            write(1, "C", 1)                        = 1
            write(1, "\0\v", 2)                     = 2
            write(1, "\4Password: ", 11)            = 11
            read(0, "\0\21", 2)                     = 2
            read(0, "uGBXHxID3dJRALw2\0", 17)       = 17
            ...
            write(4, "uGBXHxID3dJRALw2", 16)        = 16
            write(4, "\0", 1)                       = 1
            

            GeoffMontee Geoff Montee (Inactive) added a comment - - edited Hi laca , I was able to reproduce that. It seems to be the exact same problem as MDEV-19882 . I reproduced this by setting up a docker instance on my RHEL 7 system that runs the database: sudo systemctl start docker sudo docker run -it --rm --network=host --security-opt seccomp:unconfined php:7.3-fpm-alpine /bin/sh apk add --no-cache strace apk add --no-cache mysql-client apk add --no-cache mariadb-connector-c docker-php-ext-install mysqli tee pamtest.php << EOF <?php \$link = mysqli_connect("127.0.0.1", "alice", "uGBXHxID3dJRALw2", "test"); if (!\$link) { echo "Error: Unable to connect to MySQL." . PHP_EOL; echo "Debugging errno: " . mysqli_connect_errno() . PHP_EOL; echo "Debugging error: " . mysqli_connect_error() . PHP_EOL; exit; } echo "Success: A proper connection to MySQL was made! The my_db database is great." . PHP_EOL; echo "Host information: " . mysqli_get_host_info(\$link) . PHP_EOL; mysqli_close(\$link); ?> EOF On the database server, I had to configure pam_use_cleartext_plugin : $ sudo mysql -u root --execute="SHOW GLOBAL VARIABLES LIKE 'pam%'" +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | pam_use_cleartext_plugin | ON | | pam_winbind_workaround | OFF | +--------------------------+-------+ Next, I attached strace to the mysqld process: sudo mkdir strace/ cd strace/ sudo strace -o strace.out -f -ff -p $(pidof mysqld) And then back on the docker instance, I ran the PHP script while also attaching strace to the process: strace -o strace.out -f -ff php -f pamtest.php The strace output from the PHP script shows that the password is being transmitted properly: recvfrom(3, "\26\0\0\2\376mysql_clear_password\0", 32768, MSG_DONTWAIT, NULL, NULL) = 26 sendto(3, "\20\0\0\3uGBXHxID3dJRALw2", 20, MSG_DONTWAIT, NULL, 0) = 20 The strace output from mysqld shows that auth_pam_tool receives the correct password, but it truncates the password when it sends it to the PAM service: read(0, "\0", 1) = 1 read(0, "\0\5", 2) = 2 read(0, "alice", 5) = 5 read(0, "\0\7", 2) = 2 read(0, "mariadb", 7) = 7 ... write(1, "C", 1) = 1 write(1, "\0\v", 2) = 2 write(1, "\4Password: ", 11) = 11 read(0, "\0\20", 2) = 2 read(0, "uGBXHxID3dJRALw2", 16) = 16 ... write(4, "uGBXHxID3dJRALw", 15) = 15 write(4, "\0", 1) = 1 This is the same behavior reported in MDEV-19882 . When I compare these to the strace from a working client, I see that the password is NULL-terminated, and the length is one character longer: read(0, "\0", 1) = 1 read(0, "\0\5", 2) = 2 read(0, "alice", 5) = 5 read(0, "\0\7", 2) = 2 read(0, "mariadb", 7) = 7 ... write(1, "C", 1) = 1 write(1, "\0\v", 2) = 2 write(1, "\4Password: ", 11) = 11 read(0, "\0\21", 2) = 2 read(0, "uGBXHxID3dJRALw2\0", 17) = 17 ... write(4, "uGBXHxID3dJRALw2", 16) = 16 write(4, "\0", 1) = 1
            laca Laszlo Soos added a comment -

            Hi GeoffMontee,

            Sorry for not mentioning it earlier, yes I do indeed use cleartext_plugin on server side.

            Thanks,
            Laszlo

            laca Laszlo Soos added a comment - Hi GeoffMontee , Sorry for not mentioning it earlier, yes I do indeed use cleartext_plugin on server side. Thanks, Laszlo

            The relevant code in PHP's mysqlnd driver is in these locations:

            https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L610

            https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L115

            It does look like this code is probably not considering the password's NULL terminator to be part of the auth data that would get sent over the wire.

            GeoffMontee Geoff Montee (Inactive) added a comment - The relevant code in PHP's mysqlnd driver is in these locations: https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L610 https://github.com/php/php-src/blob/php-7.3.10/ext/mysqlnd/mysqlnd_auth.c#L115 It does look like this code is probably not considering the password's NULL terminator to be part of the auth data that would get sent over the wire.

            I reported the following PHP bug about this:

            https://bugs.php.net/bug.php?id=78680

            GeoffMontee Geoff Montee (Inactive) added a comment - I reported the following PHP bug about this: https://bugs.php.net/bug.php?id=78680
            danblack Daniel Black added a comment -

            Upstream php-7.4+ fix approved - https://github.com/php/php-src/pull/6667

            danblack Daniel Black added a comment - Upstream php-7.4+ fix approved - https://github.com/php/php-src/pull/6667

            People

              serg Sergei Golubchik
              laca Laszlo Soos
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.