From a366b7af0914101341ecd3dbead3f0328b9c187a Mon Sep 17 00:00:00 2001 From: Peter Knut Date: Tue, 1 Oct 2024 17:50:57 +0200 Subject: [PATCH] MySQL: Fix editing user's proxy privilege, refactoring - Uncheck all other priviledges if 'All privileges' is checked. - Refactor related functions. --- adminer/include/editing.inc.php | 52 ++++++++++++++++++++---------- adminer/static/default.css | 1 + adminer/static/functions.js | 20 ++++++++---- adminer/user.inc.php | 56 +++++++++++++++++++++++++-------- 4 files changed, 93 insertions(+), 36 deletions(-) diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index 81b6d13c..621f3105 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -384,25 +384,43 @@ function normalize_enum($match) { return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'"; } -/** Issue grant or revoke commands -* @param string GRANT or REVOKE -* @param array -* @param string -* @param string -* @return bool -*/ -function grant($grant, $privileges, $columns, $on) { - if (!$privileges) { - return true; +/** + * Issue grant or revoke commands. + * + * @param bool $grant + * @param array $privileges + * @param string $columns + * @param string $on + * @param string $user + * + * @return bool + */ +function grant($grant, array $privileges, $columns, $on, $user) { + if (!$privileges) return true; + + if ($privileges == ["ALL PRIVILEGES", "GRANT OPTION"]) { + if ($grant) { + return (bool) queries("GRANT ALL PRIVILEGES ON $on TO $user WITH GRANT OPTION"); + } else { + return queries("REVOKE ALL PRIVILEGES ON $on FROM $user") && + queries("REVOKE GRANT OPTION ON $on FROM $user"); + } } - if ($privileges == array("ALL PRIVILEGES", "GRANT OPTION")) { - // can't be granted or revoked together - return ($grant == "GRANT" - ? queries("$grant ALL PRIVILEGES$on WITH GRANT OPTION") - : queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on") - ); + + if ($privileges == ["GRANT OPTION", "PROXY"]) { + if ($grant) { + return (bool) queries("GRANT PROXY ON $on TO $user WITH GRANT OPTION"); + } else { + return (bool) queries("REVOKE PROXY ON $on FROM $user"); + } } - return queries("$grant " . preg_replace('~(GRANT OPTION)\([^)]*\)~', '\1', implode("$columns, ", $privileges) . $columns) . $on); + + return (bool) queries( + ($grant ? "GRANT " : "REVOKE ") . + preg_replace('~(GRANT OPTION)\([^)]*\)~', '$1', implode("$columns, ", $privileges) . $columns) . + " ON $on " . + ($grant ? "TO " : "FROM ") . $user + ); } /** Drop old object and create a new one diff --git a/adminer/static/default.css b/adminer/static/default.css index ef54dee0..7875be1b 100644 --- a/adminer/static/default.css +++ b/adminer/static/default.css @@ -30,6 +30,7 @@ input.default { box-shadow: 1px 1px 1px #777; } input.required { box-shadow: 1px 1px 1px red; } input.maxlength { box-shadow: 1px 1px 1px red; } input.wayoff { left: -1000px; position: absolute; } +.center { text-align: center; } .block { display: block; } .version { color: #777; font-size: 67%; } .js .hidden, .nojs .jsonly { display: none; } diff --git a/adminer/static/functions.js b/adminer/static/functions.js index 6668f254..19c1ee06 100644 --- a/adminer/static/functions.js +++ b/adminer/static/functions.js @@ -211,13 +211,21 @@ function tableCheck() { } } -/** Uncheck single element -* @param string -*/ +/** + * Uncheck single element. + */ function formUncheck(id) { - var el = qs('#' + id); - el.checked = false; - trCheck(el); + formUncheckAll("#" + id); +} + +/** + * Uncheck elements matched by selector. + */ +function formUncheckAll(selector) { + for (const element of qsa(selector)) { + element.checked = false; + trCheck(element); + } } /** Get number of checked elements matching given name diff --git a/adminer/user.inc.php b/adminer/user.inc.php index 423db3b3..b3f044d1 100644 --- a/adminer/user.inc.php +++ b/adminer/user.inc.php @@ -85,8 +85,8 @@ if ($_POST && !$error) { unset($grants[$object]); } if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && ( - !grant("REVOKE", $revoke, $match[2], " ON $match[1] FROM $new_user") //! SQL injection - || !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user") + !grant(false, $revoke, $match[2], $match[1], $new_user) //! SQL injection + || !grant(true, $grant, $match[2], $match[1], $new_user) )) { $error = true; break; @@ -100,7 +100,7 @@ if ($_POST && !$error) { } elseif (!isset($_GET["grant"])) { foreach ($grants as $object => $revoke) { if (preg_match('~^(.+)(\(.*\))?$~U', $object, $match)) { - grant("REVOKE", array_keys($revoke), $match[2], " ON $match[1] FROM $new_user"); + grant(false, array_keys($revoke), $match[2], $match[1], $new_user); } } } @@ -150,33 +150,63 @@ foreach ($grants as $object => $grant) { } echo "\n"; -foreach (array( +foreach ([ "" => "", "Server Admin" => lang('Server'), "Databases" => lang('Database'), "Tables" => lang('Table'), "Columns" => lang('Column'), "Procedures" => lang('Routine'), -) as $context => $desc) { + ] as $context => $desc) { foreach ((array) $privileges[$context] as $privilege => $comment) { - echo "$desc' . h($privilege); + echo ""; + if ($desc) { + echo "$desc"; + } + echo "' . h($privilege) . ""; + $i = 0; + foreach ($grants as $object => $grant) { $name = "'grants[$i][" . h(strtoupper($privilege)) . "]'"; $value = $grant[strtoupper($privilege)]; - if ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*")) { - echo ""; + + $proxiedUser = strpos($object, "@") !== false; + $newObject = $object == ".*"; + $allPrivileges = $privilege == "All privileges"; + $grantOption = $privilege == "Grant option"; + + if ($object == "*.*" && $privilege == "Proxy") { + echo ""; + } elseif ($proxiedUser && $privilege != "Proxy" && !$grantOption) { + echo ""; + } elseif ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*") && !(($proxiedUser || $newObject) && $privilege == "Proxy")) { + echo ""; } elseif (isset($_GET["grant"])) { - echo ""; + echo ""; } else { - echo "