Update to new Horde_Crypt code
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 26 Feb 2009 07:04:03 +0000 (00:04 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 26 Feb 2009 07:04:03 +0000 (00:04 -0700)
12 files changed:
imp/ajax.php
imp/compose.php
imp/lib/Compose.php
imp/lib/Crypt/Pgp.php [new file with mode: 0644]
imp/lib/Crypt/Smime.php [new file with mode: 0644]
imp/lib/Crypt/pgp.php [deleted file]
imp/lib/Crypt/smime.php [deleted file]
imp/lib/Mime/Viewer/pgp.php
imp/lib/Mime/Viewer/plain.php
imp/lib/Mime/Viewer/smime.php
imp/pgp.php
imp/smime.php

index 1f99374..9fb6fb5 100644 (file)
@@ -697,29 +697,39 @@ case 'SMIMEPersonal':
     $passphrase = Util::getFormData('dialog_input');
 
     if ($action == 'SMIMEPersonal') {
-        $imp_smime = Horde_Crypt::singleton(array('imp', 'smime'));
-        $secure_check = $imp_smime->requireSecureConnection();
-        if (!is_a($secure_check, 'PEAR_Error') && $passphrase) {
-            $res = $imp_smime->storePassphrase($passphrase);
+        $imp_smime = Horde_Crypt::singleton(array('IMP', 'Smime'));
+        try {
+            $imp_smime->requireSecureConnection();
+            if ($passphrase) {
+                if ($imp_smime->storePassphrase($passphrase)) {
+                    $result->success = 1;
+                } else {
+                    $result->error = _("Invalid passphrase entered.");
+                }
+            } else {
+                $result->error = _("No passphrase entered.");
+            }
+        } catch (Horde_Exception $e) {
+            $result->error = $e->getMessage();
         }
     } else {
-        $imp_pgp = Horde_Crypt::singleton(array('imp', 'pgp'));
-        $secure_check = $imp_pgp->requireSecureConnection();
-        if (is_a($secure_check, 'PEAR_Error') && $passphrase) {
-            $res = $imp_pgp->storePassphrase(($action == 'PGPSymmetric') ? 'symmetric' : 'personal', $passphrase, Util::getFormData('symmetricid'));
+        $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
+        try {
+            $imp_pgp->requireSecureConnection();
+            if ($passphrase) {
+                if ($imp_pgp->storePassphrase(($action == 'PGPSymmetric') ? 'symmetric' : 'personal', $passphrase, Util::getFormData('symmetricid'))) {
+                    $result->success = 1;
+                } else {
+                    $result->error = _("Invalid passphrase entered.");
+                }
+            } else {
+                $result->error = _("No passphrase entered.");
+            }
+        } catch (Horde_Exception $e) {
+            $result->error = $e->getMessage();
         }
     }
 
-    if (is_a($secure_check, 'PEAR_Error')) {
-        $result->error = $secure_check->getMessage();
-    } elseif (!$passphrase) {
-        $result->error = _("No passphrase entered.");
-    } elseif ($res) {
-        $result->success = 1;
-    } else {
-        $result->error = _("Invalid passphrase entered.");
-    }
-
     if ($_SESSION['imp']['view'] != 'dimp') {
         $notify = false;
     }
index 02f8ee5..f3796cf 100644 (file)
@@ -748,7 +748,7 @@ if ($prefs->getValue('use_pgp')) {
         try {
             $addrs = $imp_compose->recipientList($header);
             if (!empty($addrs['list'])) {
-                $imp_pgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
+                $imp_pgp = &Horde_Crypt::singleton(array('IMP', 'Pgp'));
                 foreach ($addrs['list'] as $val) {
                     $imp_pgp->getPublicKey($val);
                 }
index f257ef7..cf18add 100644 (file)
@@ -1022,7 +1022,7 @@ class IMP_Compose
 
         if ($attach_flag) {
             if ($this->_pgpAttachPubkey) {
-                $imp_pgp = Horde_Crypt::singleton(array('imp', 'pgp'));
+                $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
                 $base->addPart($imp_pgp->publicKeyMIMEPart());
             }
 
@@ -1036,7 +1036,7 @@ class IMP_Compose
         if ($GLOBALS['prefs']->getValue('use_pgp') &&
             !empty($GLOBALS['conf']['utils']['gnupg']) &&
             in_array($encrypt, array(IMP::PGP_ENCRYPT, IMP::PGP_SIGN, IMP::PGP_SIGNENC, IMP::PGP_SYM_ENCRYPT, IMP::PGP_SYM_SIGNENC))) {
-            $imp_pgp = Horde_Crypt::singleton(array('imp', 'pgp'));
+            $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
 
             switch ($encrypt) {
             case IMP::PGP_SIGN:
@@ -1092,7 +1092,7 @@ class IMP_Compose
             }
         } elseif ($GLOBALS['prefs']->getValue('use_smime') &&
                   in_array($encrypt, array(IMP::SMIME_ENCRYPT, IMP::SMIME_SIGN, IMP::SMIME_SIGNENC))) {
-            $imp_smime = Horde_Crypt::singleton(array('imp', 'smime'));
+            $imp_smime = Horde_Crypt::singleton(array('IMP', 'Smime'));
 
             /* Check to see if we have the user's passphrase yet. */
             if (in_array($encrypt, array(IMP::SMIME_SIGN, IMP::SMIME_SIGNENC))) {
diff --git a/imp/lib/Crypt/Pgp.php b/imp/lib/Crypt/Pgp.php
new file mode 100644 (file)
index 0000000..fba6014
--- /dev/null
@@ -0,0 +1,585 @@
+<?php
+/**
+ * The IMP_Crypt_pgp:: class contains all functions related to handling
+ * PGP messages within IMP.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Crypt_Pgp extends Horde_Crypt_Pgp
+{
+    /* Name of PGP public key field in addressbook. */
+    const PUBKEY_FIELD = 'pgpPublicKey';
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        parent::__construct(array(
+            'program' => $GLOBALS['conf']['utils']['gnupg'],
+            'temp' => Horde::getTempDir()
+        ));
+    }
+
+    /**
+     * Generate the personal Public/Private keypair and store in prefs.
+     *
+     * @param string $realname    See Horde_Crypt_Pgp::
+     * @param string $email       See Horde_Crypt_Pgp::
+     * @param string $passphrase  See Horde_Crypt_Pgp::
+     * @param string $comment     See Horde_Crypt_Pgp::
+     * @param string $keylength   See Horde_Crypt_Pgp::
+     *
+     * @throws Horde_Exception
+     */
+    public function generatePersonalKeys($name, $email, $passphrase,
+                                         $comment = '', $keylength = 1024)
+    {
+        $keys = $this->generateKey($name, $email, $passphrase, $comment, $keylength);
+
+        /* Store the keys in the user's preferences. */
+        $this->addPersonalPublicKey($keys['public']);
+        $this->addPersonalPrivateKey($keys['private']);
+    }
+
+    /**
+     * Add the personal public key to the prefs.
+     *
+     * @param mixed $public_key  The public key to add (either string or
+     *                           array).
+     */
+    public function addPersonalPublicKey($public_key)
+    {
+        $GLOBALS['prefs']->setValue('pgp_public_key', (is_array($public_key)) ? implode('', $public_key) : $public_key);
+    }
+
+    /**
+     * Add the personal private key to the prefs.
+     *
+     * @param mixed $private_key  The private key to add (either string or
+     *                            array).
+     */
+    public function addPersonalPrivateKey($private_key)
+    {
+        $GLOBALS['prefs']->setValue('pgp_private_key', (is_array($private_key)) ? implode('', $private_key) : $private_key);
+    }
+
+    /**
+     * Get the personal public key from the prefs.
+     *
+     * @return string  The personal PGP public key.
+     */
+    public function getPersonalPublicKey()
+    {
+        return $GLOBALS['prefs']->getValue('pgp_public_key');
+    }
+
+    /**
+     * Get the personal private key from the prefs.
+     *
+     * @return string  The personal PGP private key.
+     */
+    public function getPersonalPrivateKey()
+    {
+        return $GLOBALS['prefs']->getValue('pgp_private_key');
+    }
+
+    /**
+     * Deletes the specified personal keys from the prefs.
+     */
+    public function deletePersonalKeys()
+    {
+        $GLOBALS['prefs']->setValue('pgp_public_key', '');
+        $GLOBALS['prefs']->setValue('pgp_private_key', '');
+
+        $this->unsetPassphrase('personal');
+    }
+
+    /**
+     * Add a public key to an address book.
+     *
+     * @param string $public_key  An PGP public key.
+     *
+     * @return array  See Horde_Crypt_Pgp::pgpPacketInformation()
+     * @throws Horde_Exception
+     */
+    public function addPublicKey($public_key)
+    {
+        /* Make sure the key is valid. */
+        $key_info = $this->pgpPacketInformation($public_key);
+        if (!isset($key_info['signature'])) {
+            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
+        }
+
+        /* Remove the '_SIGNATURE' entry. */
+        unset($key_info['signature']['_SIGNATURE']);
+
+        /* Store all signatures that appear in the key. */
+        foreach ($key_info['signature'] as $id => $sig) {
+            /* Check to make sure the key does not already exist in ANY
+             * address book and remove the id from the key_info for a correct
+             * output. */
+            try {
+                $result = $this->getPublicKey($sig['email'], null, false);
+                if (!empty($result)) {
+                    unset($key_info['signature'][$id]);
+                    continue;
+                }
+            } catch (Horde_Exception $e) {}
+
+            /* Add key to the user's address book. */
+            $result = $GLOBALS['registry']->call('contacts/addField', array($sig['email'], $sig['name'], self::PUBKEY_FIELD, $public_key, $GLOBALS['prefs']->getValue('add_source')));
+            if (is_a($result, 'PEAR_Error')) {
+                throw new Horde_Exception($result);
+            }
+        }
+
+        return $key_info;
+    }
+
+    /**
+     * Retrieves a public key by e-mail.
+     *
+     * First, the key will be attempted to be retrieved from a user's address
+     * book(s).
+     * Second, if unsuccessful, the key is attempted to be retrieved via a
+     * public PGP keyserver.
+     *
+     * @param string $address      The e-mail address to search by.
+     * @param string $fingerprint  The fingerprint of the user's key.
+     * @param boolean $server      Whether to check the public key servers for
+     *                             the key.
+     *
+     * @return string  The PGP public key requested.
+     * @throws Horde_Exception
+     */
+    public function getPublicKey($address, $fingerprint = null, $server = true)
+    {
+        /* If there is a cache driver configured, try to get the public key
+         * from the cache. */
+        if (($cache = IMP::getCache())) {
+            $result = $cache->get("PGPpublicKey_" . $address . $fingerprint, 3600);
+            if ($result) {
+                Horde::logMessage('PGPpublicKey: ' . serialize($result), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+                return $result;
+            }
+        }
+
+        /* Try retrieving by e-mail only first. */
+        $params = IMP_Compose::getAddressSearchParams();
+        $result = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true));
+
+        /* TODO: Retrieve by ID. */
+
+        /* See if the address points to the user's public key. */
+        if (is_a($result, 'PEAR_Error')) {
+            require_once 'Horde/Identity.php';
+            $identity = Identity::singleton(array('imp', 'imp'));
+            $personal_pubkey = $this->getPersonalPublicKey();
+            if (!empty($personal_pubkey) && $identity->hasAddress($address)) {
+                $result = $personal_pubkey;
+            }
+        }
+
+        /* Try retrieving via a PGP public keyserver. */
+        if ($server && is_a($result, 'PEAR_Error')) {
+            $result = $this->getFromPublicKeyserver($fingerprint, $address);
+        }
+
+        /* Return now, if no public key found at all. */
+        if (is_a($result, 'PEAR_Error')) {
+            throw new Horde_Exception($result);
+        }
+
+        /* If more than one public key is returned, just return the first in
+         * the array. There is no way of knowing which is the "preferred" key,
+         * if the keys are different. */
+        if (is_array($result)) {
+            reset($result);
+        }
+
+        /* If there is a cache driver configured and a cache object exists,
+         * store the public key in the cache. */
+        if (is_object($cache)) {
+            $cache->set("PGPpublicKey_" . $address . $fingerprint, $result, 3600);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Retrieves all public keys from a user's address book(s).
+     *
+     * @return array  All PGP public keys available.
+     * @throws Horde_Exception
+     */
+    public function listPublicKeys()
+    {
+        $params = IMP_Compose::getAddressSearchParams();
+        if (empty($params['sources'])) {
+            return array();
+        }
+
+        $res = $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(self::PUBKEY_FIELD, $params['sources']));
+        if (is_a($res, 'PEAR_Error')) {
+            throw new Horde_Exception($res);
+        }
+
+        return $res;
+    }
+
+    /**
+     * Deletes a public key from a user's address book(s) by e-mail.
+     *
+     * @param string $email  The e-mail address to delete.
+     *
+     * @throws Horde_Exception
+     */
+    public function deletePublicKey($email)
+    {
+        $params = IMP_Compose::getAddressSearchParams();
+        $res = $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources']));
+        if (is_a($res, 'PEAR_Error')) {
+            throw new Horde_Exception($res);
+        }
+
+        return $res;
+    }
+
+    /**
+     * Get a public key via a public PGP keyserver.
+     *
+     * @param string $fingerprint  The fingerprint of the requested key.
+     * @param string $address      The email address of the requested key.
+     *
+     * @return string  See Horde_Crypt_Pgp::getPublicKeyserver()
+     * @throws Horde_Exception
+     */
+    public function getFromPublicKeyserver($fingerprint, $address = null)
+    {
+        return $this->_keyserverConnect($fingerprint, 'get', $address);
+    }
+
+    /**
+     * Send a public key to a public PGP keyserver.
+     *
+     * @param string $pubkey  The PGP public key.
+     *
+     * @return string  See Horde_Crypt_Pgp::putPublicKeyserver()
+     * @throws Horde_Exception
+     */
+    public function sendToPublicKeyserver($pubkey)
+    {
+        return $this->_keyserverConnect($pubkey, 'put');
+    }
+
+    /**
+     * Connect to the keyservers
+     *
+     * @param string $data        The data to send to the keyserver.
+     * @param string $method      The method to use - either 'get' or 'put'.
+     * @param string $additional  Any additional data.
+     *
+     * @return string  See Horde_Crypt_Pgp::getPublicKeyserver() -or-
+     *                     Horde_Crypt_Pgp::putPublicKeyserver().
+     * @throws Horde_Exception
+     */
+    protected function _keyserverConnect($data, $method, $additional = null)
+    {
+        global $conf;
+
+        if (empty($conf['utils']['gnupg_keyserver'])) {
+            throw new Horde_Exception(_("Public PGP keyserver support has been disabled."), 'horde.warning');
+        }
+
+        $timeout = (empty($conf['utils']['gnupg_timeout'])) ? PGP_KEYSERVER_TIMEOUT : $conf['utils']['gnupg_timeout'];
+
+        if ($method == 'put') {
+            return $this->putPublicKeyserver($data, $conf['utils']['gnupg_keyserver'][0], $timeout);
+        }
+
+        foreach ($conf['utils']['gnupg_keyserver'] as $server) {
+            try {
+                return $this->getPublicKeyserver($data, $server, $timeout, $additional);
+            } catch (Horde_Exception $e) {}
+        }
+        throw new Horde_Exception(_("Could not connect to public PGP keyserver"));
+    }
+
+    /**
+     * Verifies a signed message with a given public key.
+     *
+     * @param string $text       The text to verify.
+     * @param string $address    E-mail address of public key.
+     * @param string $signature  A PGP signature block.
+     *
+     * @return stdClass  See Horde_Crypt_Pgp::decrypt().
+     * @throws Horde_Exception
+     */
+    public function verifySignature($text, $address, $signature = '')
+    {
+        $fingerprint = null;
+
+        /* Get fingerprint of key. */
+        if (!empty($signature)) {
+            $packet_info = $this->pgpPacketInformation($signature);
+            if (isset($packet_info['fingerprint'])) {
+                $fingerprint = $packet_info['fingerprint'];
+            }
+        } else {
+            $fingerprint = $this->getSignersKeyID($text);
+        }
+
+        $public_key = $this->getPublicKey($address, $fingerprint);
+
+        if (empty($signature)) {
+            $options = array('type' => 'signature');
+        } else {
+            $options = array('type' => 'detached-signature', 'signature' => $signature);
+        }
+        $options['pubkey'] = $public_key;
+
+        return $this->decrypt($text, $options);
+    }
+
+    /**
+     * Decrypt a message with user's public/private keypair or a passphrase.
+     *
+     * @param string $text         The text to decrypt.
+     * @param string $type         Either 'literal', 'personal', or
+     *                             'symmetric'.
+     * @param boolean $passphrase  If $type is 'personal' or 'symmetrical',
+     *                             the passphrase to use.
+     *
+     * @return stdClass  See Horde_Crypt_Pgp::decrypt().
+     * @throws Horde_Exception
+     */
+    public function decryptMessage($text, $type, $passphrase = null)
+    {
+        switch ($type) {
+        case 'literal':
+            return $this->decrypt($text, array('type' => 'message', 'no_passphrase' => true));
+            break;
+
+        case 'symmetric':
+            return $this->decrypt($text, array('type' => 'message', 'passphrase' => $passphrase));
+            break;
+
+        case 'personal':
+            return $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $passphrase));
+        }
+    }
+
+    /**
+     * Gets a passphrase from the session cache.
+     *
+     * @param integer $type  The type of passphrase. Either 'personal' or
+     *                       'symmetric'.
+     * @param string $id     If $type is 'symmetric', the ID of the stored
+     *                       passphrase.
+     *
+     * @return mixed  The passphrase, if set, or null.
+     */
+    public function getPassphrase($type, $id = null)
+    {
+        if ($type == 'personal') {
+            $id = 'personal';
+        }
+
+        return isset($_SESSION['imp']['cache']['pgp'][$type][$id])
+            ? Horde_Secret::read(IMP::getAuthKey(), $_SESSION['imp']['cache']['pgp'][$type][$id])
+            : null;
+    }
+
+    /**
+     * Store's the user's passphrase in the session cache.
+     *
+     * @param integer $type       The type of passphrase. Either 'personal' or
+     *                            'symmetric'.
+     * @param string $passphrase  The user's passphrase.
+     * @param string $id          If $type is 'symmetric', the ID of the
+     *                            stored passphrase.
+     *
+     * @return boolean  Returns true if correct passphrase, false if incorrect.
+     */
+    public function storePassphrase($type, $passphrase, $id)
+    {
+        if ($type == 'personal') {
+            if ($this->verifyPassphrase($this->getPersonalPublicKey(), $this->getPersonalPrivateKey(), $passphrase) === false) {
+                return false;
+            }
+            $id = 'personal';
+        }
+
+        $_SESSION['imp']['cache']['pgp'][$type][$id] = Horde_Secret::write(IMP::getAuthKey(), $passphrase);
+        return true;
+    }
+
+    /**
+     * Clear the passphrase from the session cache.
+     *
+     * @param integer $type       The type of passphrase. Either 'personal' or
+     *                            'symmetric'.
+     * @param string $id          If $type is 'symmetric', the ID of the
+     *                            stored passphrase. Else, all passphrases
+     *                            are deleted.
+     */
+    public function unsetPassphrase($type, $id = null)
+    {
+        if (($type == 'symmetric') && !is_null($id)) {
+            unset($_SESSION['imp']['cache']['pgp']['symmetric'][$id]);
+        } else {
+            unset($_SESSION['imp']['cache']['pgp'][$type]);
+        }
+    }
+
+    /**
+     * Generates a cache ID for symmetric message data.
+     *
+     * @param string $mailbox  The mailbox of the message.
+     * @param integer $uid     The UID of the message.
+     * @param string $id       The MIME ID of the message.
+     *
+     * @return string  A unique symmetric cache ID.
+     */
+    public function getSymmetricID($mailbox, $uid, $id)
+    {
+        return implode('|', array($mailbox, $uid, $id));
+    }
+
+    /**
+     * Generates the javascript code for saving public keys.
+     *
+     * @param string $mailbox  The mailbox of the message.
+     * @param integer $uid     The UID of the message.
+     * @param string $id       The MIME ID of the message.
+     *
+     * @return string  The URL for saving public keys.
+     */
+    public function savePublicKeyURL($mailbox, $uid, $id)
+    {
+        $params = array(
+            'actionID' => 'save_attachment_public_key',
+            'uid' => $uid,
+            'mime_id' => $id
+        );
+        return IMP::popupIMPString('pgp.php', $params, 450, 200);
+    }
+
+    /**
+     * Provide the list of parameters needed for signing a message.
+     *
+     * @return array  The list of parameters needed by encrypt().
+     */
+    protected function _signParameters()
+    {
+        return array(
+            'pubkey' => $this->getPersonalPublicKey(),
+            'privkey' => $this->getPersonalPrivateKey(),
+            'passphrase' => $this->getPassphrase('personal')
+        );
+    }
+
+    /**
+     * Provide the list of parameters needed for encrypting a message.
+     *
+     * @param array $addresses   The e-mail address of the keys to use for
+     *                           encryption.
+     * @param string $symmetric  If true, the symmetric password to use for
+     *                           encrypting. If null, uses the personal key.
+     *
+     * @return array  The list of parameters needed by encrypt().
+     * @throws Horde_Exception
+     */
+    protected function _encryptParameters($addresses, $symmetric)
+    {
+        if (!is_null($symmetric)) {
+            return array(
+                'symmetric' => true,
+                'passphrase' => $symmetric
+            );
+        }
+
+        $addr_list = array();
+
+        foreach ($addresses as $val) {
+            $addrOb = Horde_Mime_Address::bareAddress($val, $_SESSION['imp']['maildomain'], true);
+            $key_addr = array_pop($addrOb);
+
+            /* Get the public key for the address. */
+            $addr_list[$key_addr] = $this->getPublicKey($key_addr);
+        }
+
+        return array('recips' => $addr_list);
+    }
+
+    /**
+     * Sign a Horde_Mime_Part using PGP using IMP default parameters.
+     *
+     * @param Horde_Mime_Part $mime_part  The object to sign.
+     *
+     * @return Horde_Mime_Part  See Horde_Crypt_Pgp::signMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPsignMIMEPart($mime_part)
+    {
+        return $this->signMIMEPart($mime_part, $this->_signParameters());
+    }
+
+    /**
+     * Encrypt a Horde_Mime_Part using PGP using IMP default parameters.
+     *
+     * @param Horde_Mime_Part $mime_part  The object to encrypt.
+     * @param array $addresses            The e-mail address of the keys to
+     *                                    use for encryption.
+     * @param string $symmetric           If true, the symmetric password to
+     *                                    use for encrypting. If null, uses
+     *                                    the personal key.
+     *
+     * @return Horde_Mime_Part  See Horde_Crypt_Pgp::encryptMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPencryptMIMEPart($mime_part, $addresses,
+                                       $symmetric = null)
+    {
+        return $this->encryptMIMEPart($mime_part, $this->_encryptParameters($addresses, $symmetric));
+    }
+
+    /**
+     * Sign and Encrypt a Horde_Mime_Part using PGP using IMP default
+     * parameters.
+     *
+     * @param Horde_Mime_Part $mime_part  The object to sign and encrypt.
+     * @param array $addresses            The e-mail address of the keys to
+     *                                    use for encryption.
+     * @param string $symmetric           If true, the symmetric password to
+     *                                    use for encrypting. If null, uses
+     *                                    the personal key.
+     *
+     * @return Horde_Mime_Part  See Horde_Crypt_Pgp::signAndencryptMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPsignAndEncryptMIMEPart($mime_part, $addresses,
+                                              $symmetric = null)
+    {
+        return $this->signAndEncryptMIMEPart($mime_part, $this->_signParameters(), $this->_encryptParameters($addresses, $symmetric));
+    }
+
+    /**
+     * Generate a Horde_Mime_Part object, in accordance with RFC 2015/3156,
+     * that contains the user's public key.
+     *
+     * @return Horde_Mime_Part  See Horde_Crypt_Pgp::publicKeyMIMEPart().
+     */
+    public function publicKeyMIMEPart()
+    {
+        return parent::publicKeyMIMEPart($this->getPersonalPublicKey());
+    }
+
+}
diff --git a/imp/lib/Crypt/Smime.php b/imp/lib/Crypt/Smime.php
new file mode 100644 (file)
index 0000000..c9764de
--- /dev/null
@@ -0,0 +1,428 @@
+<?php
+/**
+ * The IMP_Crypt_Smime:: class contains all functions related to handling
+ * S/MIME messages within IMP.
+ *
+ * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Mike Cochrane <mike@graftonhall.co.nz>
+ * @package IMP
+ */
+class IMP_Crypt_Smime extends Horde_Crypt_Smime
+{
+    /* Name of the S/MIME public key field in addressbook. */
+    const PUBKEY_FIELD = 'smimePublicKey';
+
+    /**
+     * Constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct(array('temp' => Horde::getTempDir()));
+    }
+
+    /**
+     * Add the personal public key to the prefs.
+     *
+     * @param mixed $key  The public key to add (either string or array).
+     */
+    public function addPersonalPublicKey($key)
+    {
+        $GLOBALS['prefs']->setValue('smime_public_key', (is_array($key)) ? implode('', $key) : $key);
+    }
+
+    /**
+     * Add the personal private key to the prefs.
+     *
+     * @param mixed $key  The private key to add (either string or array).
+     */
+    public function addPersonalPrivateKey($key)
+    {
+        $GLOBALS['prefs']->setValue('smime_private_key', (is_array($key)) ? implode('', $key) : $key);
+    }
+
+    /**
+     * Add the list of additional certs to the prefs.
+     *
+     * @param mixed $key  The private key to add (either string or array).
+     */
+    public function addAdditionalCert($key)
+    {
+        $GLOBALS['prefs']->setValue('smime_additional_cert', (is_array($key)) ? implode('', $key) : $key);
+    }
+
+    /**
+     * Get the personal public key from the prefs.
+     *
+     * @return string  The personal S/MIME public key.
+     */
+    public function getPersonalPublicKey()
+    {
+        return $GLOBALS['prefs']->getValue('smime_public_key');
+    }
+
+    /**
+     * Get the personal private key from the prefs.
+     *
+     * @return string  The personal S/MIME private key.
+     */
+    public function getPersonalPrivateKey()
+    {
+        return $GLOBALS['prefs']->getValue('smime_private_key');
+    }
+
+    /**
+     * Get any additional certificates from the prefs.
+     *
+     * @return string  Additional signing certs for inclusion.
+     */
+    public function getAdditionalCert()
+    {
+        return $GLOBALS['prefs']->getValue('smime_additional_cert');
+    }
+
+    /**
+     * Deletes the specified personal keys from the prefs.
+     */
+    public function deletePersonalKeys()
+    {
+        $GLOBALS['prefs']->setValue('smime_public_key', '');
+        $GLOBALS['prefs']->setValue('smime_private_key', '');
+        $GLOBALS['prefs']->setValue('smime_additional_cert', '');
+        $this->unsetPassphrase();
+    }
+
+    /**
+     * Add a public key to an address book.
+     *
+     * @param string $cert  A public certificate to add.
+     *
+     * @throws Horde_Exception
+     */
+    public function addPublicKey($cert)
+    {
+        /* Make sure the certificate is valid. */
+        $key_info = openssl_x509_parse($cert);
+        if (!is_array($key_info) || !isset($key_info['subject'])) {
+            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
+        }
+
+        /* Add key to the user's address book. */
+        $email = $this->getEmailFromKey($cert);
+        if (is_null($email)) {
+            throw new Horde_Exception(_("No email information located in the public key."), 'horde.error');
+        }
+
+        /* Get the name corresponding to this key. */
+        if (isset($key_info['subject']['CN'])) {
+            $name = $key_info['subject']['CN'];
+        } elseif (isset($key_info['subject']['OU'])) {
+            $name = $key_info['subject']['OU'];
+        } else {
+            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
+        }
+
+        $res = $GLOBALS['registry']->call('contacts/addField', array($email, $name, self::PUBKEY_FIELD, $cert, $GLOBALS['prefs']->getValue('add_source')));
+        if (is_a($res, 'PEAR_Error')) {
+            throw new Horde_Exception($res);
+        }
+    }
+
+    /**
+     * Returns the params needed to encrypt a message being sent to the
+     * specified email address.
+     *
+     * @param string $address  The e-mail address of the recipient.
+     *
+     * @return array  The list of parameters needed by encrypt().
+     * @throws Horde_Exception
+     */
+    protected function _encryptParameters($address)
+    {
+        /* We can only encrypt if we are sending to a single person. */
+        $addrOb = Horde_Mime_Address::bareAddress($address, $_SESSION['imp']['maildomain'], true);
+        $key_addr = array_pop($addrOb);
+
+        $public_key = $this->getPublicKey($key_addr);
+
+        return array(
+            'pubkey' => $public_key,
+            'type' => 'message'
+        );
+    }
+
+    /**
+     * Retrieves a public key by e-mail.
+     * The key will be retrieved from a user's address book(s).
+     *
+     * @param string $address  The e-mail address to search for.
+     *
+     * @return string  The S/MIME public key requested.
+     * @throws Horde_Exception
+     */
+    public function getPublicKey($address)
+    {
+        $params = IMP_Compose::getAddressSearchParams();
+        $key = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true));
+
+        /* See if the address points to the user's public key. */
+        if (is_a($key, 'PEAR_Error')) {
+            require_once 'Horde/Identity.php';
+            $identity = &Identity::singleton(array('imp', 'imp'));
+            $personal_pubkey = $this->getPersonalPublicKey();
+            if (!empty($personal_pubkey) && $identity->hasAddress($address)) {
+                return $personal_pubkey;
+            }
+            throw new Horde_Exception($key);
+        }
+
+        /* If more than one public key is returned, just return the first in
+         * the array. There is no way of knowing which is the "preferred" key,
+         * if the keys are different. */
+        return is_array($key) ? reset($key) : $key;
+    }
+
+    /**
+     * Retrieves all public keys from a user's address book(s).
+     *
+     * @return array  All PGP public keys available.
+     * @throws Horde_Exception
+     */
+    public function listPublicKeys()
+    {
+        $params = IMP_Compose::getAddressSearchParams();
+        if (empty($params['sources'])) {
+            return array();
+        }
+        $res = $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(self::PUBKEY_FIELD, $params['sources']));
+        if (is_a($res, 'PEAR_Error')) {
+            throw new Horde_Exception($res);
+        }
+
+        return $res;
+    }
+
+    /**
+     * Deletes a public key from a user's address book(s) by e-mail.
+     *
+     * @param string $email  The e-mail address to delete.
+     *
+     * @throws Horde_Exception
+     */
+    public function deletePublicKey($email)
+    {
+        $params = IMP_Compose::getAddressSearchParams();
+        $res = $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources']));
+        if (is_a($res, 'PEAR_Error')) {
+            throw new Horde_Exception($res);
+        }
+    }
+
+    /**
+     * Returns the parameters needed for signing a message.
+     *
+     * @return array  The list of parameters needed by encrypt().
+     */
+    protected function _signParameters()
+    {
+        return array(
+            'type' => 'signature',
+            'pubkey' => $this->getPersonalPublicKey(),
+            'privkey' => $this->getPersonalPrivateKey(),
+            'passphrase' => $this->getPassphrase(),
+            'sigtype' => 'detach',
+            'certs' => $this->getAdditionalCert()
+        );
+    }
+
+    /**
+     * Verifies a signed message with a given public key.
+     *
+     * @param string $text  The text to verify.
+     *
+     * @return stdClass  See Horde_Crypt_Smime::verify().
+     * @throws Horde_Exception
+     */
+    public function verifySignature($text)
+    {
+        return $this->verify($text, empty($GLOBALS['conf']['utils']['openssl_cafile']) ? array() : $GLOBALS['conf']['utils']['openssl_cafile']);
+    }
+
+
+    /**
+     * Decrypt a message with user's public/private keypair.
+     *
+     * @param string $text  The text to decrypt.
+     *
+     * @return string  See Horde_Crypt_Smime::decrypt().
+     * @throws Horde_Exception
+     */
+    public function decryptMessage($text)
+    {
+        return $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $this->getPassphrase()));
+    }
+
+    /**
+     * Gets the user's passphrase from the session cache.
+     *
+     * @return mixed  The passphrase, if set.  Returns false if the passphrase
+     *                has not been loaded yet.  Returns null if no passphrase
+     *                is needed.
+     */
+    public function getPassphrase()
+    {
+        $private_key = $GLOBALS['prefs']->getValue('smime_private_key');
+        if (empty($private_key)) {
+            return false;
+        }
+
+        if (isset($_SESSION['imp']['smime']['passphrase'])) {
+            return Horde_Secret::read(IMP::getAuthKey(), $_SESSION['imp']['smime']['passphrase']);
+        } elseif (isset($_SESSION['imp']['smime']['null_passphrase'])) {
+            return ($_SESSION['imp']['smime']['null_passphrase']) ? null : false;
+        } else {
+            $res = $this->verifyPassphrase($private_key, null);
+            if (!isset($_SESSION['imp']['smime'])) {
+                $_SESSION['imp']['smime'] = array();
+            }
+            $_SESSION['imp']['smime']['null_passphrase'] = ($res) ? null : false;
+            return $_SESSION['imp']['smime']['null_passphrase'];
+        }
+    }
+
+    /**
+     * Store's the user's passphrase in the session cache.
+     *
+     * @param string $passphrase  The user's passphrase.
+     *
+     * @return boolean  Returns true if correct passphrase, false if incorrect.
+     */
+    public function storePassphrase($passphrase)
+    {
+        if ($this->verifyPassphrase($this->getPersonalPrivateKey(), $passphrase) === false) {
+            return false;
+        }
+
+        if (!isset($_SESSION['imp']['smime'])) {
+            $_SESSION['imp']['smime'] = array();
+        }
+        $_SESSION['imp']['smime']['passphrase'] = Horde_Secret::write(IMP::getAuthKey(), $passphrase);
+
+        return true;
+    }
+
+    /**
+     * Clear the passphrase from the session cache.
+     */
+    public function unsetPassphrase()
+    {
+        unset($_SESSION['imp']['smime']['null_passphrase'], $_SESSION['imp']['smime']['passphrase']);
+    }
+
+    /**
+     * Generates the javascript code for saving public keys.
+     *
+     * @param string $mailbox  The mailbox of the message.
+     * @param integer $uid     The UID of the message.
+     * @param string $id       The MIME ID of the message.
+     *
+     * @return string  The URL for saving public keys.
+     */
+    public function savePublicKeyURL($mailbox, $uid, $id)
+    {
+        $params = array(
+            'actionID' => 'save_attachment_public_key',
+            'uid' => $uid,
+            'mime_id' => $id
+        );
+        return IMP::popupIMPString('smime.php', $params, 450, 200);
+    }
+
+    /**
+     * Encrypt a MIME_Part using S/MIME using IMP defaults.
+     *
+     * @param MIME_Part $mime_part  The MIME_Part object to encrypt.
+     * @param mixed $to_address     The e-mail address of the key to use for
+     *                              encryption.
+     *
+     * @return MIME_Part  See Horde_Crypt_Smime::encryptMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPencryptMIMEPart($mime_part, $to_address)
+    {
+        return $this->encryptMIMEPart($mime_part, $this->_encryptParameters($to_address));
+    }
+
+    /**
+     * Sign a MIME_Part using S/MIME using IMP defaults.
+     *
+     * @param MIME_Part $mime_part  The MIME_Part object to sign.
+     *
+     * @return MIME_Part  See Horde_Crypt_Smime::signMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPsignMIMEPart($mime_part)
+    {
+        return $this->signMIMEPart($mime_part, $this->_signParameters());
+    }
+
+    /**
+     * Sign and encrypt a MIME_Part using S/MIME using IMP defaults.
+     *
+     * @param MIME_Part $mime_part  The MIME_Part object to sign and encrypt.
+     * @param string $to_address    The e-mail address of the key to use for
+     *                              encryption.
+     *
+     * @return MIME_Part  See Horde_Crypt_Smime::signAndencryptMIMEPart().
+     * @throws Horde_Exception
+     */
+    public function IMPsignAndEncryptMIMEPart($mime_part, $to_address)
+    {
+        return $this->signAndEncryptMIMEPart($mime_part, $this->_signParameters(), $this->_encryptParameters($to_address));
+    }
+
+    /**
+     * Store the public/private/additional certificates in the preferences
+     * from a given PKCS 12 file.
+     *
+     * @param string $pkcs12    The PKCS 12 data.
+     * @param string $password  The password of the PKCS 12 file.
+     * @param string $pkpass    The password to use to encrypt the private key.
+     *
+     * @throws Horde_Exception
+     */
+    public function addFromPKCS12($pkcs12, $password, $pkpass = null)
+    {
+        $sslpath = (empty($GLOBALS['conf']['utils']['openssl_binary'])) ? null : $GLOBALS['conf']['utils']['openssl_binary'];
+        $params = array('sslpath' => $sslpath, 'password' => $password);
+        if (!empty($pkpass)) {
+            $params['newpassword'] = $pkpass;
+        }
+
+        $res = $this->parsePKCS12Data($pkcs12, $params);
+        $this->addPersonalPrivateKey($res->private);
+        $this->addPersonalPublicKey($res->public);
+        $this->addAdditionalCert($res->certs);
+    }
+
+    /**
+     * Extract the contents from signed S/MIME data.
+     *
+     * @param string $data  The signed S/MIME data.
+     *
+     * @return string  The contents embedded in the signed data.
+     * @throws Horde_Exception
+     */
+    public function extractSignedContents($data)
+    {
+        $sslpath = empty($GLOBALS['conf']['utils']['openssl_binary'])
+            ? null
+            : $GLOBALS['conf']['utils']['openssl_binary'];
+
+        return parent::extractSignedContents($data, $sslpath);
+    }
+
+}
diff --git a/imp/lib/Crypt/pgp.php b/imp/lib/Crypt/pgp.php
deleted file mode 100644 (file)
index 3633b31..0000000
+++ /dev/null
@@ -1,613 +0,0 @@
-<?php
-/**
- * The IMP_Horde_Crypt_pgp:: class contains all functions related to handling
- * PGP messages within IMP.
- *
- * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-class IMP_Horde_Crypt_pgp extends Horde_Crypt_pgp
-{
-    /* Name of PGP public key field in addressbook. */
-    const PUBKEY_FIELD = 'pgpPublicKey';
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        parent::__construct(array(
-            'program' => $GLOBALS['conf']['utils']['gnupg'],
-            'temp' => Horde::getTempDir()
-        ));
-    }
-
-    /**
-     * Generate the personal Public/Private keypair and store in prefs.
-     *
-     * @param string $realname    See Horde_Crypt_pgp::
-     * @param string $email       See Horde_Crypt_pgp::
-     * @param string $passphrase  See Horde_Crypt_pgp::
-     * @param string $comment     See Horde_Crypt_pgp::
-     * @param string $keylength   See Horde_Crypt_pgp::
-     *
-     * @throws Horde_Exception
-     */
-    public function generatePersonalKeys($name, $email, $passphrase,
-                                         $comment = '', $keylength = 1024)
-    {
-        $keys = $this->generateKey($name, $email, $passphrase, $comment, $keylength);
-        if (is_a($keys, 'PEAR_Error')) {
-            throw new Horde_Exception($keys);
-        }
-
-        /* Store the keys in the user's preferences. */
-        $this->addPersonalPublicKey($keys['public']);
-        $this->addPersonalPrivateKey($keys['private']);
-    }
-
-    /**
-     * Add the personal public key to the prefs.
-     *
-     * @param mixed $public_key  The public key to add (either string or
-     *                           array).
-     */
-    public function addPersonalPublicKey($public_key)
-    {
-        $GLOBALS['prefs']->setValue('pgp_public_key', (is_array($public_key)) ? implode('', $public_key) : $public_key);
-    }
-
-    /**
-     * Add the personal private key to the prefs.
-     *
-     * @param mixed $private_key  The private key to add (either string or
-     *                            array).
-     */
-    public function addPersonalPrivateKey($private_key)
-    {
-        $GLOBALS['prefs']->setValue('pgp_private_key', (is_array($private_key)) ? implode('', $private_key) : $private_key);
-    }
-
-    /**
-     * Get the personal public key from the prefs.
-     *
-     * @return string  The personal PGP public key.
-     */
-    public function getPersonalPublicKey()
-    {
-        return $GLOBALS['prefs']->getValue('pgp_public_key');
-    }
-
-    /**
-     * Get the personal private key from the prefs.
-     *
-     * @return string  The personal PGP private key.
-     */
-    public function getPersonalPrivateKey()
-    {
-        return $GLOBALS['prefs']->getValue('pgp_private_key');
-    }
-
-    /**
-     * Deletes the specified personal keys from the prefs.
-     */
-    public function deletePersonalKeys()
-    {
-        $GLOBALS['prefs']->setValue('pgp_public_key', '');
-        $GLOBALS['prefs']->setValue('pgp_private_key', '');
-
-        $this->unsetPassphrase('personal');
-    }
-
-    /**
-     * Add a public key to an address book.
-     *
-     * @param string $public_key  An PGP public key.
-     *
-     * @return array  See Horde_Crypt_pgp::pgpPacketInformation()
-     * @throws Horde_Exception
-     */
-    public function addPublicKey($public_key)
-    {
-        /* Make sure the key is valid. */
-        $key_info = $this->pgpPacketInformation($public_key);
-        if (!isset($key_info['signature'])) {
-            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
-        }
-
-        /* Remove the '_SIGNATURE' entry. */
-        unset($key_info['signature']['_SIGNATURE']);
-
-        /* Store all signatures that appear in the key. */
-        foreach ($key_info['signature'] as $id => $sig) {
-            /* Check to make sure the key does not already exist in ANY
-             * address book and remove the id from the key_info for a correct
-             * output. */
-            try {
-                $result = $this->getPublicKey($sig['email'], null, false);
-                if (!empty($result)) {
-                    unset($key_info['signature'][$id]);
-                    continue;
-                }
-            } catch (Horde_Exception $e) {}
-
-            /* Add key to the user's address book. */
-            $result = $GLOBALS['registry']->call('contacts/addField', array($sig['email'], $sig['name'], self::PUBKEY_FIELD, $public_key, $GLOBALS['prefs']->getValue('add_source')));
-            if (is_a($result, 'PEAR_Error')) {
-                throw new Horde_Exception($result);
-            }
-        }
-
-        return $key_info;
-    }
-
-    /**
-     * Retrieves a public key by e-mail.
-     *
-     * First, the key will be attempted to be retrieved from a user's address
-     * book(s).
-     * Second, if unsuccessful, the key is attempted to be retrieved via a
-     * public PGP keyserver.
-     *
-     * @param string $address      The e-mail address to search by.
-     * @param string $fingerprint  The fingerprint of the user's key.
-     * @param boolean $server      Whether to check the publick key servers for
-     *                             the key.
-     *
-     * @return string  The PGP public key requested.
-     * @throws Horde_Exception
-     */
-    public function getPublicKey($address, $fingerprint = null, $server = true)
-    {
-        /* If there is a cache driver configured, try to get the public key
-         * from the cache. */
-        if (($cache = IMP::getCache())) {
-            $result = $cache->get("PGPpublicKey_" . $address . $fingerprint, 3600);
-            if ($result) {
-                Horde::logMessage('PGPpublicKey: ' . serialize($result), __FILE__, __LINE__, PEAR_LOG_DEBUG);
-                return $result;
-            }
-        }
-
-        /* Try retrieving by e-mail only first. */
-        $params = IMP_Compose::getAddressSearchParams();
-        $result = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true));
-
-        /* TODO: Retrieve by ID. */
-
-        /* See if the address points to the user's public key. */
-        if (is_a($result, 'PEAR_Error')) {
-            require_once 'Horde/Identity.php';
-            $identity = Identity::singleton(array('imp', 'imp'));
-            $personal_pubkey = $this->getPersonalPublicKey();
-            if (!empty($personal_pubkey) && $identity->hasAddress($address)) {
-                $result = $personal_pubkey;
-            }
-        }
-
-        /* Try retrieving via a PGP public keyserver. */
-        if ($server && is_a($result, 'PEAR_Error')) {
-            $result = $this->getFromPublicKeyserver($fingerprint, $address);
-        }
-
-        /* Return now, if no public key found at all. */
-        if (is_a($result, 'PEAR_Error')) {
-            throw new Horde_Exception($result);
-        }
-
-        /* If more than one public key is returned, just return the first in
-         * the array. There is no way of knowing which is the "preferred" key,
-         * if the keys are different. */
-        if (is_array($result)) {
-            reset($result);
-        }
-
-        /* If there is a cache driver configured and a cache object exists,
-         * store the public key in the cache. */
-        if (is_object($cache)) {
-            $cache->set("PGPpublicKey_" . $address . $fingerprint, $result, 3600);
-        }
-
-        return $result;
-    }
-
-    /**
-     * Retrieves all public keys from a user's address book(s).
-     *
-     * @return array  All PGP public keys available.
-     * @throws Horde_Exception
-     */
-    public function listPublicKeys()
-    {
-        $params = IMP_Compose::getAddressSearchParams();
-        if (empty($params['sources'])) {
-            return array();
-        }
-
-        $res = $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(self::PUBKEY_FIELD, $params['sources']));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Deletes a public key from a user's address book(s) by e-mail.
-     *
-     * @param string $email  The e-mail address to delete.
-     *
-     * @throws Horde_Exception
-     */
-    public function deletePublicKey($email)
-    {
-        $params = IMP_Compose::getAddressSearchParams();
-        $res = $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources']));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Get a public key via a public PGP keyserver.
-     *
-     * @param string $fingerprint  The fingerprint of the requested key.
-     * @param string $address      The email address of the requested key.
-     *
-     * @return string  See Horde_Crypt_pgp::getPublicKeyserver()
-     * @throws Horde_Exception
-     */
-    public function getFromPublicKeyserver($fingerprint, $address = null)
-    {
-        return $this->_keyserverConnect($fingerprint, 'get', $address);
-    }
-
-    /**
-     * Send a public key to a public PGP keyserver.
-     *
-     * @param string $pubkey  The PGP public key.
-     *
-     * @return string  See Horde_Crypt_pgp::putPublicKeyserver()
-     * @throws Horde_Exception
-     */
-    public function sendToPublicKeyserver($pubkey)
-    {
-        return $this->_keyserverConnect($pubkey, 'put');
-    }
-
-    /**
-     * Connect to the keyservers
-     *
-     * @param string $data        The data to send to the keyserver.
-     * @param string $method      The method to use - either 'get' or 'put'.
-     * @param string $additional  Any additional data.
-     *
-     * @return string  See Horde_Crypt_pgp::getPublicKeyserver() -or-
-     *                     Horde_Crypt_pgp::putPublicKeyserver().
-     * @throws Horde_Exception
-     */
-    protected function _keyserverConnect($data, $method, $additional = null)
-    {
-        global $conf;
-
-        if (!empty($conf['utils']['gnupg_keyserver'])) {
-            $timeout = (empty($conf['utils']['gnupg_timeout'])) ? PGP_KEYSERVER_TIMEOUT : $conf['utils']['gnupg_timeout'];
-            if ($method == 'get') {
-                foreach ($conf['utils']['gnupg_keyserver'] as $server) {
-                    $result = $this->getPublicKeyserver($data, $server, $timeout, $additional);
-                    if (!is_a($result, 'PEAR_Error')) {
-                        return $result;
-                    }
-                }
-                throw new Horde_Exception(_("Could not connect to public PGP keyserver"));
-            } else {
-                return $this->putPublicKeyserver($data, $conf['utils']['gnupg_keyserver'][0], $timeout);
-            }
-        }
-
-        throw new Horde_Exception(_("Public PGP keyserver support has been disabled."), 'horde.warning');
-    }
-
-    /**
-     * Verifies a signed message with a given public key.
-     *
-     * @param string $text       The text to verify.
-     * @param string $address    E-mail address of public key.
-     * @param string $signature  A PGP signature block.
-     *
-     * @return string  See Horde_Crypt_pgp::decryptSignature()  -or-
-     *                     Horde_Crypt_pgp::decryptDetachedSignature().
-     * @throws Horde_Exception
-     */
-    public function verifySignature($text, $address, $signature = '')
-    {
-        $fingerprint = null;
-
-        /* Get fingerprint of key. */
-        if (!empty($signature)) {
-            $packet_info = $this->pgpPacketInformation($signature);
-            if (isset($packet_info['fingerprint'])) {
-                $fingerprint = $packet_info['fingerprint'];
-            }
-        } else {
-            $fingerprint = $this->getSignersKeyID($text);
-        }
-
-        $public_key = $this->getPublicKey($address, $fingerprint);
-
-        if (empty($signature)) {
-            $options = array('type' => 'signature');
-        } else {
-            $options = array('type' => 'detached-signature', 'signature' => $signature);
-        }
-        $options['pubkey'] = $public_key;
-
-        /* decrypt() returns a PEAR_Error object on error. */
-        $res = $this->decrypt($text, $options);
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Decrypt a message with user's public/private keypair or a passphrase.
-     *
-     * @param string $text         The text to decrypt.
-     * @param string $type         Either 'literal', 'personal', or
-     *                             'symmetric'.
-     * @param boolean $passphrase  If $type is 'personal' or 'symmetrical',
-     *                             the passphrase to use.
-     *
-     * @return string  The decrypted message.
-     * @throws Horde_Exception
-     */
-    public function decryptMessage($text, $type, $passphrase = null)
-    {
-        switch ($type) {
-        case 'literal':
-            $res = $this->decrypt($text, array('type' => 'message', 'no_passphrase' => true));
-            break;
-
-        case 'symmetric':
-            $res = $this->decrypt($text, array('type' => 'message', 'passphrase' => $passphrase));
-            break;
-
-        case 'personal':
-            $res = $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $passphrase));
-            break;
-        }
-
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Gets a passphrase from the session cache.
-     *
-     * @param integer $type  The type of passphrase. Either 'personal' or
-     *                       'symmetric'.
-     * @param string $id     If $type is 'symmetric', the ID of the stored
-     *                       passphrase.
-     *
-     * @return mixed  The passphrase, if set, or null.
-     */
-    public function getPassphrase($type, $id = null)
-    {
-        if ($type == 'personal') {
-            $id = 'personal';
-        }
-
-        return isset($_SESSION['imp']['cache']['pgp'][$type][$id])
-            ? Horde_Secret::read(IMP::getAuthKey(), $_SESSION['imp']['cache']['pgp'][$type][$id])
-            : null;
-    }
-
-    /**
-     * Store's the user's passphrase in the session cache.
-     *
-     * @param integer $type       The type of passphrase. Either 'personal' or
-     *                            'symmetric'.
-     * @param string $passphrase  The user's passphrase.
-     * @param string $id          If $type is 'symmetric', the ID of the
-     *                            stored passphrase.
-     *
-     * @return boolean  Returns true if correct passphrase, false if incorrect.
-     */
-    public function storePassphrase($type, $passphrase, $id)
-    {
-        if ($type == 'personal') {
-            if ($this->verifyPassphrase($this->getPersonalPublicKey(), $this->getPersonalPrivateKey(), $passphrase) === false) {
-                return false;
-            }
-            $id = 'personal';
-        }
-
-        $_SESSION['imp']['cache']['pgp'][$type][$id] = Horde_Secret::write(IMP::getAuthKey(), $passphrase);
-        return true;
-    }
-
-    /**
-     * Clear the passphrase from the session cache.
-     *
-     * @param integer $type       The type of passphrase. Either 'personal' or
-     *                            'symmetric'.
-     * @param string $id          If $type is 'symmetric', the ID of the
-     *                            stored passphrase. Else, all passphrases
-     *                            are deleted.
-     */
-    public function unsetPassphrase($type, $id = null)
-    {
-        if (($type == 'symmetric') && !is_null($id)) {
-            unset($_SESSION['imp']['cache']['pgp']['symmetric'][$id]);
-        } else {
-            unset($_SESSION['imp']['cache']['pgp'][$type]);
-        }
-    }
-
-    /**
-     * Generates a cache ID for symmetric message data.
-     *
-     * @param string $mailbox  The mailbox of the message.
-     * @param integer $uid     The UID of the message.
-     * @param string $id       The MIME ID of the message.
-     *
-     * @return string  A unique symmetric cache ID.
-     */
-    public function getSymmetricID($mailbox, $uid, $id)
-    {
-        return implode('|', array($mailbox, $uid, $id));
-    }
-
-    /**
-     * Generates the javascript code for saving public keys.
-     *
-     * @param string $mailbox  The mailbox of the message.
-     * @param integer $uid     The UID of the message.
-     * @param string $id       The MIME ID of the message.
-     *
-     * @return string  The URL for saving public keys.
-     */
-    public function savePublicKeyURL($mailbox, $uid, $id)
-    {
-        $params = array(
-            'actionID' => 'save_attachment_public_key',
-            'uid' => $uid,
-            'mime_id' => $id
-        );
-        return IMP::popupIMPString('pgp.php', $params, 450, 200);
-    }
-
-    /**
-     * Provide the list of parameters needed for signing a message.
-     *
-     * @return array  The list of parameters needed by encrypt().
-     */
-    protected function _signParameters()
-    {
-        return array(
-            'pubkey' => $this->getPersonalPublicKey(),
-            'privkey' => $this->getPersonalPrivateKey(),
-            'passphrase' => $this->getPassphrase('personal')
-        );
-    }
-
-    /**
-     * Provide the list of parameters needed for encrypting a message.
-     *
-     * @param array $addresses   The e-mail address of the keys to use for
-     *                           encryption.
-     * @param string $symmetric  If true, the symmetric password to use for
-     *                           encrypting. If null, uses the personal key.
-     *
-     * @return array  The list of parameters needed by encrypt().
-     * @throws Horde_Exception
-     */
-    protected function _encryptParameters($addresses, $symmetric)
-    {
-        if (!is_null($symmetric)) {
-            return array(
-                'symmetric' => true,
-                'passphrase' => $symmetric
-            );
-        }
-
-        $addr_list = array();
-
-        foreach ($addresses as $val) {
-            $addrOb = Horde_Mime_Address::bareAddress($val, $_SESSION['imp']['maildomain'], true);
-            $key_addr = array_pop($addrOb);
-
-            /* Get the public key for the address. */
-            $addr_list[$key_addr] = $this->getPublicKey($key_addr);
-        }
-
-        return array('recips' => $addr_list);
-    }
-
-    /**
-     * Sign a Horde_Mime_Part using PGP using IMP default parameters.
-     *
-     * @param Horde_Mime_Part $mime_part  The object to sign.
-     *
-     * @return Horde_Mime_Part  See Horde_Crypt_pgp::signMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPsignMIMEPart($mime_part)
-    {
-        $res = $this->signMIMEPart($mime_part, $this->_signParameters());
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-        return $res;
-    }
-
-    /**
-     * Encrypt a Horde_Mime_Part using PGP using IMP default parameters.
-     *
-     * @param Horde_Mime_Part $mime_part  The object to encrypt.
-     * @param array $addresses            The e-mail address of the keys to
-     *                                    use for encryption.
-     * @param string $symmetric           If true, the symmetric password to
-     *                                    use for encrypting. If null, uses
-     *                                    the personal key.
-     *
-     * @return Horde_Mime_Part  See Horde_Crypt_pgp::encryptMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPencryptMIMEPart($mime_part, $addresses,
-                                       $symmetric = null)
-    {
-        $res = $this->encryptMIMEPart($mime_part, $this->_encryptParameters($addresses, $symmetric));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-        return $res;
-    }
-
-    /**
-     * Sign and Encrypt a Horde_Mime_Part using PGP using IMP default parameters.
-     *
-     * @param Horde_Mime_Part $mime_part  The object to sign and encrypt.
-     * @param array $addresses            The e-mail address of the keys to
-     *                                    use for encryption.
-     * @param string $symmetric           If true, the symmetric password to
-     *                                    use for encrypting. If null, uses
-     *                                    the personal key.
-     *
-     * @return Horde_Mime_Part  See Horde_Crypt_pgp::signAndencryptMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPsignAndEncryptMIMEPart($mime_part, $addresses,
-                                              $symmetric = null)
-    {
-        $res = $this->signAndEncryptMIMEPart($mime_part, $this->_signParameters(), $this->_encryptParameters($addresses, $symmetric));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-        return $res;
-    }
-
-    /**
-     * Generate a Horde_Mime_Part object, in accordance with RFC 2015/3156,
-     * that contains the user's public key.
-     *
-     * @return Horde_Mime_Part  See Horde_Crypt_pgp::publicKeyMIMEPart().
-     */
-    public function publicKeyMIMEPart()
-    {
-        return parent::publicKeyMIMEPart($this->getPersonalPublicKey());
-    }
-
-}
diff --git a/imp/lib/Crypt/smime.php b/imp/lib/Crypt/smime.php
deleted file mode 100644 (file)
index 450a058..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-<?php
-/**
- * The IMP_SMIME:: class contains all functions related to handling
- * S/MIME messages within IMP.
- *
- * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Mike Cochrane <mike@graftonhall.co.nz>
- * @package IMP
- */
-class IMP_Horde_Crypt_smime extends Horde_Crypt_smime
-{
-    /* Name of the S/MIME public key field in addressbook. */
-    const PUBKEY_FIELD = 'smimePublicKey';
-
-    /**
-     * Constructor.
-     */
-    public function __construct()
-    {
-        parent::__construct(array('temp' => Horde::getTempDir()));
-    }
-
-    /**
-     * Add the personal public key to the prefs.
-     *
-     * @param mixed $key  The public key to add (either string or array).
-     */
-    public function addPersonalPublicKey($key)
-    {
-        $GLOBALS['prefs']->setValue('smime_public_key', (is_array($key)) ? implode('', $key) : $key);
-    }
-
-    /**
-     * Add the personal private key to the prefs.
-     *
-     * @param mixed $key  The private key to add (either string or array).
-     */
-    public function addPersonalPrivateKey($key)
-    {
-        $GLOBALS['prefs']->setValue('smime_private_key', (is_array($key)) ? implode('', $key) : $key);
-    }
-
-    /**
-     * Add the list of additional certs to the prefs.
-     *
-     * @param mixed $key  The private key to add (either string or array).
-     */
-    public function addAdditionalCert($key)
-    {
-        $GLOBALS['prefs']->setValue('smime_additional_cert', (is_array($key)) ? implode('', $key) : $key);
-    }
-
-    /**
-     * Get the personal public key from the prefs.
-     *
-     * @return string  The personal S/MIME public key.
-     */
-    public function getPersonalPublicKey()
-    {
-        return $GLOBALS['prefs']->getValue('smime_public_key');
-    }
-
-    /**
-     * Get the personal private key from the prefs.
-     *
-     * @return string  The personal S/MIME private key.
-     */
-    public function getPersonalPrivateKey()
-    {
-        return $GLOBALS['prefs']->getValue('smime_private_key');
-    }
-
-    /**
-     * Get any additional certificates from the prefs.
-     *
-     * @return string  Additional signing certs for inclusion.
-     */
-    public function getAdditionalCert()
-    {
-        return $GLOBALS['prefs']->getValue('smime_additional_cert');
-    }
-
-    /**
-     * Deletes the specified personal keys from the prefs.
-     */
-    public function deletePersonalKeys()
-    {
-        $GLOBALS['prefs']->setValue('smime_public_key', '');
-        $GLOBALS['prefs']->setValue('smime_private_key', '');
-        $GLOBALS['prefs']->setValue('smime_additional_cert', '');
-        $this->unsetPassphrase();
-    }
-
-    /**
-     * Add a public key to an address book.
-     *
-     * @param string $cert  A public certificate to add.
-     *
-     * @throws Horde_Exception
-     */
-    public function addPublicKey($cert)
-    {
-        /* Make sure the certificate is valid. */
-        $key_info = openssl_x509_parse($cert);
-        if (!is_array($key_info) || !isset($key_info['subject'])) {
-            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
-        }
-
-        /* Add key to the user's address book. */
-        $email = $this->getEmailFromKey($cert);
-        if (is_null($email)) {
-            throw new Horde_Exception(_("No email information located in the public key."), 'horde.error');
-        }
-
-        /* Get the name corresponding to this key. */
-        if (isset($key_info['subject']['CN'])) {
-            $name = $key_info['subject']['CN'];
-        } elseif (isset($key_info['subject']['OU'])) {
-            $name = $key_info['subject']['OU'];
-        } else {
-            throw new Horde_Exception(_("Not a valid public key."), 'horde.error');
-        }
-
-        $res = $GLOBALS['registry']->call('contacts/addField', array($email, $name, self::PUBKEY_FIELD, $cert, $GLOBALS['prefs']->getValue('add_source')));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-    }
-
-    /**
-     * Returns the params needed to encrypt a message being sent to the
-     * specified email address.
-     *
-     * @param string $address  The e-mail address of the recipient.
-     *
-     * @return array  The list of parameters needed by encrypt().
-     * @throws Horde_Exception
-     */
-    protected function _encryptParameters($address)
-    {
-        /* We can only encrypt if we are sending to a single person. */
-        $addrOb = Horde_Mime_Address::bareAddress($address, $_SESSION['imp']['maildomain'], true);
-        $key_addr = array_pop($addrOb);
-
-        $public_key = $this->getPublicKey($key_addr);
-
-        return array(
-            'pubkey' => $public_key,
-            'type' => 'message'
-        );
-    }
-
-    /**
-     * Retrieves a public key by e-mail.
-     * The key will be retrieved from a user's address book(s).
-     *
-     * @param string $address  The e-mail address to search for.
-     *
-     * @return string  The S/MIME public key requested.
-     * @throws Horde_Exception
-     */
-    public function getPublicKey($address)
-    {
-        $params = IMP_Compose::getAddressSearchParams();
-        $key = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true));
-
-        /* See if the address points to the user's public key. */
-        if (is_a($key, 'PEAR_Error')) {
-            require_once 'Horde/Identity.php';
-            $identity = &Identity::singleton(array('imp', 'imp'));
-            $personal_pubkey = $this->getPersonalPublicKey();
-            if (!empty($personal_pubkey) && $identity->hasAddress($address)) {
-                return $personal_pubkey;
-            }
-            throw new Horde_Exception($key);
-        }
-
-        /* If more than one public key is returned, just return the first in
-         * the array. There is no way of knowing which is the "preferred" key,
-         * if the keys are different. */
-        return is_array($key) ? reset($key) : $key;
-    }
-
-    /**
-     * Retrieves all public keys from a user's address book(s).
-     *
-     * @return array  All PGP public keys available.
-     * @throws Horde_Exception
-     */
-    public function listPublicKeys()
-    {
-        $params = IMP_Compose::getAddressSearchParams();
-        if (empty($params['sources'])) {
-            return array();
-        }
-        $res = $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(self::PUBKEY_FIELD, $params['sources']));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Deletes a public key from a user's address book(s) by e-mail.
-     *
-     * @param string $email  The e-mail address to delete.
-     *
-     * @throws Horde_Exception
-     */
-    public function deletePublicKey($email)
-    {
-        $params = IMP_Compose::getAddressSearchParams();
-        $res = $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources']));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-    }
-
-    /**
-     * Returns the parameters needed for signing a message.
-     *
-     * @return array  The list of parameters needed by encrypt().
-     */
-    protected function _signParameters()
-    {
-        return array(
-            'type' => 'signature',
-            'pubkey' => $this->getPersonalPublicKey(),
-            'privkey' => $this->getPersonalPrivateKey(),
-            'passphrase' => $this->getPassphrase(),
-            'sigtype' => 'detach',
-            'certs' => $this->getAdditionalCert()
-        );
-    }
-
-    /**
-     * Verifies a signed message with a given public key.
-     *
-     * @param string $text  The text to verify.
-     *
-     * @return stdClass  See Horde_Crypt_smime::verify().
-     */
-    public function verifySignature($text)
-    {
-        return $this->verify($text, empty($GLOBALS['conf']['utils']['openssl_cafile']) ? array() : $GLOBALS['conf']['utils']['openssl_cafile']);
-    }
-
-
-    /**
-     * Decrypt a message with user's public/private keypair.
-     *
-     * @param string $text  The text to decrypt.
-     *
-     * @return string  See Horde_Crypt_smime::decrypt().
-     * @throws Horde_Exception
-     */
-    public function decryptMessage($text)
-    {
-        /* decrypt() returns a PEAR_Error object on error. */
-        $res = $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $this->getPassphrase()));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Gets the user's passphrase from the session cache.
-     *
-     * @return mixed  The passphrase, if set.  Returns false if the passphrase
-     *                has not been loaded yet.  Returns null if no passphrase
-     *                is needed.
-     */
-    public function getPassphrase()
-    {
-        $private_key = $GLOBALS['prefs']->getValue('smime_private_key');
-        if (empty($private_key)) {
-            return false;
-        }
-
-        if (isset($_SESSION['imp']['smime']['passphrase'])) {
-            return Horde_Secret::read(IMP::getAuthKey(), $_SESSION['imp']['smime']['passphrase']);
-        } elseif (isset($_SESSION['imp']['smime']['null_passphrase'])) {
-            return ($_SESSION['imp']['smime']['null_passphrase']) ? null : false;
-        } else {
-            $res = $this->verifyPassphrase($private_key, null);
-            if (!isset($_SESSION['imp']['smime'])) {
-                $_SESSION['imp']['smime'] = array();
-            }
-            $_SESSION['imp']['smime']['null_passphrase'] = ($res) ? null : false;
-            return $_SESSION['imp']['smime']['null_passphrase'];
-        }
-    }
-
-    /**
-     * Store's the user's passphrase in the session cache.
-     *
-     * @param string $passphrase  The user's passphrase.
-     *
-     * @return boolean  Returns true if correct passphrase, false if incorrect.
-     */
-    public function storePassphrase($passphrase)
-    {
-        if ($this->verifyPassphrase($this->getPersonalPrivateKey(), $passphrase) === false) {
-            return false;
-        }
-
-        if (!isset($_SESSION['imp']['smime'])) {
-            $_SESSION['imp']['smime'] = array();
-        }
-        $_SESSION['imp']['smime']['passphrase'] = Horde_Secret::write(IMP::getAuthKey(), $passphrase);
-
-        return true;
-    }
-
-    /**
-     * Clear the passphrase from the session cache.
-     */
-    public function unsetPassphrase()
-    {
-        unset($_SESSION['imp']['smime']['null_passphrase'], $_SESSION['imp']['smime']['passphrase']);
-    }
-
-    /**
-     * Generates the javascript code for saving public keys.
-     *
-     * @param string $mailbox  The mailbox of the message.
-     * @param integer $uid     The UID of the message.
-     * @param string $id       The MIME ID of the message.
-     *
-     * @return string  The URL for saving public keys.
-     */
-    public function savePublicKeyURL($mailbox, $uid, $id)
-    {
-        $params = array(
-            'actionID' => 'save_attachment_public_key',
-            'uid' => $uid,
-            'mime_id' => $id
-        );
-        return IMP::popupIMPString('smime.php', $params, 450, 200);
-    }
-
-    /**
-     * Encrypt a MIME_Part using S/MIME using IMP defaults.
-     *
-     * @param MIME_Part $mime_part  The MIME_Part object to encrypt.
-     * @param mixed $to_address     The e-mail address of the key to use for
-     *                              encryption.
-     *
-     * @return MIME_Part  See Horde_Crypt_smime::encryptMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPencryptMIMEPart($mime_part, $to_address)
-    {
-        $res = $this->encryptMIMEPart($mime_part, $this->_encryptParameters($to_address));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Sign a MIME_Part using S/MIME using IMP defaults.
-     *
-     * @param MIME_Part $mime_part  The MIME_Part object to sign.
-     *
-     * @return MIME_Part  See Horde_Crypt_smime::signMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPsignMIMEPart($mime_part)
-    {
-        $res = $this->signMIMEPart($mime_part, $this->_signParameters());
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Sign and encrypt a MIME_Part using S/MIME using IMP defaults.
-     *
-     * @param MIME_Part $mime_part  The MIME_Part object to sign and encrypt.
-     * @param string $to_address    The e-mail address of the key to use for
-     *                              encryption.
-     *
-     * @return MIME_Part  See Horde_Crypt_smime::signAndencryptMIMEPart().
-     * @throws Horde_Exception
-     */
-    public function IMPsignAndEncryptMIMEPart($mime_part, $to_address)
-    {
-        $res = $this->signAndEncryptMIMEPart($mime_part, $this->_signParameters(), $this->_encryptParameters($to_address));
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-    /**
-     * Store the public/private/additional certificates in the preferences
-     * from a given PKCS 12 file.
-     *
-     * @param string $pkcs12    The PKCS 12 data.
-     * @param string $password  The password of the PKCS 12 file.
-     * @param string $pkpass    The password to use to encrypt the private key.
-     *
-     * @throws Horde_Exception
-     */
-    public function addFromPKCS12($pkcs12, $password, $pkpass = null)
-    {
-        $openssl = $this->checkForOpenSSL();
-        if (is_a($openssl, 'PEAR_Error')) {
-            throw new Horde_Exception($openssl);
-        }
-
-        $sslpath = (empty($GLOBALS['conf']['utils']['openssl_binary'])) ? null : $GLOBALS['conf']['utils']['openssl_binary'];
-        $params = array('sslpath' => $sslpath, 'password' => $password);
-        if (!empty($pkpass)) {
-            $params['newpassword'] = $pkpass;
-        }
-        $res = $this->parsePKCS12Data($pkcs12, $params);
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        $this->addPersonalPrivateKey($res->private);
-        $this->addPersonalPublicKey($res->public);
-        $this->addAdditionalCert($res->certs);
-    }
-
-    /**
-     * Extract the contents from signed S/MIME data.
-     *
-     * @param string $data  The signed S/MIME data.
-     *
-     * @return string  The contents embedded in the signed data.
-     * @throws Horde_Exception
-     */
-    public function extractSignedContents($data)
-    {
-        $sslpath = empty($GLOBALS['conf']['utils']['openssl_binary'])
-            ? null
-            : $GLOBALS['conf']['utils']['openssl_binary'];
-
-        $res = parent::extractSignedContents($data, $sslpath);
-        if (is_a($res, 'PEAR_Error')) {
-            throw new Horde_Exception($res);
-        }
-
-        return $res;
-    }
-
-}
index 1eb7ee5..2a31d28 100644 (file)
@@ -36,9 +36,9 @@ class IMP_Horde_Mime_Viewer_pgp extends Horde_Mime_Viewer_Driver
     );
 
     /**
-     * IMP_Horde_Crypt_PGP object.
+     * IMP_Crypt_Pgp object.
      *
-     * @var IMP_Horde_Crypt_PGP
+     * @var IMP_Crypt_Pgp
      */
     protected $_imppgp;
 
