array("All privileges" => "")); $result = $dbh->query("SHOW PRIVILEGES"); while ($row = $result->fetch_assoc()) { foreach (explode(",", ($row["Privilege"] == "Grant option" ? "" : $row["Context"])) as $context) { $privileges[$context][$row["Privilege"]] = $row["Comment"]; } } $result->free(); $privileges["Server Admin"] += $privileges["File access on server"]; $privileges["Databases"]["Create routine"] = $privileges["Procedures"]["Create routine"]; // MySQL bug #30305 unset($privileges["Procedures"]["Create routine"]); $privileges["Columns"] = array(); foreach (array("Select", "Insert", "Update", "References") as $val) { $privileges["Columns"][$val] = $privileges["Tables"][$val]; } unset($privileges["Server Admin"]["Usage"]); foreach ($privileges["Tables"] as $key => $val) { unset($privileges["Databases"][$key]); } function grant($grant, $privileges, $columns, $on) { if (!$privileges) { return true; } 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") ); } return queries("$grant " . preg_replace('~(GRANT OPTION)\\([^)]*\\)~', '\\1', implode("$columns, ", $privileges) . $columns) . $on); } $new_grants = array(); if ($_POST) { foreach ($_POST["objects"] as $key => $val) { $new_grants[$val] = ((array) $new_grants[$val]) + ((array) $_POST["grants"][$key]); } } $grants = array(); $old_pass = ""; if (isset($_GET["host"]) && ($result = $dbh->query("SHOW GRANTS FOR " . $dbh->quote($_GET["user"]) . "@" . $dbh->quote($_GET["host"])))) { //! use information_schema for MySQL 5 - column names in column privileges are not escaped while ($row = $result->fetch_row()) { if (preg_match('~GRANT (.*) ON (.*) TO ~', $row[0], $match) && preg_match_all('~ *([^(,]*[^ ,(])( *\\([^)]+\\))?~', $match[1], $matches, PREG_SET_ORDER)) { //! escape the part between ON and TO foreach ($matches as $val) { $grants["$match[2]$val[2]"][$val[1]] = true; if (ereg(' WITH GRANT OPTION', $row[0])) { //! don't check inside strings and identifiers $grants["$match[2]$val[2]"]["GRANT OPTION"] = true; } } } if (preg_match("~ IDENTIFIED BY PASSWORD '([^']+)~", $row[0], $match)) { $old_pass = $match[1]; } } $result->free(); } if ($_POST && !$error) { $old_user = (isset($_GET["host"]) ? $dbh->quote($_GET["user"]) . "@" . $dbh->quote($_GET["host"]) : "''"); $new_user = $dbh->quote($_POST["user"]) . "@" . $dbh->quote($_POST["host"]); // if $_GET["host"] is not set then $new_user is always different $pass = $dbh->quote($_POST["pass"]); if ($_POST["drop"]) { query_redirect("DROP USER $old_user", $SELF . "privileges=", lang('User has been dropped.')); } else { if ($old_user == $new_user) { queries("SET PASSWORD FOR $new_user = " . ($_POST["hashed"] ? $pass : "PASSWORD($pass)")); } else { $error = !queries(($dbh->server_info < 5 ? "GRANT USAGE ON *.* TO" : "CREATE USER") . " $new_user IDENTIFIED BY" . ($_POST["hashed"] ? " PASSWORD" : "") . " $pass"); } if (!$error) { $revoke = array(); foreach ($new_grants as $object => $grant) { if (isset($_GET["grant"])) { $grant = array_filter($grant); } $grant = array_keys($grant); if (isset($_GET["grant"])) { // no rights to mysql.user table $revoke = array_diff(array_keys(array_filter($new_grants[$object], 'strlen')), $grant); } elseif ($old_user == $new_user) { $old_grant = array_keys((array) $grants[$object]); $revoke = array_diff($old_grant, $grant); $grant = array_diff($grant, $old_grant); 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") )) { $error = true; break; } } } if (!$error && isset($_GET["host"])) { if ($old_user != $new_user) { queries("DROP USER $old_user"); } elseif (!isset($_GET["grant"])) { foreach ($grants as $object => $revoke) { if (preg_match('~^(.+)(\\(.*\\))?$~U', $object, $match)) { queries("REVOKE " . grant(array_keys($revoke), $match[2]) . " ON $match[1] FROM $new_user"); } } } } query_redirect(queries(), $SELF . "privileges=", (isset($_GET["host"]) ? lang('User has been altered.') : lang('User has been created.')), !$error, false, $error); if ($old_user != $new_user) { // delete new user in case of an error $dbh->query("DROP USER $new_user"); } } } page_header((isset($_GET["host"]) ? lang('Username') . ": " . h("$_GET[user]@$_GET[host]") : lang('Create user')), $error, array("privileges" => array('', lang('Privileges')))); if ($_POST) { $row = $_POST; $grants = $new_grants; } else { $row = $_GET + array("host" => $dbh->result($dbh->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)"))); // create user on the same domain by default $row["pass"] = $old_pass; if (strlen($old_pass)) { $row["hashed"] = true; } $grants[""] = true; } ?>
">
">
">
\n"; echo "" . lang('Privileges'); $i = 0; foreach ($grants as $object => $grant) { echo '' . ($object != "*.*" ? "" : "*.*"); //! separate db, table, columns, PROCEDURE|FUNCTION, routine $i++; } echo "\n"; foreach (array( "" => "", "Server Admin" => lang('Server'), "Databases" => lang('Database'), "Tables" => lang('Table'), "Columns" => lang('Column'), "Procedures" => lang('Routine'), ) as $context => $desc) { foreach ((array) $privileges[$context] as $privilege => $comment) { echo "$desc' . 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 " "; } elseif (isset($_GET["grant"])) { echo ""; } else { echo ""; //! uncheck all except grant if all is checked } $i++; } } } echo "\n"; ?>

>