Skip to content

Commit 6c4eb9b

Browse files
author
Till Brehm
committed
Merge branch '5418-database-user-creation-not-working-on-mysql-8' into 'stable-3.1'
Resolve "Database user creation not working on MySQL 8" Closes #5418 See merge request ispconfig/ispconfig3!1127
2 parents 231aab7 + 6ea5e9e commit 6c4eb9b

File tree

8 files changed

+281
-34
lines changed

8 files changed

+281
-34
lines changed

install/lib/installer_base.lib.php

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,27 @@ public function reconfigure_app($service, $reconfigure_services_answer) {
235235
public function configure_database() {
236236
global $conf;
237237

238-
//* check sql-mode
239-
/*$check_sql_mode = $this->db->queryOneRecord("SELECT @@sql_mode");
240-
241-
if ($check_sql_mode['@@sql_mode'] != '' && $check_sql_mode['@@sql_mode'] != 'NO_ENGINE_SUBSTITUTION') {
242-
echo "Wrong SQL-mode. You should use NO_ENGINE_SUBSTITUTION. Add\n\n";
243-
echo " sql-mode=\"NO_ENGINE_SUBSTITUTION\"\n\n";
244-
echo"to the mysqld-section in your mysql-config on this server and restart mysqld afterwards\n";
245-
die();
246-
}*/
247-
248-
$unwanted_sql_plugins = array('validate_password');
249-
$sql_plugins = $this->db->queryAllRecords("SELECT plugin_name FROM information_schema.plugins WHERE plugin_status='ACTIVE' AND plugin_name IN ?", $unwanted_sql_plugins);
250-
if(is_array($sql_plugins) && !empty($sql_plugins)) {
251-
foreach ($sql_plugins as $plugin) echo "Login in to MySQL and disable $plugin[plugin_name] with:\n\n UNINSTALL PLUGIN $plugin[plugin_name];";
252-
die();
238+
//** Check for unwanted plugins
239+
if ($this->db->getDatabaseType() == 'mysql' && $this->db->getDatabaseVersion(true) >= 8) {
240+
// component approach since MySQL 8.0
241+
$unwanted_components = [
242+
'file://component_validate_password',
243+
];
244+
$sql_components = $this->db->queryAllRecords("SELECT * FROM mysql.component where component_urn IN ?", $unwanted_components);
245+
if(is_array($sql_components) && !empty($sql_components)) {
246+
foreach ($sql_components as $component) {
247+
$component_name = parse_url($component['component_urn'], PHP_URL_HOST);
248+
echo "Login in to MySQL and disable '{$component_name}' with:\n\n UNINSTALL COMPONENT '{$component['component_urn']}';\n\n";
249+
}
250+
die();
251+
}
252+
} else {
253+
$unwanted_sql_plugins = array('validate_password');
254+
$sql_plugins = $this->db->queryAllRecords("SELECT plugin_name FROM information_schema.plugins WHERE plugin_status='ACTIVE' AND plugin_name IN ?", $unwanted_sql_plugins);
255+
if(is_array($sql_plugins) && !empty($sql_plugins)) {
256+
foreach ($sql_plugins as $plugin) echo "Login in to MySQL and disable $plugin[plugin_name] with:\n\n UNINSTALL PLUGIN $plugin[plugin_name];";
257+
die();
258+
}
253259
}
254260

255261
//** Create the database
@@ -308,6 +314,15 @@ public function add_database_server_record() {
308314
if(!$this->db->query($query, $conf['mysql']['database'] . ".*", $conf['mysql']['ispconfig_user'], $from_host)) {
309315
$this->error('Unable to grant databse permissions to user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage);
310316
}
317+
318+
// add correct administrative rights to IPSConfig user (SUPER is deprecated and unnecessarily powerful)
319+
if ($this->db->getDatabaseType() == 'mysql' && $this->db->getDatabaseVersion(true) >= 8) {
320+
// there might be more needed on replicated db environments, this was not tested
321+
$query = 'GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO ?@?';
322+
if(!$this->db->query($query, $conf['mysql']['ispconfig_user'], $from_host)) {
323+
$this->error('Unable to grant administrative permissions to user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage);
324+
}
325+
}
311326

312327
//* Set the database name in the DB library
313328
$this->db->setDBName($conf['mysql']['database']);

install/lib/mysql.lib.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,41 @@ public function mapType($metaType, $typeValue) {
761761
break;
762762
}
763763
}
764+
765+
/**
766+
* Get the database type (mariadb or mysql)
767+
*
768+
* @access public
769+
* @return string 'mariadb' or string 'mysql'
770+
*/
771+
772+
public function getDatabaseType() {
773+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
774+
if(stristr($tmp['version'],'mariadb')) {
775+
return 'mariadb';
776+
} else {
777+
return 'mysql';
778+
}
779+
}
780+
781+
/**
782+
* Get the database version
783+
*
784+
* @access public
785+
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
786+
* @return string version number
787+
*/
788+
789+
public function getDatabaseVersion($major_version_only = false) {
790+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
791+
$version = explode('-', $tmp['version']);
792+
if($major_version_only == true) {
793+
$version_parts = explode('.', $version[0]);
794+
return $version_parts[0];
795+
} else {
796+
return $version[0];
797+
}
798+
}
764799

765800
}
766801

install/sql/incremental/upd_dev_collection.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ ALTER TABLE `mail_user` ADD `disableindexer-worker` ENUM('n','y') CHARACTER SET
3737
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`;
3838

3939
-- change cc and sender_cc column type
40-
ALTER TABLE `mail_user` CHANGE `cc` `cc` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
40+
ALTER TABLE `mail_user` CHANGE `cc` `cc` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci;
4141

4242
-- remove SPDY option
4343
ALTER TABLE `web_domain` DROP COLUMN `enable_spdy`;
@@ -62,7 +62,7 @@ ALTER TABLE `web_domain` CHANGE `nginx_directives` `nginx_directives` mediumtext
6262
ALTER TABLE `mail_user` MODIFY `move_junk` enum('y','a','n') NOT NULL DEFAULT 'y';
6363

6464
-- Change id_rsa column to TEXT format
65-
ALTER TABLE `client` CHANGE `id_rsa` `id_rsa` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
65+
ALTER TABLE `client` CHANGE `id_rsa` `id_rsa` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci;
6666

6767
ALTER TABLE `directive_snippets` ADD `update_sites` ENUM('y','n') NOT NULL DEFAULT 'n' ;
6868

install/sql/ispconfig3.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ CREATE TABLE `client` (
253253
`canceled` enum('n','y') NOT NULL DEFAULT 'n',
254254
`can_use_api` enum('n','y') NOT NULL DEFAULT 'n',
255255
`tmp_data` mediumblob,
256-
`id_rsa` text NOT NULL DEFAULT '',
256+
`id_rsa` text,
257257
`ssh_rsa` varchar(600) NOT NULL DEFAULT '',
258258
`customer_no_template` varchar(255) DEFAULT 'R[CLIENTID]C[CUSTOMER_NO]',
259259
`customer_no_start` int(11) NOT NULL DEFAULT '1',
@@ -1040,7 +1040,7 @@ CREATE TABLE `mail_user` (
10401040
`maildir` varchar(255) NOT NULL default '',
10411041
`maildir_format` varchar(255) NOT NULL default 'maildir',
10421042
`quota` bigint(20) NOT NULL default '-1',
1043-
`cc` text NOT NULL default '',
1043+
`cc` text,
10441044
`sender_cc` varchar(255) NOT NULL default '',
10451045
`homedir` varchar(255) NOT NULL default '',
10461046
`autoresponder` enum('n','y') NOT NULL default 'n',

interface/lib/classes/db_mysql.inc.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,76 @@ public function mapType($metaType, $typeValue) {
11061106
}
11071107
}
11081108

1109+
/**
1110+
* Get the database type (mariadb or mysql)
1111+
*
1112+
* @access public
1113+
* @return string 'mariadb' or string 'mysql'
1114+
*/
1115+
1116+
public function getDatabaseType() {
1117+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
1118+
if(stristr($tmp['version'],'mariadb')) {
1119+
return 'mariadb';
1120+
} else {
1121+
return 'mysql';
1122+
}
1123+
}
1124+
1125+
/**
1126+
* Get the database version
1127+
*
1128+
* @access public
1129+
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
1130+
* @return string version number
1131+
*/
1132+
1133+
public function getDatabaseVersion($major_version_only = false) {
1134+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
1135+
$version = explode('-', $tmp['version']);
1136+
if($major_version_only == true) {
1137+
$version_parts = explode('.', $version[0]);
1138+
return $version_parts[0];
1139+
} else {
1140+
return $version[0];
1141+
}
1142+
}
1143+
1144+
/**
1145+
* Get a mysql password hash
1146+
*
1147+
* @access public
1148+
* @param string cleartext password
1149+
* @return string Password hash
1150+
*/
1151+
1152+
public function getPasswordHash($password) {
1153+
1154+
$password_type = 'password';
1155+
1156+
/* Disabled until caching_sha2_password is implemented
1157+
if($this->getDatabaseType() == 'mysql' && $this->getDatabaseVersion(true) >= 8) {
1158+
// we are in MySQL 8 mode
1159+
$tmp = $this->queryOneRecord("show variables like 'default_authentication_plugin'");
1160+
if($tmp['default_authentication_plugin'] == 'caching_sha2_password') {
1161+
$password_type = 'caching_sha2_password';
1162+
}
1163+
}
1164+
*/
1165+
1166+
if($password_type == 'caching_sha2_password') {
1167+
/*
1168+
caching_sha2_password hashing needs to be implemented, have not
1169+
found valid PHP implementation for the new password hash type.
1170+
*/
1171+
} else {
1172+
$password_hash = '*'.strtoupper(sha1(sha1($password, true)));
1173+
}
1174+
1175+
return $password_hash;
1176+
}
1177+
1178+
11091179
}
11101180

11111181
/**

interface/lib/classes/tform_base.inc.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,8 +1358,7 @@ protected function _getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $
13581358
$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]),'ISO-8859-1');
13591359
$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
13601360
} elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
1361-
$tmp = $app->db->queryOneRecord("SELECT PASSWORD(?) as `crypted`", stripslashes($record[$key]));
1362-
$record[$key] = $tmp['crypted'];
1361+
$record[$key] = $app->db->getPasswordHash($record[$key]);
13631362
$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
13641363
} else {
13651364
$record[$key] = md5(stripslashes($record[$key]));
@@ -1390,8 +1389,7 @@ protected function _getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $
13901389
$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]),'ISO-8859-1');
13911390
$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
13921391
} elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
1393-
$tmp = $app->db->queryOneRecord("SELECT PASSWORD(?) as `crypted`", stripslashes($record[$key]));
1394-
$record[$key] = $tmp['crypted'];
1392+
$record[$key] = $app->db->getPasswordHash($record[$key]);
13951393
$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
13961394
} else {
13971395
$record[$key] = md5(stripslashes($record[$key]));

server/lib/classes/db_mysql.inc.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,75 @@ public function mapType($metaType, $typeValue) {
11061106
}
11071107
}
11081108

1109+
/**
1110+
* Get the database type (mariadb or mysql)
1111+
*
1112+
* @access public
1113+
* @return string 'mariadb' or string 'mysql'
1114+
*/
1115+
1116+
public function getDatabaseType() {
1117+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
1118+
if(stristr($tmp['version'],'mariadb')) {
1119+
return 'mariadb';
1120+
} else {
1121+
return 'mysql';
1122+
}
1123+
}
1124+
1125+
/**
1126+
* Get the database version
1127+
*
1128+
* @access public
1129+
* @param bool $major_version_only = true will return the major version only, e.g. 8 for MySQL 8
1130+
* @return string version number
1131+
*/
1132+
1133+
public function getDatabaseVersion($major_version_only = false) {
1134+
$tmp = $this->queryOneRecord('SELECT VERSION() as version');
1135+
$version = explode('-', $tmp['version']);
1136+
if($major_version_only == true) {
1137+
$version_parts = explode('.', $version[0]);
1138+
return $version_parts[0];
1139+
} else {
1140+
return $version[0];
1141+
}
1142+
}
1143+
1144+
/**
1145+
* Get a mysql password hash
1146+
*
1147+
* @access public
1148+
* @param string cleartext password
1149+
* @return string Password hash
1150+
*/
1151+
1152+
public function getPasswordHash($password) {
1153+
1154+
$password_type = 'password';
1155+
1156+
/* Disabled until caching_sha2_password is implemented
1157+
if($this->getDatabaseType() == 'mysql' && $this->getDatabaseVersion(true) >= 8) {
1158+
// we are in MySQL 8 mode
1159+
$tmp = $this->queryOneRecord("show variables like 'default_authentication_plugin'");
1160+
if($tmp['default_authentication_plugin'] == 'caching_sha2_password') {
1161+
$password_type = 'caching_sha2_password';
1162+
}
1163+
}
1164+
*/
1165+
1166+
if($password_type == 'caching_sha2_password') {
1167+
/*
1168+
caching_sha2_password hashing needs to be implemented, have not
1169+
found valid PHP implementation for the new password hash type.
1170+
*/
1171+
} else {
1172+
$password_hash = '*'.strtoupper(sha1(sha1($password, true)));
1173+
}
1174+
1175+
return $password_hash;
1176+
}
1177+
11091178
}
11101179

11111180
/**

0 commit comments

Comments
 (0)