Commit 8182d8ab authored by Till Brehm's avatar Till Brehm
Browse files

#5418 Add suport for MySQL 8

parent 09767f8c
Pipeline #4727 passed with stage
in 7 minutes and 49 seconds
......@@ -235,17 +235,26 @@ class installer_base {
public function configure_database() {
global $conf;
//* check sql-mode
/*$check_sql_mode = $this->db->queryOneRecord("SELECT @@sql_mode");
//** Check for unwanted plugins
if ($this->db->getDatabaseType() == 'mysql' && $this->db->getDatabaseVersion(true) >= 8) {
// component approach since MySQL 8.0
$unwanted_components = [
'file://component_validate_password',
];
$sql_components = $this->db->queryAllRecords("SELECT * FROM mysql.component where component_urn IN ?", $unwanted_components);
if(is_array($sql_components) && !empty($sql_components)) {
foreach ($sql_components as $component) {
$component_name = parse_url($component['component_urn'], PHP_URL_HOST);
echo "Login in to MySQL and disable '{$component_name}' with:\n\n UNINSTALL COMPONENT '{$component['component_urn']}';\n\n";
}
die();
}
if ($check_sql_mode['@@sql_mode'] != '' && $check_sql_mode['@@sql_mode'] != 'NO_ENGINE_SUBSTITUTION') {
echo "Wrong SQL-mode. You should use NO_ENGINE_SUBSTITUTION. Add\n\n";
echo " sql-mode=\"NO_ENGINE_SUBSTITUTION\"\n\n";
echo"to the mysqld-section in your mysql-config on this server and restart mysqld afterwards\n";
die();
}*/
$unwanted_sql_plugins = [''];
} else {
$unwanted_sql_plugins = array('validate_password');
}
$unwanted_sql_plugins = array('validate_password');
$sql_plugins = $this->db->queryAllRecords("SELECT plugin_name FROM information_schema.plugins WHERE plugin_status='ACTIVE' AND plugin_name IN ?", $unwanted_sql_plugins);
if(is_array($sql_plugins) && !empty($sql_plugins)) {
foreach ($sql_plugins as $plugin) echo "Login in to MySQL and disable $plugin[plugin_name] with:\n\n UNINSTALL PLUGIN $plugin[plugin_name];";
......@@ -308,6 +317,15 @@ class installer_base {
if(!$this->db->query($query, $conf['mysql']['database'] . ".*", $conf['mysql']['ispconfig_user'], $from_host)) {
$this->error('Unable to grant databse permissions to user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage);
}
// add correct administrative rights to IPSConfig user (SUPER is deprecated and unnecessarily powerful)
if ($this->db->getDatabaseType() == 'mysql' && $this->db->getDatabaseVersion(true) >= 8) {
// there might be more needed on replicated db environments, this was not tested
$query = 'GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO ?@?';
if(!$this->db->query($query, $conf['mysql']['ispconfig_user'], $from_host)) {
$this->error('Unable to grant administrative permissions to user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage);
}
}
//* Set the database name in the DB library
$this->db->setDBName($conf['mysql']['database']);
......
......@@ -761,6 +761,41 @@ class db
break;
}
}
/**
* Get the database type (mariadb or mysql)
*
* @access public
* @return string 'mariadb' or string 'mysql'
*/
public function getDatabaseType() {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
if(stristr($tmp['version'],'mariadb')) {
return 'mariadb';
} else {
return 'mysql';
}
}
/**
* Get the database version
*
* @access public
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
* @return string version number
*/
public function getDatabaseVersion($major_version_only = false) {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
$version = explode('-', $tmp['version']);
if($major_version_only == true) {
$version_parts = explode('.', $version[0]);
return $version_parts[0];
} else {
return $version[0];
}
}
}
......
......@@ -37,7 +37,7 @@ ALTER TABLE `mail_user` ADD `disableindexer-worker` ENUM('n','y') CHARACTER SET
ALTER TABLE `dns_rr` CHANGE `type` `type` ENUM('A','AAAA','ALIAS','CNAME','DNAME','CAA','DS','HINFO','LOC','MX','NAPTR','NS','PTR','RP','SRV','SSHFP','TXT','TLSA','DNSKEY') NULL DEFAULT NULL AFTER `name`;
-- change cc and sender_cc column type
ALTER TABLE `mail_user` CHANGE `cc` `cc` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
ALTER TABLE `mail_user` CHANGE `cc` `cc` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- remove SPDY option
ALTER TABLE `web_domain` DROP COLUMN `enable_spdy`;
......@@ -62,7 +62,7 @@ ALTER TABLE `web_domain` CHANGE `nginx_directives` `nginx_directives` mediumtext
ALTER TABLE `mail_user` MODIFY `move_junk` enum('y','a','n') NOT NULL DEFAULT 'y';
-- Change id_rsa column to TEXT format
ALTER TABLE `client` CHANGE `id_rsa` `id_rsa` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
ALTER TABLE `client` CHANGE `id_rsa` `id_rsa` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci;
ALTER TABLE `directive_snippets` ADD `update_sites` ENUM('y','n') NOT NULL DEFAULT 'n' ;
......
......@@ -253,7 +253,7 @@ CREATE TABLE `client` (
`canceled` enum('n','y') NOT NULL DEFAULT 'n',
`can_use_api` enum('n','y') NOT NULL DEFAULT 'n',
`tmp_data` mediumblob,
`id_rsa` text NOT NULL DEFAULT '',
`id_rsa` text,
`ssh_rsa` varchar(600) NOT NULL DEFAULT '',
`customer_no_template` varchar(255) DEFAULT 'R[CLIENTID]C[CUSTOMER_NO]',
`customer_no_start` int(11) NOT NULL DEFAULT '1',
......@@ -1040,7 +1040,7 @@ CREATE TABLE `mail_user` (
`maildir` varchar(255) NOT NULL default '',
`maildir_format` varchar(255) NOT NULL default 'maildir',
`quota` bigint(20) NOT NULL default '-1',
`cc` text NOT NULL default '',
`cc` text,
`sender_cc` varchar(255) NOT NULL default '',
`homedir` varchar(255) NOT NULL default '',
`autoresponder` enum('n','y') NOT NULL default 'n',
......
......@@ -1106,6 +1106,76 @@ class db
}
}
/**
* Get the database type (mariadb or mysql)
*
* @access public
* @return string 'mariadb' or string 'mysql'
*/
public function getDatabaseType() {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
if(stristr($tmp['version'],'mariadb')) {
return 'mariadb';
} else {
return 'mysql';
}
}
/**
* Get the database version
*
* @access public
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
* @return string version number
*/
public function getDatabaseVersion($major_version_only = false) {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
$version = explode('-', $tmp['version']);
if($major_version_only == true) {
$version_parts = explode('.', $version[0]);
return $version_parts[0];
} else {
return $version[0];
}
}
/**
* Get a mysql password hash
*
* @access public
* @param string cleartext password
* @return string Password hash
*/
public function getPasswordHash($password) {
$password_type = 'password';
/* Disabled until caching_sha2_password is implemented
if($this->getDatabaseType() == 'mysql' && $this->getDatabaseVersion(true) >= 8) {
// we are in MySQL 8 mode
$tmp = $this->queryOneRecord("show variables like 'default_authentication_plugin'");
if($tmp['default_authentication_plugin'] == 'caching_sha2_password') {
$password_type = 'caching_sha2_password';
}
}
*/
if($password_type == 'caching_sha2_password') {
/*
caching_sha2_password hashing needs to be implemented, have not
found valid PHP implementation for the new password hash type.
*/
} else {
$password_hash = '*'.strtoupper(sha1(sha1($password, true)));
}
return $password_hash;
}
}
/**
......
......@@ -1358,8 +1358,7 @@ class tform_base {
$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]),'ISO-8859-1');
$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
} elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
$tmp = $app->db->queryOneRecord("SELECT PASSWORD(?) as `crypted`", stripslashes($record[$key]));
$record[$key] = $tmp['crypted'];
$record[$key] = $app->db->getPasswordHash($record[$key]);
$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
} else {
$record[$key] = md5(stripslashes($record[$key]));
......@@ -1390,8 +1389,7 @@ class tform_base {
$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]),'ISO-8859-1');
$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
} elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
$tmp = $app->db->queryOneRecord("SELECT PASSWORD(?) as `crypted`", stripslashes($record[$key]));
$record[$key] = $tmp['crypted'];
$record[$key] = $app->db->getPasswordHash($record[$key]);
$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
} else {
$record[$key] = md5(stripslashes($record[$key]));
......
......@@ -1106,6 +1106,75 @@ class db
}
}
/**
* Get the database type (mariadb or mysql)
*
* @access public
* @return string 'mariadb' or string 'mysql'
*/
public function getDatabaseType() {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
if(stristr($tmp['version'],'mariadb')) {
return 'mariadb';
} else {
return 'mysql';
}
}
/**
* Get the database version
*
* @access public
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
* @return string version number
*/
public function getDatabaseVersion($major_version_only = false) {
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
$version = explode('-', $tmp['version']);
if($major_version_only == true) {
$version_parts = explode('.', $version[0]);
return $version_parts[0];
} else {
return $version[0];
}
}
/**
* Get a mysql password hash
*
* @access public
* @param string cleartext password
* @return string Password hash
*/
public function getPasswordHash($password) {
$password_type = 'password';
/* Disabled until caching_sha2_password is implemented
if($this->getDatabaseType() == 'mysql' && $this->getDatabaseVersion(true) >= 8) {
// we are in MySQL 8 mode
$tmp = $this->queryOneRecord("show variables like 'default_authentication_plugin'");
if($tmp['default_authentication_plugin'] == 'caching_sha2_password') {
$password_type = 'caching_sha2_password';
}
}
*/
if($password_type == 'caching_sha2_password') {
/*
caching_sha2_password hashing needs to be implemented, have not
found valid PHP implementation for the new password hash type.
*/
} else {
$password_hash = '*'.strtoupper(sha1(sha1($password, true)));
}
return $password_hash;
}
}
/**
......
......@@ -101,12 +101,7 @@ class mysql_clientdb_plugin {
$success = true;
if(!preg_match('/\*[A-F0-9]{40}$/', $database_password)) {
$result = $link->query("SELECT PASSWORD('" . $link->escape_string($database_password) . "') as `crypted`");
if($result) {
$row = $result->fetch_assoc();
$database_password = $row['crypted'];
$result->free();
}
$database_password = $app->db->getPasswordHash($password);
}
$app->log("Calling $action for $database_name with access $user_access_mode and hosts " . implode(', ', $host_list), LOGLEVEL_DEBUG);
......@@ -151,9 +146,32 @@ class mysql_clientdb_plugin {
$success = true;
}
if(!$link->query("GRANT " . $grants . " ON `".$database_name."`.* TO '".$link->escape_string($database_user)."'@'$db_host' IDENTIFIED BY PASSWORD '".$link->escape_string($database_password)."'")) $success = false;
$app->log("GRANT " . $grants . " ON `".$database_name."`.* TO '".$link->escape_string($database_user)."'@'$db_host' IDENTIFIED BY PASSWORD '".$link->escape_string($database_password)."' success? " . ($success ? 'yes' : 'no'), LOGLEVEL_DEBUG);
} elseif($action == 'REVOKE') {
// Create the user
$link->query("CREATE USER '".$link->escape_string($database_user)."'@'$db_host'");
$app->log("CREATE USER '".$link->escape_string($database_user)."'@'$db_host'", LOGLEVEL_DEBUG);
// set the password
// MySQL < 5.7 and MariadB 10
if(!$link->query("UPDATE mysql.user SET `Password` = '".$link->escape_string($database_password)."' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) {
if($this->getDatabaseType($link) == 'mysql' && $this->getDatabaseVersion($link, true) >= 8) {
// for MySQL >= 8, we set authentication plugin to old mode to ensure that older additional php versions can still connect to the database
if(!$link->query("UPDATE mysql.user SET `authentication_string` = '".$link->escape_string($database_password)."', `plugin` = 'mysql_native_password' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) $success = false;
} else {
// MySQL 5.7, the Password field has been renamed to authentication_string
if(!$link->query("UPDATE mysql.user SET `authentication_string` = '".$link->escape_string($database_password)."' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) $success = false;
}
}
if($success == true){
$link->query("FLUSH PRIVILEGES");
$app->log("PASSWORD SET FOR '".$link->escape_string($database_user)."'@'$db_host' success? " . ($success ? 'yes' : 'no'), LOGLEVEL_DEBUG);
}
// Set the grant
if(!$link->query("GRANT " . $grants . " ON `".$link->escape_string($database_name)."`.* TO '".$link->escape_string($database_user)."'@'$db_host'")) $success = false;
$app->log("GRANT " . $grants . " ON `".$link->escape_string($database_name)."`.* TO '".$link->escape_string($database_user)."'@'$db_host' success? " . ($success ? 'yes' : 'no'), LOGLEVEL_DEBUG);
} elseif($action == 'REVOKE') {
if(!$link->query("REVOKE ALL PRIVILEGES ON `".$database_name."`.* FROM '".$link->escape_string($database_user)."'@'$db_host'")) $success = false;
} elseif($action == 'DROP') {
if(!$link->query("DROP USER '".$link->escape_string($database_user)."'@'$db_host'")) $success = false;
......@@ -165,8 +183,13 @@ class mysql_clientdb_plugin {
if(trim($database_password) != '') {
// MySQL < 5.7 and MariadB 10
if(!$link->query("UPDATE mysql.user SET `Password` = '".$link->escape_string($database_password)."' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) {
// MySQL 5.7, the Password field has been renamed to authentication_string
if(!$link->query("UPDATE mysql.user SET `authentication_string` = '".$link->escape_string($database_password)."' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) $success = false;
if($this->getDatabaseType($link) == 'mysql' && $this->getDatabaseVersion($link, true) >= 8) {
// for MySQL >= 8, we set authentication plugin to old mode to ensure that older additional php versions can still connect to the database
if(!$link->query("UPDATE mysql.user SET `authentication_string` = '".$link->escape_string($database_password)."', `plugin` = 'mysql_native_password' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) $success = false;
} else {
// MySQL 5.7, the Password field has been renamed to authentication_string
if(!$link->query("UPDATE mysql.user SET `authentication_string` = '".$link->escape_string($database_password)."' WHERE `Host` = '".$db_host."' AND `User` = '".$link->escape_string($database_user)."'")) $success = false;
}
}
if($success == true) $link->query("FLUSH PRIVILEGES");
}
......@@ -772,6 +795,43 @@ class mysql_clientdb_plugin {
$link->close();
}
function getDatabaseType($link) {
$result = $link->query('SELECT VERSION() as version');
if($result) {
$tmp = $result->fetch_assoc();
$result->free();
if(stristr($tmp['version'],'mariadb')) {
return 'mariadb';
} else {
return 'mysql';
}
} else {
return false;
}
}
function getDatabaseVersion($link, $major_version_only = false) {
$result = $link->query('SELECT VERSION() as version');
if($result) {
$tmp = $result->fetch_assoc();
$result->free();
$version = explode('-', $tmp['version']);
if($major_version_only == true) {
$version_parts = explode('.', $version[0]);
return $version_parts[0];
} else {
return $version[0];
}
} else {
return false;
}
}
} // end class
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment