Uploaded image for project: 'MariaDB Connector/C'
  1. MariaDB Connector/C
  2. CONC-441

Default user name for C/C is wrong if login user is different from effective user

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 3.1.3
    • 3.1.8
    • None
    • None

    Description

      For command-line tools, if no user name is provided, then the default behavior is supposed to be that the client will use the name of the current Unix user.

      From the MySQL documentation:

      On Unix, most MySQL clients by default try to log in using the current Unix user name as the MySQL user name, but that is for convenience only.

      https://dev.mysql.com/doc/refman/5.7/en/user-names.html

      And from the MariaDB documentation:

      -u, --user=name User for login, if not current user.

      https://mariadb.com/kb/en/library/mysql-command-line-client/

      However, at the moment, the wrong user name is used by default if the login user is different from the effective user.

      How the Default User Name is Determined

      MariaDB Connector/C determines the default user name by calling read_user_name() to get the current user:

      https://github.com/MariaDB/mariadb-connector-c/blob/v3.1.3/libmariadb/mariadb_lib.c#L498

      It is called in send_client_reply_packet():

      https://github.com/MariaDB/mariadb-connector-c/blob/v3.1.3/plugins/auth/my_auth.c#L311

      The read_user_name() function gets the user name by checking the following items in the following order:

      • If geteuid() returns 0, then root is used.
      • If getlogin() is not NULL, then its return value is used.
      • If getpwuid(geteuid()) is not NULL, then its return value is used.
      • If the USER environment variable is set, then its assigned value is used.
      • If the LOGNAME environment variable is set, then its assigned value is used.
      • If the LOGIN environment variable is set, then its assigned value is used.

      This order can cause unexpected results in some cases.

      How to Reproduce

      For example, let's say that we change users by doing something like this:

      $ whoami
      ec2-user
      $ sudo -u mysql bash
      $ whoami
      mysql
      $ printenv USER
      mysql
      $ printenv LOGNAME
      mysql
      $ printenv LOGIN
      $ id
      uid=997(mysql) gid=994(mysql) groups=994(mysql),1005(shadow)
      $ cat /proc/self/loginuid
      1000
      $ id 1000
      uid=1000(ec2-user) gid=1000(ec2-user) groups=1000(ec2-user),4(adm),10(wheel),190(systemd-journal)
      

      In this case, our effective user is mysql, but the login user is still ec2-user.

      Let's start tcpdump:

      sudo tcpdump -i any -w mariadb_traffic.pcap port 3306
      

      And then let's run a client without providing a user name:

      $ mysql --plugin-dir=/usr/lib64/mysql/plugin/ -h 127.0.0.1
      [mariadb] Password:
      

      Authentication will fail, because the user name is wrong.

      Let's read the tcpdump file:

      sudo tcpdump -q -X -r mariadb_traffic.pcap
      

      The client handshake response looks like this for me:

      00:28:51.270909 IP localhost.38338 > localhost.mysql: tcp 0
              0x0000:  4508 0034 54e6 4000 4006 e7d3 7f00 0001  E..4T.@.@.......
              0x0010:  7f00 0001 95c2 0cea 5d84 b993 2a65 a5ae  ........]...*e..
              0x0020:  8010 0156 fe28 0000 0101 080a 0057 ed76  ...V.(.......W.v
              0x0030:  0057 ed76 0000 0000 0000 0000 0000 0000  .W.v............
              0x0040:  0000 0000                                ....
      00:28:51.271046 IP localhost.38338 > localhost.mysql: tcp 194
              0x0000:  4508 00f6 54e7 4000 4006 e710 7f00 0001  E...T.@.@.......
              0x0010:  7f00 0001 95c2 0cea 5d84 b993 2a65 a5ae  ........]...*e..
              0x0020:  8018 0156 feea 0000 0101 080a 0057 ed76  ...V.........W.v
              0x0030:  0057 ed76 be00 0001 84a6 9f20 0000 0001  .W.v............
              0x0040:  2100 0000 0000 0000 0000 0000 0000 0000  !...............
              0x0050:  0000 0000 0700 0000 6563 322d 7573 6572  ........ec2-user
              0x0060:  0000 6d79 7371 6c5f 6e61 7469 7665 5f70  ..mysql_native_p
              0x0070:  6173 7377 6f72 6400 7d03 5f6f 7305 4c69  assword.}._os.Li
              0x0080:  6e75 780c 5f63 6c69 656e 745f 6e61 6d65  nux._client_name
              0x0090:  0a6c 6962 6d61 7269 6164 6204 5f70 6964  .libmariadb._pid
              0x00a0:  0435 3937 330f 5f63 6c69 656e 745f 7665  .5973._client_ve
              0x00b0:  7273 696f 6e05 332e 312e 3409 5f70 6c61  rsion.3.1.4._pla
              0x00c0:  7466 6f72 6d06 7838 365f 3634 0c70 726f  tform.x86_64.pro
              0x00d0:  6772 616d 5f6e 616d 6505 6d79 7371 6c0c  gram_name.mysql.
              0x00e0:  5f73 6572 7665 725f 686f 7374 0931 3237  _server_host.127
              0x00f0:  2e30 2e30 2e31 0000 0000 0000 0000 0000  .0.0.1..........
              0x0100:  0000 0000 0000
      

      We can see from the packet content that C/C thinks the user name is ec2-user instead of mysql.

      The error message sent by the server also references this incorrect ec2-user user name:

      $ mysql --plugin-dir=/usr/lib64/mysql/plugin/ -h 127.0.0.1
      [mariadb] Password:
      ERROR 1045 (28000): Access denied for user 'ec2-user'@'localhost' (using password: NO)
      

      Suggested Fix

      MariaDB Connector/C's version of the read_user_name() function should be fixed to use the effective user as the default user.

      Attachments

        Issue Links

          Activity

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

            I see that the read_user_name() function gets the user name by going through the following order:

            • Using the user name root if geteuid() returns 0.
            • Using the user name returned by getlogin(), unless it is NULL.
            • Using the user name returned by getpwuid(geteuid()), unless it is NULL.
            • Using the user name assigned to the USER environment variable, unless it is not set.
            • Using the user name assigned to the LOGNAME environment variable, unless it is not set.
            • Using the user name assigned to the LOGIN environment variable, unless it is not set.

            See here:

            https://github.com/MariaDB/mariadb-connector-c/blob/v3.1.4/libmariadb/mariadb_lib.c#L499

            I created a quick test program to check the return values of getlogin() and getpwuid(geteuid()):

            $ cat read_user_name.c
             
            #include <pwd.h>
            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <errno.h>
             
            int
            main(int argc, char *argv[])
            {
                struct passwd *result;
             
                char *login_user;
                char *effective_user;
             
                if ((login_user = getlogin()) != NULL)
                {
                    printf("User name of login user is: %s\n", login_user);
                }
                else
                    printf("Could not get user name of login user\n");
             
                if ((result = getpwuid(geteuid())) != NULL)
                {
                    effective_user = result->pw_name;
                    printf("User name of effective user is: %s\n", effective_user);
                }
                else
                    printf("Could not get user name of effective user\n");
             
                return 0;
            }
            

            This seems to indicate that getpwuid(geteuid()) returns the correct user name, but getlogin() does not. For example:

            [ec2-user@ip-172-30-0-105 tmp]$ whoami
            ec2-user
            [ec2-user@ip-172-30-0-105 tmp]$ sudo -u mysql bash
            bash-4.2$ whoami
            mysql
            bash-4.2$ id
            uid=997(mysql) gid=994(mysql) groups=994(mysql),1005(shadow)
            bash-4.2$ gcc read_user_name.c
            bash-4.2$ ./a.out
            User name of login user is: ec2-user
            User name of effective user is: mysql
            

            Since the connector defaults to the return value of getlogin(), this is why the mysql client is using the wrong user name:

            bash-4.2$ mysql --plugin-dir=/usr/lib64/mysql/plugin/ -h 127.0.0.1 -pbadpassword
            ERROR 1045 (28000): Access denied for user 'ec2-user'@'localhost' (using password: NO)
            

            GeoffMontee Geoff Montee (Inactive) added a comment - - edited I see that the read_user_name() function gets the user name by going through the following order: Using the user name root if geteuid() returns 0 . Using the user name returned by getlogin() , unless it is NULL . Using the user name returned by getpwuid(geteuid()) , unless it is NULL . Using the user name assigned to the USER environment variable, unless it is not set. Using the user name assigned to the LOGNAME environment variable, unless it is not set. Using the user name assigned to the LOGIN environment variable, unless it is not set. See here: https://github.com/MariaDB/mariadb-connector-c/blob/v3.1.4/libmariadb/mariadb_lib.c#L499 I created a quick test program to check the return values of getlogin() and getpwuid(geteuid()) : $ cat read_user_name.c   #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h>   int main(int argc, char *argv[]) { struct passwd *result;   char *login_user; char *effective_user;   if ((login_user = getlogin()) != NULL) { printf("User name of login user is: %s\n", login_user); } else printf("Could not get user name of login user\n");   if ((result = getpwuid(geteuid())) != NULL) { effective_user = result->pw_name; printf("User name of effective user is: %s\n", effective_user); } else printf("Could not get user name of effective user\n");   return 0; } This seems to indicate that getpwuid(geteuid()) returns the correct user name, but getlogin() does not. For example: [ec2-user@ip-172-30-0-105 tmp]$ whoami ec2-user [ec2-user@ip-172-30-0-105 tmp]$ sudo -u mysql bash bash-4.2$ whoami mysql bash-4.2$ id uid=997(mysql) gid=994(mysql) groups=994(mysql),1005(shadow) bash-4.2$ gcc read_user_name.c bash-4.2$ ./a.out User name of login user is: ec2-user User name of effective user is: mysql Since the connector defaults to the return value of getlogin() , this is why the mysql client is using the wrong user name: bash-4.2$ mysql --plugin-dir=/usr/lib64/mysql/plugin/ -h 127.0.0.1 -pbadpassword ERROR 1045 (28000): Access denied for user 'ec2-user'@'localhost' (using password: NO)
            georg Georg Richter added a comment -

            fixed in rev. e8023f3bf05839aaf4d797747f265822ea4a0514

            georg Georg Richter added a comment - fixed in rev. e8023f3bf05839aaf4d797747f265822ea4a0514

            georg,

            This commit doesn't look like it would fix this issue:

            https://github.com/MariaDB/mariadb-connector-c/commit/e8023f3bf05839aaf4d797747f265822ea4a0514

            As far as I can tell, the problem is that getlogin() is used over getpwuid(geteuid()). See my previous comment for a test program that shows the difference.

            GeoffMontee Geoff Montee (Inactive) added a comment - georg , This commit doesn't look like it would fix this issue: https://github.com/MariaDB/mariadb-connector-c/commit/e8023f3bf05839aaf4d797747f265822ea4a0514 As far as I can tell, the problem is that getlogin() is used over getpwuid(geteuid()) . See my previous comment for a test program that shows the difference.
            mschorm Michal Schorm added a comment -

            Hello, Red Hat here, we've just got hit (rather) hard by this issue.

            —

            We have put MariaDB 10.4.12 into Fedora 32 - which is now in BETA freeze.
            Turns out, a lot of users and test are relying on this - documented - usage; which is broken now.

            Unfortunattely we were searching for the bug in auth_socket plugin, which is now default in MariaDB 10.4.

            —

            There are other packages, which builds on top of (or utilizes) MariaDB. Those packages have build-time tests which rely on switching the user.
            With this bug, they (suddenly) fail, thus the build of te package fail, and if it can't be built for a next Fedora release, such package has to be dropped from the distribution.

            We would be grateful for fix or a workaround ASAP.

            We have only two spots left for the fix in Fedora - either for F32 Final Freeze, or as a F32 zero-day update (which would cause various other issues, since the F32 images would be distributed without the fix)
            The Final Freeze is at the beginning of April.
            We are likely to start preparing downstream patch to apply before the Final Freeze, but we'd much prefer to be fixed upstream, since our knowledge about the DB code is limited and it may be much easier fir you to do it and not to make a mistake in it

            —

            Thanks Geoff for the fine detective job

            mschorm Michal Schorm added a comment - Hello, Red Hat here, we've just got hit (rather) hard by this issue. — We have put MariaDB 10.4.12 into Fedora 32 - which is now in BETA freeze. Turns out, a lot of users and test are relying on this - documented - usage; which is broken now. Unfortunattely we were searching for the bug in auth_socket plugin, which is now default in MariaDB 10.4. — There are other packages, which builds on top of (or utilizes) MariaDB. Those packages have build-time tests which rely on switching the user. With this bug, they (suddenly) fail, thus the build of te package fail, and if it can't be built for a next Fedora release, such package has to be dropped from the distribution. We would be grateful for fix or a workaround ASAP. We have only two spots left for the fix in Fedora - either for F32 Final Freeze, or as a F32 zero-day update (which would cause various other issues, since the F32 images would be distributed without the fix) The Final Freeze is at the beginning of April . We are likely to start preparing downstream patch to apply before the Final Freeze, but we'd much prefer to be fixed upstream, since our knowledge about the DB code is limited and it may be much easier fir you to do it and not to make a mistake in it — Thanks Geoff for the fine detective job
            georg Georg Richter added a comment -

            fixed. rev. 8c773db1fb4b59f2c428589398c7d47b88756aa5

            georg Georg Richter added a comment - fixed. rev. 8c773db1fb4b59f2c428589398c7d47b88756aa5

            Hi mschorm,

            georg's fix will be in MariaDB Connector/C 3.1.8, which should be released with MariaDB Server 10.4.13. I believe that release is currently planned for sometime around the end of April, but ralf.gebhardt@mariadb.com can correct me if I'm wrong. I hope that timeline works for you guys.

            Thanks!

            GeoffMontee Geoff Montee (Inactive) added a comment - Hi mschorm , georg 's fix will be in MariaDB Connector/C 3.1.8, which should be released with MariaDB Server 10.4.13. I believe that release is currently planned for sometime around the end of April, but ralf.gebhardt@mariadb.com can correct me if I'm wrong. I hope that timeline works for you guys. Thanks!
            mschorm Michal Schorm added a comment -

            I can´t wait for the fix, but that's fine.
            I did proceed with taking the latest sources of CONC/C and rebuilding the 'mariadb-connector-c' and 'mariadb' Fedora packages.

            This is our chance to get the fixed version available to the users with Fedora 32.
            Once you release new versions, I'll update ASAP.

            Thanks for the patch !

            mschorm Michal Schorm added a comment - I can´t wait for the fix, but that's fine. I did proceed with taking the latest sources of CONC/C and rebuilding the 'mariadb-connector-c' and 'mariadb' Fedora packages. This is our chance to get the fixed version available to the users with Fedora 32. Once you release new versions, I'll update ASAP. Thanks for the patch !

            People

              georg Georg Richter
              GeoffMontee Geoff Montee (Inactive)
              Votes:
              2 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.