diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php index 0a0f85fd..4285f4bc 100644 --- a/actions/admin/settings/130.webserver.php +++ b/actions/admin/settings/130.webserver.php @@ -94,6 +94,15 @@ return array( 'default' => '/var/customers/logs/', 'save_method' => 'storeSettingField', ), + 'system_customersslpath' => array( + 'label' => $lng['serversettings']['customerssl_directory'], + 'settinggroup' => 'system', + 'varname' => 'customer_ssl_path', + 'type' => 'string', + 'string_type' => 'dir', + 'default' => '/etc/apache2/ssl/', + 'save_method' => 'storeSettingField', + ), 'system_phpappendopenbasedir' => array( 'label' => $lng['serversettings']['phpappendopenbasedir'], 'settinggroup' => 'system', diff --git a/customer_domains.php b/customer_domains.php index ae594057..333ed464 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -151,6 +151,15 @@ elseif($page == 'domains') $row['documentroot'] = makeCorrectDir(substr($row['documentroot'], strlen($userinfo['documentroot']))); } + // get ssl-ips if activated + // FIXME for multi-ip later + $show_ssledit = false; + if ($settings['system']['use_ssl'] == '1' + && $row['ssl_ipandport'] != 0 + && $row['caneditdomain'] == '1' + ) { + $show_ssledit = true; + } $row = htmlentities_array($row); eval("\$domains.=\"" . getTemplate("domains/domains_domain") . "\";"); } @@ -634,5 +643,124 @@ elseif($page == 'domains') } } } +elseif ($page == 'domainssleditor') { + + if ($action == '' + || $action == 'view' + ) { + if (isset($_POST['send']) + && $_POST['send'] == 'send' + ) { + + $ssl_cert_file = isset($_POST['ssl_cert_file']) ? $_POST['ssl_cert_file'] : ''; + $ssl_key_file = isset($_POST['ssl_key_file']) ? $_POST['ssl_key_file'] : ''; + $ssl_ca_file = isset($_POST['ssl_ca_file']) ? $_POST['ssl_ca_file'] : ''; + $ssl_cert_chainfile = isset($_POST['ssl_cert_chainfile']) ? $_POST['ssl_cert_chainfile'] : ''; + $do_insert = isset($_POST['do_insert']) ? (($_POST['do_insert'] == 1) ? true : false) : false; + + if ($ssl_cert_file != '' && $ssl_key_file == '') { + standard_error('sslcertificateismissingprivatekey'); + } + + $do_verify = true; + + // no cert-file given -> forget everything + if ($ssl_cert_file == '') { + $ssl_key_file = ''; + $ssl_ca_file = ''; + $ssl_cert_chainfile = ''; + $do_verify = false; + } + + // verify certificate content + if ($do_verify) { + // array openssl_x509_parse ( mixed $x509cert [, bool $shortnames = true ] ) + // openssl_x509_parse() returns information about the supplied x509cert, including fields such as + // subject name, issuer name, purposes, valid from and valid to dates etc. + $cert_content = openssl_x509_parse($ssl_cert_file); + + if (is_array($cert_content) + && isset($cert_content['subject']) + && isset($cert_content['subject']['CN']) + ) { + // TODO self-signed certs might differ and don't need/want this + /* + $domain = $db->query_first("SELECT * FROM `".TABLE_PANEL_DOMAINS."` WHERE `id`='".(int)$id."'"); + if (strtolower($cert_content['subject']['CN']) != strtolower($idna_convert->decode($domain['domain']))) { + standard_error('sslcertificatewrongdomain'); + } + */ + + // bool openssl_x509_check_private_key ( mixed $cert , mixed $key ) + // Checks whether the given key is the private key that corresponds to cert. + if (openssl_x509_check_private_key($ssl_cert_file, $ssl_key_file) === false) { + standard_error('sslcertificateinvalidcertkeypair'); + } + + // check optional stuff + if ($ssl_ca_file != '') { + $ca_content = openssl_x509_parse($ssl_ca_file); + if (!is_array($ca_content)) { + // invalid + standard_error('sslcertificateinvalidca'); + } + } + if ($ssl_cert_chainfile != '') { + $chain_content = openssl_x509_parse($ssl_cert_chainfile); + if (!is_array($chain_content)) { + // invalid + standard_error('sslcertificateinvalidchain'); + } + } + } else { + standard_error('sslcertificateinvalidcert'); + } + } + + // Add/Update database entry + $qrystart = "UPDATE "; + $qrywhere = "WHERE "; + if ($do_insert) { + $qrystart = "INSERT INTO "; + $qrywhere = ", "; + } + $db->query($qrystart." `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` SET + `ssl_cert_file` = '".$db->escape($ssl_cert_file)."', + `ssl_key_file` = '".$db->escape($ssl_key_file)."', + `ssl_ca_file` = '".$db->escape($ssl_ca_file)."', + `ssl_cert_chainfile` = '".$db->escape($ssl_cert_chainfile)."' + ".$qrywhere." `domainid`='".(int)$id."';" + ); + + // back to domain overview + redirectTo($filename, array('page' => 'domains', 's' => $s)); + } + + $result = $db->query_first("SELECT * FROM `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` + WHERE `domainid`='".(int)$id."';" + ); + + $do_insert = false; + // if no entry can be found, behave like we have empty values + if (!is_array($result) || !isset($result['ssl_cert_file'])) { + $result = array( + 'ssl_cert_file' => '', + 'ssl_key_file' => '', + 'ssl_ca_file' => '', + 'ssl_cert_chainfile' => '' + ); + $do_insert = true; + } + + $result = htmlentities_array($result); + + $ssleditor_data = include_once dirname(__FILE__).'/lib/formfields/customer/domains/formfield.domain_ssleditor.php'; + $ssleditor_form = htmlform::genHTMLForm($ssleditor_data); + + $title = $ssleditor_data['domain_ssleditor']['title']; + $image = $ssleditor_data['domain_ssleditor']['image']; + + eval("echo \"" . getTemplate("domains/domain_ssleditor") . "\";"); + } +} -?> diff --git a/install/froxlor.sql b/install/froxlor.sql index fac01608..76337d89 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -512,6 +512,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'documentroot_use_default_value', '0'), ('system', 'passwordcryptfunc', '1'), ('system', 'axfrservers', ''), + ('system', 'customer_ssl_path', '/etc/apache2/ssl/'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin@SERVERNAME'), ('panel', 'phpmyadmin_url', ''), @@ -539,7 +540,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'phpconfigs_hidestdsubdomain', '0'), ('panel', 'allow_theme_change_admin', '1'), ('panel', 'allow_theme_change_customer', '1'), - ('panel', 'version', '0.9.29-dev3'); + ('panel', 'version', '0.9.29-dev4'); @@ -917,3 +918,13 @@ CREATE TABLE IF NOT EXISTS `domain_docrootsettings` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; +DROP TABLE IF EXISTS `domain_ssl_settings`; +CREATE TABLE IF NOT EXISTS `domain_ssl_settings` ( + `id` int(5) NOT NULL auto_increment, + `domainid` int(11) NOT NULL, + `ssl_cert_file` text NOT NULL, + `ssl_key_file` text NOT NULL, + `ssl_ca_file` text NOT NULL, + `ssl_cert_chainfile` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 12984dd9..c1796c9b 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -2109,3 +2109,24 @@ if (isFroxlorVersion('0.9.29-dev2')) { updateToVersion('0.9.29-dev3'); } + +if (isFroxlorVersion('0.9.29-dev3')) { + showUpdateStep("Updating from 0.9.29-dev3 to 0.9.29-dev4", true); + lastStepStatus(0); + + showUpdateStep("Adding new tables to database"); + $db->query("CREATE TABLE IF NOT EXISTS `domain_ssl_settings` ( + `id` int(5) NOT NULL auto_increment, + `domainid` int(11) NOT NULL, + `ssl_cert_file` text NOT NULL, + `ssl_key_file` text NOT NULL, + `ssl_ca_file` text NOT NULL, + `ssl_cert_chainfile` text NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;"); + lastStepStatus(0); + + $system_customersslpath = isset($_POST['system_customersslpath']) ? makeCorrectDir($_POST['system_customersslpath']) : '/etc/apache2/ssl/'; + $db->query("INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'customer_ssl_path', '".$db->escape($system_customersslpath)."');"); + updateToVersion('0.9.29-dev4'); +} diff --git a/install/updates/preconfig.php b/install/updates/preconfig.php index cd997652..39f5930e 100644 --- a/install/updates/preconfig.php +++ b/install/updates/preconfig.php @@ -52,4 +52,3 @@ function versionInUpdate($current_version, $version_to_check) return (version_compare2($current_version, $version_to_check) == -1 ? true : false); } - diff --git a/install/updates/preconfig/0.9/preconfig_0.9.inc.php b/install/updates/preconfig/0.9/preconfig_0.9.inc.php index 82312eac..d1fcada3 100644 --- a/install/updates/preconfig/0.9/preconfig_0.9.inc.php +++ b/install/updates/preconfig/0.9/preconfig_0.9.inc.php @@ -533,4 +533,12 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version) $question.= ''; eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";"); } + + if (versionInUpdate($current_version, '0.9.29-dev4')) { + $has_preconfig = true; + $description = 'As customers can now specify ssl-certificate data for their domains, you need to specify where the generated files are stored
'; + $question = 'Specify the directory for customer ssl-certificates: '; + $question.= ''; + eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";"); + } } diff --git a/lib/formfields/customer/domains/formfield.domain_ssleditor.php b/lib/formfields/customer/domains/formfield.domain_ssleditor.php new file mode 100644 index 00000000..3788b18a --- /dev/null +++ b/lib/formfields/customer/domains/formfield.domain_ssleditor.php @@ -0,0 +1,67 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Formfields + * + */ + +return array( + 'domain_ssleditor' => array( + 'title' => $lng['panel']['ssleditor'], + 'image' => 'icons/ssl.png', + 'sections' => array( + 'section_a' => array( + 'title' => 'SSL certificates', + 'image' => 'icons/ssl.png', + 'fields' => array( + 'ssl_cert_file' => array( + 'style' => 'vertical-align:top;', + 'label' => $lng['admin']['ipsandports']['ssl_cert_file_content'], + 'desc' => $lng['admin']['ipsandports']['ssl_paste_description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12, + 'value' => $result['ssl_cert_file'] + ), + 'ssl_key_file' => array( + 'style' => 'vertical-align:top;', + 'label' => $lng['admin']['ipsandports']['ssl_key_file_content'], + 'desc' => $lng['admin']['ipsandports']['ssl_paste_description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12, + 'value' => $result['ssl_key_file'] + ), + 'ssl_ca_file' => array( + 'style' => 'vertical-align:top;', + 'label' => $lng['admin']['ipsandports']['ssl_ca_file_content'], + 'desc' => $lng['admin']['ipsandports']['ssl_paste_description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12, + 'value' => $result['ssl_ca_file'] + ), + 'ssl_cert_chainfile' => array( + 'style' => 'vertical-align:top;', + 'label' => $lng['admin']['ipsandports']['ssl_cert_chainfile_content'], + 'desc' => $lng['admin']['ipsandports']['ssl_paste_description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12, + 'value' => $result['ssl_cert_chainfile'] + ) + ) + ) + ) + ) +); diff --git a/lib/tables.inc.php b/lib/tables.inc.php index 7e7601a9..f8c59f2c 100644 --- a/lib/tables.inc.php +++ b/lib/tables.inc.php @@ -54,6 +54,7 @@ define('TABLE_PANEL_REDIRECTCODES', 'redirect_codes'); define('TABLE_PANEL_DOMAINREDIRECTS', 'domain_redirect_codes'); define('TABLE_PANEL_IPDOCROOTSETTINGS', 'ipsandports_docrootsettings'); define('TABLE_PANEL_DOMDOCROOTSETTINGS', 'domain_docrootsettings'); +define('TABLE_PANEL_DOMAIN_SSL_SETTINGS', 'domain_ssl_settings'); // APS constants @@ -73,6 +74,6 @@ define('PACKAGE_ENABLED', 2); // VERSION INFO -$version = '0.9.29-dev3'; +$version = '0.9.29-dev4'; $dbversion = '2'; $branding = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 9fb857ea..29cbd151 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1942,3 +1942,17 @@ $lng['serversettings']['panel_allow_theme_change_admin'] = 'Allow admins to chan $lng['serversettings']['panel_allow_theme_change_customer'] = 'Allow customers to change the theme'; $lng['serversettings']['axfrservers']['title'] = 'AXFR servers'; $lng['serversettings']['axfrservers']['description'] = 'A comma separated list of IP addresses allowed to transfer (AXFR) dns zones.'; +$lng['panel']['ssleditor'] = 'SSL settings for this domain'; +$lng['admin']['ipsandports']['ssl_paste_description'] = 'Paste your complete certificate content in the textbox'; +$lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Content of the ssl certificate'; +$lng['admin']['ipsandports']['ssl_key_file_content'] = 'Content of the ssl (private-) key file'; +$lng['admin']['ipsandports']['ssl_ca_file_content'] = 'Content of the ssl CA file (optional)'; +$lng['admin']['ipsandports']['ssl_cert_chainfile_content'] = 'Content of the certificate chainfile (optional)'; +$lng['error']['sslcertificateismissingprivatekey'] = 'You need to specify a private key for your certificate'; +$lng['error']['sslcertificatewrongdomain'] = 'The given certificate does not belong to this domain'; +$lng['error']['sslcertificateinvalidcert'] = 'The given certificate-content does not seem to be a valid certificate'; +$lng['error']['sslcertificateinvalidcertkeypair'] = 'The given private-key does not belong to the given certificate'; +$lng['error']['sslcertificateinvalidca'] = 'The given CA certificate data does not seem to be a valid certificate'; +$lng['error']['sslcertificateinvalidchain'] = 'The given certificate chain data does not seem to be a valid certificate'; +$lng['serversettings']['customerssl_directory']['title'] = 'Webserver customer-ssl certificates-directory'; +$lng['serversettings']['customerssl_directory']['description'] = 'Where should customer-specified ssl-certificates be created?'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 5d1ec026..3734feef 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1663,3 +1663,17 @@ $lng['serversettings']['panel_allow_theme_change_admin'] = 'Erlaube Admins das T $lng['serversettings']['panel_allow_theme_change_customer'] = 'Erlaube Kunden das Theme zu wechseln'; $lng['serversettings']['axfrservers']['title'] = 'AXFR Server'; $lng['serversettings']['axfrservers']['description'] = 'Eine komma-getrennte Liste von IP Adressen, die DNS Zonen transferieren dürfen (AXFR).'; +$lng['panel']['ssleditor'] = 'SSL Einstellungen für diese Domain'; +$lng['admin']['ipsandports']['ssl_paste_description'] = 'Bitte den Inhalt der Zertifikatsdatei in das Textfeld kopieren'; +$lng['admin']['ipsandports']['ssl_cert_file_content'] = 'Inhalt des SSL Zertifikats'; +$lng['admin']['ipsandports']['ssl_key_file_content'] = 'Inhalt der Key-Datei (private key)'; +$lng['admin']['ipsandports']['ssl_ca_file_content'] = 'Inhalt der SSL CA Datei (optional)'; +$lng['admin']['ipsandports']['ssl_cert_chainfile_content'] = 'Inhalt des Zertifikats-chainfile (optional)'; +$lng['error']['sslcertificateismissingprivatekey'] = 'Für das Zertifikat muss eine Key-Datei (private key) angegeben werden'; +$lng['error']['sslcertificatewrongdomain'] = 'Das angegebene Zertifikat gilt nicht für die gewählte Domain'; +$lng['error']['sslcertificateinvalidcert'] = 'Der angegebene Zertifikatsinhalt scheint kein gültiges Zertifikat zu sein'; +$lng['error']['sslcertificateinvalidcertkeypair'] = 'Der angegebene Key (private-key) gehört nicht zum angegebenen Zertifikat'; +$lng['error']['sslcertificateinvalidca'] = 'Die angegebenen CA Zertifikatsdaten scheinen kein gültiges Zertifikat zu sein'; +$lng['error']['sslcertificateinvalidchain'] = 'Die angegebenen Zertifikats-Chain-Daten scheinen kein gültiges Zertifikat zu sein'; +$lng['serversettings']['customerssl_directory']['title'] = 'Webserver Kunden-SSL Zertifikats-Verzeichnis'; +$lng['serversettings']['customerssl_directory']['description'] = 'Wo sollen kundenspezifizierte SSL Zertifikate erstellt werden?'; diff --git a/templates/Froxlor/assets/img/icons/ssl.png b/templates/Froxlor/assets/img/icons/ssl.png new file mode 100644 index 00000000..a54e26d3 Binary files /dev/null and b/templates/Froxlor/assets/img/icons/ssl.png differ diff --git a/templates/Froxlor/customer/domains/domain_ssleditor.tpl b/templates/Froxlor/customer/domains/domain_ssleditor.tpl new file mode 100644 index 00000000..d72bfada --- /dev/null +++ b/templates/Froxlor/customer/domains/domain_ssleditor.tpl @@ -0,0 +1,34 @@ +$header +
+
+

+ {$title}  + {$title} +

+
+ +
+ +
+
+ Froxlor - {$title} + + + {$ssleditor_form} +
+ +

+ + + + + + + + +

+
+
+
+
+$footer diff --git a/templates/Froxlor/customer/domains/domains_domain.tpl b/templates/Froxlor/customer/domains/domains_domain.tpl index 8899e07a..b5c3c737 100644 --- a/templates/Froxlor/customer/domains/domains_domain.tpl +++ b/templates/Froxlor/customer/domains/domains_domain.tpl @@ -15,6 +15,11 @@ {$lng['panel']['delete']}   + + + {$lng['panel']['ssleditor']} +   + ({$lng['domains']['isassigneddomain']})