Fix MySQL password handling for users with unix auth https://github.com/webmin/webmin/issues/1333

Additionally fixed renaming of admin user and password, all at once or separetely
This commit is contained in:
Ilia Rostovtsev
2020-11-28 21:02:50 +03:00
parent 823ea74ca1
commit 125cc7b418
3 changed files with 76 additions and 47 deletions

View File

@@ -57,18 +57,22 @@ print &ui_table_row($text{'user_user'},
$text{'user_all'}));
# Password field
my $master_login = ($u->[1] eq ($config{'login'} || "root"));
my $epassfield1 = $fieldmap{'Password'} || 1e10;
my $epassfield2 = $fieldmap{'authentication_string'} || 1e10;
my $plugin = $fieldmap{'plugin'};
my $unixsocket = $plugin && $u->[$plugin] eq 'unix_socket';
my $nopass = (($epassfield1 && !$u->[$epassfield1]) &&
($epassfield2 && !$u->[$epassfield2]));
my $lock_supported = $u->[$fieldmap{'account_locked'}] eq 'Y' || $u->[$fieldmap{'account_locked'}] eq 'N';
$lock_supported = 0 if ($master_login);
my $locked = $u->[$fieldmap{'account_locked'}] eq 'Y';
print &ui_table_row($text{'user_pass'},
&ui_radio("mysqlpass_mode", $in{'new'} ? 0 :
$lock_supported && $locked ? 4 :
$nopass ? 2 : 1,
[ $lock_supported && $locked ? () : [ 2, $text{'user_none'} ],
$in{'new'} ? ( ) : ($lock_supported && $locked) || $nopass ? () : ( [ 1, $text{'user_leave'} ] ),
$nopass && !$unixsocket ? 2 : 1,
[ (($lock_supported && $locked) || $master_login) ? () : [ 2, $text{'user_none'} ],
$in{'new'} ? ( ) : ($lock_supported && $locked) || $nopass && !$unixsocket ? () : ( [ 1, $text{'user_leave'} ] ),
($in{'new'} || !$lock_supported) ? ( ) : ( [ 4, $text{'user_locked'} ] ),
[ 0, $text{'user_set'} ] ])." ".
&ui_password("mysqlpass", undef, 20));

View File

@@ -1518,7 +1518,7 @@ my ($ver, $variant) = &get_remote_mysql_variant();
my $mysql_mariadb_with_auth_string =
$variant eq "mariadb" && &compare_version_numbers($ver, "10.2") >= 0 ||
$variant eq "mysql" && &compare_version_numbers($ver, "5.7.6") >= 0;
if ($mysql_mariadb_with_auth_string) {
if ($mysql_mariadb_with_auth_string && $unescaped_plainpass) {
$sql = "alter user '$user'\@'$host' identified $plugin by '$escaped_pass'";
}
else {
@@ -1717,20 +1717,47 @@ my $lock = !defined($plainpass);
if ($lock) {
$pass = sprintf("%x", rand 16) for 1..30;
}
if ($mysql_mariadb_with_auth_string) {
if ($mysql_mariadb_with_auth_string) {
my $sp = "identified $plugin by '".$pass."'";
if ($lock_supported) {
$sp = $lock ? "account lock" : "$sp account unlock";
}
$sql = "alter user '$user'\@'$host' $sp";
&execute_sql_logged($master_db, $sql);
}
else {
$sql = "set password for '$user'\@'$host' = $password_func('$pass')";
$sql = &get_change_pass_sql($plainpass, $user, $host);
&execute_sql_logged($master_db, $sql);
}
&execute_sql_logged($master_db, $sql);
# Update module password when needed
&update_config_credentials({
'user', $user,
'olduser', $user,
'pass', $plainpass,
});
&execute_sql_logged($master_db, 'flush privileges');
}
# Update Webmin module login and pass
sub update_config_credentials
{
return if($access{'user'});
my ($c) = @_;
my $conf_user = $config{'login'} || "root";
return if($c->{'olduser'} ne $conf_user);
return if(!$c->{'user'});
$config{'login'} = $c->{'user'};
$mysql_login = $c->{'user'};
if (defined($c->{'pass'})) {
$config{'pass'} = $c->{'pass'};
$mysql_pass = $c->{'pass'};
}
&lock_file($module_config_file);
&save_module_config();
&unlock_file($module_config_file);
}
1;

View File

@@ -28,6 +28,7 @@ else {
%fieldmap = map { lc($_->{'field'}), $_->{'index'} } @desc;
$host = $in{'host_def'} ? '%' : $in{'host'};
$user = $in{'mysqluser_def'} ? '' : $in{'mysqluser'};
$user_current = $in{'olduser'} || $user;
@pfields = map { $_->[0] } &priv_fields('user');
my @ssl_field_names = &ssl_fields();
my @ssl_field_values = map { '' } @ssl_field_names;
@@ -36,20 +37,10 @@ else {
my ($ver, $variant) = &get_remote_mysql_variant();
my $plugin = &get_mysql_plugin(1);
# Rename user if needed
if ($user && $in{'olduser'} && $user ne $in{'olduser'}) {
&rename_user({
'user', $user,
'olduser', $in{'olduser'},
'host', $host,
'oldhost', $host,
});
}
# Create a new user
if ($in{'new'}) {
&create_user({
'user', $user,
'user', $user_current,
'pass', $in{'mysqlpass'},
'host', $host,
'perms', \%perms,
@@ -63,20 +54,12 @@ else {
# Update existing user's privileges
else {
&update_privileges({
'user', $user,
'user', $user_current,
'host', $host,
'perms', \%perms,
'pfields', \@pfields
});
}
# Update user password
if ($in{'mysqlpass_mode'} == 4) {
&change_user_password(undef, $user, $host)
}
elsif ($in{'mysqlpass_mode'} != 1) {
&change_user_password(($in{'mysqlpass_mode'} eq '0' ? $in{'mysqlpass'} : ''), $user, $host)
}
# Save various limits
my %mdb104_diff = ('max_connections', 'max_connections_per_hour',
@@ -91,14 +74,14 @@ else {
if ($variant eq "mariadb" && &compare_version_numbers($ver, "10.4") >= 0) {
my $f_tbl_diff = $mdb104_diff{$f} || $f;
&execute_sql_logged($mysql::master_db,
"alter user '$user'\@'$host' with $f_tbl_diff "
"alter user '$user_current'\@'$host' with $f_tbl_diff "
.($in{$f.'_def'} ? 0 : $in{$f})."");
}
else {
&execute_sql_logged($master_db,
"update user set $f = ? ".
"where user = ? and host = ?",
$in{$f.'_def'} ? 0 : $in{$f}, $user, $host);
$in{$f.'_def'} ? 0 : $in{$f}, $user_current, $host);
}
}
@@ -107,7 +90,7 @@ else {
if ($variant eq "mariadb" && &compare_version_numbers($ver, "10.4") >= 0) {
if ($in{'ssl_type'} =~ /^(NONE|SSL|X509)$/) {
&execute_sql_logged($mysql::master_db,
"alter user '$user'\@'$host' require $in{'ssl_type'}");
"alter user '$user_current'\@'$host' require $in{'ssl_type'}");
}
}
else {
@@ -117,30 +100,45 @@ else {
&execute_sql_logged($master_db,
"update user set ssl_type = ? ".
"where user = ? and host = ?",
$in{'ssl_type'}, $user, $host);
$in{'ssl_type'}, $user_current, $host);
&execute_sql_logged($master_db,
"update user set ssl_cipher = ? ".
"where user = ? and host = ?",
$in{'ssl_cipher'}, $user, $host);
$in{'ssl_cipher'}, $user_current, $host);
}
}
}
&execute_sql_logged($master_db, 'flush privileges');
if (!$in{'delete'} && !$in{'new'} &&
$in{'olduser'} eq $config{'login'} && !$access{'user'}) {
# Renamed or changed the password for the Webmin login .. update
# it too!
$config{'login'} = $in{'mysqluser'};
if ($in{'mysqlpass_mode'} eq '0') {
$config{'pass'} = $in{'mysqlpass'};
}
elsif ($in{'mysqlpass_mode'} == 2) {
$config{'pass'} = undef;
}
&lock_file($module_config_file);
&save_module_config();
&unlock_file($module_config_file);
# Rename user, if requested
if (!$in{'delete'} && !$in{'new'} &&
$user && $user_current &&
$user ne $user_current) {
&rename_user({
'user', $user,
'olduser', $user_current,
'host', $host,
'oldhost', $host,
});
&update_config_credentials({
'user', $user,
'olduser', $user_current,
});
$user_current = $user;
}
# Update user password, if requested
if ($in{'mysqlpass_mode'} == 4) {
# Never used for admin accounts
&change_user_password(undef, $user_current, $host);
}
elsif ($in{'mysqlpass_mode'} != 1) {
($in{'mysqlpass_mode'} eq '0' && !$in{'mysqlpass'}) && &error($text{'root_epass1'});
my $pass = $in{'mysqlpass'} || '';
&change_user_password($pass, $user_current, $host);
}
# Log actions
if ($in{'delete'}) {
&webmin_log("delete", "user", $in{'olduser'},
{ 'user' => $in{'olduser'},