@@ -65,7 +65,7 @@ class IMP_Horde_Mime_Viewer_pgp extends Horde_Mime_Viewer_Driver
     {
         if (empty($this->_imppgp) &&
             !empty($GLOBALS['conf']['utils']['gnupg'])) {
-            $this->_imppgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
+            $this->_imppgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
         }
 
         if (Util::getFormData('rawpgpkey')) {
@@ -146,7 +146,7 @@ class IMP_Horde_Mime_Viewer_pgp extends Horde_Mime_Viewer_Driver
         }
 
         if (empty($this->_imppgp)) {
-            $this->_imppgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
+            $this->_imppgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
         }
 
         /* PGP version information appears in the first MIME subpart. We
@@ -330,20 +330,23 @@ class IMP_Horde_Mime_Viewer_pgp extends Horde_Mime_Viewer_Driver
                     ? $this->_imppgp->verifySignature($signed_data, $this->_address)
                     : $this->_imppgp->verifySignature($signed_data, $this->_address, $sig_part->getContents());
 
-                $icon = Horde::img('alerts/success.png', _("Success"), null, $graphicsdir);
-                if (empty($sig_result)) {
-                   $sig_result = _("The message below has been verified.");
+                if ($sig_result->result) {
+                    $icon = Horde::img('alerts/success.png', _("Success"), null, $graphicsdir);
+                    $sig_text = $sig_result->message;
+                } else {
+                    $icon = Horde::img('alerts/warning.png', _("Warning"), null, $graphicsdir);
+                   $sig_text = _("The signature could not be checked because the sender's key could not be found.");
                 }
             } catch (Horde_Exception $e) {
                 $icon = Horde::img('alerts/error.png', _("Error"), null, $graphicsdir);
-                $sig_result = $e->getMessage();
+                $sig_text = $e->getMessage();
             }
 
             require_once 'Horde/Text/Filter.php';
             $ret[$base_id]['status'][] = array(
                 'icon' => $icon,
                 'text' => array(
-                    Text_Filter::filter($sig_result, 'text2html', array('parselevel' => TEXT_HTML_NOHTML))
+                    Text_Filter::filter($sig_text, 'text2html', array('parselevel' => TEXT_HTML_NOHTML))
                 )
             );
         } else {
index e875c14..a448eab 100644 (file)
@@ -166,11 +166,11 @@ class IMP_Horde_Mime_Viewer_plain extends Horde_Mime_Viewer_plain
     protected function _parsePGP()
     {
         /* Avoid infinite loop. */
-        $imp_pgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
+        $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
         $parts = $imp_pgp->parsePGPData($this->_mimepart->getContents());
         if (empty($parts) ||
             ((count($parts) == 1) &&
-             ($parts[0]['type'] == Horde_Crypt_pgp::ARMOR_TEXT))) {
+             ($parts[0]['type'] == Horde_Crypt_Pgp::ARMOR_TEXT))) {
             return null;
         }
 
@@ -181,7 +181,7 @@ class IMP_Horde_Mime_Viewer_plain extends Horde_Mime_Viewer_plain
 
         while (list(,$val) = each($parts)) {
             switch ($val['type']) {
-            case Horde_Crypt_pgp::ARMOR_TEXT:
+            case Horde_Crypt_Pgp::ARMOR_TEXT:
                 $part = new Horde_Mime_Part();
                 $part->setType('text/plain');
                 $part->setCharset($charset);
@@ -189,14 +189,14 @@ class IMP_Horde_Mime_Viewer_plain extends Horde_Mime_Viewer_plain
                 $new_part->addPart($part);
                 break;
 
-            case Horde_Crypt_pgp::ARMOR_PUBLIC_KEY:
+            case Horde_Crypt_Pgp::ARMOR_PUBLIC_KEY:
                 $part = new Horde_Mime_Part();
                 $part->setType('application/pgp-keys');
                 $part->setContents(implode("\n", $val['data']));
                 $new_part->addPart($part);
                 break;
 
-            case Horde_Crypt_pgp::ARMOR_MESSAGE:
+            case Horde_Crypt_Pgp::ARMOR_MESSAGE:
                 $part = new Horde_Mime_Part();
                 $part->setType('multipart/signed');
                 // TODO: add micalg parameter
@@ -217,9 +217,9 @@ class IMP_Horde_Mime_Viewer_plain extends Horde_Mime_Viewer_plain
                 $new_part->addPart($part);
                 break;
 
-            case Horde_Crypt_pgp::ARMOR_SIGNED_MESSAGE:
+            case Horde_Crypt_Pgp::ARMOR_SIGNED_MESSAGE:
                 if (($sig = current($parts)) &&
-                    ($sig['type'] == Horde_Crypt_pgp::ARMOR_SIGNATURE)) {
+                    ($sig['type'] == Horde_Crypt_Pgp::ARMOR_SIGNATURE)) {
                     $part = new Horde_Mime_Part();
                     $part->setType('multipart/signed');
                     // TODO: add micalg parameter
index 7d27ee3..ff42f87 100644 (file)
@@ -39,9 +39,9 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
     );
 
     /**
-     * IMP_Horde_Crypt_smime object.
+     * IMP_Crypt_Smime object.
      *
-     * @var IMP_Horde_Crypt_smime
+     * @var IMP_Crypt_Smime
      */
     protected $_impsmime = null;
 
@@ -176,7 +176,11 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
         }
 
         $raw_text = $GLOBALS['imp_imap']->utils->removeBareNewlines($this->_params['contents']->getBodyPart($this->_mimepart->getMimeId(), array('mimeheaders' => true)));
-        $sig_result = $this->_impsmime->verifySignature($raw_text);
+
+        try {
+            $sig_result = $this->_impsmime->verifySignature($raw_text);
+        } catch (Horde_Exception $e) {}
+
         return array(
             $this->_mimepart->getMimeId() => array(
                 'data' => $this->_impsmime->certToHTML($sig_result->cert),
@@ -193,9 +197,10 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
     {
         if (is_null($this->_impsmime) &&
             $GLOBALS['prefs']->getValue('use_smime')) {
-            $this->_impsmime = &Horde_Crypt::singleton(array('imp', 'smime'));
-            $openssl_check = $this->_impsmime->checkForOpenSSL();
-            if (is_a($openssl_check, 'PEAR_Error')) {
+            try {
+                $this->_impsmime = Horde_Crypt::singleton(array('IMP', 'Smime'));
+                $this->_impsmime->checkForOpenSSL();
+            } catch (Horde_Exception $e) {
                 $this->_impsmime = null;
             }
         }
@@ -204,7 +209,7 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
     /**
      * Generates HTML output for 'multipart/signed' MIME parts.
      *
-     * @return array  TODo
+     * @return array  TODO
      */
     protected function _outputSMIMESigned()
     {
@@ -241,7 +246,15 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
 
         if ($GLOBALS['prefs']->getValue('smime_verify') ||
             Util::getFormData('smime_verify_msg')) {
-            $sig_result = $this->_impsmime->verifySignature($raw_text);
+            try {
+                $sig_result = $this->_impsmime->verifySignature($raw_text);
+            } catch (Horde_Exception $e) {
+                $ret[$base_id]['status'][0]['icon'] = ($e->getCode() == 'horde.warning')
+                    ? Horde::img('alerts/warning.png', _("Warning"), null, $graphicsdir)
+                    : Horde::img('alerts/error.png', _("Error"), null, $graphicsdir);
+                $status[] = $e->getMessage();
+                return $ret;
+            }
         } else {
             switch ($_SESSION['imp']['view']) {
             case 'imp':
@@ -268,42 +281,35 @@ class IMP_Horde_Mime_Viewer_smime extends Horde_Mime_Viewer_Driver
 
         $graphicsdir = $GLOBALS['registry']->getImageDir('horde');
 
-        if (is_a($sig_result->result, 'PEAR_Error')) {
-            $ret[$base_id]['status'][0]['icon'] = ($sig_result->result->getCode() == 'horde.warning')
-                ? Horde::img('alerts/warning.png', _("Warning"), null, $graphicsdir)
-                : Horde::img('alerts/error.png', _("Error"), null, $graphicsdir);
-            $status[] = $sig_result->result->getMessage();
-        } else {
-            $ret[$base_id]['status'][0]['icon'] = Horde::img('alerts/success.png', _("Success"), null, $graphicsdir);
-
-            /* This message has been verified but there was no output
-             * from the PGP program. */
-            if (empty($sig_result->result) || ($sig_result->result === true)) {
-                $email = (is_array($sig_result->email))
-                    ? implode(', ', $sig_result->email)
-                    : $sig_result->email;
-                $status[] = sprintf(_("The message has been verified. Sender: %s."), htmlspecialchars($email));
+        $ret[$base_id]['status'][0]['icon'] = Horde::img('alerts/success.png', _("Success"), null, $graphicsdir);
+
+        /* This message has been verified but there was no output
+         * from the PGP program. */
+        if (empty($sig_result->result) || ($sig_result->result === true)) {
+            $email = (is_array($sig_result->email))
+                ? implode(', ', $sig_result->email)
+                : $sig_result->email;
+            $status[] = sprintf(_("The message has been verified. Sender: %s."), htmlspecialchars($email));
+        }
+
+        if (!empty($sig_result->cert)) {
+            $cert_details = $this->_impsmime->parseCert($sig_result->cert);
+            if (isset($cert_details['certificate']['subject']['CommonName'])) {
+                $subject = $cert_details['certificate']['subject']['CommonName'];
+            } elseif (isset($cert_details['certificate']['subject']['Email'])) {
+                $subject = $cert_details['certificate']['subject']['Email'];
+            } elseif (isset($sig_result->email)) {
+                $subject = $sig_result->email;
+            } elseif (isset($smime_from)) {
+                $subject = $smime_from;
+            } else {
+                $subject = null;
             }
 
-            if (!empty($sig_result->cert)) {
-                $cert_details = $this->_impsmime->parseCert($sig_result->cert);
-                if (isset($cert_details['certificate']['subject']['CommonName'])) {
-                    $subject = $cert_details['certificate']['subject']['CommonName'];
-                } elseif (isset($cert_details['certificate']['subject']['Email'])) {
-                    $subject = $cert_details['certificate']['subject']['Email'];
-                } elseif (isset($sig_result->email)) {
-                    $subject = $sig_result->email;
-                } elseif (isset($smime_from)) {
-                    $subject = $smime_from;
-                } else {
-                    $subject = null;
-                }
-
-                if (!empty($subject) &&
-                    $GLOBALS['registry']->hasMethod('contacts/addField') &&
-                    $GLOBALS['prefs']->getValue('add_source')) {
-                    $status[] = sprintf(_("The S/MIME certificate of %s: "), @htmlspecialchars($subject, ENT_COMPAT, NLS::getCharset())) . $this->_params['contents']->linkViewJS($this->_mimepart, 'view_attach', _("View"), array('params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))) . '/' . Horde::link('#', '', null, null, $this->_impsmime->savePublicKeyURL($sig_result->cert, $this->_params['contents']->getIndex(), $sig_id) . ' return false;') . _("Save in your Address Book") . '</a>';
-                }
+            if (!empty($subject) &&
+                $GLOBALS['registry']->hasMethod('contacts/addField') &&
+                $GLOBALS['prefs']->getValue('add_source')) {
+                $status[] = sprintf(_("The S/MIME certificate of %s: "), @htmlspecialchars($subject, ENT_COMPAT, NLS::getCharset())) . $this->_params['contents']->linkViewJS($this->_mimepart, 'view_attach', _("View"), array('params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))) . '/' . Horde::link('#', '', null, null, $this->_impsmime->savePublicKeyURL($sig_result->cert, $this->_params['contents']->getIndex(), $sig_id) . ' return false;') . _("Save in your Address Book") . '</a>';
             }
         }
 
index b1d0cf3..67474ce 100644 (file)
@@ -66,8 +66,18 @@ function _reloadWindow()
 
 require_once dirname(__FILE__) . '/lib/base.php';
 
-$imp_pgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
-$secure_check = $imp_pgp->requireSecureConnection();
+try {
+    $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
+} catch (Horde_Exception $e) {
+    Horde::fatal($e, __FILE__, __LINE__);
+}
+
+try {
+    $imp_pgp->requireSecureConnection();
+    $secure_check = true;
+} catch (Horde_Exception $e) {
+    $secure_check = false;
+}
 
 /* Run through the action handlers */
 $actionID = Util::getFormData('actionID');
@@ -345,8 +355,8 @@ if ($prefs->getValue('use_pgp')) {
     }
     $t->set('personalkey-help', Help::link('imp', 'pgp-overview-personalkey'));
 
-    $t->set('secure_check', is_a($secure_check, 'PEAR_Error'));
-    if (!$t->get('secure_check')) {
+    $t->set('secure_check', !$secure_check);
+    if ($secure_check) {
         $t->set('has_key', $prefs->getValue('pgp_public_key') && $prefs->getValue('pgp_private_key'));
         if ($t->get('has_key')) {
             $t->set('viewpublic', Horde::link(Util::addParameter($selfURL, 'actionID', 'view_personal_public_key'), _("View Personal Public Key"), null, 'view_key'));
index 5fab5b1..205eea0 100644 (file)
@@ -80,8 +80,18 @@ function _printKeyInfo($cert)
 
 require_once dirname(__FILE__) . '/lib/base.php';
 
-$imp_smime = &Horde_Crypt::singleton(array('imp', 'smime'));
-$secure_check = $imp_smime->requireSecureConnection();
+try {
+    $imp_smime = Horde_Crypt::singleton(array('IMP', 'Smime'));
+} catch (Horde_Exception $e) {
+    Horde::fatal($e, __FILE__, __LINE__);
+}
+
+try {
+    $imp_smime->requireSecureConnection();
+    $secure_check = true;
+} catch (Horde_Exception $e) {
+    $secure_check = false;
+}
 
 /* Run through the action handlers */
 $actionID = Util::getFormData('actionID');
@@ -230,13 +240,18 @@ $selfURL = Horde::applicationUrl('smime.php');
 
 /* If S/MIME preference not active, or openssl PHP extension not available, do
  * NOT show S/MIME Admin screen. */
-$openssl_check = $imp_smime->checkForOpenSSL();
+try {
+    $imp_smime->checkForOpenSSL();
+    $openssl_check = true;
+} catch
+    $openssl_check = false;
+}
 
 /* If S/MIME preference not active, do NOT show S/MIME Admin screen. */
 $t = new IMP_Template();
 $t->setOption('gettext', true);
 $t->set('use_smime_help', Help::link('imp', 'smime-overview'));
-if (!is_a($openssl_check, 'PEAR_Error') && $prefs->getValue('use_smime')) {
+if ($openssl_check && $prefs->getValue('use_smime')) {
     Horde::addScriptFile('imp.js', 'imp', true);
     $t->set('smimeactive', true);
     $t->set('manage_pubkey-help', Help::link('imp', 'smime-manage-pubkey'));