From 06313e510a5907b8083ca83d68042616c7b8c8cd Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 10 Feb 2015 16:10:54 +0100 Subject: [PATCH] *space changes only* --- ssl/api/Ssl.php | 25 +- ssl/panel/admin/ssl_doimport.php | 71 +- ssl/panel/admin/ssl_donew.php | 77 +-- ssl/panel/admin/ssl_finalize.php | 63 +- ssl/panel/admin/ssl_list.php | 148 +++-- ssl/panel/admin/ssl_new.php | 235 +++---- ssl/panel/admin/ssl_share.php | 59 +- ssl/panel/admin/ssl_view.php | 353 +++++----- ssl/panel/class/m_ssl.php | 1046 +++++++++++++++--------------- 9 files changed, 1035 insertions(+), 1042 deletions(-) diff --git a/ssl/api/Ssl.php b/ssl/api/Ssl.php index d75ac02e..be7a0ac6 100644 --- a/ssl/api/Ssl.php +++ b/ssl/api/Ssl.php @@ -3,18 +3,13 @@ /** * SSL Api of AlternC, used by alternc-api package */ -class Alternc_Api_Object_Ssl { - - const ERR_INVALID_ARGUMENT = 11151901; - const ERR_ALTERNC_FUNCTION = 11151902; +class Alternc_Api_Object_Ssl extends Alternc_Api_Legacyobject { + protected $ssl; + function __construct($service) { - global $ssl,$cuid; - if (!($service instanceof Alternc_Api_Service)) { - throw new \Exception("Bad argument: service is not an Alternc_Api_Service", self::ERR_INVALID_ARGUMENT); - } - // We store the global $cuid to AlternC legacy classes - $cuid=$service->token->uid; + global $ssl; + parent::__construct($service); // We use the global $ssl from AlternC legacy classes $this->ssl=$ssl; } @@ -189,14 +184,4 @@ class Alternc_Api_Object_Ssl { - - /** return a proper Alternc_Api_Response from an error class and error string - * from AlternC legacy class - */ - private function alterncLegacyErrorManager() { - global $err; - return new Alternc_Api_Response( array("code" => self::ERR_ALTERNC_FUNCTION, "message" => "[".$err->clsid."] ".$err->error) ); - } - - } // class Alternc_Api_Object_Ssl \ No newline at end of file diff --git a/ssl/panel/admin/ssl_doimport.php b/ssl/panel/admin/ssl_doimport.php index 64ac8ff0..49abb14a 100644 --- a/ssl/panel/admin/ssl_doimport.php +++ b/ssl/panel/admin/ssl_doimport.php @@ -1,52 +1,53 @@ array ("post", "string", ""), - "crt" => array ("post", "string", ""), - "chain" => array ("post", "string", ""), - ); - getFields($fields); +if (!isset($is_include)) { + $fields = array( + "key" => array("post", "string", ""), + "crt" => array("post", "string", ""), + "chain" => array("post", "string", ""), + ); + getFields($fields); } if (!$key && !$crt) { - $error=_("Please enter an ssl key and a certificate"); - require_once("ssl_new.php"); - exit(); + $error = _("Please enter an ssl key and a certificate"); + require_once("ssl_new.php"); + exit(); } -$id=$ssl->import_cert($key,$crt,$chain); -$error=$err->errstr(); +$id = $ssl->import_cert($key, $crt, $chain); +$error = $err->errstr(); if ($error) { - require_once("ssl_new.php"); - exit(); + require_once("ssl_new.php"); + exit(); } -header("Location: /ssl_view.php?id=".$id); +header("Location: /ssl_view.php?id=" . $id); diff --git a/ssl/panel/admin/ssl_donew.php b/ssl/panel/admin/ssl_donew.php index 4897f3b3..598ea859 100644 --- a/ssl/panel/admin/ssl_donew.php +++ b/ssl/panel/admin/ssl_donew.php @@ -1,54 +1,57 @@ array ("request", "string", ""), - "fqdnt" => array ("request", "string", ""), - ); - getFields($fields); +if (!isset($is_include)) { + $fields = array( + "fqdn" => array("request", "string", ""), + "fqdnt" => array("request", "string", ""), + ); + getFields($fields); } if (!$fqdn && !$fqdnt) { - $error=_("Please enter a proper domain name"); - require_once("ssl_new.php"); - exit(); + $error = _("Please enter a proper domain name"); + require_once("ssl_new.php"); + exit(); } -if ($fqdnt) $d=$fqdnt; -if ($fqdn) $d=$fqdn; +if ($fqdnt) + $d = $fqdnt; +if ($fqdn) + $d = $fqdn; -$id=$ssl->new_csr($d); -$error=$err->errstr(); +$id = $ssl->new_csr($d); +$error = $err->errstr(); if ($error) { - require_once("ssl_new.php"); - exit(); + require_once("ssl_new.php"); + exit(); } -$is_include=true; -require_once("ssl_view.php"); +$is_include = true; +require_once("ssl_view.php"); diff --git a/ssl/panel/admin/ssl_finalize.php b/ssl/panel/admin/ssl_finalize.php index 2e61b9b2..440aa226 100644 --- a/ssl/panel/admin/ssl_finalize.php +++ b/ssl/panel/admin/ssl_finalize.php @@ -1,44 +1,45 @@ array ("post", "integer", ""), - "crt" => array ("post", "string", ""), - "chain" => array ("post", "string", ""), - ); +$fields = array( + "id" => array("post", "integer", ""), + "crt" => array("post", "string", ""), + "chain" => array("post", "string", ""), +); getFields($fields); -$cert=$ssl->finalize($id,$crt,$chain); +$cert = $ssl->finalize($id, $crt, $chain); echo $ssl->error; -$error=$err->errstr(); +$error = $err->errstr(); if ($error) { - require_once("ssl_list.php"); - exit(); + require_once("ssl_list.php"); + exit(); } -$info=_("Your ssl certificate has been imported successfully"); +$info = _("Your ssl certificate has been imported successfully"); -require_once("ssl_view.php"); +require_once("ssl_view.php"); diff --git a/ssl/panel/admin/ssl_list.php b/ssl/panel/admin/ssl_list.php index 3ea52986..f0d97bda 100644 --- a/ssl/panel/admin/ssl_list.php +++ b/ssl/panel/admin/ssl_list.php @@ -1,106 +1,110 @@ array ("request", "integer", null), - "filter1" => array ("request", "integer", 0), - "filter2" => array ("request", "integer", 0), - "filter4" => array ("request", "integer", 0), - "filter8" => array ("request", "integer", 0), - ); - getFields($fields); +if (!isset($is_include)) { + $fields = array( + "filter" => array("request", "integer", null), + "filter1" => array("request", "integer", 0), + "filter2" => array("request", "integer", 0), + "filter4" => array("request", "integer", 0), + "filter8" => array("request", "integer", 0), + ); + getFields($fields); } if (isset($filter1) && isset($filter2) && isset($filter4) && isset($filter8)) { - $filter=$filter1+$filter2+$filter4+$filter8; - if ($filter==0) $filter=null; + $filter = $filter1 + $filter2 + $filter4 + $filter8; + if ($filter == 0) + $filter = null; } -$r=$ssl->get_list($filter); +$r = $ssl->get_list($filter); -if (!$error) $error.=$err->errstr(); +if (!$error) + $error.=$err->errstr(); -$astatus=array( - $ssl::STATUS_PENDING => _("Pending Certificate"), - $ssl::STATUS_OK => _("Valid"), - $ssl::STATUS_EXPIRED => ("Expired"), - ); +$astatus = array( + $ssl::STATUS_PENDING => _("Pending Certificate"), + $ssl::STATUS_OK => _("Valid"), + $ssl::STATUS_EXPIRED => ("Expired"), +); include_once("head.php"); if ($error) { - echo "

$error

"; + echo "

$error

"; } if ($info) { - echo "

$info

"; + echo "

$info

"; } - ?>

-
-


- - - -
- -     -"/> + +


+ + + +
+ +     + "/>

- - - - + + + + - - - - - - - - - - - + + + + + + + + + +
"._("(shared)").""; ?>
" . _("(shared)") . ""; + ?>

- +

diff --git a/ssl/panel/admin/ssl_new.php b/ssl/panel/admin/ssl_new.php index 0fd49104..9780d1fd 100644 --- a/ssl/panel/admin/ssl_new.php +++ b/ssl/panel/admin/ssl_new.php @@ -1,163 +1,164 @@ array ("request", "string", ""), - "key" => array ("request", "string", ""), - "crt" => array ("request", "string", ""), - "chain" => array ("request", "string", ""), - ); - getFields($fields); +if (!isset($is_include)) { + $fields = array( + "fqdnt" => array("request", "string", ""), + "key" => array("request", "string", ""), + "crt" => array("request", "string", ""), + "chain" => array("request", "string", ""), + ); + getFields($fields); } -$advice=$ssl->get_new_advice(); +$advice = $ssl->get_new_advice(); ?>

$error

"; + echo "

$error

"; } ?>

- +

- 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"); ?>

- + -
- - - - - - -
- -
- - type="text" class="int" name="fqdnt" id="fqdnt" value="" size="40" maxlength="64" /> type="button" id="relist" name="relist" value=" list v " onclick="switchlist()" /> -
-

- "/>   - " onclick="document.location='ssl_list.php'"/> -

-
+
+ + + + + + +
+ +
+ + type="text" class="int" name="fqdnt" id="fqdnt" value="" size="40" maxlength="64" /> type="button" id="relist" name="relist" value=" list v " onclick="switchlist()" /> +
+

+ "/>   + " onclick="document.location = 'ssl_list.php'"/> +

+
-
-

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.)"); ?>

+
-
+
-
-

+
+

-

-

+

+

-
- - - - - - - - - - - - - -
-

- "/>   - " onclick="document.location='ssl_list.php'"/> -

-
-
+
+ + + + + + + + + + + + + +
+

+ "/>   + " onclick="document.location = 'ssl_list.php'"/> +

+
+
-
+
diff --git a/ssl/panel/admin/ssl_share.php b/ssl/panel/admin/ssl_share.php index 4368031e..c17e7716 100644 --- a/ssl/panel/admin/ssl_share.php +++ b/ssl/panel/admin/ssl_share.php @@ -1,44 +1,45 @@ enabled) { - __("This page is restricted to authorized staff"); - exit(); + __("This page is restricted to authorized staff"); + exit(); } -$fields = array ( - "id" => array ("request", "integer", 0), - "action" => array ("request", "integer", 0), - ); +$fields = array( + "id" => array("request", "integer", 0), + "action" => array("request", "integer", 0), +); getFields($fields); -if ($ssl->share($id,$action)) { - require_once("ssl_view.php"); +if ($ssl->share($id, $action)) { + require_once("ssl_view.php"); } else { - require_once("ssl_list.php"); + require_once("ssl_list.php"); } diff --git a/ssl/panel/admin/ssl_view.php b/ssl/panel/admin/ssl_view.php index c4a2cd27..cd063eca 100644 --- a/ssl/panel/admin/ssl_view.php +++ b/ssl/panel/admin/ssl_view.php @@ -1,197 +1,200 @@ array ("request", "integer", ""), - ); - getFields($fields); +if (!isset($is_include)) { + $fields = array( + "id" => array("request", "integer", ""), + ); + getFields($fields); } -$cert=$ssl->get_certificate($id); -$error=$err->errstr(); +$cert = $ssl->get_certificate($id); +$error = $err->errstr(); if ($error) { - require_once("ssl_list.php"); - exit(); + require_once("ssl_list.php"); + exit(); } include_once("head.php"); if ($info) { - echo "

$info

"; + echo "

$info

"; } -if ($cert["status"]==$ssl::STATUS_PENDING) { -?> -

- -

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."); ?>

- -
-"/> - - - - - - - - - - - - - - - - - - - - - -
-

- "/>   - " onclick="document.location='ssl_list.php'"/> - -

-
- - -

-

- - -

-

- - -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-enabled) { -?> -

(This is only useful for wildcard or multi-domain certificates)."); ?>

-

-shared"); - if ($cert["uid"]==$cuid) { -?> -

-
-"/> - -" /> -
-NOT shared"); - if ($cert["uid"]==$cuid) { +if ($cert["status"] == $ssl::STATUS_PENDING) { ?> +

+ +

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."); ?>

+ +
+ "/> + + + + + + + + + + + + + + + + + + + + + +
+

+ "/>   + " onclick="document.location = 'ssl_list.php'"/> + +

+
+ + +

+

+ + +

+

+ + +

+

-
-"/> - -" /> -
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 */