diff options
| author | Hugues Hiegel <root@paranoid> | 2015-04-21 12:49:44 +0200 | 
|---|---|---|
| committer | Hugues Hiegel <root@paranoid> | 2015-04-21 12:49:44 +0200 | 
| commit | 733f8e8d0ce6217d906d06dc4fb08e36d48ed794 (patch) | |
| tree | cff28366ff63ea6596f8026e1698090bd0b9405c /plugins/enigma/lib/enigma_driver_gnupg.php | |
| parent | ef2e7b3f9d264ec146d4dae257b1e295ab3b462a (diff) | |
| parent | a4ba3df54834ee90fb2c9930669f1229dc80261a (diff) | |
Conflicts:
	composer.json-dist
	config/defaults.inc.php
	plugins
	plugins/acl/acl.js
	plugins/acl/acl.php
	plugins/acl/skins/classic/templates/table.html
	plugins/acl/skins/larry/templates/table.html
	plugins/enigma/README
	plugins/enigma/config.inc.php.dist
	plugins/enigma/enigma.js
	plugins/enigma/enigma.php
	plugins/enigma/lib/enigma_driver.php
	plugins/enigma/lib/enigma_driver_gnupg.php
	plugins/enigma/lib/enigma_driver_phpssl.php
	plugins/enigma/lib/enigma_engine.php
	plugins/enigma/lib/enigma_error.php
	plugins/enigma/lib/enigma_key.php
	plugins/enigma/lib/enigma_signature.php
	plugins/enigma/lib/enigma_subkey.php
	plugins/enigma/lib/enigma_ui.php
	plugins/enigma/lib/enigma_userid.php
	plugins/enigma/localization/en_US.inc
	plugins/enigma/localization/ja_JP.inc
	plugins/enigma/localization/ru_RU.inc
	plugins/enigma/skins/classic/enigma.css
	plugins/enigma/skins/classic/templates/keys.html
	plugins/help/config.inc.php.dist
	plugins/help/help.php
	plugins/help/localization/en_US.inc
	plugins/jqueryui/jqueryui.php
	plugins/managesieve/Changelog
	plugins/managesieve/composer.json
	plugins/managesieve/config.inc.php.dist
	plugins/managesieve/lib/Roundcube/rcube_sieve.php
	plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
	plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
	plugins/managesieve/localization/en_US.inc
	plugins/managesieve/managesieve.js
	plugins/managesieve/skins/classic/managesieve.css
	plugins/managesieve/skins/larry/managesieve.css
	plugins/password/README
	plugins/password/config.inc.php.dist
	plugins/password/drivers/ldap.php
	plugins/password/drivers/poppassd.php
	plugins/password/drivers/vpopmaild.php
	plugins/vcard_attachments/vcardattach.js
	plugins/zipdownload/zipdownload.php
