adding vhosts table + show expired certificates

This commit is contained in:
Benjamin Sonntag 2015-02-13 17:00:22 +01:00
parent d4306ac54b
commit 999913dbdb
12 changed files with 245 additions and 32 deletions

View File

@ -14,9 +14,6 @@ case "$1" in
echo "Installing mysql table"
mysql --defaults-file=/etc/alternc/my.cnf -f < /usr/share/alternc/install/ssl.sql || true
# Create default quota "ssl" with value 0
mysql --defaults-file=/etc/alternc/my.cnf -fBse "INSERT INTO defquotas VALUES ('ssl', 0, 'default')" || true
echo "installing required apache modules"
a2enmod ssl

View File

@ -5,19 +5,28 @@ MENUFILE="/etc/alternc/menulist.txt"
case "$1" in
remove)
alternc.install || true # don't fail removal if alternc.install bails out
# TODO : we don't purge *-ssl vhosts or *-ssl templates, they may break the hosting ...
if [ -e "$CONFIGFILE" -a -x "/usr/bin/mysql" ]; then
mysql --defaults-file=${CONFIGFILE} -f -e "DELETE FROM domaines_type WHERE name IN ('vhost-ssl','vhost-mixssl','roundcube-ssl','squirrelmail-ssl','panel-ssl','php52-ssl','php52-mixssl');"
mysql --defaults-file=${CONFIGFILE} -f -e "UPDATE sub_domaines SET web_action='DELETE' WHERE type IN ('vhost-ssl','vhost-mixssl','roundcube-ssl','squirrelmail-ssl','panel-ssl','php52-ssl','php52-mixssl');"
fi
echo -e "\033[31m**********************************************"
echo "* *"
echo "* ALTERNC-SSL ACTION REQUESTED *"
echo "* *"
echo "* Please run alternc.install to fully remove *"
echo "* *"
echo "**********************************************"
echo -e "\033[0m"
;;
purge)
# Purge the certificate and alias table:
if [ -e "$CONFIGFILE" -a -x "/usr/bin/mysql" ]; then
mysql --defaults-file=${CONFIGFILE} -f -e "DROP TABLE IF EXISTS certificate;"
mysql --defaults-file=${CONFIGFILE} -f -e "DROP TABLE IF EXISTS certif_alias;"
mysql --defaults-file=${CONFIGFILE} -f -e "DROP TABLE IF EXISTS certif_hosts;"
fi
;;
esac

View File

@ -19,6 +19,7 @@
install:
install -m 0644 -g root -o root ssl.sql $(DESTDIR)/usr/share/alternc/install/
install -m 0755 -g root -o root alternc-ssl.install.php $(DESTDIR)/usr/lib/alternc/install.d/alternc-ssl
install -m 0644 -g root -o root README.txt $(DESTDIR)/var/lib/alternc/ssl/private/
# incron
install -m 0755 -g root -o root ssl_alias_manager.sh $(DESTDIR)/usr/lib/alternc/

4
ssl/README.txt Normal file
View File

@ -0,0 +1,4 @@
This folder will contains the SSL certificates,
chained certificates and private keys of VHOSTS
used by Apache to serve HTTPS pages.

View File

