adding ssl.conf for apache + updateTrigger() when a new cert arrives to update sub_domaines

This commit is contained in:
Benjamin Sonntag 2015-02-13 11:38:27 +01:00
parent 73b41264f1
commit 5a0280607f
5 changed files with 164 additions and 50 deletions

View File

@ -1,4 +1,4 @@
etc/alternc/templates/apache2 etc/alternc/templates/apache2/mods-available
etc/apache2/conf.d etc/apache2/conf.d
usr/lib/alternc/install.d usr/lib/alternc/install.d
usr/share/alternc/install usr/share/alternc/install

View File

@ -5,11 +5,17 @@
synchronize the required domain templates with the current install synchronize the required domain templates with the current install
(do they have php52, roundcube, squirrelmail, etc.?) (do they have php52, roundcube, squirrelmail, etc.?)
*/ */
if ($argv[1] == "templates") {
// install ssl.conf
echo "[alternc-ssl] Installing ssl.conf template\n";
copy("/etc/alternc/templates/apache2/mods-available/ssl.conf","/etc/apache2/mods-available/ssl.conf");
}
if ($argv[1] == "before-reload") { if ($argv[1] == "before-reload") {
// Bootstrap // Bootstrap
require_once("/usr/share/alternc/panel/class/config_nochk.php"); require_once("/usr/share/alternc/panel/class/config_nochk.php");
echo "[alternc-ssl] Installing domaines-types\n";
$db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES $db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES
('vhost-ssl', 'Locally hosted forcing HTTPS', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,txt,defmx,defmx2,mx,mx2', 'ALL', 0, 0, 0);"); ('vhost-ssl', 'Locally hosted forcing HTTPS', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,txt,defmx,defmx2,mx,mx2', 'ALL', 0, 0, 0);");
@ -19,7 +25,7 @@ if ($argv[1] == "before-reload") {
$db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES $db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES
('panel-ssl', 'AlternC panel access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'ip,ipv6,cname,txt,mx,mx2,defmx,defmx2', 'ALL', 0, 0, 1);"); ('panel-ssl', 'AlternC panel access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'ip,ipv6,cname,txt,mx,mx2,defmx,defmx2', 'ALL', 0, 0, 1);");
$db - query("SELECT * FROM domaines_type WHERE name='roundcube';"); $db->query("SELECT * FROM domaines_type WHERE name='roundcube';");
if ($db->next_record()) { if ($db->next_record()) {
$db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES $db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES
('roundcube-ssl', 'Roundcube Webmail access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'mx,mx2,defmx,defmx2,txt', 'ALL', 0, 0, 1;"); ('roundcube-ssl', 'Roundcube Webmail access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'mx,mx2,defmx,defmx2,txt', 'ALL', 0, 0, 1;");
@ -28,7 +34,7 @@ if ($argv[1] == "before-reload") {
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE type='roundcube-ssl';"); $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE type='roundcube-ssl';");
} }
$db - query("SELECT * FROM domaines_type WHERE name='squirrelmail';"); $db->query("SELECT * FROM domaines_type WHERE name='squirrelmail';");
if ($db->next_record()) { if ($db->next_record()) {
$db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES $db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES
('squirrelmail-ssl', 'Squirrelmail Webmail access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'mx,mx2,defmx,defmx2,txt', 'ALL', 0, 0, 1);"); ('squirrelmail-ssl', 'Squirrelmail Webmail access WITH SSL', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'mx,mx2,defmx,defmx2,txt', 'ALL', 0, 0, 1);");
@ -37,7 +43,7 @@ if ($argv[1] == "before-reload") {
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE type='squirrelmail-ssl';"); $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE type='squirrelmail-ssl';");
} }
$db - query("SELECT * FROM domaines_type WHERE name='php52';"); $db->query("SELECT * FROM domaines_type WHERE name='php52';");
if ($db->next_record()) { if ($db->next_record()) {
$db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES $db->query("INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, enable, only_dns, need_dns, advanced ) VALUES
('php52-ssl', 'php52 forcing HTTPS', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,txt,defmx,defmx2,mx,mx2', 'ALL', 0, 0, 0);"); ('php52-ssl', 'php52 forcing HTTPS', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,txt,defmx,defmx2,mx,mx2', 'ALL', 0, 0, 0);");
@ -69,6 +75,4 @@ if ($argv[1] == "before-reload") {
fclose($f); fclose($f);
} }
} }
} // before-reload } // before-reload

View File

@ -30,7 +30,7 @@ if ( ($argv[1]=="create" || $argv[1]=="postinst" || $argv[1]=="delete") ) {
print_r($argv); print_r($argv);
exit(); exit();
} }
$ssl->update_domain($argv[1], $argv[2], $argv[3], $argv[4]); $ssl->updateDomain($argv[1], $argv[2], $argv[3], $argv[4]);
exit(); exit();
} }
if ( ($argv[1]=="enable" || $argv[1]=="disable") ) { if ( ($argv[1]=="enable" || $argv[1]=="disable") ) {
@ -39,7 +39,7 @@ if ( ($argv[1]=="enable" || $argv[1]=="disable") ) {
print_r($argv); print_r($argv);
exit(); exit();
} }
$ssl->update_domain($argv[1], $argv[2], $argv[3] ); $ssl->updateDomain($argv[1], $argv[2], $argv[3] );
exit(); exit();
} }

