diff --git a/admin_customers.php b/admin_customers.php index 0e0906f9..a8d37e08 100644 --- a/admin_customers.php +++ b/admin_customers.php @@ -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'] . "'"); diff --git a/customer_mysql.php b/customer_mysql.php index 24c56ab1..1f1cd63e 100644 --- a/customer_mysql.php +++ b/customer_mysql.php @@ -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 . '` diff --git a/lib/classes/database/class.DbManager.php b/lib/classes/database/class.DbManager.php new file mode 100644 index 00000000..6ab2a08c --- /dev/null +++ b/lib/classes/database/class.DbManager.php @@ -0,0 +1,130 @@ + + * @author Froxlor team (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 + * @author Froxlor team (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); + } +} \ No newline at end of file diff --git a/lib/classes/database/manager/class.DbManagerMySQL.php b/lib/classes/database/manager/class.DbManagerMySQL.php new file mode 100644 index 00000000..08bf554b --- /dev/null +++ b/lib/classes/database/manager/class.DbManagerMySQL.php @@ -0,0 +1,196 @@ + + * @author Froxlor team (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 + * @author Froxlor team (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; + } + +} diff --git a/lib/functions/database/function.correctMysqlUsers.php b/lib/functions/database/function.correctMysqlUsers.php index 61b8acee..98e94378 100644 --- a/lib/functions/database/function.correctMysqlUsers.php +++ b/lib/functions/database/function.correctMysqlUsers.php @@ -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); } }