@ -63,7 +63,7 @@ if ($argv[1] == "before-reload") {
} else {
$found = false;
while ($s = fgets($f, 1024)) {
if (preg_match("#NameVirtualHost.*443#", $s)) {
if (preg_match(":[^#]*NameVirtualHost.*443:", $s)) {
$found = true;
break;
}

View File

@ -20,6 +20,11 @@
// Bootstrap
require_once("/usr/share/alternc/panel/class/config_nochk.php");
if (!isset($ssl)) {
echo "OUPS: hosting_vhost-ssl.sh launched, but ssl module not installed, exiting\n";
exit();
}
if (!isset($argv[1])) {
echo "FATAL: must be launched from functions_hosting.sh !\n";
exit();

View File

@ -0,0 +1,48 @@
<?php
/*
----------------------------------------------------------------------
AlternC - Web Hosting System
Copyright (C) 2002 by the AlternC Development Team.
http://alternc.org/
----------------------------------------------------------------------
LICENSE
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: Benjamin Sonntag
Purpose of file: DELETE an ssl certificate
----------------------------------------------------------------------
*/
require_once("../class/config.php");
$fields = array(
"id" => array("post", "integer", ""),
"delete" => array("post", "string", ""),
"confirm" => array("post", "string", ""),
);
getFields($fields);
if (!isset($delete)) {
require_once("ssl_list.php");
exit();
}
$ok = $ssl->del_certificate($id);
if ($ok) $info=_("Your SSL Certificate has been deleted");
$error = $err->errstr();
require_once("ssl_list.php");

View File

@ -30,9 +30,15 @@ $fields = array(
"id" => array("post", "integer", ""),
"crt" => array("post", "string", ""),
"chain" => array("post", "string", ""),
"delete" => array("post","string",""),
);
getFields($fields);
if ($delete!="") {
require_once("ssl_delete.php");
exit();
}
$cert = $ssl->finalize($id, $crt, $chain);
$error = $err->errstr();

View File

@ -50,9 +50,15 @@ if (!$error)
$astatus = array(
$ssl::STATUS_PENDING => _("Pending Certificate"),
$ssl::STATUS_OK => _("Valid"),
$ssl::STATUS_EXPIRED => ("Expired"),
$ssl::STATUS_EXPIRED => "<span style=\"color: red; font-weight:bold\">" . _("Expired") . "</span>",
);
$vhosts = $ssl->get_vhosts();
foreach ($vhosts as $v) {
if ($v["certif"] == 0) {
$info=_("Some of your hosting are using a <b>self-signed</b> certificate. <br>Your browser will not let you surf those domains properly<br>To fix this, buy a properly signed certificate")."<br>".$info;
}
}
include_once("head.php");
if ($error) {
@ -76,7 +82,7 @@ if ($info) {
<input type="submit" name="go" value="<?php __("Filter"); ?>"/>
</form>
<table class="tlist">
<tr><th></th><th><?php __("FQDN"); ?></th><th><?php __("Status"); ?></th><th><?php __("Valid From"); ?></th><th><?php __("Valid Until"); ?></th></tr>
<tr><th></th><th><?php __("Domain Name"); ?></th><th><?php __("Status"); ?></th><th><?php __("Validity period"); ?></th><th><?php __("Used by"); ?></th></tr>
<?php
reset($r);
while (list($key, $val) = each($r)) {
@ -85,26 +91,54 @@ if ($info) {
<td><div class="ina edit"><a href="ssl_view.php?id=<?php echo $val["id"] ?>"><?php __("Details"); ?></a></div></td>
<td><?php echo $val["fqdn"]; ?></td>
<td><?php echo $astatus[$val["status"]];
if ($val["shared"])
echo " <i>" . _("(shared)") . "</i>";
?></td>
<td><?php
echo $astatus[$val["status"]];
if ($val["shared"])
echo " <i>" . _("(shared)") . "</i>";
?></td>
<?php
if ($val["status"] != $ssl::STATUS_PENDING) {
?>
<td><?php echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validstartts"])); ?></td>
<td><?php echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validendts"])); ?></td>
<?php } else { ?>
<td><?php __("Requested on: "); ?></td>
<td><?php echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validstartts"])); ?></td>
<?php } ?>
<td><?php echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validstartts"])); ?><br>
<?php
if ($val["validendts"] < (time() + 86400 * 31))
echo "<span style=\"color: red; font-weight:bold\">";
echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validendts"]));
if ($val["validendts"] < (time() + 86400 * 31))
echo "</span>";
?></td>
<?php } else { ?>
<td><?php __("Requested on: "); ?><br>
<?php echo format_date(_('%3$d-%2$d-%1$d %4$d:%5$d'), date("Y-m-d H:i:s", $val["validstartts"])); ?></td>
<?php } ?>
<td><?php
foreach ($vhosts as $v) {
if ($v["certif"] == $val["id"]) {
$v["fqdn"] = (($v["sub"]) ? ($v["sub"] . ".") : "") . $v["domaine"];
echo "<a href=\"dom_edit.php?domain=" . $v["domaine"] . "\">" . $v["fqdn"] . "</a><br>\n";
}
}
?></td>
</tr>
<?php
}
?>
<?php
}
// Now we enumerate self-signed certificates
foreach ($vhosts as $v) {
if ($v["certif"] == 0) {
$v["fqdn"] = (($v["sub"]) ? ($v["sub"] . ".") : "") . $v["domaine"];
echo "<tr><td><div class=\"ina add\"><a href=\"ssl_new.php?fqdn=" . $v["fqdn"] . "\">" . _("Create one") . "</a></div></td>";
echo "<td colspan=\"3\"><span style=\"color: red; font-weight:bold\">" . _("This hosting has no valid certificate<br>a self-signed one has been created") . "</span></td>";
echo "<td><a href=\"dom_edit.php?domain=" . $v["domaine"] . "\">" . $v["fqdn"] . "</a></td>";
echo "</tr>";
}
}
?>
</table>
<p>&nbsp;</p>
<p>
<span class="inb add"><a href="ssl_new.php"><?php __("Create or Import a new SSL Certificate"); ?></a></span>
</p>
<?php include_once("foot.php"); ?>

View File

@ -81,6 +81,10 @@ if ($cert["status"] == $ssl::STATUS_PENDING) {
<p>
<input type="submit" class="inb ok" name="submit" value="<?php __("Save"); ?>"/> &nbsp;
<input type="button" class="inb cancel" name="cancel" value="<?php __("Cancel"); ?>" onclick="document.location = 'ssl_list.php'"/>
</p><p>
<input type="submit" class="inb delete" name="delete" value="<?php __("Delete"); ?>" onclick="return confirm('<?php
echo addslashes(_("Please confirm that you want to delete this certificate request AND ITS PRIVATE KEY!"));
?>');"/>
</p>
</form>
@ -103,7 +107,9 @@ if ($cert["status"] == $ssl::STATUS_PENDING) {
<?php
}
?>
<p>
<form method="post" action="ssl_finalize.php" name="main" id="main">
<input type="hidden" name="id" id="id" value="<?php echo $cert["id"]; ?>"/>
<p>
<span class="inb ok"><a href="ssl_list.php"><?php __("Back to my SSL Certificates"); ?></a></span>
</p>
<table border="1" cellspacing="0" cellpadding="4" class="tedit">
@ -201,8 +207,20 @@ if ($cert["status"] == $ssl::STATUS_PENDING) {
}
}
}
if ($cert["uid"] == $cuid) {
?>
<p>
<input type="submit" class="inb delete" name="delete" value="<?php __("Delete"); ?>" onclick="return confirm('<?php
echo addslashes(_("Please confirm that you want to delete this certificate AND ITS PRIVATE KEY!"));
?>');"/>
</p>
<?php
}
}
} // pending or OK ?
?>
<?php include_once("foot.php"); ?>

View File

@ -44,7 +44,7 @@ class m_ssl {
const FILTER_SHARED = 8;
const SSL_INCRON_FILE = "/var/run/alternc/ssl/generate_certif_alias";
var $myDomainesTypes = array("vhost-ssl", "vhost-mixssl", "panel-ssl", "roundcube-ssl", "squirrelmail-ssl","php52-ssl","php52-mixssl");
var $myDomainesTypes = array("vhost-ssl", "vhost-mixssl", "panel-ssl", "roundcube-ssl", "squirrelmail-ssl", "php52-ssl", "php52-mixssl");
const KEY_REPOSITORY = "/var/lib/alternc/ssl/private";
@ -109,6 +109,8 @@ class m_ssl {
function get_list(&$filter = null) {
global $db, $err, $cuid;
$err->log("ssl", "get_list");
// Expire expired certificates:
$db->query("UPDATE certificates SET status=".self::STATUS_EXPIRED." WHERE status=".self::STATUS_OK." AND validend<NOW();");
$r = array();
// If we have no filter, we filter by default on pending and ok certificates if there is more than 10 of them for the same user.
if (is_null($filter)) {
@ -152,6 +154,29 @@ class m_ssl {
}
}
// -----------------------------------------------------------------
/** Return all the Vhosts of this user using SSL certificates
* @return array all the ssl certificate and hosts of this user
*/
function get_vhosts() {
global $db, $err, $cuid;
$err->log("ssl", "get_vhosts");
$r=array();
$db->query("SELECT ch.*, UNIX_TIMESTAMP(c.validstart) AS validstartts, UNIX_TIMESTAMP(c.validend) AS validendts, sd.domaine, sd.sub "
. "FROM certif_hosts ch LEFT JOIN certificates c ON ch.certif=c.id "
. ", sub_domaines sd WHERE sd.id=ch.sub AND ch.uid=$cuid "
. "ORDER BY sd.domaine, sd.sub;");
if ($db->num_rows()) {
while ($db->next_record()) {
$r[] = $db->Record;
}
return $r;
} else {
$err->raise("ssl", _("You currently have no hosting using SSL certificate"));
return array();
}
}
// -----------------------------------------------------------------
/** Generate a new CSR, a new Private RSA Key, for FQDN.
* @param $fqdn string the FQDN of the domain name for which we want a CSR.
@ -212,6 +237,27 @@ class m_ssl {
return $db->Record;
}
// -----------------------------------------------------------------
/** Delete a Certificate for the current user.
* @return boolean TRUE if the certificate has been deleted successfully.
*/
function del_certificate($id) {
global $db, $err, $cuid;
$err->log("ssl", "del_certificate");
$id = intval($id);
$db->query("SELECT * FROM certificates WHERE uid='$cuid' AND id='$id';");
if (!$db->next_record()) {
$err->raise("ssl", _("Can't find this Certifcate"));
return false;
}
$fqdn = $db->Record["fqdn"];
$altnames = $db->Record["altnames"];
$db->query("DELETE FROM certificates WHERE uid='$cuid' AND id='$id';");
// Update any existing VHOST using this cert/key
$this->updateTrigger($fqdn, $altnames);
return true;
}
// -----------------------------------------------------------------
/** Share (or unshare) an ssl certificate
* @param $id integer the id of the certificate in the table.
@ -229,7 +275,7 @@ class m_ssl {
}
if ($action) {
$action = 1;
$this->updateTrigger($db->Record["fqdn"],$db->Record["altnames"]);
$this->updateTrigger($db->Record["fqdn"], $db->Record["altnames"]);
} else {
$action = 0;
}
@ -307,7 +353,7 @@ class m_ssl {
$err->raise("ssl", _("Can't save the Key/Crt/Chain now. Please try later."));
return false;
}
$this->updateTrigger($fqdn,$altnames);
$this->updateTrigger($fqdn, $altnames);
return $id;
}
@ -344,7 +390,7 @@ class m_ssl {
$err->raise("ssl", _("Can't save the Crt/Chain now. Please try later."));
return false;
}
$this->updateTrigger($fqdn,$altnames);
$this->updateTrigger($fqdn, $altnames);
return $certid;
}
@ -434,10 +480,17 @@ class m_ssl {
// Save crt/key/chain into KEY_REPOSITORY
$CRTDIR = self::KEY_REPOSITORY . "/" . $subdom["compte"];
@mkdir($CRTDIR);
file_put_contents($CRTDIR . "/" . $fqdn . ".crt", $cert["sslcrt"]);
file_put_contents($CRTDIR . "/" . $fqdn . ".key", $cert["sslkey"]);
if (isset($cert["sslchain"]) && $cert["sslchain"]) {
file_put_contents($CRTDIR . "/" . $fqdn . ".chain", $cert["sslchain"]);
// Don't *overwrite* existing self-signed certificates in KEY_REPOSITORY
if (isset($cert["selfsigned"]) &&
file_exists($CRTDIR . "/" . $fqdn . ".crt") &&
file_exists($CRTDIR . "/" . $fqdn . ".key")) {
echo "Self-Signed certificate reused...\n";
} else {
file_put_contents($CRTDIR . "/" . $fqdn . ".crt", $cert["sslcrt"]);
file_put_contents($CRTDIR . "/" . $fqdn . ".key", $cert["sslkey"]);
if (isset($cert["sslchain"]) && $cert["sslchain"]) {
file_put_contents($CRTDIR . "/" . $fqdn . ".chain", $cert["sslchain"]);
}
}
// edit apache conf file to set the certificate:
$s = file_get_contents($TARGET_FILE);
@ -449,7 +502,35 @@ class m_ssl {
$s = str_replace("%%CHAINLINE%%", "", $s);
}
file_put_contents($TARGET_FILE, $s);
// Edit certif_hosts:
$db->query("DELETE FROM certif_hosts WHERE sub=" . $subdom["id"] . ";");
$db->query("INSERT INTO certif_hosts SET "
. "sub=" . intval($subdom["id"]) . ", "
. "certif=" . intval($cert["id"]) . ", "
. "uid=" . intval($subdom["compte"]) . ";");
} // action==create
if ($action == "delete") {
$err->log("ssl", "update_domain:DELETE($action,$type,$fqdn)");
$offset = 0;
$found = false;
do { // try each subdomain (strtok-style) and search them in sub_domaines table:
$db->query("SELECT * FROM sub_domaines WHERE "
. "sub='" . substr($fqdn, 0, $offset) . "' AND domaine='" . substr($fqdn, $offset + ($offset != 0)) . "' "
. "AND web_action NOT IN ('','OK') AND type='" . $type . "';");
if ($db->next_record()) {
$found = true;
break;
}
$offset = strpos($fqdn, ".", $offset);
} while (true);
if (!$found) {
echo "FATAL: didn't found fqdn $fqdn in sub_domaines table !\n";
return;
}
// found and $db point to it:
$subdom = $db->Record;
$db->query("DELETE FROM certif_hosts WHERE sub=" . $subdom["id"] . ";");
}
}
// ----------------------------------------------------------------
@ -709,7 +790,8 @@ class m_ssl {
openssl_x509_export($crt, $crtout);
return array("id" => 0, "status" => 1, "shared" => 0, "fqdn" => $fqdn, "altnames" => "",
"validstart" => date("Y-m-d H:i:s"), "validend" => date("Y-m-d H:i:s", time() + 86400 * 10 * 365.249),
"sslcsr" => $csrout, "sslcrt" => $crtout, "sslkey" => $privKey, "sslchain" => ""
"sslcsr" => $csrout, "sslcrt" => $crtout, "sslkey" => $privKey, "sslchain" => "",
"selfsigned" => true,
);
}

View File

@ -19,7 +19,6 @@ CREATE TABLE `certificates` (
KEY `ssl_action` (`ssl_action`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `certif_alias` (
`name` varchar(255) NOT NULL,
`content` text NOT NULL,
@ -28,3 +27,13 @@ CREATE TABLE IF NOT EXISTS `certif_alias` (
PRIMARY KEY (`name`),
KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Global aliases defined for SSL certificates FILE validation processes';
CREATE TABLE IF NOT EXISTS `certif_hosts` (
`certif` int(10) unsigned NOT NULL,
`sub` int(10) unsigned NOT NULL,
`uid` int(10) unsigned NOT NULL,
PRIMARY KEY (`certif`,`sub`),
KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='VHosts of a user using defined or self-signed certificates';
INSERT IGNORE INTO defquotas VALUES ('ssl', 0, 'default');