diff --git a/install/install.php b/install/install.php index bb41927b33566f18df0b45a17def9f0648b2dc91..ae0da7e65cd0436a2fe4d30d3985cc6f5d7f564d 100644 --- a/install/install.php +++ b/install/install.php @@ -552,6 +552,12 @@ if($install_mode == 'standard' || strtolower($inst->simple_query('Install ISPCon $inst->install_ispconfig_interface = false; } +// Create SSL certs for non-webserver(s)? +if(!file_exists(/usr/local/ispconfig/interface/ssl/ispserver.crt)) { + if(strtolower($inst->simple_query('Do you want to create SSL certs for your server?', array('y', 'n'), 'y')) == 'y') + $inst->make_ispconfig_ssl_cert(); +} + $inst->raiseEvent('install_ispconfig::before'); $inst->install_ispconfig(); $inst->raiseEvent('install_ispconfig::after'); diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index f20d3fb7d6ab6699cade8cb356047ca02db62e30..1d7db11e9abf21ef6e3396e947ad40504ac5eace 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1,7 +1,7 @@ /dev/null", __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command); } + //** We have to change the permissions of the courier authdaemon directory to make it accessible for maildrop. + $command = 'chmod 755 /var/run/courier/authdaemon/'; + if(is_file('/var/run/courier/authdaemon/')) caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command); if(!stristr($options, 'dont-create-certs')) { //* Create the SSL certificate if(AUTOINSTALL){ @@ -2048,29 +2051,135 @@ class installer_base { } public function make_ispconfig_ssl_cert() { - global $conf,$autoinstall; + global $conf, $autoinstall; + + //* Get hostname from user entry or shell command */ + if($conf['hostname'] !== ('localhost' || '')) $hostname = $conf['hostname']; + else $hostname = exec('hostname -f'); + + // Check dns a record exist and its ip equal to server public ip + $svr_ip = file_get_contents('http://dynamicdns.park-your-domain.com/getip'); + if (checkdnsrr(idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46), 'A')) { + $dnsa=dns_get_record($hostname, DNS_A); + $dns_ips = array(); + foreach ($dnsa as $rec) { + $dns_ips[] = $rec['ip']; + } + } + + // Request for certs if no LE SSL folder for server fqdn exist + $le_live_dir = '/etc/letsencrypt/live/' . $hostname; + if (!@is_dir($le_live_dir) && in_array($svr_ip, $dns_ips)) { + // Get the default LE client name and version + $le_client = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt /opt/eff.org/certbot/venv/bin/certbot')); + $le_client = reset($le_client); + $le_info = exec($le_client . ' --version 2>&1', $ret, $val); + if(preg_match('/^(\S+|\w+)\s+(\d+(\.\d+)+)$/', $le_info, $matches)) { $le_name = $matches[1]; $le_version = $matches[2]; } + + // Define certbot commands + $acme_version = '--server https://acme-v0' . (($le_version >=0.22) ? '2' : '1') . '.api.letsencrypt.org/directory'; + $certonly = 'certonly --agree-tos --non-interactive --expand --rsa-key-size 4096'; + $webroot = '--authenticator webroot --webroot-path /var/www/html'; + $standalone = '--authenticator standalone'; + + // Only certbot is supported to prevent unknown failures + if($le_name == 'certbot' && is_executable($le_client)) { + // If this is a webserver, we use webroot + if(($conf['nginx']['installed'] || $conf['apache']['installed']) == true) { + $well_known = '/var/www/html/.well-known'; + $challenge = "$well_known/acme_challenge"; + $acme_challenge = '/usr/local/ispconfig/interface/acme/.well-known/acme-challenge'; + if (!is_dir($well_known)) mkdir($well_known, 0755, true); + if (!is_dir($challenge)) exec("ln -sf $acme_challenge $challenge"); + exec("$le_client $certonly $acme_version $webroot --email postmaster@$hostname -d $hostname"); + } + // Else, it is not webserver, so we use standalone + else + exec("$le_client $certonly $acme_version $standalone --email postmaster@$hostname -d $hostname"); + } + } + + //* Define and check ISPConfig SSL folder */ $install_dir = $conf['ispconfig_install_dir']; $ssl_crt_file = $install_dir.'/interface/ssl/ispserver.crt'; $ssl_csr_file = $install_dir.'/interface/ssl/ispserver.csr'; $ssl_key_file = $install_dir.'/interface/ssl/ispserver.key'; + $ssl_pem_file = $install_dir.'/interface/ssl/ispserver.pem'; if(!@is_dir($install_dir.'/interface/ssl')) mkdir($install_dir.'/interface/ssl', 0755, true); - $ssl_pw = substr(md5(mt_rand()), 0, 6); - exec("openssl genrsa -des3 -passout pass:$ssl_pw -out $ssl_key_file 4096"); - if(AUTOINSTALL){ - exec("openssl req -new -passin pass:$ssl_pw -passout pass:$ssl_pw -subj '/C=".escapeshellcmd($autoinstall['ssl_cert_country'])."/ST=".escapeshellcmd($autoinstall['ssl_cert_state'])."/L=".escapeshellcmd($autoinstall['ssl_cert_locality'])."/O=".escapeshellcmd($autoinstall['ssl_cert_organisation'])."/OU=".escapeshellcmd($autoinstall['ssl_cert_organisation_unit'])."/CN=".escapeshellcmd($autoinstall['ssl_cert_common_name'])."' -key $ssl_key_file -out $ssl_csr_file"); + $date = new DateTime(); + + // If the LE SSL certs for this hostname exists + if (is_dir($le_live_dir) && in_array($svr_ip, $dns_ips)) { + + // Backup existing ispserver ssl files + if (file_exists($ssl_crt_file)) rename($ssl_crt_file, $ssl_crt_file . '-' .$date->format('YmdHis') . '.bak'); + if (file_exists($ssl_crt_file)) rename($ssl_key_file, $ssl_key_file . '-' .$date->format('YmdHis') . '.bak'); + if (file_exists($ssl_crt_file)) rename($ssl_pem_file, $ssl_pem_file . '-' .$date->format('YmdHis') . '.bak'); + + // Create symlink to LE fullchain and key for ISPConfig + symlink($le_live_dir.'/fullchain.pem', $ssl_crt_file); + symlink($le_live_dir.'/privkey.pem', $ssl_key_file); + } else { - exec("openssl req -new -passin pass:$ssl_pw -passout pass:$ssl_pw -key $ssl_key_file -out $ssl_csr_file"); - } - exec("openssl req -x509 -passin pass:$ssl_pw -passout pass:$ssl_pw -key $ssl_key_file -in $ssl_csr_file -out $ssl_crt_file -days 3650"); - 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'); + // We can still use the old self-signed method + $ssl_pw = substr(md5(mt_rand()), 0, 6); + exec("openssl genrsa -des3 -passout pass:$ssl_pw -out $ssl_key_file 4096"); + if(AUTOINSTALL){ + exec("openssl req -new -passin pass:$ssl_pw -passout pass:$ssl_pw -subj '/C=".escapeshellcmd($autoinstall['ssl_cert_country'])."/ST=".escapeshellcmd($autoinstall['ssl_cert_state'])."/L=".escapeshellcmd($autoinstall['ssl_cert_locality'])."/O=".escapeshellcmd($autoinstall['ssl_cert_organisation'])."/OU=".escapeshellcmd($autoinstall['ssl_cert_organisation_unit'])."/CN=".escapeshellcmd($autoinstall['ssl_cert_common_name'])."' -key $ssl_key_file -out $ssl_csr_file"); + } else { + exec("openssl req -new -passin pass:$ssl_pw -passout pass:$ssl_pw -key $ssl_key_file -out $ssl_csr_file"); + } + exec("openssl req -x509 -passin pass:$ssl_pw -passout pass:$ssl_pw -key $ssl_key_file -in $ssl_csr_file -out $ssl_crt_file -days 3650"); + 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); + } + + // Build ispserver.pem file and chmod it + exec("cat $ssl_key_file $ssl_crt_file > $ssl_pem_file; chmod 600 $ssl_pem_file"); + + // Extend LE SSL certs to postfix + if ($conf['postfix']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig LE SSL certs to postfix?', array('y', 'n'), 'y')) == 'y') { + + // Define folder, file(s) + $cf = $conf['postfix']; + $postfix_dir = $cf['config_dir']; + if(!is_dir($postfix_dir)) $this->error("The postfix configuration directory '$postfix_dir' does not exist."); + $smtpd_crt = $postfix_dir.'/smtpd.cert'; + $smtpd_key = $postfix_dir.'/smtpd.key'; + + // Backup existing postfix ssl files + if (file_exists($smtpd_crt)) rename($smtpd_crt, $smtpd_crt . '-' .$date->format('YmdHis') . '.bak'); + if (file_exists($smtpd_key)) rename($smtpd_key, $smtpd_key . '-' .$date->format('YmdHis') . '.bak'); + + // Create symlink to ISPConfig SSL files + symlink($ssl_crt_file, $smtpd_crt); + symlink($ssl_key_file, $smtpd_key); + } + + // Extend LE SSL certs to pureftpd + if ($conf['pureftpd']['installed'] == true && strtolower($this->simple_query('Symlink ISPConfig LE SSL certs to pureftpd? Creating dhparam file takes some times.', array('y', 'n'), 'y')) == 'y') { + + // Define folder, file(s) + $pureftpd_dir = '/etc/ssl/private'; + if(!is_dir($pureftpd_dir)) mkdir($pureftpd_dir, 0755, true); + $pureftpd_pem = $pureftpd_dir.'/pure-ftpd.pem'; + + // Backup existing pureftpd ssl files + if (file_exists($pureftpd_pem)) rename($pureftpd_pem, $pureftpd_pem . '-' .$date->format('YmdHis') . '.bak'); + + // Create symlink to ISPConfig SSL files + symlink($ssl_pem_file, $pureftpd_pem); + if (!file_exists("$pureftpd_dir/pure-ftpd-dhparams.pem")) + exec("cd $pureftpd_dir; openssl dhparam -out dhparam4096.pem 4096; ln -sf dhparam4096.pem pure-ftpd-dhparams.pem"); + } + + exec("chown -R root:root $install_dir/interface/ssl"); } diff --git a/install/update.php b/install/update.php index 3a51546f04cf0250ab006fa6263bf2aa3a248681..8e5a1ff9327fe9a476e40136334e164e8b4d6125 100644 --- a/install/update.php +++ b/install/update.php @@ -503,6 +503,12 @@ if ($inst->install_ispconfig_interface) { } } +// Create SSL certs for non-webserver(s)? +if(!file_exists(/usr/local/ispconfig/interface/ssl/ispserver.crt)) { + if(strtolower($inst->simple_query('Do you want to create SSL certs for your server?', array('y', 'n'), 'y')) == 'y') + $inst->make_ispconfig_ssl_cert(); +} + $inst->raiseEvent('install_ispconfig::before'); $inst->install_ispconfig(); $inst->raiseEvent('install_ispconfig::after');