View File

@ -36,19 +36,19 @@ class m_ssl {
public $error = ""; public $error = "";
// Includes one or more of those flags to see only those certificates // Includes one or more of those flags to see only those certificates
// when listing them: // when listing them:
const FILTER_PENDING = 1; const FILTER_PENDING = 1;
const FILTER_OK = 2; const FILTER_OK = 2;
const FILTER_EXPIRED = 4; const FILTER_EXPIRED = 4;
const FILTER_SHARED = 8; const FILTER_SHARED = 8;
const SSL_INCRON_FILE = "/var/run/alternc/ssl/generate_certif_alias"; const SSL_INCRON_FILE = "/var/run/alternc/ssl/generate_certif_alias";
var $myDomainesTypes = array("vhost-ssl", "url-ssl", "panel-ssl", "roundcube-ssl", "squirrelmail-ssl"); 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"; const KEY_REPOSITORY = "/var/lib/alternc/ssl/private";
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** /**
* Constructor * Constructor
*/ */
@ -56,7 +56,7 @@ class m_ssl {
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** /**
* Hook to add the "ssl certificate" menu in the Panel * Hook to add the "ssl certificate" menu in the Panel
*/ */
@ -82,7 +82,7 @@ class m_ssl {
); );
} }
// or admin shared >0 ! // or admin shared >0 !
$db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1"); $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1");
$used = $q['u']; $used = $q['u'];
if ($db->next_record()) { if ($db->next_record()) {
@ -98,7 +98,7 @@ class m_ssl {
return $obj; return $obj;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Return all the SSL certificates for an account (or the searched one) /** Return all the SSL certificates for an account (or the searched one)
* @param $filter an integer telling which certificate we want to see (see FILTER_* constants above) * @param $filter an integer telling which certificate we want to see (see FILTER_* constants above)
* the default is showing all certificate, but only Pending and OK certificates, not expired or shared one * the default is showing all certificate, but only Pending and OK certificates, not expired or shared one
@ -110,7 +110,7 @@ class m_ssl {
global $db, $err, $cuid; global $db, $err, $cuid;
$err->log("ssl", "get_list"); $err->log("ssl", "get_list");
$r = array(); $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 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)) { if (is_null($filter)) {
$db->query("SELECT count(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1;"); $db->query("SELECT count(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1;");
$db->next_record(); $db->next_record();
@ -120,9 +120,9 @@ class m_ssl {
$filter = (self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED); $filter = (self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED);
} }
} }
// filter the filter values :) // filter the filter values :)
$filter = ($filter & (self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED)); $filter = ($filter & (self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED));
// Here filter can't be null (and will be returned to the caller !) // Here filter can't be null (and will be returned to the caller !)
$sql = ""; $sql = "";
if ($filter & self::FILTER_SHARED) { if ($filter & self::FILTER_SHARED) {
$sql = " (uid='$cuid' OR shared=1) "; $sql = " (uid='$cuid' OR shared=1) ";
@ -152,7 +152,7 @@ class m_ssl {
} }
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Generate a new CSR, a new Private RSA Key, for FQDN. /** 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. * @param $fqdn string the FQDN of the domain name for which we want a CSR.
* a wildcard certificate must start by *. * a wildcard certificate must start by *.
@ -183,7 +183,7 @@ class m_ssl {
return false; return false;
} }
$dn = array("commonName" => $fqdn); $dn = array("commonName" => $fqdn);
// override the (not taken from openssl.cnf) digest to use SHA-2 / SHA256 and not SHA-1 or MD5 : // override the (not taken from openssl.cnf) digest to use SHA-2 / SHA256 and not SHA-1 or MD5 :
$config = array("digest_alg" => "sha256"); $config = array("digest_alg" => "sha256");
$csr = openssl_csr_new($dn, $pkey, $config); $csr = openssl_csr_new($dn, $pkey, $config);
$csrout = ""; $csrout = "";
@ -196,7 +196,7 @@ class m_ssl {
return $id; return $id;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Return all informations of a given certificate for the current user. /** Return all informations of a given certificate for the current user.
* @return array all the informations of the current certificate as a hash. * @return array all the informations of the current certificate as a hash.
*/ */
@ -212,7 +212,7 @@ class m_ssl {
return $db->Record; return $db->Record;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Share (or unshare) an ssl certificate /** Share (or unshare) an ssl certificate
* @param $id integer the id of the certificate in the table. * @param $id integer the id of the certificate in the table.
* @param $action integer share (1) or unshare (0) this certificate * @param $action integer share (1) or unshare (0) this certificate
@ -222,13 +222,14 @@ class m_ssl {
global $db, $err, $cuid; global $db, $err, $cuid;
$err->log("ssl", "share"); $err->log("ssl", "share");
$id = intval($id); $id = intval($id);
$db->query("SELECT id FROM certificates WHERE uid='$cuid' AND status=" . self::STATUS_OK . " AND id='$id';"); $db->query("SELECT * FROM certificates WHERE uid='$cuid' AND status=" . self::STATUS_OK . " AND id='$id';");
if (!$db->next_record()) { if (!$db->next_record()) {
$err->raise("ssl", _("Can't find this Certifcate")); $err->raise("ssl", _("Can't find this Certifcate"));
return false; return false;
} }
if ($action) { if ($action) {
$action = 1; $action = 1;
$this->updateTrigger($db->Record["fqdn"],$db->Record["altnames"]);
} else { } else {
$action = 0; $action = 0;
} }
@ -236,7 +237,7 @@ class m_ssl {
return true; return true;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Return all the subdomains that can be ssl-enabled for the current account. /** Return all the subdomains that can be ssl-enabled for the current account.
* @return array of strings : all the subdomains. * @return array of strings : all the subdomains.
* Excludes the one for which a cert is already available * Excludes the one for which a cert is already available
@ -245,7 +246,7 @@ class m_ssl {
global $db, $err, $cuid; global $db, $err, $cuid;
$err->log("ssl", "get_new_advice"); $err->log("ssl", "get_new_advice");
$r = array(); $r = array();
// my certificates, either OK or PENDING (not expired) or the SHARED one (only OK then) // my certificates, either OK or PENDING (not expired) or the SHARED one (only OK then)
$db->query("SELECT fqdn FROM certificates WHERE $db->query("SELECT fqdn FROM certificates WHERE
(uid='$cuid' AND status IN (" . self::STATUS_PENDING . "," . self::STATUS_OK . ") ) (uid='$cuid' AND status IN (" . self::STATUS_PENDING . "," . self::STATUS_OK . ") )
OR (shared=1 AND status=" . self::STATUS_OK . ") OR (shared=1 AND status=" . self::STATUS_OK . ")
@ -254,7 +255,7 @@ class m_ssl {
while ($db->next_record()) { while ($db->next_record()) {
$r[] = $db->f("fqdn"); $r[] = $db->f("fqdn");
} }
// Now we get all our subdomains for certain domaines_types // Now we get all our subdomains for certain domaines_types
$db->query("SELECT sub,domaine FROM sub_domaines WHERE compte='$cuid' AND type IN ('vhost', 'url', 'roundcube', 'squirrelmail', 'panel', 'php52');"); $db->query("SELECT sub,domaine FROM sub_domaines WHERE compte='$cuid' AND type IN ('vhost', 'url', 'roundcube', 'squirrelmail', 'panel', 'php52');");
$advice = array(); $advice = array();
while ($db->next_record()) { while ($db->next_record()) {
@ -274,7 +275,7 @@ class m_ssl {
return($advice); return($advice);
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Import an existing ssl Key, Certificate and (maybe) a Chained Cert /** Import an existing ssl Key, Certificate and (maybe) a Chained Cert
* @param $key string the X.509 PEM-encoded RSA key * @param $key string the X.509 PEM-encoded RSA key
* @param $crt string the X.509 PEM-encoded certificate, which *must* * @param $crt string the X.509 PEM-encoded certificate, which *must*
@ -299,17 +300,18 @@ class m_ssl {
$fqdn = $crtdata["subject"]["CN"]; $fqdn = $crtdata["subject"]["CN"];
$altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]); $altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
// Everything is PERFECT and has been thoroughly checked, let's insert those in the DB ! // Everything is PERFECT and has been thoroughly checked, let's insert those in the DB !
$sql = "INSERT INTO certificates SET uid='$cuid', status=" . self::STATUS_OK . ", shared=0, fqdn='" . addslashes($fqdn) . "', altnames='" . addslashes($altnames) . "', validstart=FROM_UNIXTIME(" . intval($validstart) . "), validend=FROM_UNIXTIME(" . intval($validend) . "), sslkey='" . addslashes($key) . "', sslcrt='" . addslashes($crt) . "', sslchain='" . addslashes($chain) . "';"; $sql = "INSERT INTO certificates SET uid='$cuid', status=" . self::STATUS_OK . ", shared=0, fqdn='" . addslashes($fqdn) . "', altnames='" . addslashes($altnames) . "', validstart=FROM_UNIXTIME(" . intval($validstart) . "), validend=FROM_UNIXTIME(" . intval($validend) . "), sslkey='" . addslashes($key) . "', sslcrt='" . addslashes($crt) . "', sslchain='" . addslashes($chain) . "';";
$db->query($sql); $db->query($sql);
if (!($id = $db->lastid())) { if (!($id = $db->lastid())) {
$err->raise("ssl", _("Can't save the Key/Crt/Chain now. Please try later.")); $err->raise("ssl", _("Can't save the Key/Crt/Chain now. Please try later."));
return false; return false;
} }
$this->updateTrigger($fqdn,$altnames);
return $id; return $id;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Import an ssl certificate into an existing certificate entry in the DB. /** Import an ssl certificate into an existing certificate entry in the DB.
* (finalize an enrollment process) * (finalize an enrollment process)
* @param $certid integer the ID in the database of the SSL Certificate * @param $certid integer the ID in the database of the SSL Certificate
@ -336,16 +338,17 @@ class m_ssl {
$fqdn = $crtdata["subject"]["CN"]; $fqdn = $crtdata["subject"]["CN"];
$altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]); $altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
// Everything is PERFECT and has been thoroughly checked, let's insert those in the DB ! // Everything is PERFECT and has been thoroughly checked, let's insert those in the DB !
$sql = "UPDATE certificates SET status=" . self::STATUS_OK . ", shared=0, fqdn='" . addslashes($fqdn) . "', altnames='" . addslashes($altnames) . "', validstart=FROM_UNIXTIME(" . intval($validstart) . "), validend=FROM_UNIXTIME(" . intval($validend) . "), sslcrt='" . addslashes($crt) . "', sslchain='" . addslashes($chain) . "' WHERE id='$certid' ;"; $sql = "UPDATE certificates SET status=" . self::STATUS_OK . ", shared=0, fqdn='" . addslashes($fqdn) . "', altnames='" . addslashes($altnames) . "', validstart=FROM_UNIXTIME(" . intval($validstart) . "), validend=FROM_UNIXTIME(" . intval($validend) . "), sslcrt='" . addslashes($crt) . "', sslchain='" . addslashes($chain) . "' WHERE id='$certid' ;";
if (!$db->query($sql)) { if (!$db->query($sql)) {
$err->raise("ssl", _("Can't save the Crt/Chain now. Please try later.")); $err->raise("ssl", _("Can't save the Crt/Chain now. Please try later."));
return false; return false;
} }
$this->updateTrigger($fqdn,$altnames);
return $certid; return $certid;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Function called by a hook when an AlternC member is deleted. /** Function called by a hook when an AlternC member is deleted.
* @access private * @access private
* TODO: delete unused ssl certificates ?? > do this in the crontab. * TODO: delete unused ssl certificates ?? > do this in the crontab.
@ -357,7 +360,7 @@ class m_ssl {
return true; return true;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Hook which returns the used quota for the $name service for the current user. /** Hook which returns the used quota for the $name service for the current user.
* @param $name string name of the quota * @param $name string name of the quota
* @return integer the number of service used or false if an error occured * @return integer the number of service used or false if an error occured
@ -374,14 +377,32 @@ class m_ssl {
return $q; return $q;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Launched by functions in this class
* when a certificate is validated, expired or shared.
* so that existing vhost using expired or self-signed certificates
* may have the chance to use a proper one automagically
* @param string $fqdn the FQDN of the certificate
* @param string $altnames any alternative names this certificate may have.
*/
public function updateTrigger($fqdn, $altnames = "") {
global $db;
$fqdns = array($fqdn);
$an = explode("\n", $altnames);
foreach ($an as $a)
if (trim($a))
$fqdns[] = trim($a);
$db->query("UPDATE sub_domaines SET web_action='UPDATE' WHERE if(LENGTH(sub)>0,CONCAT(sub,'.',domaine),domaine) IN ('" . implode("','", $fqdns) . "');");
}
// -----------------------------------------------------------------
/** Launched by hosting_functions.sh launched by update_domaines.sh /** Launched by hosting_functions.sh launched by update_domaines.sh
* Action may be create/postinst/delete/enable/disable * Action may be create/postinst/delete/enable/disable
* Change the template for this domain name to have the proper CERTIFICATE * Change the template for this domain name to have the proper CERTIFICATE
* An algorithm determine the best possible certificate, which may be a BAD one * An algorithm determine the best possible certificate, which may be a BAD one
* (like a generic admin-shared or self-signed for localhost as a last chance) * (like a generic admin-shared or self-signed for localhost as a last chance)
*/ */
public function update_domain($action, $type, $fqdn, $mail = 0, $value = "") { public function updateDomain($action, $type, $fqdn, $mail = 0, $value = "") {
global $db, $err; global $db, $err;
$err->log("ssl", "update_domain($action,$type,$fqdn)"); $err->log("ssl", "update_domain($action,$type,$fqdn)");
if (!in_array($type, $this->myDomainesTypes)) { if (!in_array($type, $this->myDomainesTypes)) {
@ -408,8 +429,6 @@ class m_ssl {
// found and $db point to it: // found and $db point to it:
$subdom = $db->Record; $subdom = $db->Record;
$TARGET_FILE = "/var/lib/alternc/apache-vhost/" . substr($subdom["compte"], -1) . "/" . $subdom["compte"] . "/" . $fqdn . ".conf"; $TARGET_FILE = "/var/lib/alternc/apache-vhost/" . substr($subdom["compte"], -1) . "/" . $subdom["compte"] . "/" . $fqdn . ".conf";
// DEBUG
echo "TARGET_FILE:".$TARGET_FILE."\n";
$cert = $this->searchBestCert($subdom["compte"], $fqdn); $cert = $this->searchBestCert($subdom["compte"], $fqdn);
// DEBUG echo "Return from searchBestCert(" . $subdom["compte"] . "," . $fqdn . ") is "; print_r($cert); // DEBUG echo "Return from searchBestCert(" . $subdom["compte"] . "," . $fqdn . ") is "; print_r($cert);
// Save crt/key/chain into KEY_REPOSITORY // Save crt/key/chain into KEY_REPOSITORY
@ -433,7 +452,7 @@ class m_ssl {
} // action==create } // action==create
} }
// --------------op--------------------------------------------------- // ----------------------------------------------------------------
/** Search for the best certificate for a user and a fqdn /** Search for the best certificate for a user and a fqdn
* Return a hash with sslcrt, sslkey and maybe sslchain. * Return a hash with sslcrt, sslkey and maybe sslchain.
* return ANYWAY : if necessary, return a newly created (and stored in KEY_REPOSITORY localhost self-signed certificate... * return ANYWAY : if necessary, return a newly created (and stored in KEY_REPOSITORY localhost self-signed certificate...
@ -449,7 +468,7 @@ class m_ssl {
. "AND (fqdn='" . $fqdn . "' OR fqdn='" . $wildcard . "' OR altnames LIKE '%" . $fqdn . "%') " . "AND (fqdn='" . $fqdn . "' OR fqdn='" . $wildcard . "' OR altnames LIKE '%" . $fqdn . "%') "
. "ORDER BY (validstart<=NOW() AND validend>=NOW()) DESC, validstart DESC "); . "ORDER BY (validstart<=NOW() AND validend>=NOW()) DESC, validstart DESC ");
while ($db->next_record()) { while ($db->next_record()) {
if ($db->fqdn == $fqdn) { if ($db->Record["fqdn"] == $fqdn) {
return $db->Record; return $db->Record;
} }
$altnames = explode("\n", $db->Record["altnames"]); $altnames = explode("\n", $db->Record["altnames"]);
@ -465,7 +484,7 @@ class m_ssl {
return $crt; return $crt;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Export every information for an AlternC's account /** Export every information for an AlternC's account
* @access private * @access private
* EXPERIMENTAL 'sid' function ;) * EXPERIMENTAL 'sid' function ;)
@ -486,7 +505,7 @@ class m_ssl {
return $str; return $str;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Returns the list of alternate names of an X.509 SSL Certificate /** Returns the list of alternate names of an X.509 SSL Certificate
* from the attribute list. * from the attribute list.
* @param $str string the $crtdata["extensions"]["subjectAltName"] from openssl * @param $str string the $crtdata["extensions"]["subjectAltName"] from openssl
@ -501,7 +520,7 @@ class m_ssl {
} }
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Add (immediately) a global alias to the HTTP /** Add (immediately) a global alias to the HTTP
* certif_alias table and add it to apache configuration * certif_alias table and add it to apache configuration
* by launching a incron action. * by launching a incron action.
@ -523,7 +542,7 @@ class m_ssl {
return true; return true;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Removes (immediately) a global alias to the HTTP /** Removes (immediately) a global alias to the HTTP
* certif_alias table and add it to apache configuration * certif_alias table and add it to apache configuration
* by launching a incron action. * by launching a incron action.
@ -542,7 +561,7 @@ class m_ssl {
return true; return true;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/** Check that a crt is a proper certificate /** Check that a crt is a proper certificate
* @param $crt string an SSL Certificate * @param $crt string an SSL Certificate
* @param $chain string is a list of certificates * @param $chain string is a list of certificates
@ -553,14 +572,14 @@ class m_ssl {
*/ */
function check_cert($crt, $chain, $key = "", $certid = null) { function check_cert($crt, $chain, $key = "", $certid = null) {
global $db; global $db;
// Check that the key crt and chain are really SSL certificates and keys // Check that the key crt and chain are really SSL certificates and keys
$crt = trim(str_replace("\r\n", "\n", $crt)) . "\n"; $crt = trim(str_replace("\r\n", "\n", $crt)) . "\n";
$key = trim(str_replace("\r\n", "\n", $key)) . "\n"; $key = trim(str_replace("\r\n", "\n", $key)) . "\n";
$chain = trim(str_replace("\r\n", "\n", $chain)) . "\n"; $chain = trim(str_replace("\r\n", "\n", $chain)) . "\n";
$this->error = ""; $this->error = "";
if (trim($key) == "" && !is_null($certid)) { if (trim($key) == "" && !is_null($certid)) {
// find it in the DB : // find it in the DB :
$db->query("SELECT sslkey FROM certificates WHERE id=" . intval($certid) . ";"); $db->query("SELECT sslkey FROM certificates WHERE id=" . intval($certid) . ";");
if (!$db->next_record()) { if (!$db->next_record()) {
$this->error.=_("Can't find the private key in the certificate table, please check your form."); $this->error.=_("Can't find the private key in the certificate table, please check your form.");
@ -589,7 +608,7 @@ class m_ssl {
return false; return false;
} }
// We split the chained certificates in individuals certificates : // We split the chained certificates in individuals certificates :
$chains = array(); $chains = array();
$status = 0; $status = 0;
$new = ""; $new = "";
@ -611,8 +630,8 @@ class m_ssl {
$new.=$line . "\n"; $new.=$line . "\n";
} }
} }
// here chains contains all the ssl certificates in the chained certs. // here chains contains all the ssl certificates in the chained certs.
// Now we check those using Openssl functions (real check :) ) // Now we check those using Openssl functions (real check :) )
$rchains = array(); $rchains = array();
$i = 0; $i = 0;
foreach ($chains as $tmpcert) { foreach ($chains as $tmpcert) {
@ -635,13 +654,13 @@ class m_ssl {
$this->error.=_("The private key is invalid.") . "\n"; $this->error.=_("The private key is invalid.") . "\n";
} }
if (!$this->error) { if (!$this->error) {
// check that the private key and the certificates are matching : // check that the private key and the certificates are matching :
if (!openssl_x509_check_private_key($rcrt, $rkey)) { if (!openssl_x509_check_private_key($rcrt, $rkey)) {
$this->error.=_("The private key is not the one signed inside the certificate.") . "\n"; $this->error.=_("The private key is not the one signed inside the certificate.") . "\n";
} }
} }
if (!$this->error) { if (!$this->error) {
// Everything is fine, let's recreate crt, chain, key from our internal OpenSSL structures: // Everything is fine, let's recreate crt, chain, key from our internal OpenSSL structures:
if (!openssl_x509_export($rcrt, $crt)) { if (!openssl_x509_export($rcrt, $crt)) {
$this->error.=_("Can't export your certificate as a string, please check its syntax.") . "\n"; $this->error.=_("Can't export your certificate as a string, please check its syntax.") . "\n";
} }

91
ssl/ssl.conf Normal file
View File

@ -0,0 +1,91 @@
# ############################################################################
# WARNING : this file is overwritten by alternc.install.
# Edit /etc/alternc/templates/apache2/mods-available/ instead.
# ############################################################################
<IfModule mod_ssl.c>
#
# Pseudo Random Number Generator (PRNG):
# Configure one or more sources to seed the PRNG of the SSL library.
# The seed data should be of good random quality.
# WARNING! On some platforms /dev/random blocks if not enough entropy
# is available. This means you then cannot use the /dev/random device
# because it would lead to very long connection times (as long as
# it requires to make more entropy available). But usually those
# platforms additionally provide a /dev/urandom device which doesn't
# block. So, if available, use this one instead. Read the mod_ssl User
# Manual for more details.
#
SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect builtin
SSLRandomSeed connect file:/dev/urandom 512
##
## SSL Global Context
##
## All SSL configuration in this context applies both to
## the main server and all SSL-enabled virtual hosts.
##
#
# Some MIME-types for downloading Certificates and CRLs
#
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
# Pass Phrase Dialog:
# Configure the pass phrase gathering process.
# The filtering dialog program (`builtin' is a internal
# terminal dialog) has to provide the pass phrase on stdout.
SSLPassPhraseDialog builtin
# Inter-Process Session Cache:
# Configure the SSL Session Cache: First the mechanism
# to use and second the expiring timeout (in seconds).
# (The mechanism dbm has known memory leaks and should not be used).
#SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache
SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
SSLSessionCacheTimeout 300
# Semaphore:
# Configure the path to the mutual exclusion semaphore the
# SSL engine uses internally for inter-process synchronization.
SSLMutex file:${APACHE_RUN_DIR}/ssl_mutex
# SSL Cipher Suite:
# List the ciphers that the client is permitted to negotiate. See the
# ciphers(1) man page from the openssl package for list of all available
# options.
# Enable only secure ciphers:
#SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLCipherSuite ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM
# Other possible ciphersuite (requires wheezy-version of apache2 at least)
#SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
# Speed-optimized SSL Cipher configuration:
# If speed is your main concern (on busy HTTPS servers e.g.),
# you might want to force clients to specific, performance
# optimized ciphers. In this case, prepend those ciphers
# to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
# Caveat: by giving precedence to RC4-SHA and AES128-SHA
# (as in the example below), most connections will no longer
# have perfect forward secrecy - if the server's key is
# compromised, captures of past or future traffic must be
# considered compromised, too.
#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
SSLHonorCipherOrder on
# enable only secure protocols: SSLv3 and TLSv1, but not SSLv2
#SSLProtocol all -SSLv2
SSLProtocol all -SSLv2 -SSLv3
# Allow insecure renegotiation with clients which do not yet support the
# secure renegotiation protocol. Default: Off
#SSLInsecureRenegotiation on
# Whether to forbid non-SNI clients to access name based virtual hosts.
# Default: Off
SSLStrictSNIVHostCheck Off
</IfModule>