- Certificate Request (CSR) and a RSA Key (KEY) here, then give the CSR to the Certificate Authority, which will give you a certificate (CRT) and also often a chained certificate (CHAIN)."); ?>
+ Certificate Request (CSR) and a RSA Key (KEY) here, then give the CSR to the Certificate Authority, which will give you a certificate (CRT) and also often a chained certificate (CHAIN)."); ?>
-
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
-
Certificate Request file (CSR) and a RSA Key file (KEY) for a given domain name"); ?>
+
Certificate Request file (CSR) and a RSA Key file (KEY) for a given domain name"); ?>
-
+
-
+
-
-
www.example.com is NOT valid for intranet.example.com or intranet.www.example.com !"); ?> (If you want to get a valid certificate for all the subdomains of a domain, use a wildcard notation (eg: *.example.com). Please note that a wildcard certificate is usually more expensive than normal one.)"); ?>
-
+
+
www.example.com is NOT valid for intranet.example.com or intranet.www.example.com !"); ?> (If you want to get a valid certificate for all the subdomains of a domain, use a wildcard notation (eg: *.example.com). Please note that a wildcard certificate is usually more expensive than normal one.)"); ?>
Certificate Request File (CSR) has been created, along with its private RSA Key (KEY). Please find below the CSR you must send to your SSL Certificate provider."); ?>
-
-
Certificate File (CRT) and a Chained Certificate File (CHAIN), please paste them here to finish the enrollment."); ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-enabled) {
-?>
-
(This is only useful for wildcard or multi-domain certificates)."); ?>
Certificate Request File (CSR) has been created, along with its private RSA Key (KEY). Please find below the CSR you must send to your SSL Certificate provider."); ?>
+
+
Certificate File (CRT) and a Chained Certificate File (CHAIN), please paste them here to finish the enrollment."); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ enabled) {
+ ?>
+
(This is only useful for wildcard or multi-domain certificates)."); ?>
+
+ shared");
+ if ($cert["uid"] == $cuid) {
+ ?>
+
+
+ NOT shared");
+ if ($cert["uid"] == $cuid) {
+ ?>
+
+
+
+
-
diff --git a/ssl/panel/class/m_ssl.php b/ssl/panel/class/m_ssl.php
index 0ceab919..963dfaf1 100644
--- a/ssl/panel/class/m_ssl.php
+++ b/ssl/panel/class/m_ssl.php
@@ -1,4 +1,5 @@
getquota("ssl");
- $obj=null;
- if ($q['t']>0) {
- $obj = array(
- 'title' => _("SSL Certificates"),
- 'ico' => 'images/ssl.png',
- 'link' => 'toggle',
- 'pos' => 130,
- 'links' => array(),
- ) ;
-
- if ( $quota->cancreate("ssl") ) {
- $obj['links'][] =
- array (
- 'ico' => 'images/new.png',
- 'txt' => _("New SSL certificate"),
- 'url' => "ssl_new.php",
- 'class' => '',
- );
- }
-
- // or admin shared >0 !
- $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1");
- $used=$q['u'];
- if ($db->next_record()) {
- $used=$db->f("cnt");
- }
- if ( $used > 0 ) { // if there are some SSL certificates
- $obj['links'][] =
- array (
- 'txt' => _("List SSL Certificates"),
- 'url' => "ssl_list.php"
- );
- }
+ // -----------------------------------------------------------------
+ /**
+ * Constructor
+ */
+ function m_ssl() {
+
}
- return $obj;
- }
-
+ // -----------------------------------------------------------------
+ /**
+ * Hook to add the "ssl certificate" menu in the Panel
+ */
+ function hook_menu() {
+ global $quota, $db, $cuid;
+ $q = $quota->getquota("ssl");
+ $obj = null;
+ if ($q['t'] > 0) {
+ $obj = array(
+ 'title' => _("SSL Certificates"),
+ 'ico' => 'images/ssl.png',
+ 'link' => 'toggle',
+ 'pos' => 130,
+ 'links' => array(),
+ );
- /* ----------------------------------------------------------------- */
- /** 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)
- * the default is showing all certificate, but only Pending and OK certificates, not expired or shared one
- * when there is more than 10.
- * @return array all the ssl certificate this user can use
- * (each array is the content of the certificates table)
- */
- function get_list(&$filter=null) {
- global $db,$err,$cuid;
- $err->log("ssl","get_list");
- $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)) {
- $db->query("SELECT count(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1;");
- $db->next_record();
- if ($db->f("cnt")>10) {
- $filter=(self::FILTER_PENDING | self::FILTER_OK);
- } else {
- $filter=(self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED);
- }
- }
- // filter the filter values :)
- $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 !)
- $sql="";
- if ($filter & self::FILTER_SHARED) {
- $sql=" (uid='$cuid' OR shared=1) ";
- } else {
- $sql=" uid='$cuid' ";
- }
- $sql.=" AND status IN (-1";
- if ($filter & self::FILTER_PENDING) $sql.=",".self::STATUS_PENDING;
- if ($filter & self::FILTER_OK) $sql.=",".self::STATUS_OK;
- if ($filter & self::FILTER_EXPIRED) $sql.=",".self::STATUS_EXPIRED;
- $sql.=") ";
- $db->query("SELECT *, UNIX_TIMESTAMP(validstart) AS validstartts, UNIX_TIMESTAMP(validend) AS validendts FROM certificates WHERE $sql ORDER BY shared, fqdn;");
- if ($db->num_rows()) {
- while ($db->next_record()) {
- $r[]=$db->Record;
- }
- return $r;
- } else {
- $err->raise("ssl",_("No SSL certificates available"));
- return array();
- }
- }
+ if ($quota->cancreate("ssl")) {
+ $obj['links'][] = array(
+ 'ico' => 'images/new.png',
+ 'txt' => _("New SSL certificate"),
+ 'url' => "ssl_new.php",
+ 'class' => '',
+ );
+ }
-
- /* ----------------------------------------------------------------- */
- /** 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.
- * a wildcard certificate must start by *.
- * @return integer the Certificate ID created in the MySQL database
- * or false if an error occurred
- */
- function new_csr($fqdn) {
- global $db,$err,$cuid;
- $err->log("ssl","new_csr");
- if (substr($fqdn,0,2)=="*.") {
- $f=substr($fqdn,2);
- } else {
- $f=$fqdn;
+ // or admin shared >0 !
+ $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1");
+ $used = $q['u'];
+ if ($db->next_record()) {
+ $used = $db->f("cnt");
+ }
+ if ($used > 0) { // if there are some SSL certificates
+ $obj['links'][] = array(
+ 'txt' => _("List SSL Certificates"),
+ 'url' => "ssl_list.php"
+ );
+ }
+ }
+ return $obj;
}
- if (checkfqdn($f)) {
- $err->raise("ssl",_("Bad FQDN domain name"));
- return false;
- }
- putenv("OPENSSL_CONF=/etc/alternc/openssl.cnf");
- $pkey=openssl_pkey_new();
- if (!$pkey) {
- $err->raise("ssl",_("Can't generate a private key (1)"));
- return false;
- }
- if (!openssl_pkey_export($pkey, $privKey)) {
- $err->raise("ssl",_("Can't generate a private key (2)"));
- return false;
- }
- $dn=array("commonName" => $fqdn);
- // override the (not taken from openssl.cnf) digest to use SHA-2 / SHA256 and not SHA-1 or MD5 :
- $config=array("digest_alg"=>"sha256");
- $csr=openssl_csr_new($dn, $pkey,$config);
- openssl_csr_export($csr, $csrout);
- $db->query("INSERT INTO certificates SET uid='$cuid', status=".self::STATUS_PENDING.", shared=0, fqdn='".addslashes($fqdn)."', altnames='', validstart=NOW(), sslcsr='".addslashes($csrout)."', sslkey='".addslashes($privKey)."';");
- if (!($id=$db->lastid())) {
- $err->raise("ssl",_("Can't generate a CSR"));
- return false;
- }
- return $id;
- }
-
- /* ----------------------------------------------------------------- */
- /** Return all informations of a given certificate for the current user.
- * @return array all the informations of the current certificate as a hash.
- */
- function get_certificate($id) {
- global $db,$err,$cuid;
- $err->log("ssl","get_certificate");
- $id=intval($id);
- $db->query("SELECT *, UNIX_TIMESTAMP(validstart) AS validstartts, UNIX_TIMESTAMP(validend) AS validendts FROM certificates WHERE (uid='$cuid' OR (shared=1 AND status=".self::STATUS_OK.") ) AND id='$id';");
- if (!$db->next_record()) {
- $err->raise("ssl",_("Can't find this Certifcate"));
- return false;
+ // -----------------------------------------------------------------
+ /** 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)
+ * the default is showing all certificate, but only Pending and OK certificates, not expired or shared one
+ * when there is more than 10.
+ * @return array all the ssl certificate this user can use
+ * (each array is the content of the certificates table)
+ */
+ function get_list(&$filter = null) {
+ global $db, $err, $cuid;
+ $err->log("ssl", "get_list");
+ $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)) {
+ $db->query("SELECT count(*) AS cnt FROM certificates WHERE uid='$cuid' OR shared=1;");
+ $db->next_record();
+ if ($db->f("cnt") > 10) {
+ $filter = (self::FILTER_PENDING | self::FILTER_OK);
+ } else {
+ $filter = (self::FILTER_PENDING | self::FILTER_OK | self::FILTER_EXPIRED | self::FILTER_SHARED);
+ }
+ }
+ // filter the filter values :)
+ $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 !)
+ $sql = "";
+ if ($filter & self::FILTER_SHARED) {
+ $sql = " (uid='$cuid' OR shared=1) ";
+ } else {
+ $sql = " uid='$cuid' ";
+ }
+ $sql.=" AND status IN (-1";
+ if ($filter & self::FILTER_PENDING)
+ $sql.="," . self::STATUS_PENDING;
+ if ($filter & self::FILTER_OK)
+ $sql.="," . self::STATUS_OK;
+ if ($filter & self::FILTER_EXPIRED)
+ $sql.="," . self::STATUS_EXPIRED;
+ $sql.=") ";
+ $db->query("SELECT *, UNIX_TIMESTAMP(validstart) AS validstartts, UNIX_TIMESTAMP(validend) AS validendts FROM certificates WHERE $sql ORDER BY shared, fqdn;");
+ if ($db->num_rows()) {
+ while ($db->next_record()) {
+ $r[] = $db->Record;
+ }
+ return $r;
+ } else {
+ $err->raise("ssl", _("No SSL certificates available"));
+ return array();
+ }
}
- return $db->Record;
- }
-
- /* ----------------------------------------------------------------- */
- /** Share (or unshare) an ssl certificate
- * @param $id integer the id of the certificate in the table.
- * @param $action integer share (1) or unshare (0) this certificate
- * @return boolean
- */
- function share($id,$action=1) {
- global $db,$err,$cuid;
- $err->log("ssl","share");
- $id=intval($id);
- $db->query("SELECT id FROM certificates WHERE uid='$cuid' AND status=".self::STATUS_OK." AND id='$id';");
- if (!$db->next_record()) {
- $err->raise("ssl",_("Can't find this Certifcate"));
- return false;
+ // -----------------------------------------------------------------
+ /** 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.
+ * a wildcard certificate must start by *.
+ * @return integer the Certificate ID created in the MySQL database
+ * or false if an error occurred
+ */
+ function new_csr($fqdn) {
+ global $db, $err, $cuid;
+ $err->log("ssl", "new_csr");
+ if (substr($fqdn, 0, 2) == "*.") {
+ $f = substr($fqdn, 2);
+ } else {
+ $f = $fqdn;
+ }
+ if (checkfqdn($f)) {
+ $err->raise("ssl", _("Bad FQDN domain name"));
+ return false;
+ }
+ putenv("OPENSSL_CONF=/etc/alternc/openssl.cnf");
+ $pkey = openssl_pkey_new();
+ if (!$pkey) {
+ $err->raise("ssl", _("Can't generate a private key (1)"));
+ return false;
+ }
+ if (!openssl_pkey_export($pkey, $privKey)) {
+ $err->raise("ssl", _("Can't generate a private key (2)"));
+ return false;
+ }
+ $dn = array("commonName" => $fqdn);
+ // override the (not taken from openssl.cnf) digest to use SHA-2 / SHA256 and not SHA-1 or MD5 :
+ $config = array("digest_alg" => "sha256");
+ $csr = openssl_csr_new($dn, $pkey, $config);
+ openssl_csr_export($csr, $csrout);
+ $db->query("INSERT INTO certificates SET uid='$cuid', status=" . self::STATUS_PENDING . ", shared=0, fqdn='" . addslashes($fqdn) . "', altnames='', validstart=NOW(), sslcsr='" . addslashes($csrout) . "', sslkey='" . addslashes($privKey) . "';");
+ if (!($id = $db->lastid())) {
+ $err->raise("ssl", _("Can't generate a CSR"));
+ return false;
+ }
+ return $id;
}
- if ($action) $action=1; else $action=0;
- $db->query("UPDATE certificates SET shared=$action WHERE id='$id';");
- return true;
- }
+ // -----------------------------------------------------------------
+ /** Return all informations of a given certificate for the current user.
+ * @return array all the informations of the current certificate as a hash.
+ */
+ function get_certificate($id) {
+ global $db, $err, $cuid;
+ $err->log("ssl", "get_certificate");
+ $id = intval($id);
+ $db->query("SELECT *, UNIX_TIMESTAMP(validstart) AS validstartts, UNIX_TIMESTAMP(validend) AS validendts FROM certificates WHERE (uid='$cuid' OR (shared=1 AND status=" . self::STATUS_OK . ") ) AND id='$id';");
+ if (!$db->next_record()) {
+ $err->raise("ssl", _("Can't find this Certifcate"));
+ return false;
+ }
+ return $db->Record;
+ }
- /* ----------------------------------------------------------------- */
- /** Return all the subdomains that can be ssl-enabled for the current account.
- * @return array of strings : all the subdomains.
- * Excludes the one for which a cert is already available
- */
- function get_new_advice() {
- global $db,$err,$cuid;
- $err->log("ssl","get_new_advice");
- $r=array();
- // my certificates, either OK or PENDING (not expired) or the SHARED one (only OK then)
- $db->query("SELECT fqdn FROM certificates WHERE
- (uid='$cuid' AND status IN (".self::STATUS_PENDING.",".self::STATUS_OK.") )
- OR (shared=1 AND status=".self::STATUS_OK.")
+ // -----------------------------------------------------------------
+ /** Share (or unshare) an ssl certificate
+ * @param $id integer the id of the certificate in the table.
+ * @param $action integer share (1) or unshare (0) this certificate
+ * @return boolean
+ */
+ function share($id, $action = 1) {
+ global $db, $err, $cuid;
+ $err->log("ssl", "share");
+ $id = intval($id);
+ $db->query("SELECT id FROM certificates WHERE uid='$cuid' AND status=" . self::STATUS_OK . " AND id='$id';");
+ if (!$db->next_record()) {
+ $err->raise("ssl", _("Can't find this Certifcate"));
+ return false;
+ }
+ if ($action)
+ $action = 1;
+ else
+ $action = 0;
+ $db->query("UPDATE certificates SET shared=$action WHERE id='$id';");
+ return true;
+ }
+
+ // -----------------------------------------------------------------
+ /** Return all the subdomains that can be ssl-enabled for the current account.
+ * @return array of strings : all the subdomains.
+ * Excludes the one for which a cert is already available
+ */
+ function get_new_advice() {
+ global $db, $err, $cuid;
+ $err->log("ssl", "get_new_advice");
+ $r = array();
+ // my certificates, either OK or PENDING (not expired) or the SHARED one (only OK then)
+ $db->query("SELECT fqdn FROM certificates WHERE
+ (uid='$cuid' AND status IN (" . self::STATUS_PENDING . "," . self::STATUS_OK . ") )
+ OR (shared=1 AND status=" . self::STATUS_OK . ")
ORDER BY shared, fqdn;");
- $r=array();
- while ($db->next_record()) {
- $r[]=$db->f("fqdn");
- }
- // 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');");
- $advice=array();
- while ($db->next_record()) {
- $me=$db->f("sub");
- if ($me) $me.=".";
- $me.=$db->f("domaine");
- if (!in_array($me,$r) && !in_array($me,$advice)) {
- $advice[]=$me;
- }
- if (!in_array("*.".$db->f("domaine"),$r) && !in_array("*.".$db->f("domaine"),$advice)) {
- $advice[]="*.".$db->f("domaine");
- }
- }
- sort($advice);
- return($advice);
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Import an existing ssl Key, Certificate and (maybe) a Chained Cert
- * @param $key string the X.509 PEM-encoded RSA key
- * @param $crt string the X.509 PEM-encoded certificate, which *must*
- * be the one signinf the private RSA key in $key
- * @param $chain string the X.509 PEM-encoded list of SSL Certificate chain if intermediate authorities
- * @return integer the ID of the newly created certificate in the table
- * or false if an error occurred
- */
- function import_cert($key,$crt,$chain="") {
- global $cuid, $err, $db;
- $err->log("ssl","import_cert");
-
- $result=$this->check_cert($crt,$chain,$key);
- if ($result===false) {
- $err->raise("ssl",$this->error);
- return false;
- }
- list($crt,$chain,$key,$crtdata)=$result;
-
- $validstart=$crtdata['validFrom_time_t'];
- $validend=$crtdata['validTo_time_t'];
- $fqdn=$crtdata["subject"]["CN"];
- $altnames=$this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
-
- // 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)."';";
- $db->query($sql);
- if (!($id=$db->lastid())) {
- $err->raise("ssl",_("Can't save the Key/Crt/Chain now. Please try later."));
- return false;
- }
- return $id;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Import an ssl certificate into an existing certificate entry in the DB.
- * (finalize an enrollment process)
- * @param $certid integer the ID in the database of the SSL Certificate
- * @param $crt string the X.509 PEM-encoded certificate, which *must*
- * be the one signing the private RSA key in certificate $certid
- * @param $chain string the X.509 PEM-encoded list of SSL Certificate chain if intermediate authorities
- * @return integer the ID of the updated certificate in the table
- * or false if an error occurred
- */
- function finalize($certid,$crt,$chain) {
- global $cuid, $err, $db;
- $err->log("ssl","finalize");
-
- $certid=intval($certid);
- $result=$this->check_cert($crt,$chain,"",$certid);
- if ($result===false) {
- $err->raise("ssl",$this->error);
- return false;
- }
- list($crt,$chain,$key,$crtdata)=$result;
-
- $validstart=$crtdata['validFrom_time_t'];
- $validend=$crtdata['validTo_time_t'];
- $fqdn=$crtdata["subject"]["CN"];
- $altnames=$this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
-
- // 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' ;";
- if (!$db->query($sql)) {
- $err->raise("ssl",_("Can't save the Crt/Chain now. Please try later."));
- return false;
- }
- return $certid;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Function called by a hook when an AlternC member is deleted.
- * @access private
- * TODO: delete unused ssl certificates ?? > do this in the crontab.
- */
- function alternc_del_member() {
- global $db,$err,$cuid;
- $err->log("ssl","alternc_del_member");
- $db->query("UPDATE certificates SET ssl_action='DELETE' WHERE uid='$cuid'");
- return true;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Hook which returns the used quota for the $name service for the current user.
- * @param $name string name of the quota
- * @return integer the number of service used or false if an error occured
- * @access private
- */
- function hook_quota_get() {
- global $db,$err,$cuid;
- $err->log("ssl","getquota");
- $q=Array("name"=>"ssl", "description"=>_("SSL Certificates"), "used"=>0);
- $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' AND status!=".self::STATUS_EXPIRED);
- if ($db->next_record()) {
- $q['used']=$db->f("cnt");
- }
- return $q;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Export every information for an AlternC's account
- * @access private
- * EXPERIMENTAL 'sid' function ;)
- */
- function alternc_export_conf() {
- global $db,$err;
- $err->log("ssl","export");
- $f=$this->get_list();
- $str=" ";
- $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' AND status!=".self::STATUS_EXPIRED);
- while ($db->next_record()) {
- $str.=" ".($db->Record["id"])."\n";
- $str.=" ".($db->Record["sslcsr"])."\n";
- $str.=" ".($db->Record["sslkey"])."\n";
- $str.=" ".($db->Record["sslcrt"])."\n";
- $str.=" ".($db->Record["sslchain"])."\n";
- }
- $str.=" \n";
- return $str;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Returns the list of alternate names of an X.509 SSL Certificate
- * from the attribute list.
- * @param $str string the $crtdata["extensions"]["subjectAltName"] from openssl
- * @return array an array of FQDNs
- */
- function parseAltNames($str) {
- if (preg_match_all("#DNS:([^,]*),#",$str,$mat, PREG_PATTERN_ORDER)) {
- return implode("\n",$mat[1]);
- } else {
- return "";
- }
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Add (immediately) a global alias to the HTTP
- * certif_alias table and add it to apache configuration
- * by launching a incron action.
- * name is the name of the alias, starting by /
- * content is the content of the filename stored at this location
- * If an alias with the same name already exists, return false.
- * if the alias has been properly defined, return true.
- * @return boolean
- */
- function alias_add($name,$content) {
- global $err,$cuid,$db;
- $db->query("SELECT name FROM certif_alias WHERE name='".addslashes($name)."';");
- if ($db->next_record()) {
- $err->raise("ssl",_("Alias already exists"));
- return false;
- }
- $db->query("INSERT INTO certif_alias SET name='".addslashes($name)."', content='".addslashes($content)."', uid=".intval($cuid).";");
- touch(self::SSL_INCRON_FILE);
- return true;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Removes (immediately) a global alias to the HTTP
- * certif_alias table and add it to apache configuration
- * by launching a incron action.
- * name is the name of the alias, starting by /
- * @return boolean
- */
- function alias_del($name) {
- global $err,$cuid,$db;
- $db->query("SELECT name FROM certif_alias WHERE name='".addslashes($name)."' AND uid=".intval($cuid).";");
- if (!$db->next_record()) {
- $err->raise("ssl",_("Alias not found"));
- return false;
- }
- $db->query("DELETE FROM certif_alias WHERE name='".addslashes($name)."' AND uid=".intval($cuid).";");
- touch(self::SSL_INCRON_FILE);
- return true;
- }
-
-
- /* ----------------------------------------------------------------- */
- /** Check that a crt is a proper certificate
- * @param $crt string an SSL Certificate
- * @param $chain string is a list of certificates
- * @param $key string is a rsa key associated with certificate
- * @param $certid if no key is specified, use it from this certificate ID in the table
- * @return array the crt, chain, key, crtdata(array) after a proper reformatting
- * or false if an error occurred (in that case $this->error is filled)
- */
- function check_cert($crt,$chain,$key="",$certid=null) {
- global $err,$cuid,$db;
- // Check that the key crt and chain are really SSL certificates and keys
- $crt=trim(str_replace("\r\n","\n",$crt))."\n";
- $key=trim(str_replace("\r\n","\n",$key))."\n";
- $chain=trim(str_replace("\r\n","\n",$chain))."\n";
-
- $this->error="";
- if (trim($key)=="" && !is_null($certid)) {
- // find it in the DB :
- $db->query("SELECT sslkey FROM certificates WHERE id=".intval($certid).";");
- if (!$db->next_record()) {
- $this->error.=_("Can't find the private key in the certificate table, please check your form.");
- return false;
- }
- $key=$db->f("sslkey");
- $key=trim(str_replace("\r\n","\n",$key))."\n";
- }
-
- if (substr($crt,0,28)!="-----BEGIN CERTIFICATE-----\n" ||
- substr($crt,-26,26)!="-----END CERTIFICATE-----\n") {
- $this->error.=_("The certificate must begin by BEGIN CERTIFICATE and end by END CERTIFICATE lines. Please check you pasted it in PEM form.")."\n";
- }
- if ($chain &&
- (substr($chain,0,28)!="-----BEGIN CERTIFICATE-----\n" ||
- substr($chain,-26,26)!="-----END CERTIFICATE-----\n")) {
- $this->error.=_("The chained certificate must begin by BEGIN CERTIFICATE and end by END CERTIFICATE lines. Please check you pasted it in PEM form.")."\n";
- }
- if ( (substr($key,0,32)!="-----BEGIN RSA PRIVATE KEY-----\n" ||
- substr($key,-30,30)!="-----END RSA PRIVATE KEY-----\n") &&
- (substr($key,0,28)!="-----BEGIN PRIVATE KEY-----\n" ||
- substr($key,-26,26)!="-----END PRIVATE KEY-----\n") )
- {
- $this->error.=_("The private key must begin by BEGIN (RSA )PRIVATE KEY and end by END (RSA )PRIVATE KEY lines. Please check you pasted it in PEM form.")."\n";
- }
- if ($this->error) {
- return false;
+ $r = array();
+ while ($db->next_record()) {
+ $r[] = $db->f("fqdn");
+ }
+ // 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');");
+ $advice = array();
+ while ($db->next_record()) {
+ $me = $db->f("sub");
+ if ($me)
+ $me.=".";
+ $me.=$db->f("domaine");
+ if (!in_array($me, $r) && !in_array($me, $advice)) {
+ $advice[] = $me;
+ }
+ if (!in_array("*." . $db->f("domaine"), $r) && !in_array("*." . $db->f("domaine"), $advice)) {
+ $advice[] = "*." . $db->f("domaine");
+ }
+ }
+ sort($advice);
+ return($advice);
}
- // We split the chained certificates in individuals certificates :
- $chains=array();
- $status=0; $new="";
- $lines=explode("\n",$chain);
- foreach($lines as $line) {
- if ($line=="-----BEGIN CERTIFICATE-----" && $status==0) {
- $status=1;
- $new=$line."\n";
- continue;
- }
- if ($line=="-----END CERTIFICATE-----" && $status==1) {
- $status=0;
- $new.=$line."\n";
- $chains[]=$new;
- $new="";
- continue;
- }
- if ($status==1) {
- $new.=$line."\n";
- }
- }
- // here chains contains all the ssl certificates in the chained certs.
- // Now we check those using Openssl functions (real check :) )
- $rchains=array(); $i=0;
- foreach($chains as $tmpcert) {
- $i++;
- $tmpr=openssl_x509_read($tmpcert);
- if ($tmpr===false) {
- $this->error.=sprintf(_("The %d-th certificate in the chain is invalid"),$i)."\n";
- } else {
- $rchains[]=$tmpr;
- }
- }
- $validstart=0; $validend=0;
- $rcrt=openssl_x509_read($crt);
- $crtdata = openssl_x509_parse($crt);
- if ($rcrt===false || $crtdata===false) {
- $this->error.=_("The certificate is invalid.")."\n";
+ // -----------------------------------------------------------------
+ /** Import an existing ssl Key, Certificate and (maybe) a Chained Cert
+ * @param $key string the X.509 PEM-encoded RSA key
+ * @param $crt string the X.509 PEM-encoded certificate, which *must*
+ * be the one signinf the private RSA key in $key
+ * @param $chain string the X.509 PEM-encoded list of SSL Certificate chain if intermediate authorities
+ * @return integer the ID of the newly created certificate in the table
+ * or false if an error occurred
+ */
+ function import_cert($key, $crt, $chain = "") {
+ global $cuid, $err, $db;
+ $err->log("ssl", "import_cert");
+
+ $result = $this->check_cert($crt, $chain, $key);
+ if ($result === false) {
+ $err->raise("ssl", $this->error);
+ return false;
+ }
+ list($crt, $chain, $key, $crtdata) = $result;
+
+ $validstart = $crtdata['validFrom_time_t'];
+ $validend = $crtdata['validTo_time_t'];
+ $fqdn = $crtdata["subject"]["CN"];
+ $altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
+
+ // 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) . "';";
+ $db->query($sql);
+ if (!($id = $db->lastid())) {
+ $err->raise("ssl", _("Can't save the Key/Crt/Chain now. Please try later."));
+ return false;
+ }
+ return $id;
}
- $rkey=openssl_pkey_get_private($key);
- if ($rkey===false) {
- $this->error.=_("The private key is invalid.")."\n";
- }
- if (!$this->error) {
- // check that the private key and the certificates are matching :
- if (!openssl_x509_check_private_key($rcrt,$rkey)) {
- $this->error.=_("The private key is not the one signed inside the certificate.")."\n";
- }
- }
- if (!$this->error) {
- // Everything is fine, let's recreate crt, chain, key from our internal OpenSSL structures:
- if (!openssl_x509_export($rcrt,$crt)) {
- $this->error.=_("Can't export your certificate as a string, please check its syntax.")."\n";
- }
- $chain="";
- foreach($rchains as $r) {
- if (!openssl_x509_export($r,$tmp)) {
- $this->error.=_("Can't export one of your chained certificates as a string, please check its syntax.")."\n";
- } else {
- $chain.=$tmp;
- }
- }
- if (!openssl_pkey_export($rkey,$key)) {
- $this->error.=_("Can't export your private key as a string, please check its syntax.")."\n";
- }
- }
- return array($crt,$chain,$key,$crtdata);
- } // check_cert
+ // -----------------------------------------------------------------
+ /** Import an ssl certificate into an existing certificate entry in the DB.
+ * (finalize an enrollment process)
+ * @param $certid integer the ID in the database of the SSL Certificate
+ * @param $crt string the X.509 PEM-encoded certificate, which *must*
+ * be the one signing the private RSA key in certificate $certid
+ * @param $chain string the X.509 PEM-encoded list of SSL Certificate chain if intermediate authorities
+ * @return integer the ID of the updated certificate in the table
+ * or false if an error occurred
+ */
+ function finalize($certid, $crt, $chain) {
+ global $cuid, $err, $db;
+ $err->log("ssl", "finalize");
-
-} /* Class m_ssl */
+ $certid = intval($certid);
+ $result = $this->check_cert($crt, $chain, "", $certid);
+ if ($result === false) {
+ $err->raise("ssl", $this->error);
+ return false;
+ }
+ list($crt, $chain, $key, $crtdata) = $result;
+
+ $validstart = $crtdata['validFrom_time_t'];
+ $validend = $crtdata['validTo_time_t'];
+ $fqdn = $crtdata["subject"]["CN"];
+ $altnames = $this->parseAltNames($crtdata["extensions"]["subjectAltName"]);
+
+ // 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' ;";
+ if (!$db->query($sql)) {
+ $err->raise("ssl", _("Can't save the Crt/Chain now. Please try later."));
+ return false;
+ }
+ return $certid;
+ }
+
+ // -----------------------------------------------------------------
+ /** Function called by a hook when an AlternC member is deleted.
+ * @access private
+ * TODO: delete unused ssl certificates ?? > do this in the crontab.
+ */
+ function alternc_del_member() {
+ global $db, $err, $cuid;
+ $err->log("ssl", "alternc_del_member");
+ $db->query("UPDATE certificates SET ssl_action='DELETE' WHERE uid='$cuid'");
+ return true;
+ }
+
+ // -----------------------------------------------------------------
+ /** Hook which returns the used quota for the $name service for the current user.
+ * @param $name string name of the quota
+ * @return integer the number of service used or false if an error occured
+ * @access private
+ */
+ function hook_quota_get() {
+ global $db, $err, $cuid;
+ $err->log("ssl", "getquota");
+ $q = Array("name" => "ssl", "description" => _("SSL Certificates"), "used" => 0);
+ $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' AND status!=" . self::STATUS_EXPIRED);
+ if ($db->next_record()) {
+ $q['used'] = $db->f("cnt");
+ }
+ return $q;
+ }
+
+ // -----------------------------------------------------------------
+ /** Export every information for an AlternC's account
+ * @access private
+ * EXPERIMENTAL 'sid' function ;)
+ */
+ function alternc_export_conf() {
+ global $db, $err;
+ $err->log("ssl", "export");
+ $f = $this->get_list();
+ $str = " ";
+ $db->query("SELECT COUNT(*) AS cnt FROM certificates WHERE uid='$cuid' AND status!=" . self::STATUS_EXPIRED);
+ while ($db->next_record()) {
+ $str.=" " . ($db->Record["id"]) . "\n";
+ $str.=" " . ($db->Record["sslcsr"]) . "\n";
+ $str.=" " . ($db->Record["sslkey"]) . "\n";
+ $str.=" " . ($db->Record["sslcrt"]) . "\n";
+ $str.=" " . ($db->Record["sslchain"]) . "\n";
+ }
+ $str.=" \n";
+ return $str;
+ }
+
+ // -----------------------------------------------------------------
+ /** Returns the list of alternate names of an X.509 SSL Certificate
+ * from the attribute list.
+ * @param $str string the $crtdata["extensions"]["subjectAltName"] from openssl
+ * @return array an array of FQDNs
+ */
+ function parseAltNames($str) {
+ if (preg_match_all("#DNS:([^,]*),#", $str, $mat, PREG_PATTERN_ORDER)) {
+ return implode("\n", $mat[1]);
+ } else {
+ return "";
+ }
+ }
+
+ // -----------------------------------------------------------------
+ /** Add (immediately) a global alias to the HTTP
+ * certif_alias table and add it to apache configuration
+ * by launching a incron action.
+ * name is the name of the alias, starting by /
+ * content is the content of the filename stored at this location
+ * If an alias with the same name already exists, return false.
+ * if the alias has been properly defined, return true.
+ * @return boolean
+ */
+ function alias_add($name, $content) {
+ global $err, $cuid, $db;
+ $db->query("SELECT name FROM certif_alias WHERE name='" . addslashes($name) . "';");
+ if ($db->next_record()) {
+ $err->raise("ssl", _("Alias already exists"));
+ return false;
+ }
+ $db->query("INSERT INTO certif_alias SET name='" . addslashes($name) . "', content='" . addslashes($content) . "', uid=" . intval($cuid) . ";");
+ touch(self::SSL_INCRON_FILE);
+ return true;
+ }
+
+ // -----------------------------------------------------------------
+ /** Removes (immediately) a global alias to the HTTP
+ * certif_alias table and add it to apache configuration
+ * by launching a incron action.
+ * name is the name of the alias, starting by /
+ * @return boolean
+ */
+ function alias_del($name) {
+ global $err, $cuid, $db;
+ $db->query("SELECT name FROM certif_alias WHERE name='" . addslashes($name) . "' AND uid=" . intval($cuid) . ";");
+ if (!$db->next_record()) {
+ $err->raise("ssl", _("Alias not found"));
+ return false;
+ }
+ $db->query("DELETE FROM certif_alias WHERE name='" . addslashes($name) . "' AND uid=" . intval($cuid) . ";");
+ touch(self::SSL_INCRON_FILE);
+ return true;
+ }
+
+ // -----------------------------------------------------------------
+ /** Check that a crt is a proper certificate
+ * @param $crt string an SSL Certificate
+ * @param $chain string is a list of certificates
+ * @param $key string is a rsa key associated with certificate
+ * @param $certid if no key is specified, use it from this certificate ID in the table
+ * @return array the crt, chain, key, crtdata(array) after a proper reformatting
+ * or false if an error occurred (in that case $this->error is filled)
+ */
+ function check_cert($crt, $chain, $key = "", $certid = null) {
+ global $err, $cuid, $db;
+ // Check that the key crt and chain are really SSL certificates and keys
+ $crt = trim(str_replace("\r\n", "\n", $crt)) . "\n";
+ $key = trim(str_replace("\r\n", "\n", $key)) . "\n";
+ $chain = trim(str_replace("\r\n", "\n", $chain)) . "\n";
+
+ $this->error = "";
+ if (trim($key) == "" && !is_null($certid)) {
+ // find it in the DB :
+ $db->query("SELECT sslkey FROM certificates WHERE id=" . intval($certid) . ";");
+ if (!$db->next_record()) {
+ $this->error.=_("Can't find the private key in the certificate table, please check your form.");
+ return false;
+ }
+ $key = $db->f("sslkey");
+ $key = trim(str_replace("\r\n", "\n", $key)) . "\n";
+ }
+
+ if (substr($crt, 0, 28) != "-----BEGIN CERTIFICATE-----\n" ||
+ substr($crt, -26, 26) != "-----END CERTIFICATE-----\n") {
+ $this->error.=_("The certificate must begin by BEGIN CERTIFICATE and end by END CERTIFICATE lines. Please check you pasted it in PEM form.") . "\n";
+ }
+ if ($chain &&
+ (substr($chain, 0, 28) != "-----BEGIN CERTIFICATE-----\n" ||
+ substr($chain, -26, 26) != "-----END CERTIFICATE-----\n")) {
+ $this->error.=_("The chained certificate must begin by BEGIN CERTIFICATE and end by END CERTIFICATE lines. Please check you pasted it in PEM form.") . "\n";
+ }
+ if ((substr($key, 0, 32) != "-----BEGIN RSA PRIVATE KEY-----\n" ||
+ substr($key, -30, 30) != "-----END RSA PRIVATE KEY-----\n") &&
+ (substr($key, 0, 28) != "-----BEGIN PRIVATE KEY-----\n" ||
+ substr($key, -26, 26) != "-----END PRIVATE KEY-----\n")) {
+ $this->error.=_("The private key must begin by BEGIN (RSA )PRIVATE KEY and end by END (RSA )PRIVATE KEY lines. Please check you pasted it in PEM form.") . "\n";
+ }
+ if ($this->error) {
+ return false;
+ }
+
+ // We split the chained certificates in individuals certificates :
+ $chains = array();
+ $status = 0;
+ $new = "";
+ $lines = explode("\n", $chain);
+ foreach ($lines as $line) {
+ if ($line == "-----BEGIN CERTIFICATE-----" && $status == 0) {
+ $status = 1;
+ $new = $line . "\n";
+ continue;
+ }
+ if ($line == "-----END CERTIFICATE-----" && $status == 1) {
+ $status = 0;
+ $new.=$line . "\n";
+ $chains[] = $new;
+ $new = "";
+ continue;
+ }
+ if ($status == 1) {
+ $new.=$line . "\n";
+ }
+ }
+ // here chains contains all the ssl certificates in the chained certs.
+ // Now we check those using Openssl functions (real check :) )
+ $rchains = array();
+ $i = 0;
+ foreach ($chains as $tmpcert) {
+ $i++;
+ $tmpr = openssl_x509_read($tmpcert);
+ if ($tmpr === false) {
+ $this->error.=sprintf(_("The %d-th certificate in the chain is invalid"), $i) . "\n";
+ } else {
+ $rchains[] = $tmpr;
+ }
+ }
+ $validstart = 0;
+ $validend = 0;
+ $rcrt = openssl_x509_read($crt);
+ $crtdata = openssl_x509_parse($crt);
+ if ($rcrt === false || $crtdata === false) {
+ $this->error.=_("The certificate is invalid.") . "\n";
+ }
+
+ $rkey = openssl_pkey_get_private($key);
+ if ($rkey === false) {
+ $this->error.=_("The private key is invalid.") . "\n";
+ }
+ if (!$this->error) {
+ // check that the private key and the certificates are matching :
+ if (!openssl_x509_check_private_key($rcrt, $rkey)) {
+ $this->error.=_("The private key is not the one signed inside the certificate.") . "\n";
+ }
+ }
+ if (!$this->error) {
+ // Everything is fine, let's recreate crt, chain, key from our internal OpenSSL structures:
+ if (!openssl_x509_export($rcrt, $crt)) {
+ $this->error.=_("Can't export your certificate as a string, please check its syntax.") . "\n";
+ }
+ $chain = "";
+ foreach ($rchains as $r) {
+ if (!openssl_x509_export($r, $tmp)) {
+ $this->error.=_("Can't export one of your chained certificates as a string, please check its syntax.") . "\n";
+ } else {
+ $chain.=$tmp;
+ }
+ }
+ if (!openssl_pkey_export($rkey, $key)) {
+ $this->error.=_("Can't export your private key as a string, please check its syntax.") . "\n";
+ }
+ }
+ return array($crt, $chain, $key, $crtdata);
+ }
+
+// check_cert
+}
+
+/* Class m_ssl */