Aleksander Machniak
2015-09-13 cffe97eb6ede164d8169dda4e8922baea3dda0e1
CS improvements + some doc
7 files modified
211 ■■■■■ changed files
plugins/enigma/lib/enigma_driver.php 18 ●●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_driver_gnupg.php 118 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_driver_phpssl.php 16 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_engine.php 26 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_error.php 16 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_subkey.php 1 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_ui.php 16 ●●●● patch | view | raw | blame | history
plugins/enigma/lib/enigma_driver.php
@@ -33,11 +33,16 @@
    /**
     * Encryption.
     *
     * @param string Message body
     * @param array  List of key-password mapping
     *
     * @return mixed Encrypted message or enigma_error on failure
     */
    abstract function encrypt($text, $keys);
    /**
     * Decryption..
     * Decryption.
     *
     * @param string Encrypted message
     * @param array  List of key-password mapping
@@ -46,6 +51,13 @@
    /**
     * Signing.
     *
     * @param string Message body
     * @param string Key ID
     * @param string Key password
     * @param int    Signing mode (enigma_engine::SIGN_*)
     *
     * @return mixed True on success or enigma_error on failure
     */
    abstract function sign($text, $key, $passwd, $mode = null);
@@ -107,6 +119,10 @@
    /**
     * Key deletion.
     *
     * @param string Key ID
     *
     * @return mixed True on success or enigma_error
     */
    abstract function delete_key($keyid);
}
plugins/enigma/lib/enigma_driver_gnupg.php
@@ -19,10 +19,10 @@
class enigma_driver_gnupg extends enigma_driver
{
    private $rc;
    private $gpg;
    private $homedir;
    private $user;
    protected $rc;
    protected $gpg;
    protected $homedir;
    protected $user;
    function __construct($user)
@@ -42,15 +42,15 @@
        $homedir = $this->rc->config->get('enigma_pgp_homedir', INSTALL_PATH . 'plugins/enigma/home');
        if (!$homedir)
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::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,
            return new enigma_error(enigma_error::INTERNAL,
                "Keys directory doesn't exists: $homedir");
        if (!is_writable($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Keys directory isn't writeable: $homedir");
        $homedir = $homedir . '/' . $this->user;
@@ -60,10 +60,10 @@
            mkdir($homedir, 0700);
        if (!file_exists($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Unable to create keys directory: $homedir");
        if (!is_writable($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Unable to write to keys directory: $homedir");
        $this->homedir = $homedir;
@@ -82,10 +82,12 @@
    }
    /**
     * Encrypt a message
     * Encryption.
     *
     * @param string The message
     * @param array  List of keys
     * @param string Message body
     * @param array  List of key-password mapping
     *
     * @return mixed Encrypted message or enigma_error on failure
     */
    function encrypt($text, $keys)
    {
@@ -94,8 +96,7 @@
                $this->gpg->addEncryptKey($key);
            }
            $dec = $this->gpg->encrypt($text, true);
            return $dec;
            return $this->gpg->encrypt($text, true);
        }
        catch (Exception $e) {
            return $this->get_error_from_exception($e);
@@ -107,6 +108,8 @@
     *
     * @param string Encrypted message
     * @param array  List of key-password mapping
     *
     * @return mixed Decrypted message or enigma_error on failure
     */
    function decrypt($text, $keys = array())
    {
@@ -115,14 +118,23 @@
                $this->gpg->addDecryptKey($key, $password);
            }
            $dec = $this->gpg->decrypt($text);
            return $dec;
            return $this->gpg->decrypt($text);
        }
        catch (Exception $e) {
            return $this->get_error_from_exception($e);
        }
    }
    /**
     * Signing.
     *
     * @param string Message body
     * @param string Key ID
     * @param string Key password
     * @param int    Signing mode (enigma_engine::SIGN_*)
     *
     * @return mixed True on success or enigma_error on failure
     */
    function sign($text, $key, $passwd, $mode = null)
    {
        try {
@@ -134,6 +146,14 @@
        }
    }
    /**
     * Signature verification.
     *
     * @param string Message body
     * @param string Signature, if message is of type PGP/MIME and body doesn't contain it
     *
     * @return mixed Signature information (enigma_signature) or enigma_error
     */
    function verify($text, $signature)
    {
        try {
@@ -145,6 +165,14 @@
        }
    }
    /**
     * Key file import.
     *
     * @param string  File name or file content
     * @param bollean True if first argument is a filename
     *
     * @return mixed Import status array or enigma_error
     */
    public function import($content, $isfile=false)
    {
        try {
@@ -158,6 +186,13 @@
        }
    }
    /**
     * Key export.
     *
     * @param string Key ID
     *
     * @return mixed Key content or enigma_error
     */
    public function export($keyid)
    {
        try {
@@ -168,6 +203,13 @@
        }
    }
    /**
     * Keys listing.
     *
     * @param string Optional pattern for key ID, user ID or fingerprint
     *
     * @return mixed Array of enigma_key objects or enigma_error
     */
    public function list_keys($pattern='')
    {
        try {
@@ -186,6 +228,13 @@
        }
    }
    /**
     * Single key information.
     *
     * @param string Key ID, user ID or fingerprint
     *
     * @return mixed Key (enigma_key) object or enigma_error
     */
    public function get_key($keyid)
    {
        $list = $this->list_keys($keyid);
@@ -226,6 +275,13 @@
        }
    }
    /**
     * Key deletion.
     *
     * @param string Key ID
     *
     * @return mixed True on success or enigma_error
     */
    public function delete_key($keyid)
    {
        // delete public key
@@ -236,11 +292,11 @@
            $code = $result->getCode();
            // if not found, delete private key
            if ($code == enigma_error::E_KEYNOTFOUND) {
            if ($code == enigma_error::KEYNOTFOUND) {
                $result = $this->delete_privkey($keyid);
            }
            // need to delete private key first
            else if ($code == enigma_error::E_DELKEY) {
            else if ($code == enigma_error::DELKEY) {
                $key = $this->get_key($keyid);
                for ($i = count($key->subkeys) - 1; $i >= 0; $i--) {
                    $type = $key->subkeys[$i]->can_encrypt ? 'priv' : 'pub';
@@ -255,7 +311,10 @@
        return $result;
    }
    public function delete_privkey($keyid)
    /**
     * Private key deletion.
     */
    protected function delete_privkey($keyid)
    {
        try {
            $this->gpg->deletePrivateKey($keyid);
@@ -266,7 +325,10 @@
        }
    }
    public function delete_pubkey($keyid)
    /**
     * Public key deletion.
     */
    protected function delete_pubkey($keyid)
    {
        try {
            $this->gpg->deletePublicKey($keyid);
@@ -284,27 +346,27 @@
     *
     * @return enigma_error Error object
     */
    private function get_error_from_exception($e)
    protected function get_error_from_exception($e)
    {
        $data = array();
        if ($e instanceof Crypt_GPG_KeyNotFoundException) {
            $error = enigma_error::E_KEYNOTFOUND;
            $error = enigma_error::KEYNOTFOUND;
            $data['id'] = $e->getKeyId();
        }
        else if ($e instanceof Crypt_GPG_BadPassphraseException) {
            $error = enigma_error::E_BADPASS;
            $error = enigma_error::BADPASS;
            $data['bad']     = $e->getBadPassphrases();
            $data['missing'] = $e->getMissingPassphrases();
        }
        else if ($e instanceof Crypt_GPG_NoDataException) {
            $error = enigma_error::E_NODATA;
            $error = enigma_error::NODATA;
        }
        else if ($e instanceof Crypt_GPG_DeletePrivateKeyException) {
            $error = enigma_error::E_DELKEY;
            $error = enigma_error::DELKEY;
        }
        else {
            $error = enigma_error::E_INTERNAL;
            $error = enigma_error::INTERNAL;
        }
        $msg = $e->getMessage();
@@ -319,7 +381,7 @@
     *
     * @return enigma_signature Signature object
     */
    private function parse_signature($sig)
    protected function parse_signature($sig)
    {
        $user = $sig->getUserId();
@@ -343,7 +405,7 @@
     *
     * @return enigma_key Key object
     */
    private function parse_key($key)
    protected function parse_key($key)
    {
        $ekey = new enigma_key();
plugins/enigma/lib/enigma_driver_phpssl.php
@@ -39,15 +39,15 @@
        $homedir = $this->rc->config->get('enigma_smime_homedir', INSTALL_PATH . '/plugins/enigma/home');
        if (!$homedir)
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Option 'enigma_smime_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,
            return new enigma_error(enigma_error::INTERNAL,
                "Keys directory doesn't exists: $homedir");
        if (!is_writable($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Keys directory isn't writeable: $homedir");
        $homedir = $homedir . '/' . $this->user;
@@ -57,10 +57,10 @@
            mkdir($homedir, 0700);
        if (!file_exists($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Unable to create keys directory: $homedir");
        if (!is_writable($homedir))
            return new enigma_error(enigma_error::E_INTERNAL,
            return new enigma_error(enigma_error::INTERNAL,
                "Unable to write to keys directory: $homedir");
        $this->homedir = $homedir;
@@ -104,7 +104,7 @@
        if ($sig !== true) {
            // try without certificate verification
            $sig      = openssl_pkcs7_verify($msg_file, PKCS7_NOVERIFY, $cert_file);
            $validity = enigma_error::E_UNVERIFIED;
            $validity = enigma_error::UNVERIFIED;
        }
        if ($sig === true) {
@@ -112,7 +112,7 @@
        }
        else {
            $errorstr = $this->get_openssl_error();
            $sig = new enigma_error(enigma_error::E_INTERNAL, $errorstr);
            $sig = new enigma_error(enigma_error::INTERNAL, $errorstr);
        }
        // remove temp files
@@ -211,7 +211,7 @@
        if (empty($cert) || empty($cert['subject'])) {
            $errorstr = $this->get_openssl_error();
            return new enigma_error(enigm_error::E_INTERNAL, $errorstr);
            return new enigma_error(enigma_error::INTERNAL, $errorstr);
        }
        $data = new enigma_signature();
plugins/enigma/lib/enigma_engine.php
@@ -146,7 +146,7 @@
        $key = $this->find_key($from, true);
        if (empty($key)) {
            return new enigma_error(enigma_error::E_KEYNOTFOUND);
            return new enigma_error(enigma_error::KEYNOTFOUND);
        }
        // check if we have password for this key
@@ -156,7 +156,7 @@
        if ($pass === null) {
            // ask for password
            $error = array('missing' => array($key->id => $key->name));
            return new enigma_error(enigma_error::E_BADPASS, '', $error);
            return new enigma_error(enigma_error::BADPASS, '', $error);
        }
        // select mode
@@ -197,10 +197,10 @@
        $result = $this->pgp_sign($body, $key->id, $pass, $pgp_mode);
        if ($result !== true) {
            if ($result->getCode() == enigma_error::E_BADPASS) {
            if ($result->getCode() == enigma_error::BADPASS) {
                // ask for password
                $error = array('missing' => array($key->id => $key->name));
                return new enigma_error(enigma_error::E_BADPASS, '', $error);
                return new enigma_error(enigma_error::BADPASS, '', $error);
            }
            return $result;
@@ -238,7 +238,7 @@
        }
        if (empty($recipients)) {
            return new enigma_error(enigma_error::E_KEYNOTFOUND);
            return new enigma_error(enigma_error::KEYNOTFOUND);
        }
        $recipients = array_unique($recipients);
@@ -248,7 +248,7 @@
            $key = $this->find_key($email);
            if (empty($key)) {
                return new enigma_error(enigma_error::E_KEYNOTFOUND, '', array(
                return new enigma_error(enigma_error::KEYNOTFOUND, '', array(
                    'missing' => $email
                ));
            }
@@ -729,7 +729,7 @@
        // @TODO: Handle big bodies using (temp) files
        $sig = $this->pgp_driver->verify($msg_body, $sig_body);
        if (($sig instanceof enigma_error) && $sig->getCode() != enigma_error::E_KEYNOTFOUND)
        if (($sig instanceof enigma_error) && $sig->getCode() != enigma_error::KEYNOTFOUND)
            rcube::raise_error(array(
                'code' => 600, 'type' => 'php',
                'file' => __FILE__, 'line' => __LINE__,
@@ -754,7 +754,7 @@
        if ($result instanceof enigma_error) {
            $err_code = $result->getCode();
            if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
            if (!in_array($err_code, array(enigma_error::KEYNOTFOUND, enigma_error::BADPASS)))
                rcube::raise_error(array(
                    'code' => 600, 'type' => 'php',
                    'file' => __FILE__, 'line' => __LINE__,
@@ -785,7 +785,7 @@
        if ($result instanceof enigma_error) {
            $err_code = $result->getCode();
            if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
            if (!in_array($err_code, array(enigma_error::KEYNOTFOUND, enigma_error::BADPASS)))
                rcube::raise_error(array(
                    'code' => 600, 'type' => 'php',
                    'file' => __FILE__, 'line' => __LINE__,
@@ -814,7 +814,7 @@
        if ($result instanceof enigma_error) {
            $err_code = $result->getCode();
            if (!in_array($err_code, array(enigma_error::E_KEYNOTFOUND, enigma_error::E_BADPASS)))
            if (!in_array($err_code, array(enigma_error::KEYNOTFOUND, enigma_error::BADPASS)))
                rcube::raise_error(array(
                    'code' => 600, 'type' => 'php',
                    'file' => __FILE__, 'line' => __LINE__,
@@ -1075,10 +1075,8 @@
            $config = $this->rc->decrypt($config);
            $config = @unserialize($config);
        }
        if($this->password_time) {
            $threshold = time() - $this->password_time;
        }
        $threshold = $this->password_time ? time() - $this->password_time : 0;
        $keys      = array();
        // delete expired passwords
plugins/enigma/lib/enigma_error.php
@@ -22,14 +22,14 @@
    private $data = array();
    // error codes
    const E_OK          = 0;
    const E_INTERNAL    = 1;
    const E_NODATA      = 2;
    const E_KEYNOTFOUND = 3;
    const E_DELKEY      = 4;
    const E_BADPASS     = 5;
    const E_EXPIRED     = 6;
    const E_UNVERIFIED  = 7;
    const OK          = 0;
    const INTERNAL    = 1;
    const NODATA      = 2;
    const KEYNOTFOUND = 3;
    const DELKEY      = 4;
    const BADPASS     = 5;
    const EXPIRED     = 6;
    const UNVERIFIED  = 7;
    function __construct($code = null, $message = '', $data = array())
plugins/enigma/lib/enigma_subkey.php
@@ -47,5 +47,4 @@
    {
        return enigma_key::format_fingerprint($this->fingerprint);
    }
}
plugins/enigma/lib/enigma_ui.php
@@ -724,11 +724,11 @@
                $attrib['class'] = 'enigmaerror';
                $code            = $status->getCode();
                if ($code == enigma_error::E_KEYNOTFOUND) {
                if ($code == enigma_error::KEYNOTFOUND) {
                    $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')),
                        $this->enigma->gettext('decryptnokey')));
                }
                else if ($code == enigma_error::E_BADPASS) {
                else if ($code == enigma_error::BADPASS) {
                    $msg = rcube::Q($this->enigma->gettext('decryptbadpass'));
                    $this->password_prompt($status);
                }
@@ -756,7 +756,7 @@
            if ($sig instanceof enigma_signature) {
                $sender = ($sig->name ? $sig->name . ' ' : '') . '<' . $sig->email . '>';
                if ($sig->valid === enigma_error::E_UNVERIFIED) {
                if ($sig->valid === enigma_error::UNVERIFIED) {
                    $attrib['class'] = 'enigmawarning';
                    $msg = str_replace('$sender', $sender, $this->enigma->gettext('sigunverified'));
                    $msg = str_replace('$keyid', $sig->id, $msg);
@@ -771,7 +771,7 @@
                    $msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext('siginvalid')));
                }
            }
            else if ($sig && $sig->getCode() == enigma_error::E_KEYNOTFOUND) {
            else if ($sig && $sig->getCode() == enigma_error::KEYNOTFOUND) {
                $attrib['class'] = 'enigmawarning';
                $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($sig->getData('id')),
                    $this->enigma->gettext('signokey')));
@@ -890,11 +890,11 @@
        if ($mode && ($status instanceof enigma_error)) {
            $code = $status->getCode();
            if ($code == enigma_error::E_KEYNOTFOUND) {
            if ($code == enigma_error::KEYNOTFOUND) {
                $vars = array('email' => $status->getData('missing'));
                $msg  = 'enigma.' . $mode . 'nokey';
            }
            else if ($code == enigma_error::E_BADPASS) {
            else if ($code == enigma_error::BADPASS) {
                $msg  = 'enigma.' . $mode . 'badpass';
                $type = 'warning';
@@ -932,11 +932,11 @@
            if ($status instanceof enigma_error) {
                $code = $status->getCode();
                if ($code == enigma_error::E_KEYNOTFOUND) {
                if ($code == enigma_error::KEYNOTFOUND) {
                    $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')),
                        $this->enigma->gettext('decryptnokey')));
                }
                else if ($code == enigma_error::E_BADPASS) {
                else if ($code == enigma_error::BADPASS) {
                    $this->password_prompt($status, array('compose-init' => true));
                    return $p;
                }