diff --git a/.gitignore b/.gitignore index d42aee61f4caf9d716977a21353bf598c3092220..cf164550796288e7d65d6fb3e726063e52c1a3df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .DS_Store /nbproject/private/ .phplint-cache +.buildpath +.project +.settings/ \ No newline at end of file diff --git a/install/install.php b/install/install.php index 9dff3facf2e71a085e1cbc0994eb7cc8e967957b..18473ae90e402554c91d08014758dda5954e8457 100644 --- a/install/install.php +++ b/install/install.php @@ -30,30 +30,30 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* ISPConfig 3 installer. - + ------------------------------------------------------------------------------------- - Interactive install ------------------------------------------------------------------------------------- run: - + php install.php - + ------------------------------------------------------------------------------------- - Noninteractive (autoinstall) mode ------------------------------------------------------------------------------------- - + The autoinstall mode can read the installer questions from a .ini style file or from - a php config file. Examples for both file types are in the docs folder. + a php config file. Examples for both file types are in the docs folder. See autoinstall.ini.sample and autoinstall.conf_sample.php. - + run: - + php install.php --autoinstall=autoinstall.ini - + or - + php install.php --autoinstall=autoinstall.conf.php - + */ error_reporting(E_ALL|E_STRICT); @@ -202,17 +202,17 @@ if(!function_exists('mysqli_connect')) die('No PHP MySQLi functions available. P //** Get MySQL root credentials $finished = false; do { - $tmp_mysql_server_host = $inst->free_query('MySQL server hostname', $conf['mysql']['host'],'mysql_hostname'); + $tmp_mysql_server_host = $inst->free_query('MySQL server hostname', $conf['mysql']['host'],'mysql_hostname'); $tmp_mysql_server_port = $inst->free_query('MySQL server port', $conf['mysql']['port'],'mysql_port'); - $tmp_mysql_server_admin_user = $inst->free_query('MySQL root username', $conf['mysql']['admin_user'],'mysql_root_user'); - $tmp_mysql_server_admin_password = $inst->free_query('MySQL root password', $conf['mysql']['admin_password'],'mysql_root_password'); - $tmp_mysql_server_database = $inst->free_query('MySQL database to create', $conf['mysql']['database'],'mysql_database'); + $tmp_mysql_server_admin_user = $inst->free_query('MySQL root username', $conf['mysql']['admin_user'],'mysql_root_user'); + $tmp_mysql_server_admin_password = $inst->free_query('MySQL root password', $conf['mysql']['admin_password'],'mysql_root_password'); + $tmp_mysql_server_database = $inst->free_query('MySQL database to create', $conf['mysql']['database'],'mysql_database'); $tmp_mysql_server_charset = $inst->free_query('MySQL charset', $conf['mysql']['charset'],'mysql_charset'); - + if($install_mode == 'expert') { swriteln("The next two questions are about the internal ISPConfig database user and password.\nIt is recommended to accept the defaults which are 'ispconfig' as username and a random password.\nIf you use a different password, use only numbers and chars for the password.\n"); - - $conf['mysql']['ispconfig_user'] = $inst->free_query('ISPConfig mysql database username', $conf['mysql']['ispconfig_user'],'mysql_ispconfig_user'); + + $conf['mysql']['ispconfig_user'] = $inst->free_query('ISPConfig mysql database username', $conf['mysql']['ispconfig_user'],'mysql_ispconfig_user'); $conf['mysql']['ispconfig_password'] = $inst->free_query('ISPConfig mysql database password', $conf['mysql']['ispconfig_password'],'mysql_ispconfig_password'); } @@ -240,6 +240,7 @@ unset($tmp); //** Initializing database connection include_once 'lib/mysql.lib.php'; $inst->db = new db(); +$mysqlServerInfo = $inst->db->serverInfo(); //** Begin with standard or expert installation @@ -262,10 +263,10 @@ if($install_mode == 'expert' && strtolower($inst->simple_query('Shall this serve //** Get MySQL root credentials $finished = false; do { - $tmp_mysql_server_host = $inst->free_query('MySQL master server hostname', $conf['mysql']['master_host'],'mysql_master_hostname'); + $tmp_mysql_server_host = $inst->free_query('MySQL master server hostname', $conf['mysql']['master_host'],'mysql_master_hostname'); $tmp_mysql_server_port = $inst->free_query('MySQL master server port', $conf['mysql']['master_port'],'mysql_master_port'); - $tmp_mysql_server_admin_user = $inst->free_query('MySQL master server root username', $conf['mysql']['master_admin_user'],'mysql_master_root_user'); - $tmp_mysql_server_admin_password = $inst->free_query('MySQL master server root password', $conf['mysql']['master_admin_password'],'mysql_master_root_password'); + $tmp_mysql_server_admin_user = $inst->free_query('MySQL master server root username', $conf['mysql']['master_admin_user'],'mysql_master_root_user'); + $tmp_mysql_server_admin_password = $inst->free_query('MySQL master server root password', $conf['mysql']['master_admin_password'],'mysql_master_root_password'); $tmp_mysql_server_database = $inst->free_query('MySQL master server database name', $conf['mysql']['master_database'],'mysql_master_database'); //* Initialize the MySQL server connection @@ -294,7 +295,7 @@ if($install_mode == 'expert' && strtolower($inst->simple_query('Shall this serve } //* Create the mysql database -$inst->configure_database(); +$inst->configure_database($mysqlServerInfo); //* Check for Web-Server if(!$conf['apache']['installed'] && !$conf['nginx']['installed']) { @@ -318,7 +319,7 @@ if($install_mode == 'expert') { swriteln('Adding ISPConfig server record to database.'); swriteln(''); } -$inst->add_database_server_record(); +$inst->add_database_server_record($mysqlServerInfo); if($install_mode == 'standard' || strtolower($inst->simple_query('Configure Mail', array('y', 'n') , 'y','configure_mail') ) == 'y') { @@ -414,7 +415,7 @@ if($force) { $force = @($conf['pureftpd']['installed']) ? true : $inst->force_configure_app('pureftpd', ($install_mode == 'expert')); if($force) { swriteln('Configuring Pureftpd'); - $inst->configure_pureftpd(); + $inst->configure_pureftpd($mysqlServerInfo); } //** Configure DNS @@ -565,7 +566,7 @@ if($install_mode == 'standard' || strtolower($inst->simple_query('Install ISPCon if($conf['nginx']['installed'] == true) $conf['nginx']['vhost_port'] = $ispconfig_vhost_port; unset($ispconfig_vhost_port); - if(strtolower($inst->simple_query('Do you want a secure (SSL) connection to the ISPConfig web interface', array('y', 'n'), 'y','ispconfig_use_ssl')) == 'y') { + if(strtolower($inst->simple_query('Do you want a secure (SSL) connection to the ISPConfig web interface', array('y', 'n'), 'y','ispconfig_use_ssl')) == 'y') { $inst->make_ispconfig_ssl_cert(); } $inst->install_ispconfig_interface = true; diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 4f72c6920b0169c9de3cf890ba928c56ca1e47bb..1d2bae765f26f67c74107a5de4a331523e5f9d44 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -32,7 +32,10 @@ class installer_base { var $wb = array(); var $language = 'en'; - var $db; + /** + * @var db Internal pointer to instance of db library. + */ + public $db; public $conf; public $install_ispconfig_interface = true; public $is_update = false; // true if it is an update, falsi if it is a new install @@ -221,10 +224,13 @@ class installer_base { /** Create the database for ISPConfig */ - - public function configure_database() { + /** + * @param server_info $server_info + */ + public function configure_database($server_info) { global $conf; + //* check sql-mode /*$check_sql_mode = $this->db->queryOneRecord("SELECT @@sql_mode"); @@ -235,10 +241,30 @@ class installer_base { die(); }*/ - $unwanted_sql_plugins = array('validate_password'); + if ($server_info->isMysqlEightOrNewer()) { + // component approach since MySQL 8.0 + $unwanted_components = array( + '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(); + } + + $unwanted_sql_plugins = array(''); + } else { + $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];"; + foreach ($sql_plugins as $plugin) { + echo "Login in to MySQL and disable {$plugin['plugin_name']} with:\n\n UNINSTALL PLUGIN {$plugin['plugin_name']};\n\n"; + } die(); } @@ -274,8 +300,11 @@ class installer_base { } } - //** Create the server record in the database - public function add_database_server_record() { + /** + * Create the server record in the database + * @param server_info $server_info + */ + public function add_database_server_record($server_info) { global $conf; @@ -294,11 +323,21 @@ class installer_base { if(!$this->db->query($query, $conf['mysql']['ispconfig_user'], $from_host, $conf['mysql']['ispconfig_password'])) { $this->error('Unable to create database user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage); } + $query = 'GRANT SELECT, INSERT, UPDATE, DELETE ON ?? TO ?@?'; 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 ($server_info->isMysqlEightOrNewer()) { + // 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']); @@ -357,7 +396,7 @@ class installer_base { } $server_ini_content = array_to_ini($tpl_ini_array); - + $mail_server_enabled = ($conf['services']['mail'])?1:0; $web_server_enabled = ($conf['services']['web'])?1:0; $dns_server_enabled = ($conf['services']['dns'])?1:0; @@ -409,12 +448,12 @@ class installer_base { } - + public function detect_ips(){ global $conf; exec("ip addr show | awk '/global/ { print $2 }' | cut -d '/' -f 1", $output, $retval); - + if($retval == 0){ if(is_array($output) && !empty($output)){ foreach($output as $line){ @@ -655,7 +694,7 @@ class installer_base { if(!$this->dbmaster->query($query, $value['db'] . '.aps_instances', $value['user'], $host)) { $this->warning('Unable to set rights of user in master database: '.$value['db']."\n Query: ".$query."\n Error: ".$this->dbmaster->errorMessage); } - + $query = "GRANT SELECT, DELETE ON ?? TO ?@?"; if ($verbose){ echo $query ."\n"; @@ -679,7 +718,7 @@ class installer_base { if(!$this->dbmaster->query($query, $value['db'] . '.mail_backup', $value['user'], $host)) { $this->warning('Unable to set rights of user in master database: '.$value['db']."\n Query: ".$query."\n Error: ".$this->dbmaster->errorMessage); } - + $query = "GRANT SELECT, UPDATE(`dnssec_initialized`, `dnssec_info`, `dnssec_last_signed`) ON ?? TO ?@?"; if ($verbose){ echo $query ."\n"; @@ -687,7 +726,7 @@ class installer_base { if(!$this->dbmaster->query($query, $value['db'] . '.dns_soa', $value['user'], $host)) { $this->warning('Unable to set rights of user in master database: '.$value['db']."\n Query: ".$query."\n Error: ".$this->dbmaster->errorMessage); } - + $query = "GRANT SELECT, INSERT, UPDATE ON ?? TO ?@?"; if ($verbose){ echo $query ."\n"; @@ -844,9 +883,9 @@ class installer_base { exec ("postconf -M $service.$type 2> /dev/null", $out, $ret); } $postfix_service = @($out[0]=='')?false:true; - } else { //* fallback - Postfix < 2.9 + } else { //* fallback - Postfix < 2.9 $content = rf($conf['postfix']['config_dir'].'/master.cf'); - $regex = "/^((?!#)".$service.".*".$type.".*)$/m"; + $regex = "/^((?!#)".$service.".*".$type.".*)$/m"; $postfix_service = @(preg_match($regex, $content))?true:false; } @@ -894,7 +933,7 @@ class installer_base { //* mysql-virtual_relayrecipientmaps.cf $this->process_postfix_config('mysql-virtual_relayrecipientmaps.cf'); - + //* mysql-virtual_outgoing_bcc.cf $this->process_postfix_config('mysql-virtual_outgoing_bcc.cf'); @@ -953,13 +992,13 @@ class installer_base { if($conf['postgrey']['installed'] == true) { $greylisting = ', check_recipient_access mysql:/etc/postfix/mysql-virtual_policy_greylist.cf'; } - + $reject_sender_login_mismatch = ''; if(isset($server_ini_array['mail']['reject_sender_login_mismatch']) && ($server_ini_array['mail']['reject_sender_login_mismatch'] == 'y')) { $reject_sender_login_mismatch = ', reject_authenticated_sender_login_mismatch'; } unset($server_ini_array); - + $tmp = str_replace('.','\.',$conf['hostname']); $postconf_placeholders = array('{config_dir}' => $config_dir, @@ -1097,7 +1136,7 @@ class installer_base { caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); } - + public function configure_saslauthd() { global $conf; @@ -1213,17 +1252,17 @@ class installer_base { public function configure_dovecot() { global $conf; - + $virtual_transport = 'dovecot'; $configure_lmtp = false; - + // check if virtual_transport must be changed if ($this->is_update) { $tmp = $this->db->queryOneRecord("SELECT * FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . ".server", $conf['server_id']); $ini_array = ini_to_array(stripslashes($tmp['config'])); // ini_array needs not to be checked, because already done in update.php -> updateDbAndIni() - + if(isset($ini_array['mail']['mailbox_virtual_uidgid_maps']) && $ini_array['mail']['mailbox_virtual_uidgid_maps'] == 'y') { $virtual_transport = 'lmtp:unix:private/dovecot-lmtp'; $configure_lmtp = true; @@ -1307,7 +1346,7 @@ class installer_base { if(version_compare($dovecot_version,2.3) >= 0) { // Remove deprecated setting(s) removeLine($config_dir.'/'.$configfile, 'ssl_protocols ='); - + // Check if we have a dhparams file and if not, create it if(!file_exists('/etc/dovecot/dh.pem')) { swriteln('Creating new DHParams file, this takes several minutes. Do not interrupt the script.'); @@ -1330,7 +1369,7 @@ class installer_base { $content = str_replace('#2.3+','',$content); file_put_contents($config_dir.'/'.$configfile,$content); unset($content); - + } else { // remove settings which are not supported in Dovecot < 2.3 removeLine($config_dir.'/'.$configfile, 'ssl_min_protocol ='); @@ -1365,7 +1404,7 @@ class installer_base { chmod($config_dir.'/'.$configfile, 0600); chown($config_dir.'/'.$configfile, 'root'); chgrp($config_dir.'/'.$configfile, 'root'); - + // Dovecot shall ignore mounts in website directory if(is_installed('doveadm')) exec("doveadm mount add '/var/www/*' ignore > /dev/null 2> /dev/null"); @@ -1463,12 +1502,12 @@ class installer_base { public function configure_rspamd() { global $conf; - + //* These postconf commands will be executed on installation and update $server_ini_rec = $this->db->queryOneRecord("SELECT config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . '.server', $conf['server_id']); $server_ini_array = ini_to_array(stripslashes($server_ini_rec['config'])); unset($server_ini_rec); - + $mail_config = $server_ini_array['mail']; if($mail_config['content_filter'] === 'rspamd') { exec("postconf -X 'receive_override_options'"); @@ -1490,7 +1529,7 @@ class installer_base { } } exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'"); - + } if(is_user('_rspamd') && is_group('amavis')) { @@ -1498,7 +1537,7 @@ class installer_base { } elseif(is_user('rspamd') && is_group('amavis')) { exec("usermod -G amavis rspamd"); } - + if(!is_dir('/etc/rspamd/local.d/')){ mkdir('/etc/rspamd/local.d/', 0755, true); } @@ -1506,7 +1545,7 @@ class installer_base { if(!is_dir('/etc/rspamd/override.d/')){ mkdir('/etc/rspamd/override.d/', 0755, true); } - + if ( substr($mail_config['dkim_path'], strlen($mail_config['dkim_path'])-1) == '/' ) { $mail_config['dkim_path'] = substr($mail_config['dkim_path'], 0, strlen($mail_config['dkim_path'])-1); } @@ -1618,17 +1657,17 @@ class installer_base { wf('/etc/rspamd/local.d/dkim_signing.conf', $tpl->grab()); exec('chmod a+r /etc/rspamd/local.d/* /etc/rspamd/override.d/*'); - + $command = 'usermod -a -G amavis _rspamd'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + if(strpos(rf('/etc/rspamd/rspamd.conf'), '.include "$LOCAL_CONFDIR/local.d/users.conf"') === false){ af('/etc/rspamd/rspamd.conf', '.include "$LOCAL_CONFDIR/local.d/users.conf"'); } - + if(!isset($mail_config['rspamd_password']) || !$mail_config['rspamd_password']) { $mail_config['rspamd_password'] = str_shuffle(bin2hex(openssl_random_pseudo_bytes(12))); - + $server_ini_array['mail']['rspamd_password'] = $mail_config['rspamd_password']; } @@ -1640,7 +1679,7 @@ class installer_base { $this->db->query('UPDATE `server` SET `config` = ? WHERE `server_id` = ?', $server_ini_string, $conf['server_id']); unset($server_ini_array); unset($server_ini_string); - + $tpl = new tpl(); $tpl->newTemplate('rspamd_worker-controller.inc.master'); $tpl->setVar('rspamd_password', $mail_config['rspamd_password']); @@ -1679,7 +1718,11 @@ class installer_base { } - public function configure_pureftpd() { + /** + * Configures PureFTP server. + * @param server_info $server_info + */ + public function configure_pureftpd($server_info) { global $conf; $config_dir = $conf['pureftpd']['config_dir']; @@ -1698,6 +1741,11 @@ class installer_base { $content = str_replace('{mysql_server_database}', $conf['mysql']['database'], $content); $content = str_replace('{mysql_server_ip}', $conf['mysql']['ip'], $content); $content = str_replace('{server_id}', $conf['server_id'], $content); + + if($server_info->isMysqlEightOrNewer()) { + $content = str_replace(' OR expires="0000-00-00 00:00:00"', '', $content); + } + wf($config_dir.'/'.$configfile, $content); chmod($config_dir.'/'.$configfile, 0600); chown($config_dir.'/'.$configfile, 'root'); @@ -1783,14 +1831,14 @@ class installer_base { } - + //** writes bind configuration files public function process_bind_file($configfile, $target='/', $absolute=false) { global $conf; if ($absolute) $full_file_name = $target.$configfile; else $full_file_name = $conf['ispconfig_install_dir'].$target.$configfile; - + //* Backup exiting file if(is_file($full_file_name)) { copy($full_file_name, $config_dir.$configfile.'~'); @@ -1822,7 +1870,7 @@ class installer_base { chown($content, $conf['bind']['bind_user']); chgrp($content, $conf['bind']['bind_group']); chmod($content, 02770); - + //* Install scripts for dnssec implementation $this->process_bind_file('named.conf.options', '/etc/bind/', true); //TODO replace hardcoded path } @@ -1942,12 +1990,12 @@ class installer_base { if(is_file('/etc/apache2/ports.conf')) { // add a line "Listen 443" to ports conf if line does not exist replaceLine('/etc/apache2/ports.conf', 'Listen 443', 'Listen 443', 1); - + // Comment out the namevirtualhost lines, as they were added by ispconfig in ispconfig.conf file again replaceLine('/etc/apache2/ports.conf', 'NameVirtualHost *:80', '# NameVirtualHost *:80', 1); replaceLine('/etc/apache2/ports.conf', 'NameVirtualHost *:443', '# NameVirtualHost *:443', 1); } - + if(is_file('/etc/apache2/mods-available/fcgid.conf')) { // add or modify the parameters for fcgid.conf replaceLine('/etc/apache2/mods-available/fcgid.conf','MaxRequestLen','MaxRequestLen 15728640',1); @@ -1962,7 +2010,7 @@ class installer_base { } } } - + if(is_file('/etc/apache2/apache2.conf')) { if(hasLine('/etc/apache2/apache2.conf', 'Include sites-enabled/', 1) == false && hasLine('/etc/apache2/apache2.conf', 'IncludeOptional sites-enabled/', 1) == false) { if(hasLine('/etc/apache2/apache2.conf', 'Include sites-enabled/*.conf', 1) == true) { @@ -1979,16 +2027,16 @@ class installer_base { $tpl = new tpl('apache_ispconfig.conf.master'); $tpl->setVar('apache_version',getapacheversion()); - + if($this->is_update == true) { $tpl->setVar('logging',get_logging_state()); } else { $tpl->setVar('logging','yes'); } - + $records = $this->db->queryAllRecords("SELECT * FROM ?? WHERE server_id = ? AND virtualhost = 'y'", $conf['mysql']['master_database'] . '.server_ip', $conf['server_id']); $ip_addresses = array(); - + if(is_array($records) && count($records) > 0) { foreach($records as $rec) { if($rec['ip_type'] == 'IPv6') { @@ -2007,9 +2055,9 @@ class installer_base { } } } - + if(count($ip_addresses) > 0) $tpl->setLoop('ip_adresses',$ip_addresses); - + wf($vhost_conf_dir.'/ispconfig.conf', $tpl->grab()); unset($tpl); @@ -2069,7 +2117,7 @@ class installer_base { //* add a sshusers group $command = 'groupadd sshusers'; if(!is_group('sshusers')) caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + // add anonymized log option to nginxx.conf file $nginx_conf_file = $conf['nginx']['config_dir'].'/nginx.conf'; if(is_file($nginx_conf_file)) { @@ -2079,7 +2127,7 @@ class installer_base { replaceLine($nginx_conf_file, 'http {', "http {\n\n".file_get_contents('tpl/nginx_anonlog.master'), 0, 0); } } - + } public function configure_fail2ban() { @@ -2239,7 +2287,7 @@ class installer_base { $vhost_conf_dir = $conf['apache']['vhost_conf_dir']; $vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir']; $apps_vhost_servername = ($conf['web']['apps_vhost_servername'] == '')?'':'ServerName '.$conf['web']['apps_vhost_servername']; - + //* Get the apps vhost port if($this->is_update == true) { $conf['web']['apps_vhost_port'] = get_apps_vhost_port_number(); @@ -2262,7 +2310,7 @@ class installer_base { if($conf['rspamd']['installed'] == true) { $tpl->setVar('use_rspamd', 'yes'); } - + // comment out the listen directive if port is 80 or 443 if($conf['web']['apps_vhost_ip'] == 80 or $conf['web']['apps_vhost_ip'] == 443) { $tpl->setVar('vhost_port_listen','#'); @@ -2335,7 +2383,7 @@ class installer_base { } else { $content = str_replace('{use_rspamd}', '# ', $content); } - + $socket_dir = escapeshellcmd($conf['nginx']['php_fpm_socket_dir']); if(substr($socket_dir, -1) != '/') $socket_dir .= '/'; if(!is_dir($socket_dir)) exec('mkdir -p '.$socket_dir); @@ -2365,11 +2413,11 @@ class installer_base { } $content = str_replace('{use_tcp}', $use_tcp, $content); $content = str_replace('{use_socket}', $use_socket, $content); - + // SSL in apps vhost is off by default. Might change later. $content = str_replace('{ssl_on}', '', $content); $content = str_replace('{ssl_comment}', '#', $content); - + // Fix socket path on PHP 7 systems if(file_exists('/var/run/php/php7.0-fpm.sock')) $content = str_replace('/var/run/php5-fpm.sock', '/var/run/php/php7.0-fpm.sock', $content); if(file_exists('/var/run/php/php7.1-fpm.sock')) $content = str_replace('/var/run/php5-fpm.sock', '/var/run/php/php7.1-fpm.sock', $content); @@ -2421,7 +2469,7 @@ class installer_base { exec("openssl rsa -passin pass:$ssl_pw -in $ssl_key_file -out $ssl_key_file.insecure"); rename($ssl_key_file, $ssl_key_file.'.secure'); rename($ssl_key_file.'.insecure', $ssl_key_file); - + exec('chown -R root:root /usr/local/ispconfig/interface/ssl'); } @@ -2451,14 +2499,14 @@ class installer_base { //* copy the ISPConfig server part $command = 'cp -rf ../server '.$install_dir; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* Make a backup of the security settings if(is_file('/usr/local/ispconfig/security/security_settings.ini')) copy('/usr/local/ispconfig/security/security_settings.ini','/usr/local/ispconfig/security/security_settings.ini~'); - + //* copy the ISPConfig security part $command = 'cp -rf ../security '.$install_dir; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* Apply changed security_settings.ini values to new security_settings.ini file if(is_file('/usr/local/ispconfig/security/security_settings.ini~')) { $security_settings_old = ini_to_array(file_get_contents('/usr/local/ispconfig/security/security_settings.ini~')); @@ -2637,15 +2685,15 @@ class installer_base { //* Chmod the files and directories in the acme dir $command = 'chmod -R 755 '.$install_dir.'/interface/acme'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* chown the server files to the root user and group $command = 'chown -R root:root '.$install_dir.'/server'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* chown the security files to the root user and group $command = 'chown -R root:root '.$install_dir.'/security'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* chown the security directory and security_settings.ini to root:ispconfig $command = 'chown root:ispconfig '.$install_dir.'/security/security_settings.ini'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); @@ -2659,7 +2707,7 @@ class installer_base { caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); $command = 'chown root:ispconfig '.$install_dir.'/security/nginx_directives.blacklist'; caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - + //* Make the global language file directory group writable exec("chmod -R 770 $install_dir/interface/lib/lang"); @@ -2710,7 +2758,7 @@ class installer_base { exec('chmod -R 770 '.escapeshellarg($install_dir.'/interface/invoices')); exec('chown -R ispconfig:ispconfig '.escapeshellarg($install_dir.'/interface/invoices')); } - + exec('chown -R root:root /usr/local/ispconfig/interface/ssl'); // TODO: FIXME: add the www-data user to the ispconfig group. This is just for testing @@ -2768,7 +2816,7 @@ class installer_base { } else { $tpl->setVar('ssl_bundle_comment','#'); } - + $tpl->setVar('apache_version',getapacheversion()); wf($vhost_conf_dir.'/ispconfig.vhost', $tpl->grab()); @@ -2907,16 +2955,16 @@ class installer_base { //* Remove Domain module as its functions are available in the client module now if(@is_dir('/usr/local/ispconfig/interface/web/domain')) exec('rm -rf /usr/local/ispconfig/interface/web/domain'); - + //* Disable rkhunter run and update in debian cronjob as ispconfig is running and updating rkhunter if(is_file('/etc/default/rkhunter')) { replaceLine('/etc/default/rkhunter', 'CRON_DAILY_RUN="yes"', 'CRON_DAILY_RUN="no"', 1, 0); replaceLine('/etc/default/rkhunter', 'CRON_DB_UPDATE="yes"', 'CRON_DB_UPDATE="no"', 1, 0); } - + // Add symlink for patch tool if(!is_link('/usr/local/bin/ispconfig_patch')) exec('ln -s /usr/local/ispconfig/server/scripts/ispconfig_patch /usr/local/bin/ispconfig_patch'); - + // Change mode of a few files from amavisd if(is_file($conf['amavis']['config_dir'].'/conf.d/50-user')) chmod($conf['amavis']['config_dir'].'/conf.d/50-user', 0640); if(is_file($conf['amavis']['config_dir'].'/50-user~')) chmod($conf['amavis']['config_dir'].'/50-user~', 0400); @@ -3010,12 +3058,12 @@ class installer_base { chmod($conf['ispconfig_log_dir'].'/cron.log', 0660); } - + public function create_mount_script(){ global $app, $conf; $mount_script = '/usr/local/ispconfig/server/scripts/backup_dir_mount.sh'; $mount_command = ''; - + if(is_file($mount_script)) return; if(is_file('/etc/rc.local')){ $rc_local = file('/etc/rc.local'); @@ -3036,25 +3084,25 @@ class installer_base { } } } - + // This function is called at the end of the update process and contains code to clean up parts of old ISPCONfig releases public function cleanup_ispconfig() { global $app,$conf; - + // Remove directories recursively if(is_dir('/usr/local/ispconfig/interface/web/designer')) exec('rm -rf /usr/local/ispconfig/interface/web/designer'); if(is_dir('/usr/local/ispconfig/interface/web/themes/default-304')) exec('rm -rf /usr/local/ispconfig/interface/web/themes/default-304'); - + // Remove files if(is_file('/usr/local/ispconfig/interface/lib/classes/db_firebird.inc.php')) unlink('/usr/local/ispconfig/interface/lib/classes/db_firebird.inc.php'); if(is_file('/usr/local/ispconfig/interface/lib/classes/form.inc.php')) unlink('/usr/local/ispconfig/interface/lib/classes/form.inc.php'); - + // Change mode of a few files from amavisd if(is_file($conf['amavis']['config_dir'].'/conf.d/50-user')) chmod($conf['amavis']['config_dir'].'/conf.d/50-user', 0640); if(is_file($conf['amavis']['config_dir'].'/50-user~')) chmod($conf['amavis']['config_dir'].'/50-user~', 0400); if(is_file($conf['amavis']['config_dir'].'/amavisd.conf')) chmod($conf['amavis']['config_dir'].'/amavisd.conf', 0640); if(is_file($conf['amavis']['config_dir'].'/amavisd.conf~')) chmod($conf['amavis']['config_dir'].'/amavisd.conf~', 0400); - + } public function getinitcommand($servicename, $action, $init_script_directory = ''){ diff --git a/install/lib/mysql.lib.php b/install/lib/mysql.lib.php index 2528100cc51c8fc0bd096d1ef28a168a4cf42fec..4a9e6c8fb3cfd05012e7daffee266b5fc863afc7 100644 --- a/install/lib/mysql.lib.php +++ b/install/lib/mysql.lib.php @@ -64,10 +64,10 @@ class db public function __destruct() { if($this->_iConnId) mysqli_close($this->_iConnId); } - + private function do_connect() { global $conf; - + if($this->_iConnId) return true; $this->dbHost = $conf['mysql']['host']; $this->dbPort = $conf['mysql']['port']; @@ -77,7 +77,7 @@ class db $this->dbCharset = $conf["mysql"]["charset"]; $this->dbNewLink = false; $this->dbClientFlags = null; - + $this->_iConnId = mysqli_connect($this->dbHost, $this->dbUser, $this->dbPass, '', (int)$this->dbPort); $try = 0; while((!is_object($this->_iConnId) || mysqli_connect_error()) && $try < 5) { @@ -92,19 +92,19 @@ class db $this->_sqlerror('Zugriff auf Datenbankserver fehlgeschlagen! / Database server not accessible!'); return false; } - + if($this->dbName) $this->setDBName($this->dbName); $this->_setCharset(); } - + public function setDBData($host, $user, $password, $port) { $this->dbHost = $host; $this->dbUser = $user; $this->dbPass = $password; $this->dbPort = $port; } - + public function setDBName($name) { $this->dbName = $name; $this->_iConnId = mysqli_connect($this->dbHost, $this->dbUser, $this->dbPass, '', (int)$this->dbPort); @@ -114,7 +114,7 @@ class db return false; } } - + public function close() { if($this->_iConnId) mysqli_close($this->_iConnId); $this->_iConnId = null; @@ -526,7 +526,7 @@ class db if($debug == 1) echo "mySQL Error Message: ".$this->errorMessage; } } - + /* TODO: rewrite SQL */ function update($tablename, $form, $bedingung, $debug = 0) { @@ -648,6 +648,15 @@ class db return $tb_names; } + /** + * Retrieves information about RDBMS. + * @return server_info + */ + public function serverInfo() + { + return new server_info($this); + } + // gibt Feldinformationen zur Tabelle zur�ck /* $columns = array(action => add | alter | drop @@ -989,5 +998,77 @@ class fakedb_result { } +/** + * Class is dedicated to obtaining RDBMS version and other metadata information. + * It enables decicion making based on engine type and version (like to do something specific to MySQL8). + */ +class server_info { + + /** + * Constants define supported RDBMS types (like the ones this class is able to recognize). + * Percona is not recognized. + */ + const ENGINE_TYPE_MYSQL = 'mysql'; + const ENGINE_TYPE_MARIADB = 'mariadb'; + + /** + * Holds server info data; + * + * @var array with proprietary keys: + * - version = raw version from RDBMS + * - version_comment = raw version comment from RDBMS, + * - version_parts = parsed version numbers as array [{main}, {major}, {minor}], + * - engine = RDBMS engine name (lowercased) as determined from raw version/comment + */ + protected $data = []; + + /** + * Connects to db engine and reads version information and invokes new instance populated with retrieved data. + * + * @see https://stackoverflow.com/questions/43611296/how-can-i-detect-whether-connected-database-is-mariadb-or-mysql + * @param db $db + */ + public function __construct($db) { + $result = $db->query('SHOW VARIABLES WHERE Variable_name = "version" OR Variable_name = "version_comment"'); + $data = array(); + while ($row = $result->get()) { + $data[$row['Variable_name']] = $row['Value']; + } + + $parts = explode('-', $data['version'], 2); + $data['version_parts'] = explode('.', $parts[0]); + if (isset($parts[1])) { + if(strpos(strtolower($parts[1]), 'mariadb') !== false) { + $data['engine'] = self::ENGINE_TYPE_MARIADB; + } + } else { + $data['engine'] = self::ENGINE_TYPE_MYSQL; + } + + $this->data = $data; + } + + /** + * @return string A value read from one of the class constatns prefixed by 'ENGINE_TYPE_'. + */ + public function getEngine() { + return $this->data['engine']; + } + + /** + * Retrieves main version number (the one before the first dot) of the RDBMS. + * @return int + */ + public function getMainVersion() { + return (int)$this->data['version_parts'][0]; + } + + /** + * @return bool True when RDBMS is MySQL and its main version is at least eight. + */ + public function isMysqlEightOrNewer() { + return $this->getEngine() == self::ENGINE_TYPE_MYSQL && $this->getMainVersion() >= 8; + } +} -?> +?> \ No newline at end of file