fix correctMysqlUsers() function for new pdo-class, also created new wrapper for dbms-specific queries to possibly give the freedom to use anything else but MySQL (no promises so far)

Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann (d00p)
2013-12-05 13:55:01 +01:00
parent ab4f589816
commit c3336b7d0f
5 changed files with 360 additions and 117 deletions

View File

@@ -247,36 +247,20 @@ if ($page == 'customers'
Database::needRoot(true);
$last_dbserver = 0;
$dbm = new DbManager($settings);
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
Database::needRoot(true, $row_database['dbserver']);
Database::query('FLUSH PRIVILEGES;');
$dbm->getManager()->flushPrivileges();
$last_dbserver = $row_database['dbserver'];
}
if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `".$row_database['databasename']."`");
Database::pexecute($stmt, array(), false);
}
$host_res_stmt = Database::prepare("
SELECT `Host` FROM `mysql`.`user`
WHERE `User` = :dbname"
);
Database::pexecute($host_res_stmt, array('dbname' => $row_database['databasename']));
while ($host = $host_res_stmt->fetch(PDO::FETCH_ASSOC)) {
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$drop_stmt = Database::prepare("DROP USER :dbname@:host");
Database::pexecute($drop_stmt, array(':dbname' => $row_database['databasename'], ':host' => $host['Host']), false);
}
$drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `".$row_database['databasename']."`");
Database::pexecute($drop_stmt);
$dbm->getManager()->deleteDatabase($row_database['databasename']);
}
Database::query('FLUSH PRIVILEGES;');
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :id");
Database::pexecute($stmt, array('id' => $id));
@@ -1393,11 +1377,14 @@ if ($page == 'customers'
Database::needRoot(true);
$last_dbserver = 0;
$dbm = new DbManager($settings);
// For each of them
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) {
Database::query('FLUSH PRIVILEGES;');
$dbm->getManager()->flushPrivileges();
Database::needRoot(true, $row_database['dbserver']);
$last_dbserver = $row_database['dbserver'];
}
@@ -1408,19 +1395,16 @@ if ($page == 'customers'
// Prevent access, if deactivated
if ($deactivated) {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `".$row_database['databasename']."`");
Database::pexecute($stmt, array(), false);
$dbm->getManager()->disableUser($row_database['databasename'], $mysql_access_host);
} else {
// Otherwise grant access
Database::query('GRANT ALL PRIVILEGES ON `' . $row_database['databasename'] .'`.* TO `' . $row_database['databasename'] . '`@`' . $mysql_access_host . '`');
Database::query('GRANT ALL PRIVILEGES ON `' . str_replace('_', '\_', $row_database['databasename']) . '` . * TO `' . $row_database['databasename'] . '`@`' . $mysql_access_host . '`');
$dbm->getManager()->enableUser($row_database['databasename'], $mysql_access_host);
}
}
}
/* At last flush the new privileges */
Database::query('FLUSH PRIVILEGES;');
// At last flush the new privileges
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
$log->logAction(ADM_ACTION, LOG_INFO, "deactivated user '" . $result['loginname'] . "'");

View File

