1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-30 17:50:00 +02:00

MySQL: Fix editing user's proxy privilege, refactoring

- Uncheck all other priviledges if 'All privileges' is checked.
- Refactor related functions.
This commit is contained in:
Peter Knut
2024-10-01 17:50:57 +02:00
parent b039a39e4d
commit a366b7af09
4 changed files with 93 additions and 36 deletions

View File

@@ -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))), '\\')) . "'"; 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 * Issue grant or revoke commands.
* @param array *
* @param string * @param bool $grant
* @param string * @param array $privileges
* @return bool * @param string $columns
*/ * @param string $on
function grant($grant, $privileges, $columns, $on) { * @param string $user
if (!$privileges) { *
return true; * @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 if ($privileges == ["GRANT OPTION", "PROXY"]) {
return ($grant == "GRANT" if ($grant) {
? queries("$grant ALL PRIVILEGES$on WITH GRANT OPTION") return (bool) queries("GRANT PROXY ON $on TO $user WITH GRANT OPTION");
: queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on") } 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 /** Drop old object and create a new one

View File

@@ -30,6 +30,7 @@ input.default { box-shadow: 1px 1px 1px #777; }
input.required { box-shadow: 1px 1px 1px red; } input.required { box-shadow: 1px 1px 1px red; }
input.maxlength { box-shadow: 1px 1px 1px red; } input.maxlength { box-shadow: 1px 1px 1px red; }
input.wayoff { left: -1000px; position: absolute; } input.wayoff { left: -1000px; position: absolute; }
.center { text-align: center; }
.block { display: block; } .block { display: block; }
.version { color: #777; font-size: 67%; } .version { color: #777; font-size: 67%; }
.js .hidden, .nojs .jsonly { display: none; } .js .hidden, .nojs .jsonly { display: none; }

View File

@@ -211,13 +211,21 @@ function tableCheck() {
} }
} }
/** Uncheck single element /**
* @param string * Uncheck single element.
*/ */
function formUncheck(id) { function formUncheck(id) {
var el = qs('#' + id); formUncheckAll("#" + id);
el.checked = false; }
trCheck(el);
/**
* 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 /** Get number of checked elements matching given name

View File

@@ -85,8 +85,8 @@ if ($_POST && !$error) {
unset($grants[$object]); unset($grants[$object]);
} }
if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && ( if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && (
!grant("REVOKE", $revoke, $match[2], " ON $match[1] FROM $new_user") //! SQL injection !grant(false, $revoke, $match[2], $match[1], $new_user) //! SQL injection
|| !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user") || !grant(true, $grant, $match[2], $match[1], $new_user)
)) { )) {
$error = true; $error = true;
break; break;
@@ -100,7 +100,7 @@ if ($_POST && !$error) {
} elseif (!isset($_GET["grant"])) { } elseif (!isset($_GET["grant"])) {
foreach ($grants as $object => $revoke) { foreach ($grants as $object => $revoke) {
if (preg_match('~^(.+)(\(.*\))?$~U', $object, $match)) { 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 "</thead>\n"; echo "</thead>\n";
foreach (array( foreach ([
"" => "", "" => "",
"Server Admin" => lang('Server'), "Server Admin" => lang('Server'),
"Databases" => lang('Database'), "Databases" => lang('Database'),
"Tables" => lang('Table'), "Tables" => lang('Table'),
"Columns" => lang('Column'), "Columns" => lang('Column'),
"Procedures" => lang('Routine'), "Procedures" => lang('Routine'),
) as $context => $desc) { ] as $context => $desc) {
foreach ((array) $privileges[$context] as $privilege => $comment) { foreach ((array) $privileges[$context] as $privilege => $comment) {
echo "<tr" . odd() . "><td" . ($desc ? ">$desc<td" : " colspan='2'") . ' lang="en" title="' . h($comment) . '">' . h($privilege); echo "<tr" . odd() . ">";
if ($desc) {
echo "<td>$desc</td>";
}
echo "<td" . (!$desc ? " colspan='2'" : "") . ' lang="en" title="' . h($comment) . '">' . h($privilege) . "</td>";
$i = 0; $i = 0;
foreach ($grants as $object => $grant) { foreach ($grants as $object => $grant) {
$name = "'grants[$i][" . h(strtoupper($privilege)) . "]'"; $name = "'grants[$i][" . h(strtoupper($privilege)) . "]'";
$value = $grant[strtoupper($privilege)]; $value = $grant[strtoupper($privilege)];
if ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*")) {
echo "<td>"; $proxiedUser = strpos($object, "@") !== false;
$newObject = $object == ".*";
$allPrivileges = $privilege == "All privileges";
$grantOption = $privilege == "Grant option";
if ($object == "*.*" && $privilege == "Proxy") {
echo "<td></td>";
} elseif ($proxiedUser && $privilege != "Proxy" && !$grantOption) {
echo "<td></td>";
} elseif ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*") && !(($proxiedUser || $newObject) && $privilege == "Proxy")) {
echo "<td></td>";
} elseif (isset($_GET["grant"])) { } elseif (isset($_GET["grant"])) {
echo "<td><select name=$name><option><option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</select>"; echo "<td><select name=$name>" .
"<option></option>" .
"<option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "</option>" .
"<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</option>" .
"</select></td>";
} else { } else {
echo "<td align='center'><label class='block'>"; echo "<td class='center'><label class='block'>";
echo "<input type='checkbox' name=$name value='1'" . ($value ? " checked" : "") . ($privilege == "All privileges" echo "<input type='checkbox' name=$name value='1'" .
? " id='grants-$i-all'>" //! uncheck all except grant if all is checked ($value ? " checked" : "") .
: ">" . ($privilege == "Grant option" ? "" : script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };"))); ($allPrivileges ? " id='grants-$i-all'" : (!$grantOption ? " class='grants-$i'" : "")) .
">";
if ($allPrivileges) {
echo script("qsl('input').onclick = function () { if (this.checked) formUncheckAll('.grants-$i'); };");
} elseif (!$grantOption) {
echo script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };");
}
echo "</label>"; echo "</label>";
} }
$i++; $i++;
} }
echo "</tr>";
} }
} }