Detect and override password in /root/.my.cnf
authorJamie Cameron <jcameron@webmin.com>
Fri, 3 Apr 2009 20:52:41 +0000 (20:52 +0000)
committerJamie Cameron <jcameron@webmin.com>
Fri, 3 Apr 2009 20:52:41 +0000 (20:52 +0000)
mysql/CHANGELOG
mysql/mysql-lib.pl

index 5f585e0..5d4ed54 100644 (file)
@@ -81,3 +81,5 @@ The password is passed to all MySQL commands using the MYSQL_PWD environment var
 ---- Changes since 1.450 ----
 Use DBI for listing databases and tables, to reduce dependency on the un-reliable MYSQL_PWD environment variable.
 Fixed the input for setting the default value for fields.
+---- Changes since 1.470 ----
+Added code to detect a password in /root/.my.cnf which overrides the MYSQL_PWD variable, and thus causes login failures.
index 4fd3483..d9624bb 100644 (file)
@@ -648,7 +648,22 @@ else {
 # Returns 1 if passing the password via an environment variable is supported
 sub supports_env_pass
 {
-return $mysql_version >= 4.1 && !$config{'nopwd'};
+if ($mysql_version >= 4.1 && !$config{'nopwd'}) {
+       # Theortically possible .. but don't do this if ~/.my.cnf contains
+       # a [client] block with password= in it
+       my @uinfo = getpwuid($<);
+       foreach my $cf ($config{'my_cnf'}, "$uinfo[7]/.my.cnf",
+                       "$ENV{'HOME'}/.my.cnf") {
+               next if (!$cf || !-r $cf);
+               local @cf = &parse_mysql_config($cf);
+               local $client = &find("client", \@cf);
+               next if (!$client);
+               local $password = &find("password", $client->{'members'});
+               return 0 if ($password ne '');
+               }
+       return 1;
+       }
+return 0;
 }
 
 # working_env_pass()
@@ -945,43 +960,59 @@ return $config{'host'} eq '' || $config{'host'} eq 'localhost' ||
 sub get_mysql_config
 {
 if (!defined(@mysql_config_cache)) {
-       local $sect;
-       local $lnum = 0;
-       open(CONF, $config{'my_cnf'}) || return undef;
-       while(<CONF>) {
-               s/\r|\n//g;
-               s/#.*$//;
-               s/\s+$//;
-               if (/^\s*\[(\S+)\]$/) {
-                       # Start of a section
-                       $sect = { 'name' => $1,
-                                 'members' => [ ],
-                                 'line' => $lnum,
-                                 'eline' => $lnum };
-                       push(@mysql_config_cache, $sect);
-                       }
-               elsif (/^\s*(\S+)\s*=\s*(.*)$/ && $sect) {
-                       # Variable in a section
-                       push(@{$sect->{'members'}},
-                            { 'name' => $1,
-                              'value' => $2,
-                              'line' => $lnum });
-                       $sect->{'eline'} = $lnum;
-                       }
-               elsif (/^\s*(\S+)$/ && $sect) {
-                       # Single directive in a section
-                       push(@{$sect->{'members'}},
-                            { 'name' => $1,
-                              'line' => $lnum });
-                       $sect->{'eline'} = $lnum;
-                       }
-               $lnum++;
+       if (!-r $config{'my_cnf'}) {
+               return undef;
                }
-       close(CONF);
+       @mysql_config_cache = &parse_mysql_config($config{'my_cnf'});
        }
 return \@mysql_config_cache;
 }
 
+# parse_mysql_config(file)
+# Reads one MySQL config file
+sub parse_mysql_config
+{
+local ($file) = @_;
+local @rv;
+local $sect;
+local $lnum = 0;
+local $lref = &read_file_lines($file, 1);
+local $_;
+foreach (@$lref) {
+       s/\r|\n//g;
+       s/#.*$//;
+       s/\s+$//;
+       if (/^\s*\[(\S+)\]$/) {
+               # Start of a section
+               $sect = { 'name' => $1,
+                         'members' => [ ],
+                         'file' => $file,
+                         'line' => $lnum,
+                         'eline' => $lnum };
+               push(@rv, $sect);
+               }
+       elsif (/^\s*(\S+)\s*=\s*(.*)$/ && $sect) {
+               # Variable in a section
+               push(@{$sect->{'members'}},
+                    { 'name' => $1,
+                      'value' => $2,
+                      'file' => $file,
+                      'line' => $lnum });
+               $sect->{'eline'} = $lnum;
+               }
+       elsif (/^\s*(\S+)$/ && $sect) {
+               # Single directive in a section
+               push(@{$sect->{'members'}},
+                    { 'name' => $1,
+                      'file' => $file,
+                      'line' => $lnum });
+               $sect->{'eline'} = $lnum;
+               }
+       $lnum++;
+       }
+return @rv;
+}
+
 # find(name, &conf)
 sub find
 {