[ Index ] |
|
Code source de IMP H3 (4.1.5) |
1 <?php 2 3 require_once 'Horde/Crypt/smime.php'; 4 5 /** 6 * Name of the S/MIME public key field in addressbook. 7 */ 8 define('IMP_SMIME_PUBKEY_FIELD', 'smimePublicKey'); 9 10 /** 11 * The IMP_SMIME:: class contains all functions related to handling 12 * S/MIME messages within IMP. 13 * 14 * $Horde: imp/lib/Crypt/SMIME.php,v 1.45.2.16 2007/01/02 13:54:57 jan Exp $ 15 * 16 * Copyright 2002-2007 Mike Cochrane <mike@graftonhall.co.nz> 17 * 18 * See the enclosed file COPYING for license information (GPL). If you 19 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. 20 * 21 * @author Mike Cochrane <mike@graftonhall.co.nz> 22 * @since IMP 4.0 23 * @package IMP 24 */ 25 class IMP_SMIME extends Horde_Crypt_smime { 26 27 /** 28 * The list of available sources to search for keys. 29 * 30 * @var array 31 */ 32 var $_sources = array(); 33 34 /** 35 * Constructor. 36 */ 37 function IMP_SMIME() 38 { 39 /* Get the listing of all sources we search for public keys. */ 40 if (($sources = $GLOBALS['prefs']->getValue('search_sources'))) { 41 $this->_sources = explode("\t", $sources); 42 if ((count($this->_sources) == 1) && empty($this->_sources[0])) { 43 $this->_sources = array(); 44 } 45 } 46 47 parent::Horde_Crypt_smime(array('temp' => Horde::getTempDir())); 48 } 49 50 /** 51 * Add the personal public key to the prefs. 52 * 53 * @param mixed $key The public key to add (either string or array). 54 */ 55 function addPersonalPublicKey($key) 56 { 57 $GLOBALS['prefs']->setValue('smime_public_key', (is_array($key)) ? implode('', $key) : $key); 58 } 59 60 /** 61 * Add the personal private key to the prefs. 62 * 63 * @param mixed $key The private key to add (either string or array). 64 */ 65 function addPersonalPrivateKey($key) 66 { 67 $GLOBALS['prefs']->setValue('smime_private_key', (is_array($key)) ? implode('', $key) : $key); 68 } 69 70 /** 71 * Add the list of additional certs to the prefs. 72 * 73 * @param mixed $key The private key to add (either string or array). 74 */ 75 function addAdditionalCert($key) 76 { 77 $GLOBALS['prefs']->setValue('smime_additional_cert', (is_array($key)) ? implode('', $key) : $key); 78 } 79 80 /** 81 * Get the personal public key from the prefs. 82 * 83 * @return string The personal S/MIME public key. 84 */ 85 function getPersonalPublicKey() 86 { 87 return $GLOBALS['prefs']->getValue('smime_public_key'); 88 } 89 90 /** 91 * Get the personal private key from the prefs. 92 * 93 * @return string The personal S/MIME private key. 94 */ 95 function getPersonalPrivateKey() 96 { 97 return $GLOBALS['prefs']->getValue('smime_private_key'); 98 } 99 100 /** 101 * Get any additional certificates from the prefs. 102 * 103 * @return string Additional signing certs for inclusion. 104 */ 105 function getAdditionalCert() 106 { 107 return $GLOBALS['prefs']->getValue('smime_additional_cert'); 108 } 109 110 /** 111 * Deletes the specified personal keys from the prefs. 112 */ 113 function deletePersonalKeys() 114 { 115 $GLOBALS['prefs']->setValue('smime_public_key', ''); 116 $GLOBALS['prefs']->setValue('smime_private_key', ''); 117 $GLOBALS['prefs']->setValue('smime_additional_cert', ''); 118 $this->unsetPassphrase(); 119 } 120 121 /** 122 * Add a public key to an address book. 123 * 124 * @param string $cert A public certificate to add. 125 * 126 * @return boolean True on successful add. 127 * Returns PEAR_Error or error. 128 */ 129 function addPublicKey($cert) 130 { 131 /* Make sure the certificate is valid. */ 132 $key_info = openssl_x509_parse($cert); 133 if (!is_array($key_info) || !isset($key_info['subject'])) { 134 return PEAR::raiseError(_("Not a valid public key."), 'horde.error'); 135 } 136 137 /* Add key to the user's address book. */ 138 $email = $this->getEmailFromKey($cert); 139 if (is_null($email)) { 140 return PEAR::raiseError(_("No email information located in the public key."), 'horde.error'); 141 } 142 143 /* Get the name corresponding to this key. */ 144 if (isset($key_info['subject']['OU'])) { 145 $name = $key_info['subject']['OU']; 146 } elseif (isset($key_info['subject']['CN'])) { 147 $name = $key_info['subject']['CN']; 148 } else { 149 return PEAR::raiseError(_("Not a valid public key."), 'horde.error'); 150 } 151 152 $res = $GLOBALS['registry']->call('contacts/addField', array($email, $name, IMP_SMIME_PUBKEY_FIELD, $cert, $GLOBALS['prefs']->getValue('add_source'))); 153 if (is_a($res, 'PEAR_Error')) { 154 return $res; 155 } 156 157 return $key_info; 158 } 159 160 /** 161 * Returns the params needed to encrypt a message being sent to the 162 * specified email address. 163 * 164 * @access private 165 * 166 * @param string $address The e-mail address of the recipient. 167 * 168 * @return array The list of parameters needed by encrypt(). 169 * Returns PEAR_Error object on error. 170 */ 171 function _encryptParameters($address) 172 { 173 /* We can only encrypt if we are sending to a single person. */ 174 $addrOb = IMP::bareAddress($address, true); 175 $key_addr = array_pop($addrOb); 176 177 $public_key = $this->getPublicKey($key_addr); 178 if (is_a($public_key, 'PEAR_Error')) { 179 return $public_key; 180 } 181 182 return array('type' => 'message', 'pubkey' => $public_key, 'email' => $address); 183 } 184 185 /** 186 * Retrieves a public key by e-mail. 187 * The key will be retrieved from a user's address book(s). 188 * 189 * @param string $address The e-mail address to search for. 190 * 191 * @return string The S/MIME public key requested. 192 * Returns PEAR_Error object on error. 193 */ 194 function getPublicKey($address) 195 { 196 $key = $GLOBALS['registry']->call('contacts/getField', array($address, IMP_SMIME_PUBKEY_FIELD, $this->_sources, false, true)); 197 if (is_a($key, 'PEAR_Error')) { 198 require_once 'Horde/Identity.php'; 199 $identity = &Identity::singleton(array('imp', 'imp')); 200 $personal_pubkey = $this->getPersonalPublicKey(); 201 if (!empty($personal_pubkey) && $identity->hasAddress($address)) { 202 return $personal_pubkey; 203 } 204 } 205 206 /* If more than one public key is returned, just return the first in 207 * the array. There is no way of knowing which is the "preferred" key, 208 * if the keys are different. */ 209 if (is_array($key)) { 210 return reset($key); 211 } 212 213 return $key; 214 } 215 216 /** 217 * Retrieves all public keys from a user's address book(s). 218 * 219 * @return array All PGP public keys available. 220 * Returns PEAR_Error object on error. 221 * 222 */ 223 function listPublicKeys() 224 { 225 if (empty($this->_sources)) { 226 return array(); 227 } else { 228 return $GLOBALS['registry']->call('contacts/getAllAttributeValues', array(IMP_SMIME_PUBKEY_FIELD, $this->_sources)); 229 } 230 } 231 232 /** 233 * Deletes a public key from a user's address book(s) by e-mail. 234 * 235 * @param string $email The e-mail address to delete. 236 * 237 * @return PEAR_Error Returns PEAR_Error object on error. 238 */ 239 function deletePublicKey($email) 240 { 241 return $GLOBALS['registry']->call('contacts/deleteField', array($email, IMP_SMIME_PUBKEY_FIELD, $this->_sources)); 242 } 243 244 /** 245 * Returns the parameters needed for signing a message. 246 * 247 * @access private 248 * 249 * @return array The list of parameters needed by encrypt(). 250 */ 251 function _signParameters() 252 { 253 return array( 254 'type' => 'signature', 255 'pubkey' => $this->getPersonalPublicKey(), 256 'privkey' => $this->getPersonalPrivateKey(), 257 'passphrase' => $this->getPassphrase(), 258 'sigtype' => 'detach', 259 'certs' => $this->getAdditionalCert() 260 ); 261 } 262 263 /** 264 * Verifies a signed message with a given public key. 265 * 266 * @param string $text The text to verify. 267 * 268 * @return stdClass See Horde_Crypt_smime::verify(). 269 */ 270 function verifySignature($text) 271 { 272 return $this->verify($text, $GLOBALS['conf']['utils']['openssl_cafile']); 273 } 274 275 276 /** 277 * Decrypt a message with user's public/private keypair. 278 * 279 * @param string $text The text to decrypt. 280 * 281 * @return string See Horde_Crypt_smime::decrypt(). 282 * Returns PEAR_Error object on error. 283 */ 284 function decryptMessage($text) 285 { 286 /* decrypt() returns a PEAR_Error object on error. */ 287 return $this->decrypt($text, array('type' => 'message', 'pubkey' => $this->getPersonalPublicKey(), 'privkey' => $this->getPersonalPrivateKey(), 'passphrase' => $this->getPassphrase())); 288 } 289 290 /** 291 * Gets the user's passphrase from the session cache. 292 * 293 * @return mixed The passphrase, if set. Returns false if the passphrase 294 * has not been loaded yet. Returns null if no passphrase 295 * is needed. 296 */ 297 function getPassphrase() 298 { 299 $private_key = $GLOBALS['prefs']->getValue('smime_private_key'); 300 if (empty($private_key)) { 301 return false; 302 } 303 304 if (isset($GLOBALS['imp']['smime']['passphrase'])) { 305 return Secret::read(Secret::getKey('imp'), $GLOBALS['imp']['smime']['passphrase']); 306 } elseif (isset($GLOBALS['imp']['smime']['null_passphrase'])) { 307 return ($GLOBALS['imp']['smime']['null_passphrase']) ? null : false; 308 } else { 309 $res = $this->verifyPassphrase($private_key, null); 310 if (!isset($GLOBALS['imp']['smime'])) { 311 $GLOBALS['imp']['smime'] = array(); 312 } 313 $GLOBALS['imp']['smime']['null_passphrase'] = ($res) ? null : false; 314 return $GLOBALS['imp']['smime']['null_passphrase']; 315 } 316 } 317 318 /** 319 * Store's the user's passphrase in the session cache. 320 * 321 * @param string $passphrase The user's passphrase. 322 * 323 * @return boolean Returns true if correct passphrase, false if incorrect. 324 */ 325 function storePassphrase($passphrase) 326 { 327 if ($this->verifyPassphrase($this->getPersonalPrivateKey(), $passphrase) === false) { 328 return false; 329 } 330 331 if (!isset($GLOBALS['imp']['smime'])) { 332 $GLOBALS['imp']['smime'] = array(); 333 } 334 $GLOBALS['imp']['smime']['passphrase'] = Secret::write(Secret::getKey('imp'), $passphrase); 335 336 return true; 337 } 338 339 /** 340 * Clear the passphrase from the session cache. 341 */ 342 function unsetPassphrase() 343 { 344 unset($GLOBALS['imp']['smime']['null_passphrase']); 345 unset($GLOBALS['imp']['smime']['passphrase']); 346 } 347 348 /** 349 * Generates the javascript code for viewing public keys. 350 * 351 * @since IMP 4.1.3 352 * 353 * @param MIME_Part &$mime_part The MIME_Part containing the public key. 354 * @param string $cache The MIME_Part identifier. 355 * 356 * @return string The URL for saving public keys. 357 */ 358 function viewPublicKeyURL($mime_part, $from) 359 { 360 if (empty($cache)) { 361 require_once 'Horde/SessionObjects.php'; 362 $cacheSess = &Horde_SessionObjects::singleton(); 363 $oid = $cacheSess->storeOid($mime_part); 364 } 365 366 return $this->getJSOpenWinCode('view_attachment_public_key', false, array('from' => $from, 'cert' => $oid)); 367 } 368 369 /** 370 * Generates the javascript code for saving public keys. 371 * 372 * @param MIME_Part &$mime_part The MIME_Part containing the public key. 373 * @param string $cache The MIME_Part identifier. 374 * 375 * @return string The URL for saving public keys. 376 */ 377 function savePublicKeyURL($mime_part, $from) 378 { 379 if (empty($cache)) { 380 require_once 'Horde/SessionObjects.php'; 381 $cacheSess = &Horde_SessionObjects::singleton(); 382 $oid = $cacheSess->storeOid($mime_part); 383 } 384 385 return $this->getJSOpenWinCode('save_attachment_public_key', false, array('from' => $from, 'cert' => $oid)); 386 } 387 388 /** 389 * Print out the link for the javascript SMIME popup. 390 * 391 * @param integer $actionid The actionID to perform. 392 * @param mixed $reload If true, reload base window on close. If text, 393 * run this JS on close. If false, don't do 394 * anything on close. 395 * @param array $params Additional parameters needed for the reload 396 * page. 397 * 398 * @return string The javascript link. 399 */ 400 function getJSOpenWinCode($actionid, $reload = true, $params = null) 401 { 402 $popup_url = Horde::applicationUrl('smime.php'); 403 $popup_url = Util::addParameter($popup_url, 'actionID', $actionid, false); 404 if (!empty($reload)) { 405 if (is_bool($reload)) { 406 $popup_url = Util::addParameter($popup_url, 'reload', Util::removeParameter(Horde::selfUrl(true), array('actionID')), false); 407 } else { 408 require_once 'Horde/SessionObjects.php'; 409 $cacheSess = &Horde_SessionObjects::singleton(); 410 $popup_url = Util::addParameter($popup_url, 'passphrase_action', $cacheSess->storeOid($reload, false), false); 411 } 412 } 413 414 if (is_array($params)) { 415 $popup_url = Util::addParameter($popup_url, $params, null, false); 416 } 417 418 return "popup_imp('" . $popup_url . "',450,200);"; 419 } 420 421 /** 422 * Encrypt a MIME_Part using S/MIME using IMP defaults. 423 * 424 * @param MIME_Part $mime_part The MIME_Part object to encrypt. 425 * @param mixed $to_address The e-mail address of the key to use for 426 * encryption. 427 * 428 * @return MIME_Part See Horde_Crypt_smime::encryptMIMEPart(). Returns 429 * PEAR_Error on error. 430 */ 431 function IMPencryptMIMEPart($mime_part, $to_address) 432 { 433 $params = $this->_encryptParameters($to_address); 434 if (is_a($params, 'PEAR_Error')) { 435 return $params; 436 } 437 return $this->encryptMIMEPart($mime_part, $params); 438 } 439 440 /** 441 * Sign a MIME_Part using S/MIME using IMP defaults. 442 * 443 * @param MIME_Part $mime_part The MIME_Part object to sign. 444 * 445 * @return MIME_Part See Horde_Crypt_smime::signMIMEPart(). Returns 446 * PEAR_Error on error. 447 */ 448 function IMPsignMIMEPart($mime_part) 449 { 450 return $this->signMIMEPart($mime_part, $this->_signParameters()); 451 } 452 453 /** 454 * Sign and encrypt a MIME_Part using S/MIME using IMP defaults. 455 * 456 * @acccess public 457 * 458 * @param MIME_Part $mime_part The MIME_Part object to sign and encrypt. 459 * @param string $to_address The e-mail address of the key to use for 460 * encryption. 461 * 462 * @return MIME_Part See Horde_Crypt_smime::signAndencryptMIMEPart(). 463 * Returns PEAR_Error on error. 464 */ 465 function IMPsignAndEncryptMIMEPart($mime_part, $to_address) 466 { 467 $encrypt_params = $this->_encryptParameters($to_address); 468 if (is_a($encrypt_params, 'PEAR_Error')) { 469 return $encrypt_params; 470 } 471 return $this->signAndEncryptMIMEPart($mime_part, $this->_signParameters(), $encrypt_params); 472 } 473 474 /** 475 * Store the public/private/additional certificates in the preferences 476 * from a given PKCS 12 file. 477 * 478 * @acccess public 479 * 480 * @param string $pkcs12 The PKCS 12 data. 481 * @param string $password The password of the PKCS 12 file. 482 * @param string $pkpass The password to use to encrypt the private key. 483 * 484 * @return boolean True on success, PEAR_Error on error. 485 */ 486 function addFromPKCS12($pkcs12, $password, $pkpass = null) 487 { 488 $openssl = IMP_SMIME::checkForOpenSSL(); 489 if (is_a($openssl, 'PEAR_Error')) { 490 return $openssl; 491 } 492 493 $sslpath = (empty($GLOBALS['conf']['utils']['openssl_binary'])) ? null : $GLOBALS['conf']['utils']['openssl_binary']; 494 $params = array('sslpath' => $sslpath, 'password' => $password); 495 if (!empty($pkpass)) { 496 $params['newpassword'] = $pkpass; 497 } 498 $res = $this->parsePKCS12Data($pkcs12, $params); 499 if (is_a($res, 'PEAR_Error')) { 500 return $res; 501 } 502 503 $this->addPersonalPrivateKey($res->private); 504 $this->addPersonalPublicKey($res->public); 505 $this->addAdditionalCert($res->certs); 506 507 return true; 508 } 509 510 /** 511 * Extract the contents from signed S/MIME data. 512 * 513 * @param string $data The signed S/MIME data. 514 * 515 * @return string The contents embedded in the signed data. 516 * Returns PEAR_Error on error. 517 */ 518 function extractSignedContents($data) 519 { 520 $sslpath = (empty($GLOBALS['conf']['utils']['openssl_binary'])) ? null : $GLOBALS['conf']['utils']['openssl_binary']; 521 return parent::extractSignedContents($data, $sslpath); 522 } 523 524 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 12:30:07 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |