0011222: Update and decoupling of digital certificate implementation
authorFlávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
Tue, 11 Aug 2015 16:17:19 +0000 (13:17 -0300)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 12 Aug 2015 14:55:15 +0000 (16:55 +0200)
- Update implementation of customized ModSsql auth adapter
- Separate specific implementation of X.509 standard

Change-Id: Ie6d9cff53a13314ae984886c60984c0c50e479f4
Reviewed-on: https://gerrit.tine20.org/tine20/3186
Tested-by: jenkins user
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
15 files changed:
tine20/library/Custom/Auth/ModSsl/Certificate/Factory.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/Certificate/ICPBrasil.php [moved from tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/ICPBrasil.php with 66% similarity]
tine20/library/Custom/Auth/ModSsl/Certificate/X509.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/Exception/OpensslNotLoaded.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/UsernameCallback/Abstract.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/UsernameCallback/Cpf.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/UsernameCallback/Email.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/UsernameCallback/Interface.php [new file with mode: 0644]
tine20/library/Custom/Auth/ModSsl/UsernameCallback/Standard.php [new file with mode: 0644]
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl.php
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Abstract.php [deleted file]
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Apache.php [deleted file]
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Factory.php [deleted file]
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Interface.php [deleted file]
tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/X509.php [deleted file]

diff --git a/tine20/library/Custom/Auth/ModSsl/Certificate/Factory.php b/tine20/library/Custom/Auth/ModSsl/Certificate/Factory.php
new file mode 100644 (file)
index 0000000..539034e
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @todo        verify certificate format
+ * @todo        support other possible formats pkcs7, pkcs12, etc?
+ * 
+ */
+
+class Custom_Auth_ModSsl_Certificate_Factory
+{
+    
+    /**
+     *
+     * @param type $certificate
+     * @return \Custom_Auth_ModSsl_Certificate_ICPBrasil|\Custom_Auth_ModSsl_Certificate_X509
+     * @throws Custom_Auth_ModSsl_Exception_OpensslNotLoaded 
+     */
+    public static function buildCertificate($certificate, $dontSkip = FALSE)
+    {   
+        if(!extension_loaded('openssl'))
+        {
+            // No suport to openssl.....
+            throw new Custom_Auth_ModSsl_Exception_OpensslNotLoaded('Openssl not supported!');
+        }
+        
+        if (!preg_match('/^-----BEGIN CERTIFICATE-----/', $certificate)){
+            // TODO: convert to pem
+        }
+        
+        // get Oids from ICPBRASIL
+        $icpBrasilData = Custom_Auth_ModSsl_Certificate_ICPBrasil::parseICPBrasilData($certificate);
+        if ($icpBrasilData)
+        {
+            return new Custom_Auth_ModSsl_Certificate_ICPBrasil($certificate, $icpBrasilData, $dontSkip);
+        }
+        return new Custom_Auth_ModSsl_Certificate_X509($certificate, $dontSkip);
+        
+    }
+    
+}
@@ -1,38 +1,22 @@
 <?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
 
 /**
- * class to handle ICP Brasil specific certificate attributes
+ * Tine 2.0
  *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @todo       support titulo and INSS Data
- * @todo       support pf and app/server certificates data.
- * @todo       treat other OIDs
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @todo        support titulo and INSS Data
+ * @todo        support pf and app/server certificates data.
+ * @todo        treat other OIDs
+ * 
  */