@@ -109,28 +109,9 @@ if ($page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
// Begin root-session
Database::needRoot(true, $result['dbserver']);
$dbm = new DbManager($settings);
$dbm->getManager()->deleteDatabase($result['databasename']);
$log->logAction(USR_ACTION, LOG_INFO, "deleted database '" . $result['databasename'] . "'");
if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') {
// Revoke privileges (only required for MySQL 4.1.2 - 5.0.1)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM :databasename");
Database::pexecute($stmt, array("databasename" => $result['databasename']));
}
$host_res_stmt = Database::prepare("SELECT `Host` FROM `mysql`.`user`
WHERE `User`= :databasename"
);
Database::pexecute($host_res_stmt, array("databasename" => $result['databasename']));
while ($host = $host_res_stmt->fetch(PDO::FETCH_ASSOC)) {
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$stmt = Database::prepare("DROP USER :databasename@:host");
Database::pexecute($stmt, array("databasename" => $result['databasename'], "host" => $host['Host']));
}
$stmt = Database::prepare("DROP DATABASE IF EXISTS `" . $result['databasename'] . "`");
Database::pexecute($stmt, array(), false);
$stmt = Database::prepare("FLUSH PRIVILEGES");
Database::pexecute($stmt);
Database::needRoot(false);
// End root-session
@@ -189,40 +170,13 @@ if ($page == 'overview') {
// validate description before actual adding the database, #1052
$databasedescription = validate(trim($_POST['description']), 'description');
// Begin root-session
Database::needRoot(true);
if (strtoupper($settings['customer']['mysqlprefix']) == 'RANDOM') {
$result_stmt = Database::prepare('SELECT `User` FROM mysql.user');
Database::pexecute($result_stmt);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$allsqlusers[] = $row[User];
}
$username = $userinfo['loginname'] . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3);
while (in_array($username , $allsqlusers)) {
$username = $userinfo['loginname'] . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3);
}
} else {
$username = $userinfo['loginname'] . $settings['customer']['mysqlprefix'] . (intval($userinfo['mysql_lastaccountnumber']) + 1);
}
$stmt = Database::prepare("CREATE DATABASE `" . $username . "`");
Database::pexecute($stmt);
$log->logAction(USR_ACTION, LOG_INFO, "created database '" . $username . "'");
foreach (array_map('trim', explode(',', $settings['system']['mysql_access_host'])) as $mysql_access_host) {
$stmt = Database::prepare("GRANT ALL PRIVILEGES ON `" . $username . "`.*
TO :username@:host
IDENTIFIED BY 'password'"
);
Database::pexecute($stmt, array("username" => $username, "host" => $mysql_access_host));
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
Database::pexecute($stmt, array("username" => $username, "host" => $mysql_access_host, "password" => $password));
$log->logAction(USR_ACTION, LOG_NOTICE, "grant all privileges for '" . $username . "'@'" . $mysql_access_host . "'");
}
$stmt = Database::prepare("FLUSH PRIVILEGES");
Database::pexecute($stmt);
Database::needRoot(false);
// End root-session
// create database, user, set permissions, etc.pp.
$dbm = new DbManager($settings);
$dbm->createDatabase(
$userinfo['loginname'],
$password,
$userinfo['mysql_lastaccountnumber']
);
// Statement modified for Database description -- PH 2004-11-29
$stmt = Database::prepare('INSERT INTO `' . TABLE_PANEL_DATABASES . '`

View File

@@ -0,0 +1,130 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
* @since 0.9.31
*
*/
/**
* Class DbManager
*
* Wrapper-class for database-management like creating
* and removing databases, users and permissions
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*/
class DbManager {
/**
* Settings array
* @var array
*/
private $_settings = null;
/**
* FroxlorLogger object
* @var object
*/
private $_log = null;
/**
* Manager object
* @var object
*/
private $_manager = null;
/**
* main constructor
*
* @param array $settings
* @param FroxlorLogger $log
*/
public function __construct($settings, &$log = null) {
$this->_settings = $settings;
$this->_log = $log;
$this->_setManager();
}
/**
* creates a new database and a user with the
* same name with all privileges granted on the db.
* DB-name and user-name are being generated and
* the password for the user will be set
*
* @param string $loginname
* @param string $password
* @param int $last_accnumber
*
* @return bool
*/
public function createDatabase($loginname = null, $password = null, $last_accnumber = 0) {
Database::needRoot(true);
// check whether we shall create a random username
if (strtoupper($this->_settings['customer']['mysqlprefix']) == 'RANDOM') {
// get all usernames from db-manager
$allsqlusers = $this->getManager()->getAllSqlUsers();
// generate random username
$username = $loginname . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3);
// check whether it exists on the DBMS
while (in_array($username , $allsqlusers)) {
$username = $loginname . '-' . substr(md5(uniqid(microtime(), 1)), 20, 3);
}
} else {
$username = $loginname . $this->_settings['customer']['mysqlprefix'] . (intval($last_accnumber) + 1);
}
// now create the database itself
$this->getManager()->createDatabase($username);
$this->_log->logAction(USR_ACTION, LOG_INFO, "created database '" . $username . "'");
// and give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', $this->_settings['system']['mysql_access_host'])) as $mysql_access_host) {
$this->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host);
$this->_log->logAction(USR_ACTION, LOG_NOTICE, "grant all privileges for '" . $username . "'@'" . $mysql_access_host . "'");
}
$this->getManager()->flushPrivileges();
Database::needRoot(false);
return true;
}
/**
* returns the manager-object
* from where we can control it
*/
public function getManager() {
return $this->_manager;
}
/**
* set manager-object by type of
* dbms: mysql only for now
*
* sets private $_manager variable
*/
private function _setManager() {
// TODO read different dbms from settings later
$this->_manager = new DbManagerMySQL($this->_settings, $this->_log);
}
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
* @since 0.9.31
*
*/
/**
* Class DbManagerMySQL
*
* Explicit class for database-management like creating
* and removing databases, users and permissions for MySQL
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*/
class DbManagerMySQL {
/**
* Settings array
* @var array
*/
private $_settings = null;
/**
* FroxlorLogger object
* @var object
*/
private $_log = null;
/**
* main constructor
*
* @param array $settings
* @param FroxlorLogger $log
*/
public function __construct($settings, &$log = null) {
$this->_settings = $settings;
$this->_log = $log;
}
/**
* creates a database
*
* @param string $dbname
*/
public function createDatabase($dbname = null) {
Database::query("CREATE DATABASE `" . $dbname . "`");
}
/**
* grants access privileges on a database with the same
* username and sets the password for that user the given access_host
*
* @param string $username
* @param string $password
* @param string $access_host
*/
public function grantPrivilegesTo($username = null, $password = null, $access_host = null) {
// grant privileges
$stmt = Database::prepare("
GRANT ALL PRIVILEGES ON `" . $username . "`.*
TO :username@:host IDENTIFIED BY 'password'
");
Database::pexecute($stmt, array("username" => $username, "host" => $access_host));
// set passoword
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = PASSWORD(:password)");
Database::pexecute($stmt, array("username" => $username, "host" => $access_host, "password" => $password));
}
/**
* removes the given database from the dbms and also
* takes away any privileges from a user to that db
*
* @param string $dbname
*/
public function deleteDatabase($dbname = null) {
if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `".$dbname."`");
Database::pexecute($stmt, array(), false);
}
$host_res_stmt = Database::prepare("
SELECT `Host` FROM `mysql`.`user` WHERE `User` = :dbname"
);
Database::pexecute($host_res_stmt, array('dbname' => $dbname));
while ($host = $host_res_stmt->fetch(PDO::FETCH_ASSOC)) {
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$drop_stmt = Database::prepare("DROP USER :dbname@:host");
Database::pexecute($drop_stmt, array(':dbname' => $dbname, ':host' => $host['Host']), false);
}
$drop_stmt = Database::prepare("DROP DATABASE IF EXISTS `".$dbname."`");
Database::pexecute($drop_stmt);
}
/**
* removes a user from the dbms and revokes all privileges
*
* @param string $username
* @param string $host
*/
public function deleteUser($username = null, $host = null) {
if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') {
// Revoke privileges (only required for MySQL 4.1.2 - 5.0.1)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES ON * . * FROM `". $username . "`@`".$host."`");
Database::pexecute($stmt);
}
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$stmt = Database::prepare("DROP USER :username@:host");
Database::pexecute($stmt, array("username" => $username, "host" => $host));
}
/**
* removes permissions from a user
*
* @param string $username
* @param string $host (unused in mysql)
*/
public function disableUser($username = null, $host = null) {
$stmt = Database::prepare("REVOKE ALL PRIVILEGES, GRANT OPTION FROM `".$row_database['databasename']."`");
Database::pexecute($stmt, array(), false);
}
/**
* re-grant permissions to a user
*
* @param string $username
* @param string $host
*/
public function enableUser($username = null, $host = null) {
Database::query('GRANT ALL PRIVILEGES ON `' . $username .'`.* TO `' . $username . '`@`' . $host . '`');
Database::query('GRANT ALL PRIVILEGES ON `' . str_replace('_', '\_', $username) . '` . * TO `' . $username . '`@`' . $host . '`');
}
/**
* flushes the privileges...pretty obvious eh?
*/
public function flushPrivileges() {
Database::query("FLUSH PRIVILEGES");
}
/**
* return an array of all usernames used in that DBMS
*
* @param bool $user_only if false, * will be selected from mysql.user and slightly different array will be generated
*
* @return array
*/
public function getAllSqlUsers($user_only = true) {
if ($user_only == false) {
$result_stmt = Database::prepare('SELECT * FROM mysql.user');
} else {
$result_stmt = Database::prepare('SELECT `User` FROM mysql.user');
}
Database::pexecute($result_stmt);
$allsqlusers = array();
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($user_only == false) {
if (!isset($allsqlusers[$row['User']])
|| !is_array($allsqlusers[$row['User']])
) {
$allsqlusers[$row['User']] = array(
'password' => $row['Password'],
'hosts' => array()
);
}
$allsqlusers[$row['User']]['hosts'][] = $row['Host'];
} else {
$allsqlusers[] = $row['User'];
}
}
return $allsqlusers;
}
}

