if ($pgp_passphrase_dialog || $pgp_symmetric_passphrase_dialog) {
$imp_pgp = &Horde_Crypt::singleton(array('imp', 'pgp'));
Horde::addScriptFile('popup.js', 'imp', true);
- $notification->push($imp_pgp->getJSOpenWinCode($pgp_symmetric_passphrase_dialog ? 'open_symmetric_passphrase_dialog' : 'open_passphrase_dialog', "opener.focus();opener.uniqSubmit('send_message');"), 'javascript');
+ if ($pgp_passphrase_dialog) {
+ $notification->push($imp_pgp->getJSOpenWinCode('open_passphrase_dialog', "opener.focus();opener.uniqSubmit('send_message');"), 'javascript');
+ } else {
+ $notification->push($imp_pgp->getJSOpenWinCode('open_symmetric_passphrase_dialog', "opener.focus();opener.uniqSubmit('send_message');", array('symmetricid' => 'imp_compose_' . $composeCacheID)), 'javascript');
+ }
} elseif ($smime_passphrase_dialog) {
$imp_smime = &Horde_Crypt::singleton(array('imp', 'smime'));
Horde::addScriptFile('popup.js', 'imp', true);
);
if ($type != 'application/octet-stream') {
- $preview_url = Util::addParameter(Horde::applicationUrl('view.php'), array('actionID' => 'compose_attach_preview', 'id' => $atc_num, 'composeCache' => $imp_compose->getCacheId()));
+ $preview_url = Util::addParameter(Horde::applicationUrl('view.php'), array('actionID' => 'compose_attach_preview', 'id' => $atc_num, 'composeCache' => $composeCacheID));
$entry['name'] = Horde::link($preview_url, _("Preview") . ' ' . $entry['name'], 'link', 'compose_preview_window') . $entry['name'] . '</a>';
}
}
if (is_null($cacheid) || empty($instance[$cacheid])) {
- $cacheid = uniqid(mt_rand());
+ $cacheid = is_null($cacheid) ? uniqid(mt_rand()) : $cacheid;
$instance[$cacheid] = new IMP_Compose($cacheid);
}
case IMP::PGP_SIGNENC:
case IMP::PGP_SYM_SIGNENC:
/* Check to see if we have the user's passphrase yet. */
- $passphrase = $imp_pgp->getPassphrase();
+ $passphrase = $imp_pgp->getPassphrase('personal');
if (empty($passphrase)) {
return PEAR::raiseError(_("PGP: Need passphrase for personal private key."), 'horde.message', null, null, 'pgp_passphrase_dialog');
}
case IMP::PGP_SYM_SIGNENC:
/* Check to see if we have the user's symmetric passphrase
* yet. */
- $symmetric_passphrase = $imp_pgp->getSymmetricPassphrase();
+ $symmetric_passphrase = $imp_pgp->getPassphrase('symmetric', 'imp_compose_' . $this->_cacheid);
if (empty($symmetric_passphrase)) {
return PEAR::raiseError(_("PGP: Need passphrase to encrypt your message with."), 'horde.message', null, null, 'pgp_symmetric_passphrase_dialog');
}
$to_list = empty($options['from'])
? $to
: array_keys(array_flip(array_merge($to, array($options['from']))));
- $base = $imp_pgp->IMPencryptMIMEPart($base, $to_list, $encrypt == IMP::PGP_SYM_ENCRYPT);
- if ($encrypt == IMP::PGP_SYM_ENCRYPT) {
- $imp_pgp->unsetSymmetricPassphrase();
- }
+ $base = $imp_pgp->IMPencryptMIMEPart($base, $to_list, ($encrypt == IMP::PGP_SYM_ENCRYPT) ? $symmetric_passphrase : null);
break;
case IMP::PGP_SIGNENC:
$to_list = empty($options['from'])
? $to
: array_keys(array_flip(array_merge($to, array($options['from']))));
- $base = $imp_pgp->IMPsignAndEncryptMIMEPart($base, $to_list, $encrypt == IMP::PGP_SYM_SIGNENC);
- if ($encrypt == IMP::PGP_SYM_SIGNENC) {
- $imp_pgp->unsetSymmetricPassphrase();
- }
+ $base = $imp_pgp->IMPsignAndEncryptMIMEPart($base, $to_list, ($encrypt == IMP::PGP_SYM_SIGNENC) ? $symmetric_passphrase : null);
break;
}
<?php
/**
- * The IMP_PGP:: class contains all functions related to handling
+ * The IMP_Horde_Crypt_pgp:: class contains all functions related to handling
* PGP messages within IMP.
*
* Copyright 2002-2008 The Horde Project (http://www.horde.org/)
$GLOBALS['prefs']->setValue('pgp_public_key', '');
$GLOBALS['prefs']->setValue('pgp_private_key', '');
- $this->unsetPassphrase();
+ $this->unsetPassphrase('personal');
}
/**
/**
* Decrypt a message with user's public/private keypair or a passphrase.
*
- * @param string $text The text to decrypt.
- * @param boolean $symmetric_hint Whether the text has been encrypted
- * symmetrically. If null, we try to find
- * out.
- * @param boolean $passphrase Whether a passphrase has to be used.
+ * @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. Returns PEAR_Error object on
* error.
*/
- public function decryptMessage($text, $symmetric_hint = null,
- $passphrase = true)
+ public function decryptMessage($text, $type, $passphrase = null)
{
- if (is_null($symmetric_hint)) {
- $symmetric_hint = $this->encryptedSymmetrically($text);
- }
-
/* decrypt() returns a PEAR_Error object on error. */
- if (!$passphrase) {
+ switch ($type) {
+ case 'literal':
return $this->decrypt($text, array('type' => 'message', 'no_passphrase' => true));
- } elseif ($symmetric_hint) {
- return $this->decrypt($text, array('type' => 'message', 'passphrase' => $this->getSymmetricPassphrase()));
- } else {
- 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 string The passphrase, if set.
- */
- public function getPassphrase()
- {
- if (isset($_SESSION['imp']['pgp_passphrase'])) {
- return Secret::read(IMP::getAuthKey(), $_SESSION['imp']['pgp_passphrase']);
+ case 'symmetric':
+ return $this->decrypt($text, array('type' => 'message', 'passphrase' => $passphrase));
+
+ case 'personal':
+ return $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $passphrase));
}
}
/**
- * Gets the user's passphrase for symmetric encryption from the session
- * cache.
+ * 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 string The passphrase, if set.
+ * @return mixed The passphrase, if set, or null.
*/
- public function getSymmetricPassphrase()
+ public function getPassphrase($type, $id)
{
- if (isset($_SESSION['imp']['pgp_sym_passphrase'])) {
- return Secret::read(IMP::getAuthKey(), $_SESSION['imp']['pgp_sym_passphrase']);
+ if ($type == 'personal') {
+ $id = 'personal';
}
+
+ return isset($_SESSION['imp']['cache']['pgp'][$type][$id])
+ ? 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($passphrase)
+ public function storePassphrase($type, $passphrase, $id)
{
- if ($this->verifyPassphrase($this->getPersonalPublicKey(), $this->getPersonalPrivateKey(), $passphrase) === false) {
- return false;
+ if ($type == 'personal') {
+ if ($this->verifyPassphrase($this->getPersonalPublicKey(), $this->getPersonalPrivateKey(), $passphrase) === false) {
+ return false;
+ }
+ $id = 'personal';
}
- $_SESSION['imp']['pgp_passphrase'] = Secret::write(IMP::getAuthKey(), $passphrase);
- return true;
- }
-
- /**
- * Store's the user's passphrase for symmetric encryption in the session
- * cache.
- *
- * @param string $passphrase The user's passphrase.
- *
- * @return boolean True
- */
- public function storeSymmetricPassphrase($passphrase)
- {
- $_SESSION['imp']['pgp_sym_passphrase'] = Secret::write(IMP::getAuthKey(), $passphrase);
+ $_SESSION['imp']['cache']['pgp'][$type][$id] = Secret::write(IMP::getAuthKey(), $passphrase);
return true;
}
/**
* Clear the passphrase from the session cache.
*/
- public function unsetPassphrase()
+ public function unsetPassphrase($type)
{
- unset($_SESSION['imp']['pgp_passphrase']);
+ unset($_SESSION['imp']['cache']['pgp'][$type]);
}
/**
- * Clear the passphrase for symmetric encryption from the session cache.
+ * 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 unsetSymmetricPassphrase()
+ public function getSymmetricID($mailbox, $uid, $id)
{
- unset($_SESSION['imp']['pgp_sym_passphrase']);
+ return implode('|', array($mailbox, $uid, $id));
}
/**
* @param mixed $reload If true, reload base window on close. If text,
* run this JS on close. If false, don't do
* anything on close.
- * @param array $params Additional parameters needed for the reload
+ * @param array $params Additional parameters needed for the popup
* page.
*
* @return string The javascript link.
*/
- public function getJSOpenWinCode($actionid, $reload = true, $params = array())
+ public function getJSOpenWinCode($actionid, $reload = true,
+ $params = array())
{
$params['actionID'] = $actionid;
if (!empty($reload)) {
*/
protected function _signParameters()
{
- return array('pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $this->getPassphrase());
+ 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 boolean $symmetric Whether to encrypt symmetrically.
+ * @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().
* Returns PEAR_Error on error.
*/
- protected function _encryptParameters($addresses, $symmetric = false)
+ protected function _encryptParameters($addresses, $symmetric)
{
- if ($symmetric) {
- return array('symmetric' => true,
- 'passphrase' => $this->getSymmetricPassphrase());
+ if (!is_null($symmetric)) {
+ return array(
+ 'symmetric' => true,
+ 'passphrase' => $symmetric
+ );
}
$addr_list = array();
* 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 boolean $symmetric Whether to encrypt symmetrically.
+ * @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(). Returns
* PEAR_Error object on error.
*/
public function IMPencryptMIMEPart($mime_part, $addresses,
- $symmetric = false)
+ $symmetric = null)
{
$params = $this->_encryptParameters($addresses, $symmetric);
if (is_a($params, 'PEAR_Error')) {
* 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 boolean $symmetric Whether to encrypt symmetrically.
+ * @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().
- * Returns PEAR_Error object on error.
+ * Returns PEAR_Error object on error.
*/
public function IMPsignAndEncryptMIMEPart($mime_part, $addresses,
- $symmetric = false)
+ $symmetric = null)
{
$encrypt_params = $this->_encryptParameters($addresses, $symmetric);
if (is_a($encrypt_params, 'PEAR_Error')) {
}
/**
- * Generate a Horde_Mime_Part object, in accordance with RFC 2015/3156, that
- * contains the user's public key.
+ * 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().
*/
$encrypted_part = $this->_params['contents']->getMIMEPart($data_id);
$encrypted_data = $encrypted_part->getContents();
+ $symmetric_pass = $personal_pass = null;
+
/* Check if this a symmetrically encrypted message. */
$symmetric = $this->_imppgp->encryptedSymmetrically($encrypted_data);
- if ($symmetric && !$this->_imppgp->getSymmetricPassphrase()) {
- if ($_SESSION['imp']['view'] == 'imp') {
- // TODO: Fix to work with DIMP
- /* Ask for the correct passphrase if this is encrypted
- * symmetrically. */
- $status[] = Horde::link('#', _("The message below has been encrypted with PGP. You must enter the passphrase that was used to encrypt this message."), null, null, $this->_imppgp->getJSOpenWinCode('open_symmetric_passphrase_dialog') . ' return false;') . _("You must enter the passphrase that was used to encrypt this message.") . '</a>';
+ if ($symmetric) {
+ $symmetric_id = $this->_imppgp->getSymmetricID($this->_params['contents']->getMailbox(), $this->_params['contents']->getIndex(), $this->_mimepart->getMimeId());
+ $symmetric_pass = $this->_imppgp->getPassphrase('symmetric', $symmetric_id);
+
+ if (is_null($symmetric_pass)) {
+ if ($_SESSION['imp']['view'] == 'imp') {
+ // TODO: Fix to work with DIMP
+ /* Ask for the correct passphrase if this is encrypted
+ * symmetrically. */
+ $status[] = Horde::link('#', _("The message below has been encrypted with PGP. You must enter the passphrase that was used to encrypt this message."), null, null, $this->_imppgp->getJSOpenWinCode('open_symmetric_passphrase_dialog', true, array('symmetricid' => $symmetric_id)) . ' return false;') . _("You must enter the passphrase that was used to encrypt this message.") . '</a>';
+ }
+ return null;
}
- return null;
}
/* Check if this is a literal compressed message. */
$info = $this->_imppgp->pgpPacketInformation($encrypted_data);
$literal = !empty($info['literal']);
- if (!$literal && !$symmetric) {
- if (!$this->_imppgp->getPersonalPrivateKey()) {
- /* Output if there is no personal private key to decrypt
- * with. */
- $status[] = _("The message below has been encrypted with PGP, however, no personal private key exists so the message cannot be decrypted.");
- return null;
- } elseif (!$this->_imppgp->getPassphrase() &&
- ($_SESSION['imp']['view'] == 'imp')) {
- // TODO: Fix to work with DIMP
- /* Ask for the private key's passphrase if this is encrypted
- * asymmetrically. */
- $status[] = Horde::link('#', _("The message below has been encrypted with PGP. You must enter the passphrase for your PGP private key before it can be decrypted."), null, null, $this->_imppgp->getJSOpenWinCode('open_passphrase_dialog') . ' return false;') . _("You must enter the passphrase for your PGP private key to view this message.") . '</a>';
- return null;
+ if ($literal) {
+ $status[] = _("The message below has been compressed with PGP.");
+ } else {
+ $status[] = _("The message below has been encrypted with PGP.");
+ if (!$symmetric) {
+ if (!$this->_imppgp->getPersonalPrivateKey()) {
+ /* Output if there is no personal private key to decrypt
+ * with. */
+ $status[] = _("The message below has been encrypted with PGP, however, no personal private key exists so the message cannot be decrypted.");
+ return null;
+ } else {
+ $personal_pass = $this->_imppgp->getPassphrase('personal');
+
+ if (is_null($personal_pass)) {
+ if ($_SESSION['imp']['view'] == 'imp') {
+ // TODO: Fix to work with DIMP
+ /* Ask for the private key's passphrase if this is
+ * encrypted asymmetrically. */
+ $status[] = Horde::link('#', _("The message below has been encrypted with PGP. You must enter the passphrase for your PGP private key before it can be decrypted."), null, null, $this->_imppgp->getJSOpenWinCode('open_passphrase_dialog') . ' return false;') . _("You must enter the passphrase for your PGP private key to view this message.") . '</a>';
+ }
+ return null;
+ }
+ }
}
}
- $status[] = $literal ? _("The message below has been compressed with PGP.") : _("The message below has been encrypted with PGP.");
+ if (!is_null($symmetric_pass)) {
+ $decrypted_data = $this->_imppgp->decryptMessage($encrypted_data, 'symmetric', $symmetric_pass);
+ } elseif (!is_null($personal_pass)) {
+ $decrypted_data = $this->_imppgp->decryptMessage($encrypted_data, 'personal', $personal_pass);
+ } else {
+ $decrypted_data = $this->_imppgp->decryptMessage($encrypted_data, 'literal');
+ }
- $decrypted_data = $this->_imppgp->decryptMessage($encrypted_data, $symmetric, !$literal);
if (is_a($decrypted_data, 'PEAR_Error')) {
$status[] = _("The message below does not appear to be a valid PGP encrypted message. Error: ") . $decrypted_data->getMessage();
return null;
}
unset(self::$_inlinecache[$base_id][$data_id]);
- $this->_imppgp->unsetSymmetricPassphrase();
- return array($data_id => Horde_Mime_Part::parseMessage($decrypted_data->message));
+ $msg = Horde_Mime_Part::parseMessage($decrypted_data->message);
+ $msg->buildMimeIds($data_id);
+
+ return array($data_id => $msg);
}
/**
_textWindowOutput('PGP Key Information', empty($key_info) ? _("Invalid key") : $key_info);
}
-function _outputPassphraseDialog($secure_check, $symmetric = false)
+function _outputPassphraseDialog($secure_check, $symmetricid = null)
{
if (is_a($secure_check, 'PEAR_Error')) {
$GLOBALS['notification']->push($secure_check, 'horde.warning');
$t = new IMP_Template();
$t->setOption('gettext', true);
- $t->set('symmetric', $symmetric);
- $t->set('submit_url', Util::addParameter(Horde::applicationUrl('pgp.php'), 'actionID', $symmetric ? 'process_symmetric_passphrase_dialog' : 'process_passphrase_dialog'));
+ $t->set('symmetricid', $symmetricid);
+ $t->set('submit_url', Util::addParameter(Horde::applicationUrl('pgp.php'), 'actionID', $symmetricid ? 'process_symmetric_passphrase_dialog' : 'process_passphrase_dialog'));
$t->set('reload', htmlspecialchars(Util::getFormData('reload')));
$t->set('action', Util::getFormData('passphrase_action'));
$t->set('locked_img', Horde::img('locked.png', _("PGP"), null, $GLOBALS['registry']->getImageDir('horde')));
exit;
case 'open_passphrase_dialog':
- if ($imp_pgp->getPassphrase()) {
+ if ($imp_pgp->getPassphrase('personal')) {
Util::closeWindowJS();
} else {
_outputPassphraseDialog($secure_check);
exit;
case 'open_symmetric_passphrase_dialog':
- if ($imp_pgp->getSymmetricPassphrase()) {
+ $symmetricid = Util::getFormData('symmetricid');
+ if ($imp_pgp->getPassphrase('symmetric', $symmetricid)) {
Util::closeWindowJS();
} else {
- _outputPassphraseDialog($secure_check, true);
+ _outputPassphraseDialog($secure_check, $symmetricid);
}
exit;
case 'process_passphrase_dialog':
case 'process_symmetric_passphrase_dialog':
$symmetric = $actionID == 'process_symmetric_passphrase_dialog';
+ $symmetricid = Util::getFormData('symmetricid');
$passphrase = Util::getFormData('passphrase');
if (is_a($secure_check, 'PEAR_Error')) {
- _outputPassphraseDialog($secure_check, $symmetric);
+ _outputPassphraseDialog($secure_check, $symmetricid);
} elseif ($passphrase) {
- if ($symmetric) {
- $success = $imp_pgp->storeSymmetricPassphrase($passphrase);
- } else {
- $success = $imp_pgp->storePassphrase($passphrase);
- }
+ $success = $imp_pgp->storePassphrase($symmetric ? 'symmetric' : 'personal', $passphrase, $symmetricid);
+
if ($success) {
if (Util::getFormData('passphrase_action')) {
$oid = Util::getFormData('passphrase_action');
}
} else {
$notification->push("Invalid passphrase entered.", 'horde.error');
- _outputPassphraseDialog($secure_check, $symmetric);
+ _outputPassphraseDialog($secure_check, $symmetricid);
}
} else {
$notification->push("No passphrase entered.", 'horde.error');
- _outputPassphraseDialog($secure_check, $symmetric);
+ _outputPassphraseDialog($secure_check, $symmetricid);
}
exit;
case 'unset_passphrase':
- $imp_pgp->unsetPassphrase();
+ $imp_pgp->unsetPassphrase('personal');
$notification->push(_("Passphrase successfully unloaded."), 'horde.success');
break;
<if:action>
<input type="hidden" name="passphrase_action" value="<tag:action />" />
</if:action>
+<if:symmetricid>
+<input type="hidden" name="symmetricid" value="<tag:symmetricid />" />
+</if:symmetricid>
<div class="header">
<tag:locked_img />
- <if:symmetric>
- <gettext>Please enter the passphrase for this message.</gettext>
- <else:symmetric>
+ <if:symmetricid>
+ <gettext>Please enter the passphrase for this message. You will only need to enter this passphrase once per session.</gettext>
+ <else:symmetricid>
<gettext>Please enter the passphrase for your PGP private key. You will only need to enter this passphrase once per session.</gettext>
- </else:symmetric></if:symmetric>
+ </else:symmetricid></if:symmetricid>
</div>
<div class="nowrap padded">