From: Michael M Slusarz Date: Thu, 26 Feb 2009 07:04:03 +0000 (-0700) Subject: Update to new Horde_Crypt code X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=c79c6dfcd3fe5fefabd73a5eff965823577abe74;p=horde.git Update to new Horde_Crypt code --- diff --git a/imp/ajax.php b/imp/ajax.php index 1f993743e..9fb6fb59a 100644 --- a/imp/ajax.php +++ b/imp/ajax.php @@ -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; } diff --git a/imp/compose.php b/imp/compose.php index 02f8ee59a..f3796cf01 100644 --- a/imp/compose.php +++ b/imp/compose.php @@ -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); } diff --git a/imp/lib/Compose.php b/imp/lib/Compose.php index f257ef745..cf18add65 100644 --- a/imp/lib/Compose.php +++ b/imp/lib/Compose.php @@ -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 index 000000000..fba601469 --- /dev/null +++ b/imp/lib/Crypt/Pgp.php @@ -0,0 +1,585 @@ + + * @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 index 000000000..c9764de58 --- /dev/null +++ b/imp/lib/Crypt/Smime.php @@ -0,0 +1,428 @@ + + * @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 index 3633b3120..000000000 --- a/imp/lib/Crypt/pgp.php +++ /dev/null @@ -1,613 +0,0 @@ - - * @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 index 450a0582d..000000000 --- a/imp/lib/Crypt/smime.php +++ /dev/null @@ -1,461 +0,0 @@ - - * @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; - } - -} diff --git a/imp/lib/Mime/Viewer/pgp.php b/imp/lib/Mime/Viewer/pgp.php index 1eb7ee591..2a31d2874 100644 --- a/imp/lib/Mime/Viewer/pgp.php +++ b/imp/lib/Mime/Viewer/pgp.php @@ -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 { diff --git a/imp/lib/Mime/Viewer/plain.php b/imp/lib/Mime/Viewer/plain.php index e875c14da..a448eab63 100644 --- a/imp/lib/Mime/Viewer/plain.php +++ b/imp/lib/Mime/Viewer/plain.php @@ -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 diff --git a/imp/lib/Mime/Viewer/smime.php b/imp/lib/Mime/Viewer/smime.php index 7d27ee3f9..ff42f87f6 100644 --- a/imp/lib/Mime/Viewer/smime.php +++ b/imp/lib/Mime/Viewer/smime.php @@ -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") . ''; - } + 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") . ''; } } diff --git a/imp/pgp.php b/imp/pgp.php index b1d0cf3fe..67474ceb5 100644 --- a/imp/pgp.php +++ b/imp/pgp.php @@ -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')); diff --git a/imp/smime.php b/imp/smime.php index 5fab5b17a..205eea0b4 100644 --- a/imp/smime.php +++ b/imp/smime.php @@ -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'));