-class Zend_Auth_Adapter_ModSsl_Certificate_ICPBrasil extends Zend_Auth_Adapter_ModSsl_Certificate_X509
+
+class Custom_Auth_ModSsl_Certificate_ICPBrasil extends Custom_Auth_ModSsl_Certificate_X509
 {
     const OID_PF = '2.16.76.1.3.1';
     const OID_PJ_RESPONSAVEL = '2.16.76.1.3.2';
@@ -56,25 +40,21 @@ class Zend_Auth_Adapter_ModSsl_Certificate_ICPBrasil extends Zend_Auth_Adapter_M
     /**
      * @var boolean
      */
-    protected $app        = false;
-    protected $cpf        = null;
+    protected $app = false;
+    protected $cpf = null;
     protected $nascimento = null;
-    protected $nis        = null;
-    protected $rg         = null;
-    protected $orgaoUF    = null;
+    protected $nis = null;
+    protected $rg = null;
+    protected $orgaoUF = null;
     
-    public function __construct($certificate, $icpBrasilData)
+    public function __construct($certificate, $icpBrasilData, $dontSkip = FALSE)
     {
-        parent::__construct($options, $certificate);
-        
-        $icpBrasilData = self::parseICPBrasilData($this->_certificate);
-        
         // parse $oid and get specific info from
-        if ((isset($icpBrasilData[self::OID_PF]) || array_key_exists(self::OID_PF, $icpBrasilData))) {
+        if (array_key_exists(self::OID_PF, $icpBrasilData)) {
             $this->pf = true;
-        } else if ((isset($icpBrasilData[self::OID_PJ_CEI]) || array_key_exists(self::OID_PJ_CEI, $icpBrasilData))) {
+        } else if (array_key_exists(self::OID_PJ_CEI, $icpBrasilData)) {
             $this->pj = true;
-        } else if ((isset($icpBrasilData[self::OID_APP_NOMEEMPRESARIAL]) || array_key_exists(self::OID_APP_NOMEEMPRESARIAL, $icpBrasilData))) {
+        } else if (array_key_exists(self::OID_APP_NOMEEMPRESARIAL, $icpBrasilData)) {
             $this->app = true;
         }
         
@@ -88,6 +68,8 @@ class Zend_Auth_Adapter_ModSsl_Certificate_ICPBrasil extends Zend_Auth_Adapter_M
                 $this->orgaoUF['ORGAOUF'];
             }
         }
+        
+        parent::__construct($certificate, $dontSkip);
     }
     
     /**
@@ -140,7 +122,7 @@ class Zend_Auth_Adapter_ModSsl_Certificate_ICPBrasil extends Zend_Auth_Adapter_M
         );
 
         $result = array();
-        $derCertificate = self::pem2Der($certificate);
+        $derCertificate = self::pem2Der(self::_fixPemCertificate($certificate));
             
         foreach ($oids as $oid => $thisOid) {
 
@@ -212,16 +194,6 @@ class Zend_Auth_Adapter_ModSsl_Certificate_ICPBrasil extends Zend_Auth_Adapter_M
         return $this->rg;
     }
 
-    public function getUserName()
-    {
-        if ($this->isPF()) {
-            return $this->getCPF();
-        } else {
-            // TODO: throw an exception
-            return null;
-        }
-    }
-    
     public function getOrgaoUF()
     {
         return $this->orgaoUF;
diff --git a/tine20/library/Custom/Auth/ModSsl/Certificate/X509.php b/tine20/library/Custom/Auth/ModSsl/Certificate/X509.php
new file mode 100644 (file)
index 0000000..06fdf91
--- /dev/null
@@ -0,0 +1,517 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @todo        parse authorityInfoAccess, caissuer and ocsp
+ * @todo        parse authorityKeyIdentifier
+ * @todo        phpdoc of all methods
+ * @todo        change the name of the protected variables to the standart coding defalt (_var)
+ * 
+ */
+
+class Custom_Auth_ModSsl_Certificate_X509
+{
+    protected $certificate;
+    /*
+     * default values for casfile and crlspath
+     */
+    protected $casfile = 'skip';
+    protected $crlspath = 'skip';
+    
+    protected $serialNumber = null;
+    protected $version = null;
+    protected $subject = null;
+    protected $cn = null;
+    protected $issuer = null;
+    protected $issuerCn = null;
+    protected $hash = null;
+    protected $validFrom = null;
+    protected $validTo = null;
+    protected $canSign = false;
+    protected $canEncrypt = false;
+    protected $email = null;
+    protected $ca = false;
+    protected $authorityKeyIdentifier = null;
+    protected $crlDistributionPoints = null;
+    protected $authorityInfoAccess = null;
+    protected $status =  array();
+    
+    public function __construct($certificate, $dontSkip = FALSE)
+    {   
+        $config = Tinebase_Config::getInstance()->get('modssl');
+        if (is_object($config)){
+            $this->casfile = $config->casfile;
+            $this->crlspath = $config->crlspath;
+        }
+        $this->status = array('isValid' => true,'errors' => array());
+        $this->certificate = self::_fixPemCertificate($certificate);
+        $c = openssl_x509_parse($this->certificate);
+        
+        // define certificate properties
+        $this->serialNumber = $c['serialNumber'];
+        $this->version = $c['version'];
+        $this->subject = $c['subject'];
+        $this->cn = $c['subject']['CN'];
+        $this->issuer = $c['issuer'];
+        $this->issuerCn = $c['issuer']['CN'];
+        $this->hash = $this->_calcHash();
+        
+//        $dateTimezone = new DateTimeZone(Tinebase_Core::getUserTimezone());
+//        $locale = new Zend_Locale($_translation->getAdapter()->getLocale());
+        
+        // Date valid from
+        
+        $this->validFrom = Tinebase_Translation::dateToStringInTzAndLocaleFormat(new Tinebase_DateTime($c['validFrom_time_t']));
+        
+        // Date valid to
+        $this->validTo = Tinebase_Translation::dateToStringInTzAndLocaleFormat(new Tinebase_DateTime($c['validTo_time_t']));
+        $this->_parsePurpose($c['purposes']);
+        $this->_parseExtensions($c['extensions']);
+              
+        if(strtolower($this->casfile) != 'skip') {
+            $this->_validityCheck(); // skip validation, we trust the server's result
+        }
+        
+        if(strtolower($this->crlspath) != 'skip' | $dontSkip) {
+            $this->_testRevoked(); // skip test,
+        }
+    }
+
+    /**
+     * Reads a file with digital certificates in PEM format
+     *
+     * @param String $filename
+     * @return array of Addresbook_Model_Certificate
+     * @todo Add auditing code when implementation becomes available
+     */
+    static public function readCertificatesFile($filename){
+        
+        $fileContents = file_get_contents($filename);
+        if ($fileContents !== false) {
+            self::_fixPemCertificate($fileContents);
+        } else {
+            Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__
+                . ' Error reading certificates file ' . $filename
+            );
+            return array();
+        }
+
+        $result = array();
+        $match = array();
+        preg_match_all('/(-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----)/s', $fileContents, $match);
+        foreach ($match[0] as $pemCertificate) {
+            //$x509Certificate = Custom_Auth_ModSsl_Certificate_Factory::buildCertificate($pemCertificate, true);
+            $certificateModel = Custom_Model_DigitalCertificateValidation::createFromCertificate($pemCertificate, TRUE, TRUE);
+            $result[] = $certificateModel->toArray();
+        }
+        return $result;
+    }
+
+    static protected function _fixPemCertificate($certificate)
+    {
+        $pemFormat = preg_replace('/ (?!CERTIFICATE-----)/', chr(0x0D).chr(0x0A), $certificate);
+        
+        return $pemFormat;
+    }
+
+
+    protected function _calcHash() {
+        $derCertificate = self::pem2Der($this->certificate);
+        return hash('sha256', $derCertificate);
+    }
+    
+    protected function _parseExtensions($extensions)
+    {
+        if (is_array($extensions)){
+            foreach ($extensions as $extension => $value) {
+                $matches = array();
+                switch ($extension) {
+                    case 'subjectAltName':
+                        if (preg_match('/email:(\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b)/i', $value, $matches)) {
+                            $this->email = $matches[1];
+                        }
+                        break;
+                    case 'basicConstraints' :
+                        if (preg_match('/\bCA:(FALSE|TRUE)\b/', $value, $matches)) {
+                            $this->ca = $matches[1] == 'TRUE' ? TRUE : FALSE;
+                        }
+                        break;
+                    case 'crlDistributionPoints' :
+                        $lines = explode(chr(0x0A), trim($value));
+                        $crlDist = array();
+                        foreach ($lines as $line) {
+                            $line = trim($line);
+                            if (preg_match('/URI:/', $line) === 1){
+                                $crlDist[] = preg_replace('/URI:/', '', $line);
+                            }
+                        }
+                        $this->crlDistributionPoints = $crlDist;
+                        break;
+
+                    case 'authorityKeyIdentifier' :
+                        if (preg_match('/\bkeyid:(\b([a-f0-9]{2}:)+[a-f0-9]{2}\b)/i', $value, $matches))
+                        {
+                            $this->authorityKeyIdentifier = $matches[1];
+                        } else {
+                            Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ":\nauthorityKeyIdentifier not found!");
+                        }
+
+                        break;
+    //                 // TODO: ocsp
+    //                case 'authorityInfoAccess' :
+    //                    if (preg_match('/\bCA Issuers - URI:(http(?:s)?\:\/\/[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*\.[a-zA-Z]{2,6}(?:\/?|(?:\/[\w\-]+)*)(?:\/?|\/\w+\.[a-zA-Z]{2,4}(?:\?[\w]+\=[\w\-]+)?)?(?:\&[\w]+\=[\w\-]+)*\b)/', $value, $matches))
+    //                    {
+    //                        $tmp = '';
+    //                    }
+    //                    break;
+                }
+            }
+        }
+    }
+    
+    protected function _parsePurpose($purposes)
+    {
+        if (is_array($purposes)){
+            foreach ($purposes as $purpose) {
+                switch ($purpose[2]) {
+                    case 'smimesign' :
+                        $this->canSign = $purpose[0] == 1 ? true : false;
+                        break;
+                    case 'smimeencrypt' :
+                        $this->canEncrypt = $purpose[0] == 1 ? true : false;
+                        break;
+                }
+            }
+        }
+    }
+    
+    protected function _validityCheck() 
+    {
+        $cdError = Tinebase_Translation::getTranslation('Tinebase')->_('Couldn\'t verify if certificate was revoked.');
+        if(!is_file($this->casfile)) {
+            $this->status['errors'][] = 'Invalid Certificate .(CA-01)';  //'CAs file not found.';
+            $this->status['isValid'] = false;
+            return;
+        }
+        
+        $temporary_files = array();
+        $certTempFile = self::generateTempFilename($temporary_files, Tinebase_Core::getTempDir());
+        self::writeTo($certTempFile,$this->certificate);
+        
+        // Get serialnumber  by comand line ...
+        $out = array();
+        $w = exec('openssl x509 -inform PEM -in ' . $certTempFile . ' -noout -serial',$out);
+        $aux = explode('serial=',$out[0]);
+        
+        if(isset($aux[1]))  {
+            $this->serialNumber = $aux[1];
+        } else {
+            $this->serialNumber = null;
+        }
+    
+        $out = array();
+        // certificate verify ...
+        $w = exec('openssl verify -CAfile '.$this->casfile.' '.$certTempFile,$out);
+        self::removeTempFiles($temporary_files);
+        $aux = explode(' ',$w);
+        if(isset($aux[1])) {
+            if($aux[1] != 'OK') {
+                foreach($out as $item) {
+                    $aux = explode(':',$item);
+                    if(isset($aux[1])) {
+                        $this->status['errors'][] = Tinebase_Translation::getTranslation('Tinebase')->_(trim($aux[1]));
+                        $this->status['isValid'] = false;
+                    }
+                }
+                return;
+            }
+        } else {
+            $this->status['errors'][] = (isset($aux[1]) ? trim($aux[1]) : $cdError.'(CD-01)');
+            $this->status['isValid'] = false;
+        }
+       
+    }
+
+    /**
+     *
+     * @return type 
+     */
+    protected function _testRevoked()
+    {
+        $error = Tinebase_Translation::getTranslation('Tinebase')->_('Couldn\'t verify if certificate was revoked.');
+        if(!is_dir($this->crlspath)) {
+            $this->status['errors'][] = $error.'(CD-02)';  // CRL path not found.';
+            $this->status['isValid'] = false;
+            return;
+        }
+
+        // TODO: Manage our own CRLs, downloading it if needed
+        $pathToCrl = null;
+        if (!empty($this->crlDistributionPoints) && is_array($this->crlDistributionPoints)) {
+            foreach ($this->crlDistributionPoints as $url) {
+                $pathToCrl = $this->crlspath . '/' . md5($url) . '.crl';
+                if (file_exists($pathToCrl)) {
+                    break;
+                } else {
+                    $pathToCrl = null;
+                }
+            }
+        }
+
+        if (empty($pathToCrl)) {
+            // Haven't found crl at the certificate
+            $this->status['errors'][] = $error.'(CD-03)';  // Crl file not found;
+            $this->status['isValid'] = false;
+            return;
+        }
+
+        $out = array();
+        exec('openssl crl -in ' . $pathToCrl . ' -inform DER -noout -text',$out);
+
+        if(strpos($out[5],'        Next Update: ') === false) {
+            $this->status['errors'][] = $error.'(CD-04)';  // Invalid crl file found.';
+            $this->status['isValid'] = false;
+            return;
+        } else {
+            // - verify expired crl...
+            $a1 = explode(' Update: ',$out[5]);
+            if(time() >= date_timestamp_get(date_create($a1[1]))) {
+                $this->status['errors'][] = $error.'(CD-05)';   // Invalid crl file found.';
+                $this->status['isValid'] = false;
+                return;
+            }
+        }
+
+        $aux = array_search('    Serial Number: ' . $this->serialNumber, $out);
+        
+        if($aux) {
+            // cert revoked...
+            $this->status['isValid'] = false;
+            $a1 = explode('Date: ',$out[$aux+1]);
+            $this->status['errors'][] = 'REVOKED Certificate at: ' . $a1[1];
+            return;
+        }
+    }
+
+    /**
+     *
+     * @param type $ab
+     * @param type $q
+     * @param type $flag
+     * @return type 
+     */
+    public static function xBase128($ab,$q,$flag)
+    {
+        $abc = $ab;
+        if( $q > 127 ) {
+            $abc = self::xBase128($abc, floor($q / 128), 0 );
+        }
+        
+        $q = $q % 128;
+        if( $flag) {
+            $abc[] = $q;
+        } else {
+            $abc[] = 0x80 | $q;
+        }
+        
+        return $abc;
+    }
+    
+    /**
+     *
+     * @param type $oid
+     * @return type 
+     */
+    public static function oid2Hex($oid)
+    {
+        $abBinary = array();
+        $parts = explode('.',$oid);
+        $n = 0;
+        $b = 0;
+        
+        for($n = 0; $n < count($parts); $n++) {
+            if($n==0) {
+                $b = 40 * $parts[$n];
+            } elseif($n==1) {
+                $b +=  $parts[$n];
+                $abBinary[] = $b;
+            } else {
+                $abBinary = self::xBase128($abBinary, $parts[$n], 1 );
+            }
+        }
+        
+        $value =chr(0x06) . chr(count($abBinary));
+        foreach($abBinary as $item) {
+            $value .= chr($item);
+        }
+        
+        return $value;
+    }
+    
+    /**
+     * Transform cert from PEM format to DER
+     *
+     * @param string Certificate PEM format
+     * @return string Certificate DER format
+     */
+    static public function pem2Der($pemCertificate)
+    {
+        $aux = explode(chr(0x0A),$pemCertificate);
+        $derCertificate = '';
+        foreach ($aux as $i) {
+            if($i != '') {
+                if(substr($i, 0, 5) !== '-----') {
+                    $derCertificate .= $i;
+                }
+            }
+        }
+        
+        return base64_decode($derCertificate);
+    }
+    
+    public function getPemCertificateData() {
+        return $this->certificate;
+    }
+    
+    public function getSerialNumber()
+    {
+        return $this->serialNumber;
+    }
+
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    public function getSubject()
+    {
+        return $this->subject;
+    }
+
+    public function getCn()
+    {
+        return $this->cn;
+    }
+
+    public function getIssuer()
+    {
+        return $this->issuer;
+    }
+
+    public function getIssuerCn()
+    {
+        return $this->issuerCn;
+    }
+
+    public function getHash()
+    {
+        return $this->hash;
+    }
+
+    public function getValidFrom()
+    {
+        return $this->validFrom;
+    }
+
+    public function getValidTo()
+    {
+        return $this->validTo;
+    }
+      
+    public function isCanSign()
+    {
+        return $this->canSign;
+    }
+
+    public function isCanEncrypt()
+    {
+        return $this->canEncrypt;
+    }
+
+    public function getEmail()
+    {
+        return $this->email;
+    }
+
+    public function isCA()
+    {
+        return $this->ca;
+    }
+
+    /**
+     * Returns the validity of the Certificate
+     * @return boolean
+     */
+    public function isValid()
+    {
+        return ($this->status['isValid'])?true:false;
+    }
+    
+    public function getAuthorityKeyIdentifier()
+    {
+        return $this->authorityKeyIdentifier;
+    }
+
+    public function getCrlDistributionPoints()
+    {
+        return $this->crlDistributionPoints;
+    }
+
+    public function getAuthorityInfoAccess()
+    {
+        return $this->authorityInfoAccess;
+    }
+
+    public function getStatusErrors()
+    {
+        return $this->status['errors'];
+    }
+    
+    public function toArray()
+    {
+        
+        $reflectionClass = new ReflectionClass(get_class($this));
+        $array = array();
+        foreach ($reflectionClass->getProperties() as $property) {
+            $name = $property->getName();
+            if ($name !== 'casfile' &&  $name !== 'crlspath') {
+                $array[$name] = $this->$name;
+            }
+        }
+        return $array;
+        
+    }
+    
+    public static function generateTempFilename(&$tab_arqs, $path)
+    {
+
+        $list = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
+        $N = $list[rand(0,count($list)-1)].date('U').$list[rand(0,count($list)-1)].RAND(12345,9999999999).$list[rand(0,count($list)-1)].$list[rand(0,count($list)-1)].RAND(12345,9999999999).'.tmp';
+        $aux = $path.'/'.$N;
+        array_push($tab_arqs ,$aux);
+        return  $aux;
+    }
+    
+    private static function removeTempFiles($tab_arqs)
+    {
+        foreach($tab_arqs as $file ) {
+            if(file_exists($file)) {
+                unlink($file);
+            }
+        }
+    }
+    
+    public static function writeTo($file, $content)
+    {
+        return file_put_contents($file, $content);   
+    }
+
+}
\ No newline at end of file
diff --git a/tine20/library/Custom/Auth/ModSsl/Exception/OpensslNotLoaded.php b/tine20/library/Custom/Auth/ModSsl/Exception/OpensslNotLoaded.php
new file mode 100644 (file)
index 0000000..af80f27
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ *  
+ */
+
+class Custom_Auth_ModSsl_Exception_OpensslNotLoaded extends Exception
+{
+}
\ No newline at end of file
diff --git a/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Abstract.php b/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Abstract.php
new file mode 100644 (file)
index 0000000..5f45308
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * 
+ */
+
+abstract class Custom_Auth_ModSsl_UsernameCallback_Abstract implements Custom_Auth_ModSsl_UsernameCallback_Interface
+{
+    /**
+     * @var Custom_Auth_ModSsl_Certificate_X509
+     */
+    protected $certificate;
+            
+    public function __construct(Custom_Auth_ModSsl_Certificate_X509 $certificate)
+    {
+        $this->certificate = $certificate;
+    }
+    
+    public function getUsername()
+    {
+        return $this->certificate->getEmail();
+    }
+}
\ No newline at end of file
diff --git a/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Cpf.php b/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Cpf.php
new file mode 100644 (file)
index 0000000..a285911
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2015 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * 
+ */
+
+class Custom_Auth_ModSsl_UsernameCallback_Cpf extends Custom_Auth_ModSsl_UsernameCallback_Standard
+{
+    /**
+     * (non-PHPdoc)
+     * @see Custom_Auth_ModSsl_UsernameCallback_Abstract::getUsername()
+     */
+    public function getUsername()
+    {
+        if ($this->certificate instanceof Custom_Auth_ModSsl_Certificate_ICPBrasil && $this->certificate->isPF()) {
+            return $this->certificate->getCPF();
+        } else {
+            // TODO: throw an exception
+            return null;
+        }
+    }
+}
diff --git a/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Email.php b/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Email.php
new file mode 100644 (file)
index 0000000..d44ca75
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Guilherme Striquer Bisotto <guilherme.bisotto@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2015 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ *
+ */
+
+class Custom_Auth_ModSsl_UsernameCallback_Email extends Custom_Auth_ModSsl_UsernameCallback_Cpf
+{
+    public function getUsername()
+    {
+        // TODO: throw an exception in case of error
+        return $this->certificate->getEmail();
+    }
+}
\ No newline at end of file
diff --git a/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Interface.php b/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Interface.php
new file mode 100644 (file)
index 0000000..abc0399
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
+ * @author      Mario Cesar Kolling <mario.kolling@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * 
+ */
+
+interface Custom_Auth_ModSsl_UsernameCallback_Interface
+{
+    public function getUsername();
+}
diff --git a/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Standard.php b/tine20/library/Custom/Auth/ModSsl/UsernameCallback/Standard.php
new file mode 100644 (file)
index 0000000..a29ae7f
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Custom
+ * @subpackage  Auth
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ * @copyright   Copyright (c) 2009-2014 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * 
+ */
+/**
+ * Concrete class to be used into authentication classes
+ *
+ * @category   Custom
+ * @package    Auth
+ * @subpackage ModSsql
+ */
+
+class Custom_Auth_ModSsl_UsernameCallback_Standard extends Custom_Auth_ModSsl_UsernameCallback_Abstract
+{
+}
\ No newline at end of file
index 28064c6..21f94e0 100644 (file)
@@ -1,19 +1,19 @@
 <?php
 /**
  * Tine 2.0
- * 
+ *
  * @category   Zend
  * @package    Zend_Auth
  * @subpackage Zend_Auth_Adapter
- * @license    http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- * @author     Mário César Kolling <mario.koling@serpro.gov.br>
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
+ * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Mário César Kolling <mario.koling@serpro.gov.br>
  */
 
 /**
  * DigitalCertificate authentication backend adapter
- * 
+ *
  * @category   Zend
  * @package    Zend_Auth
  * @subpackage Zend_Auth_Adapter
  */
 class Zend_Auth_Adapter_ModSsl implements Zend_Auth_Adapter_Interface
 {
+
     /**
-     * The array of arrays of Zend_Ldap options passed to the constructor.
-     *
-     * @var array
-     */
-    protected $_options = array();
-    
-    /**
-     * The username of the account being authenticated.
-     *
-     * @var string
-     */
-    protected $_username = null;
-    
-    /**
-     * The password of the account being authenticated.
-     *
-     * @var string
-     */
-    protected $_password = null;
-    
-    /**
-     * Constructor
+     * Verify if client was verified by apache mod_ssl
      *
-     * @param  array  $options  An array of arrays of Zend_Ldap options
-     * @param  string $username The username of the account being authenticated
-     * @param  string $password The password of the account being authenticated
-     * @return void
+     * @return boolean true if we have all needed mod_ssl server variables
      */
-    public function __construct(array $options = array(), $username = null, $password = null)
-    {
-        $this->setOptions($options);
-        
-        if ($username !== null) {
-            $this->setUsername($username);
-        }
-        
-        if ($password !== null) {
-            $this->setPassword($password);
+    static function hasModSsl(){
+
+        // Get modssl config session
+        $config = Tinebase_Config::getInstance()->get('modssl');
+        if ($config && (!empty($_SERVER['SSL_CLIENT_CERT']) || !empty($_SERVER['HTTP_SSL_CLIENT_CERT']))
+                &&  ((!empty($_SERVER['SSL_CLIENT_VERIFY']) && $_SERVER['SSL_CLIENT_VERIFY'] == 'SUCCESS')
+                || (!empty($_SERVER['HTTP_SSL_CLIENT_VERIFY']) && $_SERVER['HTTP_SSL_CLIENT_VERIFY'] == 'SUCCESS'))) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
+                Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ModSsl detected');
+            }
+            return true;
         }
+
+        return false;
+
     }
-    
-    /**
-     * (non-PHPdoc)
-     * @see Zend_Auth_Adapter_Interface::authenticate()
-     */
+
     public function authenticate()
     {
-        // get certificate
-        try {
-            $certificate = Zend_Auth_Adapter_ModSsl_Certificate_Factory::factory($this->_options);
-        } catch (Zend_Auth_Exception $zae) {
-            return new Zend_Auth_Result(
-               Zend_Auth_Result::FAILURE, 
-               null, 
-               array($zae->getMessage())
-            );
-        }
-        
-        if (!$certificate->isValid()) {
-            // certifcate invalid
-            return new Zend_Auth_Result(
-                Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, 
-                null, 
-                $certificate->getStatusErrors()
-            ); 
-        }
-        
-        $this->setUsername($certificate->getUserName());
-        
-        return new Zend_Auth_Result(
-            Zend_Auth_Result::SUCCESS, 
-            $this->getUsername(), 
-            array('Authentication Successfull')
-        );
-    }
-    
-    /**
-     * Returns the array of arrays of Zend_Ldap options of this adapter.
-     *
-     * @return array|null
-     */
-    public function getOptions()
-    {
-        return $this->_options;
-    }
-    
-    /**
-     * Sets the array of arrays of Zend_Ldap options to be used by
-     * this adapter.
-     *
-     * @param  array $options The array of arrays of Zend_Ldap options
-     * @return Zend_Auth_Adapter_Ldap Provides a fluent interface
-     */
-    public function setOptions($options)
-    {
-        $this->_options = is_array($options) ? $options : array();
-        
-        return $this;
-    }
-    
-    /**
-     * Returns the username of the account being authenticated, or
-     * NULL if none is set.
-     *
-     * @return string|null
-     */
-    public function getUsername()
-    {
-        return $this->_username;
-    }
+        if (self::hasModSsl()) {
 
-    /**
-     * Sets the username for binding
-     *
-     * @param  string $username The username for binding
-     * @return Zend_Auth_Adapter_Ldap Provides a fluent interface
-     */
-    public function setUsername($username)
-    {
-        $this->_username = (string) $username;
-        
-        return $this;
-    }
+            // Fix to support reverseProxy without SSLProxyEngine
+            $clientCert = !empty($_SERVER['SSL_CLIENT_CERT']) ? $_SERVER['SSL_CLIENT_CERT'] : $_SERVER['HTTP_SSL_CLIENT_CERT'];
 
-    /**
-     * Returns the password of the account being authenticated, or
-     * NULL if none is set.
-     *
-     * @return string|null
-     */
-    public function getPassword()
-    {
-        return $this->_password;
-    }
+            // get Identity
+            $certificate = Custom_Auth_ModSsl_Certificate_Factory::buildCertificate($clientCert);
+            $config = Tinebase_Config::getInstance()->get('modssl');
 
-    /**
-     * Sets the passwort for the account
-     *
-     * @param  string $password The password of the account being authenticated
-     * @return Zend_Auth_Adapter_Ldap Provides a fluent interface
-     */
-    public function setPassword($password)
-    {
-        $this->_password = (string) $password;
-        
-        return $this;
+            if (class_exists($config->username_callback)) {
+                $callback = new $config->username_callback($certificate);
+            } else { // fallback to default
+                $callback = new Custom_Auth_ModSsl_UsernameCallback_Standard($certificate);
+            }
+
+            $this->setIdentity(call_user_func(array($callback, 'getUsername')));
+            $this->setCredential(null);
+            
+            if ($certificate instanceof Custom_Auth_ModSsl_Certificate_X509) {
+                if(!$certificate->isValid()) {
+                   $lines = '';
+                   foreach($certificate->getStatusErrors() as $line) {
+                       $lines .= $line . '#';
+                   }
+
+                   if (Tinebase_Core::isLogLevel(Zend_Log::ERR)) {
+                       Tinebase_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . ' ModSsl authentication for '. $this->_identity . ' failed: ' . $lines);
+                   }
+
+                   return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, $this->_identity, $certificate->getStatusErrors());
+                }
+                $messages = array('Authentication Successfull');
+
+                // If certificate is valid store it in database
+                $controller = Addressbook_Controller_Certificate::getInstance();
+                try {
+                    $controller->create(new Addressbook_Model_Certificate($certificate));
+                } catch (Tinebase_Exception_Duplicate $e) {
+                    // Fail silently if certificate already exists
+                }
+                return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_identity, $messages);
+            }
+        }
+
+        return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, 'Unknown User', array('Unknown Authentication Error'));
     }
 }