Diffstat (limited to 'plugins/enigma/lib/enigma_driver_gnupg.php')
| -rw-r--r-- | plugins/enigma/lib/enigma_driver_gnupg.php | 326 | 
1 files changed, 326 insertions, 0 deletions
| diff --git a/plugins/enigma/lib/enigma_driver_gnupg.php b/plugins/enigma/lib/enigma_driver_gnupg.php new file mode 100644 index 000000000..52a0ad66c --- /dev/null +++ b/plugins/enigma/lib/enigma_driver_gnupg.php @@ -0,0 +1,326 @@ +<?php +/* + +-------------------------------------------------------------------------+ + | GnuPG (PGP) driver for the Enigma Plugin                                | + |                                                                         | + | Copyright (C) 2010-2015 The Roundcube Dev Team                          | + |                                                                         | + | Licensed under the GNU General Public License version 3 or              | + | any later version with exceptions for skins & plugins.                  | + | See the README file for a full license statement.                       | + |                                                                         | + +-------------------------------------------------------------------------+ + | Author: Aleksander Machniak <alec@alec.pl>                              | + +-------------------------------------------------------------------------+ +*/ + +require_once 'Crypt/GPG.php'; + +class enigma_driver_gnupg extends enigma_driver +{ +    private $rc; +    private $gpg; +    private $homedir; +    private $user; + + +    function __construct($user) +    { +        $this->rc   = rcmail::get_instance(); +        $this->user = $user; +    } + +    /** +     * Driver initialization and environment checking. +     * Should only return critical errors. +     * +     * @return mixed NULL on success, enigma_error on failure +     */ +    function init() +    { +        $homedir = $this->rc->config->get('enigma_pgp_homedir', INSTALL_PATH . 'plugins/enigma/home'); + +        if (!$homedir) +            return new enigma_error(enigma_error::E_INTERNAL, +                "Option 'enigma_pgp_homedir' not specified"); + +        // check if homedir exists (create it if not) and is readable +        if (!file_exists($homedir)) +            return new enigma_error(enigma_error::E_INTERNAL, +                "Keys directory doesn't exists: $homedir"); +        if (!is_writable($homedir)) +            return new enigma_error(enigma_error::E_INTERNAL, +                "Keys directory isn't writeable: $homedir"); + +        $homedir = $homedir . '/' . $this->user; + +        // check if user's homedir exists (create it if not) and is readable +        if (!file_exists($homedir)) +            mkdir($homedir, 0700); + +        if (!file_exists($homedir)) +            return new enigma_error(enigma_error::E_INTERNAL, +                "Unable to create keys directory: $homedir"); +        if (!is_writable($homedir)) +            return new enigma_error(enigma_error::E_INTERNAL, +                "Unable to write to keys directory: $homedir"); + +        $this->homedir = $homedir; + +        // Create Crypt_GPG object +        try { +            $this->gpg = new Crypt_GPG(array( +                'homedir'   => $this->homedir, +                // 'binary'    => '/usr/bin/gpg2', +                // 'debug'     => true, +          )); +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    /** +     * Encrypt a message +     * +     * @param string The message +     * @param array  List of keys +     */ +    function encrypt($text, $keys) +    { +        try { +            foreach ($keys as $key) { +                $this->gpg->addEncryptKey($key); +            } + +            $dec = $this->gpg->encrypt($text, true); +            return $dec; +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    /** +     * Decrypt a message +     * +     * @param string Encrypted message +     * @param array  List of key-password mapping +     */ +    function decrypt($text, $keys = array()) +    { +        try { +            foreach ($keys as $key => $password) { +                $this->gpg->addDecryptKey($key, $password); +            } + +            $dec = $this->gpg->decrypt($text); +            return $dec; +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    function sign($text, $key, $passwd, $mode = null) +    { +        try { +            $this->gpg->addSignKey($key, $passwd); +            return $this->gpg->sign($text, $mode, CRYPT_GPG::ARMOR_ASCII, true); +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    function verify($text, $signature) +    { +        try { +            $verified = $this->gpg->verify($text, $signature); +            return $this->parse_signature($verified[0]); +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    public function import($content, $isfile=false) +    { +        try { +            if ($isfile) +                return $this->gpg->importKeyFile($content); +            else +                return $this->gpg->importKey($content); +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    public function list_keys($pattern='') +    { +        try { +            $keys = $this->gpg->getKeys($pattern); +            $result = array(); + +            foreach ($keys as $idx => $key) { +                $result[] = $this->parse_key($key); +                unset($keys[$idx]); +            } + +            return $result; +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    public function get_key($keyid) +    { +        $list = $this->list_keys($keyid); + +        if (is_array($list)) +            return array_shift($list); + +        // error +        return $list; +    } + +    public function gen_key($data) +    { +    } + +    public function delete_key($keyid) +    { +        // delete public key +        $result = $this->delete_pubkey($keyid); + +        // if not found, delete private key +        if ($result !== true && $result->getCode() == enigma_error::E_KEYNOTFOUND) { +            $result = $this->delete_privkey($keyid); +        } + +        return $result; +    } + +    public function delete_privkey($keyid) +    { +        try { +            $this->gpg->deletePrivateKey($keyid); +            return true; +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    public function delete_pubkey($keyid) +    { +        try { +            $this->gpg->deletePublicKey($keyid); +            return true; +        } +        catch (Exception $e) { +            return $this->get_error_from_exception($e); +        } +    } + +    /** +     * Converts Crypt_GPG exception into Enigma's error object +     * +     * @param mixed Exception object +     * +     * @return enigma_error Error object +     */ +    private function get_error_from_exception($e) +    { +        $data = array(); + +        if ($e instanceof Crypt_GPG_KeyNotFoundException) { +            $error = enigma_error::E_KEYNOTFOUND; +            $data['id'] = $e->getKeyId(); +        } +        else if ($e instanceof Crypt_GPG_BadPassphraseException) { +            $error = enigma_error::E_BADPASS; +            $data['bad']     = $e->getBadPassphrases(); +            $data['missing'] = $e->getMissingPassphrases(); +        } +        else if ($e instanceof Crypt_GPG_NoDataException) +            $error = enigma_error::E_NODATA; +        else if ($e instanceof Crypt_GPG_DeletePrivateKeyException) +            $error = enigma_error::E_DELKEY; +        else +            $error = enigma_error::E_INTERNAL; + +        $msg = $e->getMessage(); + +        return new enigma_error($error, $msg, $data); +    } + +    /** +     * Converts Crypt_GPG_Signature object into Enigma's signature object +     * +     * @param Crypt_GPG_Signature Signature object +     * +     * @return enigma_signature Signature object +     */ +    private function parse_signature($sig) +    { +        $user = $sig->getUserId(); + +        $data = new enigma_signature(); +        $data->id          = $sig->getId(); +        $data->valid       = $sig->isValid(); +        $data->fingerprint = $sig->getKeyFingerprint(); +        $data->created     = $sig->getCreationDate(); +        $data->expires     = $sig->getExpirationDate(); +        $data->name        = $user->getName(); +        $data->comment     = $user->getComment(); +        $data->email       = $user->getEmail(); + +        return $data; +    } + +    /** +     * Converts Crypt_GPG_Key object into Enigma's key object +     * +     * @param Crypt_GPG_Key Key object +     * +     * @return enigma_key Key object +     */ +    private function parse_key($key) +    { +        $ekey = new enigma_key(); + +        foreach ($key->getUserIds() as $idx => $user) { +            $id = new enigma_userid(); +            $id->name    = $user->getName(); +            $id->comment = $user->getComment(); +            $id->email   = $user->getEmail(); +            $id->valid   = $user->isValid(); +            $id->revoked = $user->isRevoked(); + +            $ekey->users[$idx] = $id; +        } + +        $ekey->name = trim($ekey->users[0]->name . ' <' . $ekey->users[0]->email . '>'); + +        foreach ($key->getSubKeys() as $idx => $subkey) { +                $skey = new enigma_subkey(); +                $skey->id          = $subkey->getId(); +                $skey->revoked     = $subkey->isRevoked(); +                $skey->created     = $subkey->getCreationDate(); +                $skey->expires     = $subkey->getExpirationDate(); +                $skey->fingerprint = $subkey->getFingerprint(); +                $skey->has_private = $subkey->hasPrivate(); +                $skey->can_sign    = $subkey->canSign(); +                $skey->can_encrypt = $subkey->canEncrypt(); + +                $ekey->subkeys[$idx] = $skey; +        }; + +        $ekey->id = $ekey->subkeys[0]->id; + +        return $ekey; +    } +} | 
