Skip to content
Commits on Source (3)
<?php
/*
Copyright (c) 2007-2019, Till Brehm, projektfarm Gmbh, Hj Ahmad Rasyid Hj Ismail
Copyright (c) 2007-2019, Till Brehm, projektfarm GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
......@@ -2660,15 +2660,53 @@ class installer_base {
}
}
private function curl_request($url, $use_ipv6 = false) {
$set_headers = [
'Connection: Close',
'User-Agent: ISPConfig/3',
'Accept: */*'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, $set_headers);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
if($use_ipv6) {
if(defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V6')) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
}
} else {
if(defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')) {
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
}
}
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
public function make_ispconfig_ssl_cert() {
global $conf, $autoinstall;
//* Get hostname from user entry or shell command */
if($conf['hostname'] !== 'localhost' && $conf['hostname'] !== '') $hostname = $conf['hostname'];
else $hostname = exec('hostname -f');
if($conf['hostname'] !== 'localhost' && $conf['hostname'] !== '') {
$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');
$svr_ip4 = $this->curl_request('https://ispconfig.org/remoteip.php', false);
$svr_ip6 = $this->curl_request('https://ispconfig.org/remoteip.php', true);
if(function_exists('idn_to_ascii')) {
if(defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46') && constant('IDNA_NONTRANSITIONAL_TO_ASCII')) {
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
......@@ -2676,74 +2714,82 @@ class installer_base {
$hostname = idn_to_ascii($hostname);
}
}
$dns_ips = array();
if (checkdnsrr($hostname, 'A')) {
$dnsa=dns_get_record($hostname, DNS_A);
$dns_ips = array();
foreach ($dnsa as $rec) {
$dns_ips[] = $rec['ip'];
if($dnsa) {
foreach ($dnsa as $rec) {
$dns_ips[] = $rec['ip'];
}
}
}
if (checkdnsrr($hostname, 'AAAA')) {
$dnsaaaa=dns_get_record($hostname, DNS_AAAA);
if($dnsaaaa) {
foreach ($dnsaaaa 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)) {
if (!@is_dir($le_live_dir) && (
($svr_ip4 && in_array($svr_ip4, $dns_ips)) || ($svr_ip6 && in_array($svr_ip6, $dns_ips))
)) {
// Set webroot path for all ISPConfig server LE certs
// $webroot_path = $conf['ispconfig_install_dir'].'/interface/acme';
// if (!@is_dir($webroot_path)) $webroot_path = '/var/www/html';
// This script is needed earlier to check and open http port 80 or standalone might fail
// Make executable and temporary symlink latest letsencrypt pre, post and renew hook script before install
if (file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_pre_hook.sh'))
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_pre_hook.sh')) {
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_pre_hook.sh', '/usr/local/bin/letsencrypt_pre_hook.sh');
if (file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_post_hook.sh'))
}
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_post_hook.sh')) {
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_post_hook.sh', '/usr/local/bin/letsencrypt_post_hook.sh');
if (file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_renew_hook.sh'))
}
if(file_exists(dirname(getcwd()) . '/server/scripts/letsencrypt_renew_hook.sh')) {
symlink(dirname(getcwd()) . '/server/scripts/letsencrypt_renew_hook.sh', '/usr/local/bin/letsencrypt_renew_hook.sh');
}
chown('/usr/local/bin/letsencrypt_pre_hook.sh', 'root');
chown('/usr/local/bin/letsencrypt_post_hook.sh', 'root');
chown('/usr/local/bin/letsencrypt_renew_hook.sh', 'root');
chmod('/usr/local/bin/letsencrypt_pre_hook.sh', 0700);
chmod('/usr/local/bin/letsencrypt_post_hook.sh', 0700);
chmod('/usr/local/bin/letsencrypt_renew_hook.sh', 0700);
// Check http port 80 status as it cannot be determined at post hook stage
$port80_status=exec('true &>/dev/null </dev/tcp/127.0.0.1/80 && echo open || echo close');
// Set pre-, post- and renew hook
$pre_hook = "--pre-hook \"letsencrypt_pre_hook.sh\"";
$renew_hook = " --renew-hook \"letsencrypt_renew_hook.sh\"";
if ($port80_status == 'close') {
if($port80_status == 'close') {
$post_hook = " --post-hook \"letsencrypt_post_hook.sh\"";
$hook = $pre_hook . $post_hook . $renew_hook;
}
else
} else {
$hook = $pre_hook . $renew_hook;
}
// 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);
// Check for Neilpang acme.sh as well
$acme = explode("\n", shell_exec('which /usr/local/ispconfig/server/scripts/acme.sh /root/.acme.sh/acme.sh'));
$acme = reset($acme);
// Attempt to use Neilpang acme.sh first, as it is now the preferred LE client
if (is_executable($acme)) {
// If this is a webserver, we use webroot
// if(($conf['nginx']['installed'] || $conf['apache']['installed']) == true)
// exec("$acme --issue -d $hostname --webroot $webroot_path $renew_hook");
if(($conf['nginx']['installed'] || $conf['apache']['installed']) == true) {
if($conf['nginx']['installed'] == true)
exec("$acme --issue --nginx -d $hostname $renew_hook");
else($conf['apache']['installed'] == true)
exec("$acme --issue --apache -d $hostname $renew_hook");
if($conf['nginx']['installed'] == true) {
exec("$acme --issue --nginx -d $hostname $renew_hook");
} elseif($conf['apache']['installed'] == true) {
exec("$acme --issue --apache -d $hostname $renew_hook");
}
// Else, it is not webserver, so we use standalone
else
else {
exec("$acme --issue --standalone -d $hostname $hook");
}
// Define LE certs name and path, then install them
if (!@is_dir($le_live_dir)) mkdir($le_live_dir, 0755, true);
$acme_cert = "--cert-file $le_live_dir/cert.pem";
......@@ -2751,13 +2797,19 @@ class installer_base {
$acme_ca = "--ca-file $le_live_dir/chain.pem";
$acme_chain = "--fullchain-file $le_live_dir/fullchain.pem";
exec("$acme --install-cert -d $hostname $acme_cert $acme_key $acme_ca $acme_chain");
// Else, we attempt to use the official LE certbot client certbot
} else {
// But only if it is otherwise available
if(is_executable($le_client)) {
// Get its version info due to be used for webroot arguement issues
$le_info = exec($le_client . ' --version 2>&1', $ret, $val);
if(preg_match('/^(\S+|\w+)\s+(\d+(\.\d+)+)$/', $le_info, $matches)) {
$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';
......@@ -2770,7 +2822,6 @@ class installer_base {
// Else, it is not webserver, so we use standalone
else
exec("$le_client $certonly $acme_version --standalone --email postmaster@$hostname -d $hostname $hook");
}
}
}
......@@ -2813,46 +2864,46 @@ class installer_base {
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 dhparam2048.pem 2048; ln -sf dhparam2048.pem pure-ftpd-dhparams.pem");
}
exec("chown -R root:root $ssl_dir");
}
......@@ -3275,7 +3326,7 @@ class installer_base {
chmod($install_dir.'/server/scripts/ispconfig_update.sh', 0700);
if(!is_link('/usr/local/bin/ispconfig_update_from_dev.sh')) symlink($install_dir.'/server/scripts/ispconfig_update.sh', '/usr/local/bin/ispconfig_update_from_dev.sh');
if(!is_link('/usr/local/bin/ispconfig_update.sh')) symlink($install_dir.'/server/scripts/ispconfig_update.sh', '/usr/local/bin/ispconfig_update.sh');
// Make executable then unlink and symlink letsencrypt pre, post and renew hook scripts
chown($install_dir.'/server/scripts/letsencrypt_pre_hook.sh', 'root');
chown($install_dir.'/server/scripts/letsencrypt_post_hook.sh', 'root');
......@@ -3289,7 +3340,7 @@ class installer_base {
symlink($install_dir.'/server/scripts/letsencrypt_pre_hook.sh', '/usr/local/bin/letsencrypt_pre_hook.sh');
symlink($install_dir.'/server/scripts/letsencrypt_post_hook.sh', '/usr/local/bin/letsencrypt_post_hook.sh');
symlink($install_dir.'/server/scripts/letsencrypt_renew_hook.sh', '/usr/local/bin/letsencrypt_renew_hook.sh');
//* Make the logs readable for the ispconfig user
if(@is_file('/var/log/mail.log')) exec('chmod +r /var/log/mail.log');
if(@is_file('/var/log/mail.warn')) exec('chmod +r /var/log/mail.warn');
......@@ -3630,5 +3681,3 @@ class installer_base {
}
}
?>