View File

@@ -27,24 +27,17 @@ function correctMysqlUsers($mysql_access_host_array) {
$sql_root = Database::getSqlData();
Database::needRoot(false);
foreach ($sql_root as $mysql_server => $mysql_server_details) {
$dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `".TABLE_PANEL_DATABASES."`");
$mysql_servers = '';
Database::needRoot(true);
while ($dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC)) {
$users = array();
$users_result_stmt = Database::query("SELECT * FROM `mysql`.`user`");
Database::needRoot(true, $dbserver['dbserver']);
Database::needSqlData();
$sql_root = Database::getSqlData();
while ($users_row = $users_result_stmt->fetch(PDO::FETCH_ASSOC)) {
if (!isset($users[$users_row['User']])
|| !is_array($users[$users_row['User']])
) {
$users[$users_row['User']] = array(
'password' => $users_row['Password'],
'hosts' => array()
);
}
$users[$users_row['User']]['hosts'][] = $users_row['Host'];
}
$dbm = new DbManager($settings);
$users = $dbm->getManager()->getAllSqlUsers(false);
$databases = array(
$sql_root['db']
@@ -53,7 +46,7 @@ function correctMysqlUsers($mysql_access_host_array) {
SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `dbserver` = :mysqlserver
");
Database::pexecute($databases_result_stmt, array('mysqlserver' => $mysql_server));
Database::pexecute($databases_result_stmt, array('mysqlserver' => $dbserver['dbserver']));
while ($databases_row = $databases_result_stmt->fetch(PDO::FETCH_ASSOC)) {
$databases[] = $databases_row['databasename'];
@@ -74,34 +67,20 @@ function correctMysqlUsers($mysql_access_host_array) {
$mysql_access_host = trim($mysql_access_host);
if (!in_array($mysql_access_host, $users[$username]['hosts'])) {
$stmt = Database::prepare("GRANT ALL PRIVILEGES ON `" . $username . "`.*
TO :username@:host
IDENTIFIED BY 'password'"
);
Database::pexecute($stmt, array("username" => $username, "host" => $mysql_access_host));
$stmt = Database::prepare("SET PASSWORD FOR :username@:host = :password");
Database::pexecute($stmt, array("username" => $username, "host" => $mysql_access_host, "password" => $password));
$dbm->getManager()->grantPrivilegesTo($username, $password, $mysql_access_host);
}
}
foreach ($users[$username]['hosts'] as $mysql_access_host) {
if (!in_array($mysql_access_host, $mysql_access_host_array)) {
if (Database::getAttribute(PDO::ATTR_SERVER_VERSION) < '5.0.2') {
// Revoke privileges (only required for MySQL 4.1.2 - 5.0.1)
$stmt = Database::prepare("REVOKE ALL PRIVILEGES ON * . * FROM `". $username . "`@`".$mysql_access_host."`");
Database::pexecute($stmt);
}
// as of MySQL 5.0.2 this also revokes privileges. (requires MySQL 4.1.2+)
$stmt = Database::prepare("DROP USER :username@:host");
Database::pexecute($stmt, array("username" => $username, "host" => $mysql_access_host));
$dbm->getManager()->deleteUser($username, $mysql_access_host);
}
}
}
}
Database::query('FLUSH PRIVILEGES');
$dbm->flushPrivileges();
Database::needRoot(false);
}
}