diff --git a/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Abstract.php b/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Abstract.php
deleted file mode 100644 (file)
index e7b3237..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @author     Lars Kneschke <l.kneschke@metaways.de>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle X509 certificates
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- */
-abstract class Zend_Auth_Adapter_ModSsl_Certificate_Abstract implements Zend_Auth_Adapter_ModSsl_Certificate_Interface
-{
-    /**
-     * The array of arrays of Zend_Ldap options passed to the constructor.
-     *
-     * @var array
-     */
-    protected $_options = array();
-    
-    protected $_certificate = null;
-    
-    /**
-     * 
-     * @param array $options
-     * @param unknown $certificate
-     */
-    public function __construct(array $options = array(), $certificate)
-    {
-        $this->setOptions($options);
-        
-        $this->setCertificate($certificate);
-    }
-    
-    public function getCertificate()
-    {
-        return $this->_certificate;
-    }
-    
-    /**
-     * Returns the array of arrays of Zend_Ldap options of this adapter.
-     *
-     * @return array|null
-     */
-    public function getOptions()
-    {
-        return $this->_options;
-    }
-    
-    /**
-     * (non-PHPdoc)
-     * @see Zend_Auth_Adapter_ModSsl_Certificate_Interface::setCertificate()
-     */
-    public function setCertificate($certificate)
-    {
-        $this->_certificate = $certificate;
-        
-        return $this;
-    }
-    
-    /**
-     * Sets the array of arrays of Zend_Ldap options to be used by
-     * this adapter.
-     *
-     * @param  array $options The array of arrays of Zend_Ldap options
-     * @return Zend_Auth_Adapter_Ldap Provides a fluent interface
-     */
-    public function setOptions($options)
-    {
-        $this->_options = is_array($options) ? $options : array();
-        
-        return $this;
-    }
-}
\ No newline at end of file
diff --git a/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Apache.php b/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Apache.php
deleted file mode 100644 (file)
index 17c6b78..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle X509 certificates
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @todo       phpdoc of all methods
- */
-class Zend_Auth_Adapter_ModSsl_Certificate_Apache extends Zend_Auth_Adapter_ModSsl_Certificate_Abstract
-{
-    protected $certificate;
-    protected $casfile;
-    protected $crlspath;
-    protected $serialNumber = null;
-    protected $version      = null;
-    protected $subject      = null;
-    protected $cn           = null;
-    protected $issuer       = null;
-    protected $issuerCn     = null;
-    protected $hash         = null;
-    protected $validFrom    = null;
-    protected $validTo      = null;
-    protected $canSign      = false;
-    protected $canEncrypt   = false;
-    protected $username     = null;
-    protected $ca           = false;
-    protected $authorityKeyIdentifier = null;
-    protected $crlDistributionPoints  = null;
-    protected $authorityInfoAccess    = null;
-    protected $status       = array(
-                                  'isValid' => false,
-                                  'errors'  => array()
-                              );
-    
-    public function getSerialNumber()
-    {
-        if (!isset($this->serialNumber)) {
-            $this->serialNumber = $this->_certificate['SSL_CLIENT_M_SERIAL'];
-        }
-        
-        return $this->serialNumber;
-    }
-
-    public function getVersion()
-    {
-        if (!isset($this->version)) {
-            $this->version = $this->_certificate['SSL_CLIENT_M_VERSION'];
-        }
-        
-        return $this->version;
-    }
-
-    public function getSubject()
-    {
-        if (!isset($this->subject)) {
-            $this->subject = array(
-                'C'             => $this->_certificate['SSL_CLIENT_S_DN_C'],
-                'ST'            => $this->_certificate['SSL_CLIENT_S_DN_ST'],
-                'L'             => $this->_certificate['SSL_CLIENT_S_DN_L'],
-                'O'             => $this->_certificate['SSL_CLIENT_S_DN_O'],
-                'OU'            => $this->_certificate['SSL_CLIENT_S_DN_OU'],
-                'CN'            => $this->_certificate['SSL_CLIENT_S_DN_CN'],
-                'emailAddress'  => $this->_certificate['SSL_CLIENT_S_DN_Email']
-                    
-            );
-        }
-        
-        return $this->subject;
-    }
-
-    public function getCn()
-    {
-        if (!isset($this->cn)) {
-            $this->cn = $this->_certificate['SSL_CLIENT_S_DN_CN'];
-        }
-        
-        return $this->cn;
-    }
-
-    public function getIssuer()
-    {
-        if (!isset($this->issuer)) {
-            $this->issuer = array(
-                'C'  => $this->_certificate['SSL_CLIENT_I_DN_C'],
-                'ST' => $this->_certificate['SSL_CLIENT_I_DN_ST'],
-                'L'  => $this->_certificate['SSL_CLIENT_I_DN_L'],
-                'O'  => $this->_certificate['SSL_CLIENT_I_DN_O'],
-                'OU' => $this->_certificate['SSL_CLIENT_I_DN_OU'],
-                'CN' => $this->_certificate['SSL_CLIENT_I_DN_CN']
-            );
-        }
-        
-        return $this->issuer;
-    }
-
-    public function getIssuerCn()
-    {
-        if (!isset($this->issuerCn)) {
-            $this->issuerCn = $this->_certificate['SSL_CLIENT_I_DN'];
-        }
-        
-        return $this->issuerCn;
-    }
-
-    public function getValidFrom()
-    {
-        if (!isset($this->validFrom)) {
-            $this->validFrom    = new Tinebase_DateTime($this->_certificate['SSL_CLIENT_V_START']);
-        }
-        
-        return $this->validFrom;
-    }
-
-    public function getValidTo()
-    {
-        if (!isset($this->validTo)) {
-            $this->validTo      = new Tinebase_DateTime($this->_certificate['SSL_CLIENT_V_END']);
-        }
-        
-        return $this->validTo;
-    }
-      
-    public function getUserName()
-    {
-        if (!isset($this->username)) {
-            if ($this->_options['tryUsernameSplit']) {
-                $parts = explode('@' , $this->_certificate['SSL_CLIENT_S_DN_Email'], 2);
-                $this->username = $parts[0];
-            } else {
-                $this->username = $this->_certificate['SSL_CLIENT_S_DN_Email'];
-            }
-        }
-        
-        return $this->username;
-    }
-
-    public function isValid()
-    {
-        return isset($this->_certificate['SSL_CLIENT_VERIFY']) && $this->_certificate['SSL_CLIENT_VERIFY'] === 'SUCCESS';
-    }
-    
-    public function getStatusErrors()
-    {
-        return $this->status['errors'];
-    }
-    
-}
\ No newline at end of file
diff --git a/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Factory.php b/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Factory.php
deleted file mode 100644 (file)
index 1934e8b..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle X509 certificates
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- */
-class Zend_Auth_Adapter_ModSsl_Certificate_Factory
-{
-    const TYPE_APACHE    = 'Apache';
-    const TYPE_X509      = 'X509';
-    const TYPE_ICPBRASIL = 'ICPBrasil';
-    
-    /**
-     * 
-     * @param unknown $factory
-     */
-    static function factory($options)
-    {
-        foreach (array(null, 'REDIRECT_', 'REDIRECT_REDIRECT_') as $prefix) {
-            if (isset($_SERVER[$prefix . 'SSL_CLIENT_VERIFY'])) {
-                $prefixLength = strlen($prefix);
-                
-                $certificate = array();
-                
-                foreach ($_SERVER as $key => $value) {
-                    if (strpos($key, $prefix . 'SSL_CLIENT') === 0) {
-                        $certificate[substr($key, $prefixLength)] = $value;
-                    }
-                }
-                
-                break;
-            }
-        }
-
-        if (!isset($certificate)) {
-            throw new Zend_Auth_Exception('No SSL variables found!');
-        }
-                
-        switch ($options['validation']) {
-            case self::TYPE_APACHE:
-                return new Zend_Auth_Adapter_ModSsl_Certificate_Apache($options, $certificate);
-                
-            case self::TYPE_ICPBRASIL:
-                return new Zend_Auth_Adapter_ModSsl_Certificate_X509($options, $certificate);
-                
-            case self::TYPE_X509:
-                return new Zend_Auth_Adapter_ModSsl_Certificate_X509($options, $certificate);
-                
-            default:
-                throw new Zend_Auth_Exception('Unsupported certificate type!');
-        } 
-    }
-}
\ No newline at end of file
diff --git a/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Interface.php b/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/Interface.php
deleted file mode 100644 (file)
index 5d267b8..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @author     Lars Kneschke <l.kneschke@metaways.de>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle X509 certificates
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- */
-interface Zend_Auth_Adapter_ModSsl_Certificate_Interface
-{
-    /**
-     * 
-     * @param array $options
-     * @param unknown $certificate
-     */
-    public function __construct(array $options = array(), $certificate);
-    
-    /**
-     * Returns the array of arrays of Zend_Ldap options of this adapter.
-     *
-     * @return array|null
-     */
-    public function getOptions();
-    
-    /**
-     * @return mixed
-     */
-    public function getCertificate();
-    
-    public function getUserName();
-    
-    /**
-     * @return boolean
-     */
-    public function isValid();
-    
-    /**
-     * Sets the array of arrays of Zend_Ldap options to be used by
-     * this adapter.
-     *
-     * @param  array $options The array of arrays of Zend_Ldap options
-     * @return Zend_Auth_Adapter_Ldap Provides a fluent interface
-     */
-    public function setOptions($options);
-    
-    /**
-     * 
-     * @param mixed $certificate
-     */
-    public function setCertificate($certificate);
-}
\ No newline at end of file
diff --git a/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/X509.php b/tine20/library/zf1ext/Zend/Auth/Adapter/ModSsl/Certificate/X509.php
deleted file mode 100644 (file)
index e7d30d6..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-<?php
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @license    http://framework.zend.com/license/new-bsd     New BSD License
- * @author     Antonio Carlos da Silva <antonio-carlos.silva@serpro.gov.br>
- * @author     Mario Cesar Kolling <mario.kolling@serpro.gov.br>
- * @copyright  Copyright (c) 2009-2013 Serpro (http://www.serpro.gov.br)
- * @copyright  Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle X509 certificates
- *
- * @category   Zend
- * @package    Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @todo       parse authorityInfoAccess, caissuer and ocsp
- * @todo       parse authorityKeyIdentifier
- * @todo       phpdoc of all methods
- */
-class Zend_Auth_Adapter_ModSsl_Certificate_X509 extends Zend_Auth_Adapter_ModSsl_Certificate_Abstract
-{
-    protected $certificate;
-    protected $casfile;
-    protected $crlspath;
-    protected $validFrom    = null;
-    protected $validTo      = null;
-    protected $canSign      = false;
-    protected $canEncrypt   = false;
-    protected $email        = null;
-    protected $ca           = false;
-    protected $authorityKeyIdentifier = null;
-    protected $crlDistributionPoints  = null;
-    protected $authorityInfoAccess    = null;
-    protected $status       = array(
-                                  'isValid' => false,
-                                  'errors'  => array()
-                              );
-    
-    protected $_parsedCertificate     = null;
-    
-    /**
-     * 
-     * @param string $certificate
-     */
-    public function __construct(array $options = array(), $certificate)
-    {
-        parent::__construct($options, $certificate);
-        
-        $this->casfile  = isset($this->_options['casfile'])  && strtolower($this->_options['casfile'])  !== 'skip' ? $this->_options['casfile']  : null;
-        $this->crlspath = isset($this->_options['crlspath']) && strtolower($this->_options['crlspath']) !== 'skip' ? $this->_options['crlspath'] : null;
-        
-        $this->_parsedCertificate = openssl_x509_parse($this->_certificate['SSL_CLIENT_CERT']);
-        
-        $this->_parseExtensions($this->_parsedCertificate['extensions']);
-    }
-    
-    /**
-     * parse certificate extensions
-     * 
-     * @param array $extensions
-     */
-    protected function _parseExtensions($extensions)
-    {
-        foreach ($extensions as $extension => $value) {
-            $matches = array();
-            
-            switch ($extension) {
-                case 'subjectAltName':
-                    if (preg_match('/email:(\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b)/i', $value, $matches)) {
-                        $this->email = $matches[1];
-                    }
-                    
-                    break;
-                    
-                case 'basicConstraints' :
-                    if (preg_match('/\bCA:(FALSE|TRUE)\b/', $value, $matches)) {
-                        $this->ca = $matches[1] == 'TRUE' ? TRUE : FALSE;
-                    }
-                    
-                    break;
-                    
-                case 'crlDistributionPoints' :
-                    $lines = explode(chr(0x0A), trim($value));
-                    
-                    foreach ($lines as &$line) {
-                        preg_match('/URI:/', $line, $matches);
-                        $line = preg_replace('/URI:/', '', $line);
-                    }
-                    
-                    $this->crlDistributionPoints = $lines;
-                    
-                    break;
-                
-//                case 'authorityKeyIdentifier' :
-//                    if (preg_match('/\bkeyid:(\b([A-F0-9]{2}:)+[[A-F0-9]{2}]\b)/', $value, $matches))
-//                    {
-//                        $tmp = '';
-//                    }
-//                    break;
-//                 // TODO: ocsp
-//                case 'authorityInfoAccess' :
-//                    if (preg_match('/\bCA Issuers - URI:(http(?:s)?\:\/\/[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*\.[a-zA-Z]{2,6}(?:\/?|(?:\/[\w\-]+)*)(?:\/?|\/\w+\.[a-zA-Z]{2,4}(?:\?[\w]+\=[\w\-]+)?)?(?:\&[\w]+\=[\w\-]+)*\b)/', $value, $matches))
-//                    {
-//                        $tmp = '';
-//                    }
-//                    break;
-            }
-        }
-    }
-    
-    /**
-     * parse certificate purpose
-     * 
-     * @param array $purposes
-     */
-    protected function _parsePurpose($purposes)
-    {
-        foreach ($purposes as $purpose) {
-            switch ($purpose[2]) {
-                case 'smimesign' :
-                    $this->canSign    = $purpose[0] == 1 ? true : false;
-                    
-                    break;
-                    
-                case 'smimeencrypt' :
-                    $this->canEncrypt = $purpose[0] == 1 ? true : false;
-                    
-                    break;
-            }
-        }
-    }
-    
-    /**
-     * check certificate validity
-     */
-    protected function _validityCheck() 
-    {
-        if (!is_file($this->casfile)) {
-            $this->status['errors'][] = 'Invalid Certificate .(CA-01)';  //'CAs file not found.';
-            $this->status['isValid'] = false;
-            
-            return;
-        }
-        
-        $temporary_files = array();
-        $certTempFile = self::generateTempFilename($temporary_files, Tinebase_Core::getTempDir());
-        self::writeTo($certTempFile,$this->certificate);
-        
-        $out = array();
-        // certificate verify ...
-        $w = exec('openssl verify -CAfile '.$this->casfile.' '.$certTempFile,$out);
-        self::removeTempFiles($temporary_files);
-        $aux = explode(' ',$w);
-        if (isset($aux[1])) {
-            if ($aux[1] != 'OK') {
-                foreach($out as $item) {
-                    $aux = explode(':',$item);
-                    if(isset($aux[1])) {
-                        $this->status['errors'][] = trim($aux[1]);
-                        $this->status['isValid'] = false;
-                    }
-                }
-                return;
-            }
-        } else {
-            $this->status['errors'][] = (isset($aux[1]) ? trim($aux[1]) : 'Couldn\'t verify if certificate was revoked.(CD-01)');
-            $this->status['isValid'] = false;
-        }
-       
-    }
-
-    /**
-     * check if certificate is revoked
-     */
-    protected function _testRevoked()
-    {
-        if (!is_dir($this->crlspath)) {
-            $this->status['errors'][] = 'Couldn\'t verify if certificate was revoked.(CD-02)';  // CRL path not found.';
-            $this->status['isValid'] = false;
-            return;
-        }
-        
-        if (!isset($this->crlDistributionPoints[0])) {
-            // Haven't found crl at the certificate
-            $this->status['errors'][] = 'Couldn\'t verify if certificate was revoked.(CD-03)';  // Crl file not found;
-            $this->status['isValid'] = false;
-            return;
-        }
-        
-        $aux = explode('/',$this->crlDistributionPoints[0]);
-        $crl = file_get_contents($this->crlspath . '/' . $aux[count($aux)-1],true);
-        $out = array();
-        $w = exec('openssl crl -in ' . $this->crlspath . '/' . $aux[count($aux)-1] . ' -inform DER -noout -text',$out);
-
-        if (strpos($out[5],'        Next Update: ') === false) {
-            $this->status['errors'][] = 'Couldn\'t verify if certificate was revoked.(CD-04)';  // Invalid crl file found.';
-            $this->status['isValid'] = false;
-            return;
-        } else {
-            // - verify expired crl...
-            $a1 = explode(' Update: ',$out[5]);
-            if (time() >= date_timestamp_get(date_create($a1[1]))) {
-                $this->status['errors'][] = 'Couldn\'t verify if certificate was revoked.(CD-05)';   // Invalid crl file found.';
-                $this->status['isValid'] = false;
-                return;
-            }
-        }
-
-        $aux = array_search('    Serial Number: ' . $this->serialNumber, $out);
-        
-        if ($aux) {
-            // cert revoked...
-            $this->status['isValid'] = false;
-            $a1 = explode('Date: ',$out[$aux+1]);
-            $this->status['errors'][] = 'REVOKED Certificate at: ' . $a1[1];
-            return;
-        }
-    }
-
-    /**
-     *
-     * @param type $ab
-     * @param type $q
-     * @param type $flag
-     * @return type 
-     */
-    public static function xBase128($ab,$q,$flag)
-    {
-        $abc = $ab;
-        if( $q > 127 ) {
-            $abc = self::xBase128($abc, floor($q / 128), 0 );
-        }
-        
-        $q = $q % 128;
-        if( $flag) {
-            $abc[] = $q;
-        } else {
-            $abc[] = 0x80 | $q;
-        }
-        
-        return $abc;
-    }
-    
-    /**
-     *
-     * @param type $oid
-     * @return type 
-     */
-    public static function oid2Hex($oid)
-    {
-        $abBinary = array();
-        $parts = explode('.',$oid);
-        $n = 0;
-        $b = 0;
-        
-        for($n = 0; $n < count($parts); $n++) {
-            if($n==0) {
-                $b = 40 * $parts[$n];
-            } elseif($n==1) {
-                $b +=  $parts[$n];
-                $abBinary[] = $b;
-            } else {
-                $abBinary = self::xBase128($abBinary, $parts[$n], 1 );
-            }
-        }
-        
-        $value =chr(0x06) . chr(count($abBinary));
-        foreach($abBinary as $item) {
-            $value .= chr($item);
-        }
-        
-        return $value;
-    }
-    
-    /**
-     * Transform cert from PEM format to DER
-     *
-     * @param string Certificate PEM format
-     * @return string Certificate DER format
-     */
-    static public function pem2Der($pemCertificate)
-    {
-        $aux = explode(chr(0x0A),$pemCertificate);
-        $derCertificate = '';
-        foreach ($aux as $i) {
-            if($i != '') {
-                if(substr($i, 0, 5) !== '-----') {
-                    $derCertificate .= $i;
-                }
-            }
-        }
-        
-        return base64_decode($derCertificate);
-    }
-    
-    public function getSerialNumber()
-    {
-        return $this->_parsedCertificate['serialNumber'];
-    }
-    
-    public function getVersion()
-    {
-        return $this->_parsedCertificate['version'];
-    }
-
-    public function getSubject()
-    {
-        return $this->_parsedCertificate['subject'];
-    }
-
-    public function getCn()
-    {
-        return $this->_parsedCertificate['subject']['CN'];
-    }
-
-    public function getIssuer()
-    {
-        return $this->_parsedCertificate['issuer'];
-    }
-
-    public function getIssuerCn()
-    {
-        return $this->_parsedCertificate['issuer']['CN'];
-    }
-
-    public function getHash()
-    {
-        return $this->_parsedCertificate['hash'];
-    }
-
-    public function getValidFrom()
-    {
-        if (!isset($this->validFrom)) {
-            $this->validFrom = new \DateTime('@' . $this->_parsedCertificate['validFrom_time_t'], new \DateTimeZone('utc'));
-        }
-        
-        return $this->validFrom;
-    }
-
-    public function getValidTo()
-    {
-        if (!isset($this->validTo)) {
-            $this->validTo = new \DateTime('@' . $this->_parsedCertificate['validTo_time_t'], new \DateTimeZone('utc'));
-        }
-        
-        return $this->validTo;
-    }
-      
-    public function isCanSign()
-    {
-        $this->_parsePurpose($this->_parsedCertificate['purposes']);
-        
-        return $this->canSign;
-    }
-
-    public function isCanEncrypt()
-    {
-        $this->_parsePurpose($this->_parsedCertificate['purposes']);
-        
-        return $this->canEncrypt;
-    }
-
-    public function getEmail()
-    {
-        if (!isset($this->email)) {
-            if (isset($this->_parsedCertificate['subject']['emailAddress'])) {
-                $this->email = $this->_parsedCertificate['subject']['emailAddress'];
-            } else {
-                $this->_parseExtensions($this->_parsedCertificate['extensions']);
-            }
-        }
-        
-        
-        return $this->email;
-    }
-
-    public function getUserName()
-    {
-        if (!isset($this->username)) {
-            if ($this->_options['tryUsernameSplit']) {
-                $parts = explode('@' , $this->getEmail(), 2);
-                $this->username = $parts[0];
-            } else {
-                $this->username = $this->getEmail();
-            }
-        }
-        
-        return $this->username;
-    }
-    
-    public function isCA()
-    {
-        return $this->ca;
-    }
-
-    public function isValid()
-    {
-        $this->status['isValid'] = isset($this->_certificate['SSL_CLIENT_VERIFY']) && 
-                                       $this->_certificate['SSL_CLIENT_VERIFY'] === 'SUCCESS';
-        
-        // skip validation if not set, we trust the server's result
-        if ($this->casfile) {
-            $this->_validityCheck();
-        }
-        
-        // skip test if not set
-        if ($this->crlspath) {
-            $this->_testRevoked(); 
-        }
-        
-        return $this->status['isValid'];
-    }
-
-    public function getAuthorityKeyIdentifier()
-    {
-        return $this->authorityKeyIdentifier;
-    }
-
-    public function getCrlDistributionPoints()
-    {
-        return $this->crlDistributionPoints;
-    }
-
-    public function getAuthorityInfoAccess()
-    {
-        return $this->authorityInfoAccess;
-    }
-
-    public function getStatusErrors()
-    {
-        return $this->status['errors'];
-    }
-
-    public static function generateTempFilename(&$tab_arqs, $path)
-    {
-        $list = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
-        $N = $list[rand(0,count($list)-1)].date('U').$list[rand(0,count($list)-1)].RAND(12345,9999999999).$list[rand(0,count($list)-1)].$list[rand(0,count($list)-1)].RAND(12345,9999999999).'.tmp';
-        $aux = $path.'/'.$N;
-        array_push($tab_arqs ,$aux);
-        return  $aux;
-    }
-
-    private static function removeTempFiles($tab_arqs)
-    {
-        foreach ($tab_arqs as $file) {
-            if (file_exists($file)) {
-                unlink($file);
-            }
-        }
-    }
-
-    public static function writeTo($file, $content)
-    {
-        return file_put_contents($file, $content);   
-    }
-}
\ No newline at end of file