Commit 13225f6a authored by Marius Burkard's avatar Marius Burkard
Browse files

- debian 10 support

parent 6a471131
#!/bin/bash
BASEDIR=$(dirname $0) ;
BASEDIR=$(realpath ${BASEDIR}) ;
CURL=$(which curl) ;
WGET=$(which wget) ;
PHP=$(which php) ;
if [ "$CURL" = "" ] ; then
if [ "$WGET" = "" ] ; then
echo "Curl and Wget missing, trying to install." ;
apt-get update -qq && apt-get -y -qq install wget ;
WGET=$(which wget) ;
fi
if [ "$WGET" = "" ] ; then
echo "Wget and curl are missing. Please install either wget or curl package." ;
exit 1 ;
fi
fi
if [ "$PHP" = "" ] ; then
echo "PHP cli missing, trying to install." ;
apt-get update -qq && apt-get -y -qq install php-cli ;
PHP=$(which php) ;
fi
if [ "$PHP" = "" ] ; then
echo "PHP cli is missing. Please install package php-cli." ;
exit 1;
fi
# TODO download package from server
${PHP} -q ${BASEDIR}/ispconfig.ai.php $@ && exit 0 || exit 1;
\ No newline at end of file
......@@ -9,7 +9,7 @@ define('CACHE_DIR', APP_DIR . '/var/cache');
require_once LIB_DIR . '/class.ISPConfig.inc.php';
try {
ISPConfigLog::setLogPriority(ISPConfigLog::PRIO_DEBUG);
ISPConfigLog::setLogPriority(ISPConfigLog::PRIO_INFO);
ISPConfig::run();
} catch(Exception $e) {
ISPConfigLog::error('Exception occured: ' . get_class($e) . ' -> ' . $e->getMessage(), true);
......
......@@ -44,13 +44,7 @@ class ISPConfig {
$sKey = $sArg;
$sValue = true;
}
if($sKey != 'module' && $sKey != 'method') {
$_GET[$sKey] = $sValue;
}
} elseif(!array_key_exists('module', $_GET)) {
$_GET['module'] = $argv[$a];
} elseif(!array_key_exists('method', $_GET)) {
$_GET['method'] = $argv[$a];
$_GET[$sKey] = $sValue;
}
}
}
......@@ -123,6 +117,10 @@ class ISPConfig {
*/
public static function run() {
self::init();
if(isset($_GET['debug']) && $_GET['debug']) {
ISPConfigLog::setLogPriority(ISPConfigLog::PRIO_DEBUG);
}
// get operating system
try {
......@@ -130,7 +128,8 @@ class ISPConfig {
ISPConfigLog::info('Starting perfect server setup for ' . $os['NAME'], true);
$installer = ISPConfigBaseOS::getOSInstance();
$installer->runPerfectSetup(true); // dry run for testing
$installer->runPerfectSetup(false);
ISPConfigLog::warn('Please delete the log files in var/log/setup-* once you don\'t need them anymore because they contain your passwords!', true);
} catch(Exception $ex) {
throw $ex;
}
......
......@@ -250,6 +250,8 @@ class ISPConfigFunctions {
if($sect != '') {
$ini[$sect] = $sect_data;
} elseif($initial_sect == '') {
return $sect_data;
}
return $ini;
......
......@@ -15,5 +15,4 @@ class ISPConfigClassException extends ISPConfigException {}
class ISPConfigLogException extends ISPConfigException {}
class ISPConfigModuleException extends ISPConfigException {}
class ISPConfigDatabaseException extends ISPConfigException {}
class ISPConfigSSHException extends ISPConfigException {}
class ISPConfigOSException extends ISPConfigException {}
\ No newline at end of file
......@@ -51,9 +51,9 @@ class ISPConfigBaseOS {
'VERSION' => $os['VERSION_ID'],
'NAME' => (isset($os['PRETTY_NAME']) ? $os['PRETTY_NAME'] : ucfirst($os['ID']) . ' ' . (isset($os['VERSION']) ? $os['VERSION'] : $os['VERSION_ID']))
);
}
} else {
} else {
throw new ISPConfigOSException('Unknown or unsupported OS.');
}
}
return self::$os_data;
......@@ -99,14 +99,14 @@ class ISPConfigBaseOS {
return $result;
}
protected function addLines($remote_file, $entries, $add_if_existing = false) {
protected function addLines($file, $entries, $add_if_existing = false) {
if(!is_array($entries)) {
$entries = array($entries);
}
$content = '';
if($this->ssh->isFile($remote_file)) {
$content = $this->ssh->getFileContents($remote_file);
if(is_file($file)) {
$content = file_get_contents($file);
}
foreach($entries as $line) {
......@@ -115,28 +115,28 @@ class ISPConfigBaseOS {
}
}
$this->ssh->putFileContents($remote_file, $content);
file_put_contents($file, $content);
return;
}
protected function uncommentLines($remote_file, $entries) {
return $this->commentUncommentLines($remote_file, $entries, true);
protected function uncommentLines($file, $entries, $commenter = '#') {
return $this->commentUncommentLines($file, $entries, true, $commenter);
}
protected function commentLines($remote_file, $entries) {
return $this->commentUncommentLines($remote_file, $entries, false);
protected function commentLines($file, $entries, $commenter = '#') {
return $this->commentUncommentLines($file, $entries, false, $commenter);
}
private function commentUncommentLines($remote_file, $entries, $uncomment = false) {
private function commentUncommentLines($file, $entries, $uncomment = false, $commenter = '#') {
if(!is_array($entries)) {
throw new ISPConfigSSHException('Invalid entries array provided.');
throw new ISPConfigOSException('Invalid entries array provided.');
}
if(!$this->ssh->isFile($remote_file)) {
throw new ISPConfigSSHException('File ' . $remote_file . ' does not exist.');
if(!is_file($file)) {
throw new ISPConfigOSException('File ' . $file . ' does not exist.');
}
$content = $this->ssh->getFileContents($remote_file);
$content = file_get_contents($file);
$active_entry = false;
$lines = explode("\n", $content);
......@@ -150,9 +150,9 @@ class ISPConfigBaseOS {
} elseif(preg_match($active_entry['last_line'], $line)) {
$active_entry = false;
if($uncomment === true) {
$line = preg_replace('/^(\s*)#+/', '$1', $line);
$line = preg_replace('/^(\s*)' . preg_quote($commenter, '/') . '+[ \t]*/', '$1', $line);
} else {
$line = '#' . $line;
$line = $commenter . $line;
}
} elseif(isset($active_entry['search']) && $active_entry['search']) {
if(!is_array($active_entry['search'])) {
......@@ -161,9 +161,9 @@ class ISPConfigBaseOS {
for($i = 0; $i < count($active_entry['search']); $i++) {
if(preg_match($active_entry['search'][$i], $line)) {
if($uncomment === true) {
$line = preg_replace('/^(\s*)#+/', '$1', $line);
$line = preg_replace('/^(\s*)' . preg_quote($commenter, '/') . '+[ \t]/', '$1', $line);
} else {
$line = '#' . $line;
$line = $commenter . $line;
}
break;
}
......@@ -173,13 +173,13 @@ class ISPConfigBaseOS {
for($i = 0; $i < count($entries); $i++) {
$entry = $entries[$i];
if(!isset($entry['first_line'])) {
throw new ISPConfigSSHException('Invalid entry (no last or first line).');
throw new ISPConfigOSException('Invalid entry (no last or first line).');
}
if(preg_match($entry['first_line'], $line)) {
if($uncomment === true) {
$line = preg_replace('/^(\s*)#+/', '$1', $line);
$line = preg_replace('/^(\s*)' . preg_quote($commenter, '/') . '+[ \t]/', '$1', $line);
} else {
$line = '#' . $line;
$line = $commenter . $line;
}
$active_entry = $entry;
break;
......@@ -202,23 +202,31 @@ class ISPConfigBaseOS {
unset($new_lines);
unset($lines);
$this->ssh->cp($remote_file, $remote_file . '~' . strftime('%Y%m%d%H%M%S', time()));
$this->ssh->putFileContents($remote_file, $content);
copy($file, $file . '~' . strftime('%Y%m%d%H%M%S', time()));
file_put_contents($file, $content);
return true;
}
protected function replaceContents($remote_file, $replacements, $add_if_missing = false, $add_to_section = null) {
/**
* @param string $file
* @param array $replacements
* @param boolean $add_if_missing
* @param string $add_to_section
* @return boolean
* @throws ISPConfigOSException
*/
protected function replaceContents($file, $replacements, $add_if_missing = false, $add_to_section = null) {
if(!is_array($replacements)) {
throw new ISPConfigSSHException('Invalid replacement array provided.');
throw new ISPConfigOSException('Invalid replacement array provided.');
}
$content = '';
$matches = array();
if($this->ssh->isFile($remote_file) == false) {
$this->ssh->putFileContents($remote_file, '');
if(is_file($file) == false) {
file_put_contents($file, '');
} else {
$content = $this->ssh->getFileContents($remote_file);
$content = file_get_contents($file);
}
foreach($replacements as $search => $replace) {
......@@ -228,7 +236,7 @@ class ISPConfigBaseOS {
$replace = $replace['replace'];
}
$need_to_add = false;
if(preg_match('/^\/.*\/[igmsuS]+$/', $search)) {
if(preg_match('/^\/.*\/[igmsuS]*$/', $search)) {
if($add_if_missing == true && !preg_match($search, $content)) {
$need_to_add = true;
} else {
......@@ -284,13 +292,16 @@ class ISPConfigBaseOS {
}
}
$this->ssh->cp($remote_file, $remote_file . '~' . strftime('%Y%m%d%H%M%S', time()));
$this->ssh->putFileContents($remote_file, $content);
copy($file, $file . '~' . strftime('%Y%m%d%H%M%S', time()));
file_put_contents($file, $content);
return true;
}
protected function getInstallCommand($packages, $dry_run = false) {
if(is_string($packages)) {
$packages = array($packages);
}
$cmd = $this->getUpdateCommand('install', $dry_run);
$cmd = str_replace('<PACKAGES>', implode(' ', $packages), $cmd);
......@@ -304,7 +315,7 @@ class ISPConfigBaseOS {
protected function installPackages($packages, $dry_run = false) {
$cmd = $this->getInstallCommand($packages, $dry_run);
return $this->exec($cmd, null, 3, array('100'));
return $this->exec($cmd, null, 3);//, array('100'));
}
protected function restartService($service_name) {
......@@ -317,6 +328,16 @@ class ISPConfigBaseOS {
return $this->exec($cmd);
}
protected function isServiceRunning($service_name) {
$cmd = $this->getRestartServiceCommand($service_name, 'status');
$result = $this->exec($cmd);
if($result === false) {
return false;
} else {
return true;
}
}
public function getPackageVersion($package) {
}
......
<?php
/**
* Description of class
*
* @author croydon
*/
class ISPConfigDebian10OS extends ISPConfigDebianOS {
protected function updateMySQLConfig($mysql_root_pw, $dry_run = false) {
ISPConfigLog::info('Writing MySQL config files.', true);
if(!$dry_run) {
$this->replaceContents('/etc/mysql/debian.cnf', array('/^password\s*=.*$/m' => 'password = ' . $mysql_root_pw));
$this->replaceContents('/etc/mysql/mariadb.conf.d/50-server.cnf', array('/^bind-address/m' => '#bind-address'), true, 'mysqld');
}
}
public function getRestartServiceCommand($service, $command = 'restart') {
if($command != 'start' && $command != 'stop' && $command != 'status') {
$command = 'restart';
}
switch($service) {
case 'mysql':
case 'mariadb':
$service = 'mariadb';
break;
case 'pureftpd':
$service = 'pure-ftpd-mysql';
break;
}
return 'systemctl ' . $command . ' ' . escapeshellarg($service) . ' 2>&1';
}
protected function getPackagesToInstall($section) {
if($section === 'mail') {
$packages = parent::getPackagesToInstall($section);
$packages[] = 'p7zip';
$packages[] = 'p7zip-full';
$packages[] = 'unrar';
$packages[] = 'lrzip';
}
return $packages;
}
protected function setDefaultPHP($dry_run) {
ISPConfigLog::info('Settings default system php version.', true);
$cmd = 'update-alternatives --set php /usr/bin/php7.3 ; update-alternatives --set php-cgi /usr/bin/php-cgi7.3';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
}
protected function installPHPMyAdmin($mysql_root_pw, $dry_run) {
ISPConfigLog::info('Installing package phpmyadmin', true);
if(!is_dir('/usr/share/phpmyadmin')) {
mkdir('/usr/share/phpmyadmin', 0755, true);
}
if(!is_dir('/etc/phpmyadmin')) {
mkdir('/etc/phpmyadmin', 0755);
}
if(!is_dir('/var/lib/phpmyadmin/tmp')) {
mkdir('/var/lib/phpmyadmin/tmp', 0777, true);
}
touch('/etc/phpmyadmin/htpasswd.setup');
$cmd = 'chown -R www-data:www-data ' . escapeshellarg('/var/lib/phpmyadmin') . ' ; cd /tmp ; rm -f phpMyAdmin-4.9.0.1-all-languages.tar.gz ; wget "https://files.phpmyadmin.net/phpMyAdmin/4.9.0.1/phpMyAdmin-4.9.0.1-all-languages.tar.gz" 2>/dev/null && tar xfz phpMyAdmin-4.9.0.1-all-languages.tar.gz && mv phpMyAdmin-4.9.0.1-all-languages/* /usr/share/phpmyadmin/ && rm -f phpMyAdmin-4.9.0.1-all-languages.tar.gz && rm -rf phpMyAdmin-4.9.0.1-all-languages';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
copy('/usr/share/phpmyadmin/config.sample.inc.php', '/usr/share/phpmyadmin/config.inc.php');
$replacements = array(
'/^(?:\s*\/\/)?\s*\$cfg\[\'blowfish_secret\'\]\s*=.*$/m' => '$cfg[\'blowfish_secret\'] = \'' . substr(sha1(uniqid('pre', true)), 0, 32) . '\';',
'/^(?:\s*\/\/)?\s*\$cfg\[\'TempDir\'\]\s*=.*$/m' => '$cfg[\'TempDir\'] = \'/var/lib/phpmyadmin/tmp\';'
);
if(!$dry_run) {
$this->replaceContents('/usr/share/phpmyadmin/config.inc.php', $replacements, true);
}
$contents = '# phpMyAdmin default Apache configuration
Alias /phpmyadmin /usr/share/phpmyadmin
<Directory /usr/share/phpmyadmin>
Options FollowSymLinks
DirectoryIndex index.php
<IfModule mod_php7.c>
AddType application/x-httpd-php .php
php_flag magic_quotes_gpc Off
php_flag track_vars On
php_flag register_globals Off
php_value include_path .
</IfModule>
</Directory>
# Authorize for setup
<Directory /usr/share/phpmyadmin/setup>
<IfModule mod_authn_file.c>
AuthType Basic
AuthName "phpMyAdmin Setup"
AuthUserFile /etc/phpmyadmin/htpasswd.setup
</IfModule>
Require valid-user
</Directory>
# Disallow web access to directories that don\'t need it
<Directory /usr/share/phpmyadmin/libraries>
Order Deny,Allow
Deny from All
</Directory>
<Directory /usr/share/phpmyadmin/setup/lib>
Order Deny,Allow
Deny from All
</Directory>';
file_put_contents('/etc/apache2/conf-available/phpmyadmin.conf', $contents);
$cmd = 'a2enconf phpmyadmin';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
$this->restartService('apache2');
$pma_pass = ISPConfigFunctions::generatePassword(15);
$pma_pass_enc = preg_replace('/[\'\\\\]/', '\\$1', $pma_pass);
$queries = array(
'CREATE DATABASE phpmyadmin;',
'CREATE USER \'pma\'@\'localhost\' IDENTIFIED BY \'' . $pma_pass_enc . '\';',
'GRANT ALL PRIVILEGES ON phpmyadmin.* TO \'pma\'@\'localhost\' IDENTIFIED BY \'' . $pma_pass_enc . '\' WITH GRANT OPTION;',
'FLUSH PRIVILEGES;'
);
foreach($queries as $query) {
$cmd = 'mysql --defaults-file=/etc/mysql/debian.cnf -e ' . escapeshellarg($query) . ' 2>&1';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
ISPConfigLog::warn('Query ' . $query . ' failed.', true);
}
}
}
$cmd = 'mysql --defaults-file=/etc/mysql/debian.cnf -D phpmyadmin < /usr/share/phpmyadmin/sql/create_tables.sql';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
ISPConfigLog::warn('Command ' . $cmd . ' failed.', true);
}
}
$uncomment = array(
array(
'first_line' => '/^(?:\s*\/\/)?\s*\$cfg\[\'Servers\'\]\[\$i\]/',
'last_line' => '/####nomatch###/',
'search' => '/^(?:\s*\/\/)?\s*\$cfg\[\'Servers\'\]\[\$i\]/'
)
);
if(!$dry_run) {
$this->uncommentLines('/usr/share/phpmyadmin/config.inc.php', $uncomment, '//');
}
$replacements = array(
'/^(?:\s*\/\/)?\s*(\$cfg\[\'Servers\'\]\[\$i\]\[\'controlhost\'\])\s*=.*$/m' => '$1 = \'localhost\';',
'/^(?:\s*\/\/)?\s*(\$cfg\[\'Servers\'\]\[\$i\]\[\'controlport\'\])\s*=.*$/m' => '$1 = \'\';',
'/^(?:\s*\/\/)?\s*(\$cfg\[\'Servers\'\]\[\$i\]\[\'controluser\'\])\s*=.*$/m' => '$1 = \'pma\';',
'/^(?:\s*\/\/)?\s*(\$cfg\[\'Servers\'\]\[\$i\]\[\'controlpass\'\])\s*=.*$/m' => '$1 = \'' . $pma_pass_enc . '\';',
);
if(!$dry_run) {
$this->replaceContents('/usr/share/phpmyadmin/config.inc.php', $replacements, false);
}
}
}
......@@ -79,7 +79,7 @@ class ISPConfigDebianOS extends ISPConfigBaseOS {
}
public function getRestartServiceCommand($service, $command = 'restart') {
if($command != 'start' && $command != 'stop') {
if($command != 'start' && $command != 'stop' && $command != 'status') {
$command = 'restart';
}
......@@ -95,6 +95,145 @@ class ISPConfigDebianOS extends ISPConfigBaseOS {
return 'service ' . escapeshellarg($service) . ' ' . $command . ' 2>&1';
}
protected function updateMySQLConfig($mysql_root_pw, $dry_run = false) {
ISPConfigLog::info('Writing MySQL config files.', true);
if(!$dry_run) {
$this->replaceContents('/etc/mysql/debian.cnf', array('/^password\s*=.*$/m' => 'password = ' . $mysql_root_pw));
$this->replaceContents('/etc/mysql/mariadb.conf.d/50-server.cnf', array('/^bind-address/m' => '#bind-address', '/^sql-mode\s*=.*?$/m' => 'sql-mode = "NO_ENGINE_SUBSTITUTION"'), true, 'mysqld');
}
}
protected function getPackagesToInstall($section) {
if($section === 'mail') {
$packages = array(
'spamassassin',
'dnsutils',
'rspamd',
'redis-server',
'resolvconf',
'clamav',
'clamav-daemon',
'unzip',
'bzip2',
'arj',
'nomarch',
'lzop',
'cabextract',
'apt-listchanges',
'libnet-ldap-perl',
'libauthen-sasl-perl',
'clamav-docs',
'daemon',
'libio-string-perl',
'libio-socket-ssl-perl',
'libnet-ident-perl',
'zip',
'libnet-dns-perl',
'libdbd-mysql-perl',
'postgrey',
'bind9',
'dnsutils'
);
}
return $packages;
}
protected function getApacheModulesToEnable() {
$modules = array('suexec', 'rewrite', 'ssl', 'actions', 'include', 'dav_fs', 'dav', 'auth_digest', 'cgi', 'headers', 'proxy_fcgi', 'alias');
return $modules;
}
protected function setDefaultPHP($dry_run) {
ISPConfigLog::info('Settings default system php version.', true);
$cmd = 'update-alternatives --set php /usr/bin/php7.0 ; update-alternatives --set php-cgi /usr/bin/php-cgi7.0';
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
}
protected function installPHPMyAdmin($mysql_root_pw, $dry_run) {
$cmd = 'APP_PASS="' . ISPConfigFunctions::generatePassword(15) . '"' . "\n";
$cmd .= 'ROOT_PASS="' . $mysql_root_pw . '"' . "\n";
$cmd .= 'APP_DB_PASS="' . ISPConfigFunctions::generatePassword(15) . '"' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/dbconfig-install boolean true" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/app-password-confirm password $APP_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/admin-user string root" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/admin-pass password $ROOT_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/mysql/app-pass password $APP_DB_PASS" | debconf-set-selections 2>&1' . "\n";
$cmd .= 'echo "phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2" | debconf-set-selections 2>&1' . "\n";
if(!$dry_run) {
$result = $this->exec($cmd);
if($result === false) {
throw new ISPConfigOSException('Command ' . $cmd . ' failed.');
}
}
ISPConfigLog::info('Installing package phpmyadmin', true);
$result = $this->installPackages('phpmyadmin', $dry_run);
if($result !== false) {
ISPConfigLog::info('Installed package phpmyadmin', true);
} else {
throw new ISPConfigOSException('Installing package failed.');
}
}
protected function fixDbconfigCommon() {
ISPConfigLog::info('Fixing dbconfig-common if neccessary');
$replacements = array(
'/_dbc_nodb="yes" dbc_mysql_exec/' => '_dbc_nodb="yes"; dbc_mysql_exec'
);
$this->replaceContents('/usr/share/dbconfig-common/internal/mysql', $replacements, false);
}
protected function setPHPTimezone() {
if(!is_file('/etc/timezone')) {
return;
}
$tz = trim(file_get_contents('/etc/timezone'));