Overview

Packages

  • IMP

Classes

  • IMP
  • IMP_Ajax_Addresses
  • IMP_Ajax_Application
  • IMP_Ajax_Application_Compose
  • IMP_Ajax_Application_Handler_Common
  • IMP_Ajax_Application_Handler_ComposeAttach
  • IMP_Ajax_Application_Handler_Draft
  • IMP_Ajax_Application_Handler_Dynamic
  • IMP_Ajax_Application_Handler_ImageUnblock
  • IMP_Ajax_Application_Handler_Mboxtoggle
  • IMP_Ajax_Application_Handler_Passphrase
  • IMP_Ajax_Application_Handler_Remote
  • IMP_Ajax_Application_Handler_RemotePrefs
  • IMP_Ajax_Application_Handler_Search
  • IMP_Ajax_Application_Handler_Smartmobile
  • IMP_Ajax_Application_ListMessages
  • IMP_Ajax_Application_ShowMessage
  • IMP_Ajax_Application_Viewport
  • IMP_Ajax_Application_Viewport_Error
  • IMP_Ajax_Imple_ImportEncryptKey
  • IMP_Ajax_Imple_ItipRequest
  • IMP_Ajax_Imple_PassphraseDialog
  • IMP_Ajax_Imple_VcardImport
  • IMP_Ajax_Queue
  • IMP_Api
  • IMP_Application
  • IMP_Auth
  • IMP_Basic_Base
  • IMP_Basic_Compose
  • IMP_Basic_Contacts
  • IMP_Basic_Error
  • IMP_Basic_Folders
  • IMP_Basic_Listinfo
  • IMP_Basic_Mailbox
  • IMP_Basic_Message
  • IMP_Basic_Pgp
  • IMP_Basic_Saveimage
  • IMP_Basic_Search
  • IMP_Basic_Searchbasic
  • IMP_Basic_Smime
  • IMP_Basic_Thread
  • IMP_Block_Newmail
  • IMP_Block_Summary
  • IMP_Compose
  • IMP_Compose_Attachment
  • IMP_Compose_Attachment_Linked_Metadata
  • IMP_Compose_Attachment_Metadata
  • IMP_Compose_Attachment_Storage
  • IMP_Compose_Attachment_Storage_AutoDetermine
  • IMP_Compose_Attachment_Storage_Temp
  • IMP_Compose_Attachment_Storage_VfsLinked
  • IMP_Compose_Exception
  • IMP_Compose_Exception_Address
  • IMP_Compose_HtmlSignature
  • IMP_Compose_Link
  • IMP_Compose_LinkedAttachment
  • IMP_Compose_Ui
  • IMP_Compose_View
  • IMP_Contacts
  • IMP_Contacts_Avatar_Addressbook
  • IMP_Contacts_Avatar_Gravatar
  • IMP_Contacts_Avatar_Unknown
  • IMP_Contacts_Flag_Host
  • IMP_Contacts_Image
  • IMP_Contents
  • IMP_Contents_InlineOutput
  • IMP_Contents_View
  • IMP_Crypt_Pgp
  • IMP_Crypt_Smime
  • IMP_Dynamic_AddressList
  • IMP_Dynamic_Base
  • IMP_Dynamic_Compose
  • IMP_Dynamic_Compose_Common
  • IMP_Dynamic_Helper_Base
  • IMP_Dynamic_Mailbox
  • IMP_Dynamic_Message
  • IMP_Exception
  • IMP_Factory_AuthImap
  • IMP_Factory_Compose
  • IMP_Factory_ComposeAtc
  • IMP_Factory_Contacts
  • IMP_Factory_Contents
  • IMP_Factory_Flags
  • IMP_Factory_Ftree
  • IMP_Factory_Identity
  • IMP_Factory_Imap
  • IMP_Factory_Mail
  • IMP_Factory_MailAutoconfig
  • IMP_Factory_Mailbox
  • IMP_Factory_MailboxCache
  • IMP_Factory_MailboxList
  • IMP_Factory_Maillog
  • IMP_Factory_MimeViewer
  • IMP_Factory_Pgp
  • IMP_Factory_PrefsSort
  • IMP_Factory_Quota
  • IMP_Factory_Search
  • IMP_Factory_Sentmail
  • IMP_Factory_Smime
  • IMP_Factory_Spam
  • IMP_Filter
  • IMP_Flag_Base
  • IMP_Flag_Imap
  • IMP_Flag_Imap_Answered
  • IMP_Flag_Imap_Deleted
  • IMP_Flag_Imap_Draft
  • IMP_Flag_Imap_Flagged
  • IMP_Flag_Imap_Forwarded
  • IMP_Flag_Imap_Junk
  • IMP_Flag_Imap_NotJunk
  • IMP_Flag_Imap_Seen
  • IMP_Flag_System_Attachment
  • IMP_Flag_System_Encrypted
  • IMP_Flag_System_HighPriority
  • IMP_Flag_System_List
  • IMP_Flag_System_LowPriority
  • IMP_Flag_System_Match_Address
  • IMP_Flag_System_Match_Flag
  • IMP_Flag_System_Match_Header
  • IMP_Flag_System_Personal
  • IMP_Flag_System_Signed
  • IMP_Flag_System_Unseen
  • IMP_Flag_User
  • IMP_Flags
  • IMP_Ftree
  • IMP_Ftree_Account
  • IMP_Ftree_Account_Imap
  • IMP_Ftree_Account_Inboxonly
  • IMP_Ftree_Account_Remote
  • IMP_Ftree_Account_Vfolder
  • IMP_Ftree_Element
  • IMP_Ftree_Eltdiff
  • IMP_Ftree_Iterator
  • IMP_Ftree_Iterator_Ancestors
  • IMP_Ftree_IteratorFilter
  • IMP_Ftree_IteratorFilter_Children
  • IMP_Ftree_IteratorFilter_Containers
  • IMP_Ftree_IteratorFilter_Expanded
  • IMP_Ftree_IteratorFilter_Invisible
  • IMP_Ftree_IteratorFilter_Mailboxes
  • IMP_Ftree_IteratorFilter_Nonimap
  • IMP_Ftree_IteratorFilter_Polled
  • IMP_Ftree_IteratorFilter_Remote
  • IMP_Ftree_IteratorFilter_Special
  • IMP_Ftree_IteratorFilter_Subscribed
  • IMP_Ftree_IteratorFilter_Vfolder
  • IMP_Ftree_Prefs
  • IMP_Ftree_Prefs_Expanded
  • IMP_Ftree_Prefs_Poll
  • IMP_Ftree_Select
  • IMP_Images
  • IMP_Imap
  • IMP_Imap_Acl
  • IMP_Imap_Cache_Wrapper
  • IMP_Imap_Config
  • IMP_Imap_Exception
  • IMP_Imap_Password
  • IMP_Imap_PermanentFlags
  • IMP_Imap_Remote
  • IMP_Indices
  • IMP_Indices_Mailbox
  • IMP_LoginTasks_SystemTask_GarbageCollection
  • IMP_LoginTasks_SystemTask_Upgrade
  • IMP_LoginTasks_SystemTask_UpgradeAuth
  • IMP_LoginTasks_Task_Autocreate
  • IMP_LoginTasks_Task_DeleteAttachmentsMonthly
  • IMP_LoginTasks_Task_DeleteSentmailMonthly
  • IMP_LoginTasks_Task_FilterOnLogin
  • IMP_LoginTasks_Task_PurgeSentmail
  • IMP_LoginTasks_Task_PurgeSpam
  • IMP_LoginTasks_Task_PurgeTrash
  • IMP_LoginTasks_Task_RecoverDraft
  • IMP_LoginTasks_Task_RenameSentmailMonthly
  • IMP_Mailbox
  • IMP_Mailbox_List
  • IMP_Mailbox_List_Pop3
  • IMP_Mailbox_List_Thread
  • IMP_Mailbox_List_Virtual
  • IMP_Mailbox_SessionCache
  • IMP_Mailbox_Ui
  • IMP_Maillog
  • IMP_Maillog_Log_Base
  • IMP_Maillog_Log_Forward
  • IMP_Maillog_Log_Mdn
  • IMP_Maillog_Log_Redirect
  • IMP_Maillog_Log_Reply
  • IMP_Maillog_Log_Replyall
  • IMP_Maillog_Log_Replylist
  • IMP_Maillog_Message
  • IMP_Maillog_Storage_Base
  • IMP_Maillog_Storage_Composite
  • IMP_Maillog_Storage_History
  • IMP_Maillog_Storage_Mdnsent
  • IMP_Maillog_Storage_Null
  • IMP_Mbox_Generate
  • IMP_Mbox_Import
  • IMP_Mbox_Size
  • IMP_Message
  • IMP_Message_Date
  • IMP_Message_Ui
  • IMP_Mime_Headers
  • IMP_Mime_Status
  • IMP_Mime_Status_RenderIssue
  • IMP_Mime_Status_RenderIssue_Display
  • IMP_Mime_Viewer_Alternative
  • IMP_Mime_Viewer_Appledouble
  • IMP_Mime_Viewer_Audio
  • IMP_Mime_Viewer_Enriched
  • IMP_Mime_Viewer_Externalbody
  • IMP_Mime_Viewer_Html
  • IMP_Mime_Viewer_Images
  • IMP_Mime_Viewer_Itip
  • IMP_Mime_Viewer_Mdn
  • IMP_Mime_Viewer_Partial
  • IMP_Mime_Viewer_Pdf
  • IMP_Mime_Viewer_Pgp
  • IMP_Mime_Viewer_Plain
  • IMP_Mime_Viewer_Related
  • IMP_Mime_Viewer_Rfc822
  • IMP_Mime_Viewer_Smil
  • IMP_Mime_Viewer_Smime
  • IMP_Mime_Viewer_Status
  • IMP_Mime_Viewer_Vcard
  • IMP_Mime_Viewer_Video
  • IMP_Mime_Viewer_Zip
  • IMP_Minimal_Base
  • IMP_Minimal_Compose
  • IMP_Minimal_Error
  • IMP_Minimal_Folders
  • IMP_Minimal_Mailbox
  • IMP_Minimal_Message
  • IMP_Minimal_Messagepart
  • IMP_Minimal_Search
  • IMP_Notification_Event_Status
  • IMP_Notification_Handler_Decorator_ImapAlerts
  • IMP_Notification_Handler_Decorator_NewmailNotify
  • IMP_Perms
  • IMP_Prefs_AttribText
  • IMP_Prefs_Identity
  • IMP_Prefs_Sort
  • IMP_Prefs_Sort_FixedDate
  • IMP_Prefs_Sort_None
  • IMP_Prefs_Sort_Sortpref
  • IMP_Prefs_Sort_Sortpref_Locked
  • IMP_Prefs_Special_Acl
  • IMP_Prefs_Special_ComposeTemplates
  • IMP_Prefs_Special_Drafts
  • IMP_Prefs_Special_Encrypt
  • IMP_Prefs_Special_Flag
  • IMP_Prefs_Special_HtmlSignature
  • IMP_Prefs_Special_ImageReplacement
  • IMP_Prefs_Special_InitialPage
  • IMP_Prefs_Special_Mailto
  • IMP_Prefs_Special_NewmailSound
  • IMP_Prefs_Special_PgpPrivateKey
  • IMP_Prefs_Special_PgpPublicKey
  • IMP_Prefs_Special_Remote
  • IMP_Prefs_Special_Searches
  • IMP_Prefs_Special_Sentmail
  • IMP_Prefs_Special_SmimePrivateKey
  • IMP_Prefs_Special_SmimePublicKey
  • IMP_Prefs_Special_Sourceselect
  • IMP_Prefs_Special_Spam
  • IMP_Prefs_Special_SpecialMboxes
  • IMP_Prefs_Special_Trash
  • IMP_Quota
  • IMP_Quota_Hook
  • IMP_Quota_Imap
  • IMP_Quota_Null
  • IMP_Quota_Ui
  • IMP_Remote
  • IMP_Remote_Account
  • IMP_Script_Package_Autocomplete
  • IMP_Script_Package_ComposeBase
  • IMP_Script_Package_DynamicBase
  • IMP_Script_Package_Editor
  • IMP_Script_Package_Imp
  • IMP_Search
  • IMP_Search_Element
  • IMP_Search_Element_Attachment
  • IMP_Search_Element_Autogenerated
  • IMP_Search_Element_Bulk
  • IMP_Search_Element_Contacts
  • IMP_Search_Element_Daterange
  • IMP_Search_Element_Flag
  • IMP_Search_Element_Header
  • IMP_Search_Element_Mailinglist
  • IMP_Search_Element_Or
  • IMP_Search_Element_Personal
  • IMP_Search_Element_Recipient
  • IMP_Search_Element_Size
  • IMP_Search_Element_Text
  • IMP_Search_Element_Within
  • IMP_Search_Filter
  • IMP_Search_Filter_Attachment
  • IMP_Search_Filter_Autogenerated
  • IMP_Search_Filter_Builtin
  • IMP_Search_Filter_Bulk
  • IMP_Search_Filter_Contacts
  • IMP_Search_Filter_Mailinglist
  • IMP_Search_Filter_Personal
  • IMP_Search_IteratorFilter
  • IMP_Search_Query
  • IMP_Search_Ui
  • IMP_Search_Vfolder
  • IMP_Search_Vfolder_Builtin
  • IMP_Search_Vfolder_Vinbox
  • IMP_Search_Vfolder_Vtrash
  • IMP_Sentmail
  • IMP_Sentmail_Mongo
  • IMP_Sentmail_Null
  • IMP_Sentmail_Sql
  • IMP_Smartmobile
  • IMP_Spam
  • IMP_Spam_Email
  • IMP_Spam_Null
  • IMP_Spam_Program
  • IMP_Test
  • IMP_Tree_Flist
  • IMP_Tree_Jquerymobile
  • IMP_Tree_Simplehtml
  • IMP_View_Subinfo

Interfaces

  • IMP_Compose_Attachment_Linked
  • IMP_Contacts_Avatar_Backend
  • IMP_Contacts_Flag_Backend
  • IMP_Spam_Base
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Copyright 2002-2014 Horde LLC (http://www.horde.org/)
  4:  *
  5:  * See the enclosed file COPYING for license information (GPL). If you
  6:  * did not receive this file, see http://www.horde.org/licenses/gpl.
  7:  *
  8:  * @category  Horde
  9:  * @copyright 2002-2014 Horde LLC
 10:  * @license   http://www.horde.org/licenses/gpl GPL
 11:  * @package   IMP
 12:  */
 13: 
 14: /**
 15:  * The IMP_Crypt_Pgp:: class contains all functions related to handling
 16:  * PGP messages within IMP.
 17:  *
 18:  * @author    Michael Slusarz <slusarz@horde.org>
 19:  * @category  Horde
 20:  * @copyright 2002-2014 Horde LLC
 21:  * @license   http://www.horde.org/licenses/gpl GPL
 22:  * @package   IMP
 23:  */
 24: class IMP_Crypt_Pgp extends Horde_Crypt_Pgp
 25: {
 26:     /* Name of PGP public key field in addressbook. */
 27:     const PUBKEY_FIELD = 'pgpPublicKey';
 28: 
 29:     /* Encryption type constants. */
 30:     const ENCRYPT = 'pgp_encrypt';
 31:     const SIGN = 'pgp_sign';
 32:     const SIGNENC = 'pgp_signenc';
 33:     const SYM_ENCRYPT = 'pgp_sym_enc';
 34:     const SYM_SIGNENC = 'pgp_syn_sign';
 35: 
 36:     /**
 37:      * Return the list of available encryption options for composing.
 38:      *
 39:      * @return array  Keys are encryption type constants, values are gettext
 40:      *                strings describing the encryption type.
 41:      */
 42:     public function encryptList()
 43:     {
 44:         $ret = array(
 45:             self::ENCRYPT => _("PGP Encrypt Message")
 46:         );
 47: 
 48:         if ($this->getPersonalPrivateKey()) {
 49:             $ret += array(
 50:                 self::SIGN => _("PGP Sign Message"),
 51:                 self::SIGNENC => _("PGP Sign/Encrypt Message")
 52:             );
 53:         }
 54: 
 55:         return $ret + array(
 56:             self::SYM_ENCRYPT => _("PGP Encrypt Message with passphrase"),
 57:             self::SYM_SIGNENC => _("PGP Sign/Encrypt Message with passphrase")
 58:         );
 59:     }
 60: 
 61:     /**
 62:      * Generate the personal Public/Private keypair and store in prefs.
 63:      *
 64:      * @param string $name        See Horde_Crypt_Pgp::.
 65:      * @param string $email       See Horde_Crypt_Pgp::.
 66:      * @param string $passphrase  See Horde_Crypt_Pgp::.
 67:      * @param string $comment     See Horde_Crypt_Pgp::.
 68:      * @param string $keylength   See Horde_Crypt_Pgp::.
 69:      * @param integer $expire     See Horde_Crypt_Pgp::.
 70:      *
 71:      * @throws Horde_Crypt_Exception
 72:      */
 73:     public function generatePersonalKeys($name, $email, $passphrase,
 74:                                          $comment = '', $keylength = 1024,
 75:                                          $expire = null)
 76:     {
 77:         $keys = $this->generateKey($name, $email, $passphrase, $comment, $keylength, $expire);
 78: 
 79:         /* Store the keys in the user's preferences. */
 80:         $this->addPersonalPublicKey($keys['public']);
 81:         $this->addPersonalPrivateKey($keys['private']);
 82:     }
 83: 
 84:     /**
 85:      * Add the personal public key to the prefs.
 86:      *
 87:      * @param mixed $public_key  The public key to add (either string or
 88:      *                           array).
 89:      */
 90:     public function addPersonalPublicKey($public_key)
 91:     {
 92:         $GLOBALS['prefs']->setValue('pgp_public_key', trim($public_key));
 93:     }
 94: 
 95:     /**
 96:      * Add the personal private key to the prefs.
 97:      *
 98:      * @param mixed $private_key  The private key to add (either string or
 99:      *                            array).
100:      */
101:     public function addPersonalPrivateKey($private_key)
102:     {
103:         $GLOBALS['prefs']->setValue('pgp_private_key', trim($private_key));
104:     }
105: 
106:     /**
107:      * Get the personal public key from the prefs.
108:      *
109:      * @return string  The personal PGP public key.
110:      */
111:     public function getPersonalPublicKey()
112:     {
113:         return $GLOBALS['prefs']->getValue('pgp_public_key');
114:     }
115: 
116:     /**
117:      * Get the personal private key from the prefs.
118:      *
119:      * @return string  The personal PGP private key.
120:      */
121:     public function getPersonalPrivateKey()
122:     {
123:         return $GLOBALS['prefs']->getValue('pgp_private_key');
124:     }
125: 
126:     /**
127:      * Deletes the specified personal keys from the prefs.
128:      */
129:     public function deletePersonalKeys()
130:     {
131:         $GLOBALS['prefs']->setValue('pgp_public_key', '');
132:         $GLOBALS['prefs']->setValue('pgp_private_key', '');
133: 
134:         $this->unsetPassphrase('personal');
135:     }
136: 
137:     /**
138:      * Add a public key to an address book.
139:      *
140:      * @param string $public_key  An PGP public key.
141:      *
142:      * @return array  See Horde_Crypt_Pgp::pgpPacketInformation()
143:      * @throws Horde_Crypt_Exception
144:      * @throws Horde_Exception
145:      */
146:     public function addPublicKey($public_key)
147:     {
148:         /* Make sure the key is valid. */
149:         $key_info = $this->pgpPacketInformation($public_key);
150:         if (!isset($key_info['signature'])) {
151:             throw new Horde_Crypt_Exception(_("Not a valid public key."));
152:         }
153: 
154:         /* Remove the '_SIGNATURE' entry. */
155:         unset($key_info['signature']['_SIGNATURE']);
156: 
157:         /* Store all signatures that appear in the key. */
158:         foreach ($key_info['signature'] as $id => $sig) {
159:             /* Check to make sure the key does not already exist in ANY
160:              * address book and remove the id from the key_info for a correct
161:              * output. */
162:             try {
163:                 $result = $this->getPublicKey($sig['email'], array('nocache' => true, 'noserver' => true));
164:                 if (!empty($result)) {
165:                     unset($key_info['signature'][$id]);
166:                     continue;
167:                 }
168:             } catch (Horde_Crypt_Exception $e) {}
169: 
170:             /* Add key to the user's address book. */
171:             $GLOBALS['registry']->call('contacts/addField', array($sig['email'], $sig['name'], self::PUBKEY_FIELD, $public_key, $GLOBALS['prefs']->getValue('add_source')));
172:         }
173: 
174:         return $key_info;
175:     }
176: 
177:     /**
178:      * Retrieves a public key by e-mail.
179:      *
180:      * First, the key will be attempted to be retrieved from a user's address
181:      * book(s).
182:      * Second, if unsuccessful, the key is attempted to be retrieved via a
183:      * public PGP keyserver.
184:      *
185:      * @param string $address  The e-mail address to search by.
186:      * @param array $options   Additional options:
187:      *   - keyid: (string) The key ID of the user's key.
188:      *            DEFAULT: key ID not used
189:      *   - nocache: (boolean) Don't retrieve from cache?
190:      *              DEFAULT: false
191:      *   - noserver: (boolean) Whether to check the public key servers for the
192:      *               key.
193:      *               DEFAULT: false
194:      *
195:      * @return string  The PGP public key requested.
196:      * @throws Horde_Crypt_Exception
197:      */
198:     public function getPublicKey($address, $options = array())
199:     {
200:         global $injector, $registry;
201: 
202:         $keyid = empty($options['keyid'])
203:             ? ''
204:             : $options['keyid'];
205: 
206:         /* If there is a cache driver configured, try to get the public key
207:          * from the cache. */
208:         if (empty($options['nocache']) && ($cache = $injector->getInstance('Horde_Cache'))) {
209:             $result = $cache->get("PGPpublicKey_" . $address . $keyid, 3600);
210:             if ($result) {
211:                 Horde::log('PGPpublicKey: ' . serialize($result), 'DEBUG');
212:                 return $result;
213:             }
214:         }
215: 
216:         try {
217:             $key = $injector->getInstance('Horde_Core_Hooks')->callHook(
218:                 'pgp_key',
219:                 'imp',
220:                 array($address, $keyid)
221:             );
222:             if ($key) {
223:                 return $key;
224:             }
225:         } catch (Horde_Exception_HookNotSet $e) {}
226: 
227:         /* Try retrieving by e-mail only first. */
228:         $result = null;
229:         try {
230:             $result = $registry->call(
231:                 'contacts/getField',
232:                 array(
233:                     $address,
234:                     self::PUBKEY_FIELD,
235:                     $injector->getInstance('IMP_Contacts')->sources,
236:                     true,
237:                     true
238:                 )
239:             );
240:         } catch (Horde_Exception $e) {}
241: 
242:         if (is_null($result)) {
243:             /* TODO: Retrieve by ID. */
244: 
245:             /* See if the address points to the user's public key. */
246:             $identity = $injector->getInstance('IMP_Identity');
247:             $personal_pubkey = $this->getPersonalPublicKey();
248:             if (!empty($personal_pubkey) && $identity->hasAddress($address)) {
249:                 $result = $personal_pubkey;
250:             } elseif (empty($options['noserver'])) {
251:                 $result = null;
252: 
253:                 try {
254:                     foreach ($this->_keyserverList() as $val) {
255:                         try {
256:                             $result = $val->get(
257:                                 empty($keyid) ? $val->getKeyId($address) : $keyid
258:                             );
259:                             break;
260:                         } catch (Exception $e) {}
261:                     }
262: 
263:                     if (is_null($result)) {
264:                         throw $e;
265:                     }
266: 
267:                     /* If there is a cache driver configured and a cache
268:                      * object exists, store the retrieved public key in the
269:                      * cache. */
270:                     if (is_object($cache)) {
271:                         $cache->set("PGPpublicKey_" . $address . $keyid, $result, 3600);
272:                     }
273:                 } catch (Horde_Crypt_Exception $e) {
274:                     /* Return now, if no public key found at all. */
275:                     Horde::log('PGPpublicKey: ' . $e->getMessage(), 'DEBUG');
276:                     throw new Horde_Crypt_Exception(sprintf(_("Could not retrieve public key for %s."), $address));
277:                 }
278:             } else {
279:                 $result = '';
280:             }
281:         }
282: 
283:         /* If more than one public key is returned, just return the first in
284:          * the array. There is no way of knowing which is the "preferred" key,
285:          * if the keys are different. */
286:         if (is_array($result)) {
287:             reset($result);
288:         }
289: 
290:         return $result;
291:     }
292: 
293:     /**
294:      * Retrieves all public keys from a user's address book(s).
295:      *
296:      * @return array  All PGP public keys available.
297:      * @throws Horde_Crypt_Exception
298:      */
299:     public function listPublicKeys()
300:     {
301:         $sources = $GLOBALS['injector']->getInstance('IMP_Contacts')->sources;
302: 
303:         return empty($sources)
304:             ? array()
305:             : $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(self::PUBKEY_FIELD, $sources));
306:     }
307: 
308:     /**
309:      * Deletes a public key from a user's address book(s) by e-mail.
310:      *
311:      * @param string $email  The e-mail address to delete.
312:      *
313:      * @throws Horde_Crypt_Exception
314:      */
315:     public function deletePublicKey($email)
316:     {
317:         return $GLOBALS['registry']->call(
318:             'contacts/deleteField',
319:             array(
320:                 $email,
321:                 self::PUBKEY_FIELD,
322:                 $GLOBALS['injector']->getInstance('IMP_Contacts')->sources
323:             )
324:         );
325:     }
326: 
327:     /**
328:      * Send a public key to a public PGP keyserver.
329:      *
330:      * @param string $pubkey  The PGP public key.
331:      *
332:      * @throws Horde_Crypt_Exception
333:      */
334:     public function sendToPublicKeyserver($pubkey)
335:     {
336:         $servers = $this->_keyserverList();
337:         $servers[0]->put($pubkey);
338:     }
339: 
340:     /**
341:      * Verifies a signed message with a given public key.
342:      *
343:      * @param string $text       The text to verify.
344:      * @param string $address    E-mail address of public key.
345:      * @param string $signature  A PGP signature block.
346:      * @param string $charset    Charset to use.
347:      *
348:      * @return stdClass  See Horde_Crypt_Pgp::decrypt().
349:      * @throws Horde_Crypt_Exception
350:      */
351:     public function verifySignature($text, $address, $signature = '',
352:                                     $charset = null)
353:     {
354:         if (!empty($signature)) {
355:             $packet_info = $this->pgpPacketInformation($signature);
356:             if (isset($packet_info['keyid'])) {
357:                 $keyid = $packet_info['keyid'];
358:             }
359:         }
360: 
361:         if (!isset($keyid)) {
362:             $keyid = $this->getSignersKeyID($text);
363:         }
364: 
365:         /* Get key ID of key. */
366:         $public_key = $this->getPublicKey($address, array('keyid' => $keyid));
367: 
368:         if (empty($signature)) {
369:             $options = array('type' => 'signature');
370:         } else {
371:             $options = array('type' => 'detached-signature', 'signature' => $signature);
372:         }
373:         $options['pubkey'] = $public_key;
374: 
375:         if (!empty($charset)) {
376:             $options['charset'] = $charset;
377:         }
378: 
379:         return $this->decrypt($text, $options);
380:     }
381: 
382:     /**
383:      * Decrypt a message with user's public/private keypair or a passphrase.
384:      *
385:      * @param string $text  The text to decrypt.
386:      * @param string $type  Either 'literal', 'personal', or 'symmetric'.
387:      * @param array $opts   Additional options:
388:      *   - passphrase: (boolean) If $type is 'personal' or 'symmetrical', the
389:      *                 passphrase to use.
390:      *   - sender: (string) The sender of the message (used to check signature
391:      *             if message is both encrypted & signed).
392:      *
393:      * @return stdClass  See Horde_Crypt_Pgp::decrypt().
394:      * @throws Horde_Crypt_Exception
395:      */
396:     public function decryptMessage($text, $type, array $opts = array())
397:     {
398:         $opts = array_merge(array(
399:             'passphrase' => null
400:         ), $opts);
401: 
402:         $pubkey = $this->getPersonalPublicKey();
403:         if (isset($opts['sender'])) {
404:             try {
405:                 $pubkey .= "\n" . $this->getPublicKey($opts['sender']);
406:             } catch (Horde_Crypt_Exception $e) {}
407:         }
408: 
409:         switch ($type) {
410:         case 'literal':
411:             return $this->decrypt($text, array(
412:                 'no_passphrase' => true,
413:                 'pubkey' => $pubkey,
414:                 'type' => 'message'
415:             ));
416:             break;
417: 
418:         case 'symmetric':
419:             return $this->decrypt($text, array(
420:                 'passphrase' => $opts['passphrase'],
421:                 'pubkey' => $pubkey,
422:                 'type' => 'message'
423:             ));
424:             break;
425: 
426:         case 'personal':
427:             return $this->decrypt($text, array(
428:                 'passphrase' => $opts['passphrase'],
429:                 'privkey' => $this->getPersonalPrivateKey(),
430:                 'pubkey' => $pubkey,
431:                 'type' => 'message'
432:             ));
433:         }
434:     }
435: 
436:     /**
437:      * Gets a passphrase from the session cache.
438:      *
439:      * @param integer $type  The type of passphrase. Either 'personal' or
440:      *                       'symmetric'.
441:      * @param string $id     If $type is 'symmetric', the ID of the stored
442:      *                       passphrase.
443:      *
444:      * @return mixed  The passphrase, if set, or null.
445:      */
446:     public function getPassphrase($type, $id = null)
447:     {
448:         if ($type == 'personal') {
449:             $id = 'personal';
450:         }
451: 
452:         return (($cache = $GLOBALS['session']->get('imp', 'pgp')) && isset($cache[$type][$id]))
453:             ? $cache[$type][$id]
454:             : null;
455:     }
456: 
457:     /**
458:      * Store's the user's passphrase in the session cache.
459:      *
460:      * @param integer $type       The type of passphrase. Either 'personal' or
461:      *                            'symmetric'.
462:      * @param string $passphrase  The user's passphrase.
463:      * @param string $id          If $type is 'symmetric', the ID of the
464:      *                            stored passphrase.
465:      *
466:      * @return boolean  Returns true if correct passphrase, false if incorrect.
467:      */
468:     public function storePassphrase($type, $passphrase, $id = null)
469:     {
470:         global $session;
471: 
472:         if ($type == 'personal') {
473:             if ($this->verifyPassphrase($this->getPersonalPublicKey(), $this->getPersonalPrivateKey(), $passphrase) === false) {
474:                 return false;
475:             }
476:             $id = 'personal';
477:         }
478: 
479:         $cache = $session->get('imp', 'pgp', Horde_Session::TYPE_ARRAY);
480:         $cache[$type][$id] = $passphrase;
481:         $session->set('imp', 'pgp', $cache, $session::ENCRYPT);
482: 
483:         return true;
484:     }
485: 
486:     /**
487:      * Clear the passphrase from the session cache.
488:      *
489:      * @param integer $type       The type of passphrase. Either 'personal' or
490:      *                            'symmetric'.
491:      * @param string $id          If $type is 'symmetric', the ID of the
492:      *                            stored passphrase. Else, all passphrases
493:      *                            are deleted.
494:      */
495:     public function unsetPassphrase($type, $id = null)
496:     {
497:         if ($cache = $GLOBALS['session']->get('imp', 'pgp')) {
498:             if (($type == 'symmetric') && !is_null($id)) {
499:                 unset($cache['symmetric'][$id]);
500:             } else {
501:                 unset($cache[$type]);
502:             }
503:             $GLOBALS['session']->set('imp', 'pgp', $cache);
504:         }
505:     }
506: 
507:     /**
508:      * Generates a cache ID for symmetric message data.
509:      *
510:      * @param string $mailbox  The mailbox of the message.
511:      * @param integer $uid     The UID of the message.
512:      * @param string $id       The MIME ID of the message.
513:      *
514:      * @return string  A unique symmetric cache ID.
515:      */
516:     public function getSymmetricId($mailbox, $uid, $id)
517:     {
518:         return implode('|', array($mailbox, $uid, $id));
519:     }
520: 
521:     /**
522:      * Provide the list of parameters needed for signing a message.
523:      *
524:      * @return array  The list of parameters needed by encrypt().
525:      */
526:     protected function _signParameters()
527:     {
528:         return array(
529:             'pubkey' => $this->getPersonalPublicKey(),
530:             'privkey' => $this->getPersonalPrivateKey(),
531:             'passphrase' => $this->getPassphrase('personal')
532:         );
533:     }
534: 
535:     /**
536:      * Provide the list of parameters needed for encrypting a message.
537:      *
538:      * @param Horde_Mail_Rfc822_List $addresses  The e-mail address of the
539:      *                                           keys to use for encryption.
540:      * @param string $symmetric                  If true, the symmetric
541:      *                                           password to use for
542:      *                                           encrypting. If null, uses the
543:      *                                           personal key.
544:      *
545:      * @return array  The list of parameters needed by encrypt().
546:      * @throws Horde_Crypt_Exception
547:      */
548:     protected function _encryptParameters(Horde_Mail_Rfc822_List $addresses,
549:                                           $symmetric)
550:     {
551:         if (!is_null($symmetric)) {
552:             return array(
553:                 'symmetric' => true,
554:                 'passphrase' => $symmetric
555:             );
556:         }
557: 
558:         $addr_list = array();
559: 
560:         foreach ($addresses as $val) {
561:             /* Get the public key for the address. */
562:             $bare_addr = $val->bare_address;
563:             $addr_list[$bare_addr] = $this->getPublicKey($bare_addr);
564:         }
565: 
566:         return array('recips' => $addr_list);
567:     }
568: 
569:     /**
570:      * Sign a Horde_Mime_Part using PGP using IMP default parameters.
571:      *
572:      * @param Horde_Mime_Part $mime_part  The object to sign.
573:      *
574:      * @return Horde_Mime_Part  See Horde_Crypt_Pgp::signMIMEPart().
575:      * @throws Horde_Crypt_Exception
576:      */
577:     public function impSignMimePart($mime_part)
578:     {
579:         return $this->signMimePart($mime_part, $this->_signParameters());
580:     }
581: 
582:     /**
583:      * Encrypt a Horde_Mime_Part using PGP using IMP default parameters.
584:      *
585:      * @param Horde_Mime_Part $mime_part         The object to encrypt.
586:      * @param Horde_Mail_Rfc822_List $addresses  The e-mail address of the
587:      *                                           keys to use for encryption.
588:      * @param string $symmetric                  If true, the symmetric
589:      *                                           password to use for
590:      *                                           encrypting. If null, uses the
591:      *                                           personal key.
592:      *
593:      * @return Horde_Mime_Part  See Horde_Crypt_Pgp::encryptMimePart().
594:      * @throws Horde_Crypt_Exception
595:      */
596:     public function impEncryptMimePart($mime_part,
597:                                        Horde_Mail_Rfc822_List $addresses,
598:                                        $symmetric = null)
599:     {
600:         return $this->encryptMimePart($mime_part, $this->_encryptParameters($addresses, $symmetric));
601:     }
602: 
603:     /**
604:      * Sign and Encrypt a Horde_Mime_Part using PGP using IMP default
605:      * parameters.
606:      *
607:      * @param Horde_Mime_Part $mime_part         The object to sign and
608:      *                                           encrypt.
609:      * @param Horde_Mail_Rfc822_List $addresses  The e-mail address of the
610:      *                                           keys to use for encryption.
611:      * @param string $symmetric                  If true, the symmetric
612:      *                                           password to use for
613:      *                                           encrypting. If null, uses the
614:      *                                           personal key.
615:      *
616:      * @return Horde_Mime_Part  See Horde_Crypt_Pgp::signAndencryptMimePart().
617:      * @throws Horde_Crypt_Exception
618:      */
619:     public function impSignAndEncryptMimePart($mime_part,
620:                                               Horde_Mail_Rfc822_List $addresses,
621:                                               $symmetric = null)
622:     {
623:         return $this->signAndEncryptMimePart($mime_part, $this->_signParameters(), $this->_encryptParameters($addresses, $symmetric));
624:     }
625: 
626:     /**
627:      * Generate a Horde_Mime_Part object, in accordance with RFC 2015/3156,
628:      * that contains the user's public key.
629:      *
630:      * @return Horde_Mime_Part  See Horde_Crypt_Pgp::publicKeyMimePart().
631:      */
632:     public function publicKeyMimePart($key = null)
633:     {
634:         return parent::publicKeyMimePart($this->getPersonalPublicKey());
635:     }
636: 
637:     /**
638:      * Extracts public/private keys from armor data.
639:      *
640:      * @param string $data  Armor text.
641:      *
642:      * @return array  Array with these keys:
643:      *   - public: (array) Array of public keys.
644:      *   - private: (array) Array of private keys.
645:      */
646:     public function getKeys($data)
647:     {
648:         global $injector;
649: 
650:         $out = array(
651:             'public' => array(),
652:             'private' => array()
653:         );
654: 
655:         foreach ($injector->getInstance('Horde_Crypt_Pgp_Parse')->parse($data) as $val) {
656:             switch ($val['type']) {
657:             case Horde_Crypt_Pgp::ARMOR_PUBLIC_KEY:
658:             case Horde_Crypt_Pgp::ARMOR_PRIVATE_KEY:
659:                 $key = implode("\n", $val['data']);
660:                 if ($key_info = $this->pgpPacketInformation($key)) {
661:                     if (($val['type'] == Horde_Crypt_Pgp::ARMOR_PUBLIC_KEY) &&
662:                         !empty($key_info['public_key'])) {
663:                         $out['public'][] = $key;
664:                     } elseif (($val['type'] == Horde_Crypt_Pgp::ARMOR_PRIVATE_KEY) &&
665:                         !empty($key_info['secret_key'])) {
666:                         $out['private'][] = $key;
667:                     }
668:                 }
669:                 break;
670:             }
671:         }
672: 
673:         if (!empty($out['private']) &&
674:             empty($out['public']) &&
675:             $res = $this->getPublicKeyFromPrivateKey(reset($out['private']))) {
676:             $out['public'][] = $res;
677:         }
678: 
679:         return $out;
680:     }
681: 
682:     /**
683:      * Return list of keyserver objects.
684:      *
685:      * @return array  List of Horde_Crypt_Pgp_Keyserver objects.
686:      * @throws Horde_Crypt_Exception
687:      */
688:     protected function _keyserverList()
689:     {
690:         global $conf, $injector;
691: 
692:         if (empty($conf['gnupg']['keyserver'])) {
693:             throw new Horde_Crypt_Exception(_("Public PGP keyserver support has been disabled."));
694:         }
695: 
696:         $http = $injector->getInstance('Horde_Core_Factory_HttpClient')->create();
697:         if (!empty($conf['gnupg']['timeout'])) {
698:             $http->{'request.timeout'} = $conf['gnupg']['timeout'];
699:         }
700: 
701:         $out = array();
702:         foreach ($conf['gnupg']['keyserver'] as $server) {
703:             $out[] = new Horde_Crypt_Pgp_Keyserver($this, array(
704:                 'http' => $http,
705:                 'keyserver' => $server
706:             ));
707:         }
708: 
709:         return $out;
710:     }
711: 
712: }
713: 
API documentation generated by ApiGen