diff --git a/connect.inc.php b/connect.inc.php
index 66126524..47e24cec 100644
--- a/connect.inc.php
+++ b/connect.inc.php
@@ -1,5 +1,5 @@
select_db($_GET["db"]) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]))) {
+if (!(strlen($_GET["db"]) ? $mysql->select_db($_GET["db"]) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]))) {
if (strlen($_GET["db"])) {
unset($_SESSION["databases"][$_GET["server"]]);
}
diff --git a/index.php b/index.php
index 9dd63f12..0b4b3a19 100644
--- a/index.php
+++ b/index.php
@@ -48,6 +48,8 @@ if (isset($_GET["dump"])) {
include "./view.inc.php";
} elseif (isset($_GET["schema"])) {
include "./schema.inc.php";
+ } elseif (isset($_GET["privileges"])) {
+ include "./privileges.inc.php";
} else { // uses CSRF token
include "./editing.inc.php";
if ($_POST) {
@@ -83,8 +85,8 @@ if (isset($_GET["dump"])) {
include "./procedure.inc.php";
} elseif (isset($_GET["trigger"])) {
include "./trigger.inc.php";
- } elseif (isset($_GET["privileges"])) {
- include "./privileges.inc.php";
+ } elseif (isset($_GET["user"])) {
+ include "./user.inc.php";
} elseif (isset($_GET["processlist"])) {
include "./processlist.inc.php";
} else {
@@ -100,8 +102,8 @@ if (isset($_GET["dump"])) {
echo "
\n";
while ($row = $result->fetch_assoc()) {
echo "";
- echo "" . htmlspecialchars($row["ROUTINE_TYPE"]) . " | ";
- echo '' . htmlspecialchars($row["ROUTINE_NAME"]) . ' | ';
+ echo "" . htmlspecialchars($row["ROUTINE_TYPE"]) . " | ";
+ echo '' . htmlspecialchars($row["ROUTINE_NAME"]) . ' | ';
echo '' . lang('Alter') . " | \n";
echo "
\n";
}
diff --git a/privileges.inc.php b/privileges.inc.php
index 22918a6a..c231b5c2 100644
--- a/privileges.inc.php
+++ b/privileges.inc.php
@@ -1,90 +1,14 @@
lang('Privileges')));
- $privileges = array();
- $result = $mysql->query("SHOW PRIVILEGES");
- while ($row = $result->fetch_assoc()) {
- foreach (explode(",", $row["Context"]) as $context) {
- $privileges[$context][$row["Privilege"]] = $row["Comment"]; //! translation
- }
- }
- $result->free();
- $privileges["Server Admin"] += $privileges["File access on server"];
- $privileges["Databases"]["Create routine"] = $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"]);
- unset($privileges["Procedures"]["Create routine"]);
- unset($privileges["Functions"]["Create routine"]);
- $grants = array();
- if (strlen($_GET["privileges"]) && ($result = $mysql->query("SHOW GRANTS FOR '" . $mysql->escape_string($_GET["name"]) . "'@'" . $mysql->escape_string($_GET["privileges"]) . "'"))) { //! 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)) { //! escape part between ON and TO
- preg_match_all('~ *([^(,]*[^ ,(])( *\\([^)]+\\))?~', $match[1], $matches, PREG_SET_ORDER);
- foreach ($matches as $val) {
- $grants["$match[2]$val[2]"][$val[1]] = true;
- }
- }
- if (preg_match('~ WITH GRANT OPTION~', $row[0])) { //! don't check inside strings and identifiers
- $grants[$match[2]]["GRANT OPTION"] = true;
- }
- }
- $result->free();
- }
- $grants[""] = true;
-
- foreach (array(
- "Server Admin" => lang('Server'),
- "Databases" => lang('Database'),
- "Tables" => lang('Table'),
- "Columns" => lang('Column'),
- "Procedures" => lang('Procedure'),
- "Functions" => lang('Function'),
- ) as $key => $val) {
- if ($privileges[$key]) {
- echo "\n";
- }
- }
- //! DROP USER, name, server, password
-} else {
- page_header(lang('Privileges'));
- echo '' . lang('Create user') . "
\n";
- //! use mysql database if possible (GRANTEE not properly escaped) or CURRENT_USER in MySQL 4 in case of insufficient privileges
- $result = $mysql->query("SELECT DISTINCT GRANTEE FROM information_schema.USER_PRIVILEGES");
- echo "\n";
- echo " | " . lang('Username') . " | " . lang('Server') . " |
\n";
- while ($row = $result->fetch_row()) {
- preg_match("~'((?:[^']+|'')*)'@'((?:[^']+|'')+)'~", $row[0], $match);
- echo '' . lang('edit') . ' | ' . htmlspecialchars(str_replace("''", "'", $match[1])) . " | " . htmlspecialchars(str_replace("''", "'", $match[2])) . " |
\n";
- }
- echo "
\n";
- $result->free();
+page_header(lang('Privileges'));
+echo '' . lang('Create user') . "
\n";
+$result = $mysql->query("SELECT User, Host FROM mysql.user ORDER BY Host, User");
+if (!$result) {
+ $result = $mysql->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1) AS User, SUBSTRING_INDEX(CURRENT_USER, '@', -1) AS Host");
}
+echo "\n";
+echo " | " . lang('Username') . " | " . lang('Server') . " |
\n";
+while ($row = $result->fetch_assoc()) {
+ echo '' . lang('edit') . ' | ' . htmlspecialchars($row["User"]) . " | " . htmlspecialchars($row["Host"]) . " |
\n";
+}
+echo "
\n";
+$result->free();
diff --git a/user.inc.php b/user.inc.php
new file mode 100644
index 00000000..9f942036
--- /dev/null
+++ b/user.inc.php
@@ -0,0 +1,168 @@
+ $val) {
+ $new_grants[$val] = ((array) $new_grants[$val]) + ((array) $_POST["grants"][$key]);
+ }
+}
+$grants = array();
+$old_pass = "";
+if (isset($_GET["host"]) && ($result = $mysql->query("SHOW GRANTS FOR '" . $mysql->escape_string($_GET["user"]) . "'@'" . $mysql->escape_string($_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)) { //! escape the part between ON and TO
+ preg_match_all('~ *([^(,]*[^ ,(])( *\\([^)]+\\))?~', $match[1], $matches, PREG_SET_ORDER);
+ foreach ($matches as $val) {
+ $grants["$match[2]$val[2]"][$val[1]] = true;
+ }
+ }
+ if (preg_match('~ WITH GRANT OPTION~', $row[0])) { //! don't check inside strings and identifiers
+ $grants[$match[2]]["GRANT OPTION"] = true;
+ }
+ if (preg_match("~ IDENTIFIED BY PASSWORD '([^']+)~", $row[0], $match)) {
+ $old_pass = $match[1];
+ }
+ }
+ $result->free();
+}
+
+if ($_POST && !$error) {
+ $old_user = $mysql->escape_string($_GET["user"]) . "'@'" . $mysql->escape_string($_GET["host"]);
+ $new_user = $mysql->escape_string($_POST["user"]) . "'@'" . (strlen($_POST["host"]) ? $mysql->escape_string($_POST["host"]) : "%");
+ $identified = " IDENTIFIED BY" . ($_POST["hashed"] ? " PASSWORD" : "") . " '" . $mysql->escape_string($_POST["pass"]) . "'";
+ if ($_POST["drop"]) {
+ if ($mysql->query("DROP USER '$old_user'")) {
+ redirect($SELF . "privileges=", lang('User has been dropped.'));
+ }
+ } elseif ($old_user == $new_user || $mysql->server_info < 5 || $mysql->query("CREATE USER '$new_user'$identified")) {
+ if ($old_user == $new_user || $mysql->server_info < 5) {
+ $mysql->query("GRANT USAGE ON *.* TO '$new_user'$identified");
+ }
+ $revoke = array();
+ foreach ($new_grants as $object => $grant) {
+ $grant = array_keys($grant);
+ if ($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('~^(.+)(\\(.*\\))?$~U', $object, $match) && (
+ ($grant && !$mysql->query("GRANT " . implode("$match[2], ", $grant) . "$match[2] ON $match[1] TO '$new_user'")) //! SQL injection
+ || ($revoke && !$mysql->query("REVOKE " . implode("$match[2], ", $revoke) . "$match[2] ON $match[1] FROM '$new_user'"))
+ )) {
+ $error = $mysql->error;
+ if ($old_user != $new_user) {
+ $mysql->query("DROP USER '$new_user'");
+ }
+ break;
+ }
+ }
+ if (!$error) {
+ if ($old_user != $new_user) {
+ $mysql->query("DROP USER '$old_user'");
+ } else {
+ foreach ($grants as $object => $revoke) {
+ if (preg_match('~^(.+)(\\(.*\\))?$~U', $object, $match)) {
+ $mysql->query("REVOKE " . implode("$match[2], ", $revoke) . "$match[2] ON $match[1] FROM '$new_user'");
+ }
+ }
+ }
+ redirect($SELF . "privileges=", (isset($_GET["host"]) ? lang('User has been altered.') : lang('User has been created.')));
+ }
+ }
+ if (!$error) {
+ $error = $mysql->error;
+ }
+}
+
+page_header((isset($_GET["host"]) ? lang('Username') . ": " . htmlspecialchars("$_GET[user]@$_GET[host]") : lang('Create user')), array("privileges" => lang('Privileges')));
+$privileges = array();
+$result = $mysql->query("SHOW PRIVILEGES");
+while ($row = $result->fetch_assoc()) {
+ foreach (explode(",", $row["Context"]) as $context) {
+ $privileges[$context][$row["Privilege"]] = $row["Comment"]; //! translation
+ }
+}
+$result->free();
+$privileges["Server Admin"] += $privileges["File access on server"];
+$privileges["Databases"]["Create routine"] = $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"]);
+unset($privileges["Procedures"]["Create routine"]);
+foreach ($privileges["Tables"] as $key => $val) {
+ unset($privileges["Databases"][$key]);
+}
+//! JS checkbox for all
+
+if ($_POST) {
+ $row = $_POST;
+ $grants = $new_grants;
+ echo "" . lang('Unable to operate user') . ": " . htmlspecialchars($error) . "
\n";
+} else {
+ $row = $_GET;
+ $row["pass"] = $old_pass;
+ if (strlen($old_pass)) {
+ $row["hashed"] = true;
+ }
+ $grants[""] = true;
+}
+
+?>
+