From: Michael M Slusarz Date: Thu, 20 Nov 2008 06:30:25 +0000 (-0700) Subject: Implementation of S/MIME stuff so far. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=e71d363c727d4c6b041bc9c4d6da109549ec60c1;p=horde.git Implementation of S/MIME stuff so far. This doesn't work yet. --- diff --git a/imp/lib/Mime/Viewer/pkcs7.php b/imp/lib/Mime/Viewer/pkcs7.php index 96f590e6f..ce0914a8e 100644 --- a/imp/lib/Mime/Viewer/pkcs7.php +++ b/imp/lib/Mime/Viewer/pkcs7.php @@ -25,93 +25,77 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver { /** - * IMP_SMIME object. + * Can this driver render various views? * - * @var IMP_SMIME - */ - protected $_impSmime; - - /** - * Classwide cache for icons for status messages. - * - * @var string + * @var boolean */ - protected $_icon = null; + protected $_capability = array( + 'embedded' => true, + 'full' => false, + 'info' => false, + 'inline' => true + ); /** - * Pointer to the IMP_Contents item. + * IMP_Horde_Crypt_smime object. * - * @var IMP_Contents + * @var IMP_Horde_Crypt_smime */ - protected $_contents = null; + protected $_impsmime = null; /** - * Classwide cache for status messages. + * Cache for inline data. * * @var array */ - protected $_status = array(); - - /** - * The MIME_Headers object for the message data. - * - * @var MIME_Headers - */ - protected $_headers; - - /** - * Some mailers set S/MIME messages to always be attachments. However, - * most of the time S/MIME is used to secure the contents of the message, - * so displaying as an attachment makes no sense. Therefore, force - * viewing inline (or at least let Horde_Mime_Viewer/IMP_Contents make the - * determination on whether the data can be viewed inline or not). - * - * @var boolean - */ - protected $_forceinline = true; + static protected $_inlinecache = array(); /** - * Render out the currently set contents. + * Return the rendered inline version of the Horde_Mime_Part object. * - * @param array $params An array with a reference to a IMP_Contents - * object. - * - * @return string The rendered text in HTML. + * @return array See Horde_Mime_Viewer_Driver::render(). */ - public function render($params) + protected function _renderInline() { - /* Set the IMP_Contents class variable. */ - $this->_contents = &$params[0]; - - $msg = ''; - - if (empty($this->_impSmime)) { - $this->_impSmime = new IMP_SMIME(); + /* Check to see if S/MIME support is available. */ + 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')) { + $this->_impsmime = null; + } } - /* Check to see if S/MIME support is available. */ - $openssl_check = $this->_impSmime->checkForOpenSSL(); - if ($GLOBALS['prefs']->getValue('use_smime') && - !is_a($openssl_check, 'PEAR_Error')) { + if (is_null($this->_impsmime)) { + $this->_impsmime = false; + } else { /* We need to insert JavaScript code now if S/MIME support is - active. */ - $msg = Util::bufferOutput(array('Horde', 'addScriptFile'), 'prototype.js', 'horde', true); - $msg .= Util::bufferOutput(array('Horde', 'addScriptFile'), 'popup.js', 'imp', true); + * active. */ + Horde::addScriptFile('prototype.js', 'horde', true); + Horde::addScriptFile('popup.js', 'imp', true); } - /* Get the type of message now. */ - $type = $this->_getSMIMEType(); - switch ($type) { + switch ($this->_getSMIMEType()) { case 'signed': - $msg .= $this->_outputSMIMESigned(); + return $this->_outputSMIMESigned(); break; case 'encrypted': - $msg .= $this->_outputSMIMEEncrypted(); - break; + return $this->_outputSMIMEEncrypted(); } + } - return $msg; + /** + * If this MIME part can contain embedded MIME parts, and those embedded + * MIME parts exist, return an altered version of the Horde_Mime_Part that + * contains the embedded MIME part information. + * + * @return mixed A Horde_Mime_Part with the embedded MIME part information + * or null if no embedded MIME parts exist. + */ + protected function _getEmbeddedMimeParts() + { } /** @@ -122,7 +106,7 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver */ protected function _outputSMIMEKey() { - if (!$GLOBALS['prefs']->getValue('use_smime')) { + if (empty($this->_impsmime)) { return _("S/MIME support is not enabled."); } else { $mime = &$this->mime_part; @@ -132,15 +116,13 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver $smime_from = $mime->getInformation('smime_from'); $raw_text = "From: $smime_from\n" . $raw_text; } - $sig_result = $this->_impSmime->verifySignature($raw_text); - return $this->_impSmime->certToHTML($sig_result->cert); + $sig_result = $this->_impsmime->verifySignature($raw_text); + return $this->_impsmime->certToHTML($sig_result->cert); } } /** - * Generates HTML output for 'multipart/signed', - * 'application/pkcs7-signature' and - * 'application/x-pkcs7-signature' MIME_Parts. + * Generates HTML output for 'multipart/signed' MIME parts. * * @return string The HTML output. */ @@ -150,118 +132,86 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver return $this->_outputSMIMEKey(); } - $cert = $text = ''; - $mime = &$this->mime_part; - $mimetype = $mime->getType(); - $active = $GLOBALS['prefs']->getValue('use_smime'); + $partlist = array_keys($this->_mimepart->contentTypeMap()); + $base_id = reset($partlist); + $signed_id = next($partlist); + $sig_id = Horde_Mime::mimeIdArithmetic($signed_id, 'next'); + + $ret = array( + $base_id => array( + 'data' => '', + 'status' => array( + array( + 'icon' => Horde::img('mime/encryption.png', 'S/MIME'), + 'text' => array() + ) + ), + 'type' => 'text/html; charset=' . NLS::getCharset() + ), + $sig_id => null + ); + $status = &$ret[$base_id]['status'][0]['text']; - $signenc = $mime->getInformation('smime_signenc'); - if ($signenc) { - $this->_status[] = _("This message has been encrypted via S/MIME."); + if (!$GLOBALS['prefs']->getValue('use_smime')) { + $status[] = _("S/MIME support is not enabled so the digital signature is unable to be verified."); + return $ret; } - $this->_initStatus($this->getIcon($mimetype), _("S/MIME")); - $this->_status[] = _("This message has been digitally signed via S/MIME."); - - if (!$active) { - $this->_status[] = _("S/MIME support is not enabled so the digital signature is unable to be verified."); - } + $status[] = _("This message has been digitally signed via S/MIME."); /* Store S/MIME results in $sig_result. */ - $sig_result = null; - if ($mimetype == 'multipart/signed') { - if (!$signenc) { - if (($mimeID = $mime->getMIMEId())) { - $mime->setContents($this->_contents->getBodyPart($mimeID)); - } else { - $mime->setContents($this->_contents->getBody()); - } - $mime->splitContents(); - } - - /* Data that is signed appears in the first MIME subpart. */ - $signed_part = $mime->getPart($mime->getRelativeMIMEId(1)); - $signed_data = rtrim($signed_part->getCanonicalContents(), "\r"); - $mime_message = Horde_Mime_Message::parseMessage($signed_data); + $raw_text = $this->_getRawSMIMEText(); - /* The S/MIME signature appears in the second MIME subpart. */ - $subpart = $mime->getPart($mime->getRelativeMIMEId(2)); - if (!$subpart || - !in_array($subpart->getType(), array('application/pkcs7-signature', 'application/x-pkcs7-signature'))) { - $this->_status[] = _("This message does not appear to be in the correct S/MIME format."); - } - } elseif (!$active) { - $this->_status[] = _("S/MIME support is not enabled so the contents of this signed message cannot be displayed."); + if ($GLOBALS['prefs']->getValue('smime_verify') || + Util::getFormData('smime_verify_msg')) { + $sig_result = $this->_impsmime->verifySignature($raw_text); + } elseif (isset($_SESSION['imp']['viewmode']) && + ($_SESSION['imp']['viewmode'] == 'imp')) { + // TODO: Fix to work with DIMP + $status[] = Horde::link(Util::addParameter(Horde::selfUrl(true), 'smime_verify_msg', 1)) . _("Click HERE to verify the message.") . ''; } - if ($active) { - $raw_text = $this->_getRawSMIMEText(); - if ($signenc && $mime->getInformation('smime_from')) { - $smime_from = $mime->getInformation('smime_from'); - $raw_text = "From: $smime_from\n" . $raw_text; - } - - if ($GLOBALS['prefs']->getValue('smime_verify') || - Util::getFormData('smime_verify_msg')) { - $sig_result = $this->_impSmime->verifySignature($raw_text); - } elseif (isset($_SESSION['imp']['viewmode']) && - ($_SESSION['imp']['viewmode'] == 'imp')) { - // TODO: Fix to work with DIMP - $this->_status[] = Horde::link(Util::addParameter(Horde::selfUrl(true), 'smime_verify_msg', 1)) . _("Click HERE to verify the message.") . ''; + if (!isset($subpart)) { + $msg_data = $this->_impsmime->extractSignedContents($raw_text); + if (is_a($msg_data, 'PEAR_Error')) { + $this->_status[] = $msg_data->getMessage(); + $mime_message = $mime; + } else { + $mime_message = Horde_Mime_Message::parseMessage($msg_data); } + } - if (!isset($subpart)) { - $msg_data = $this->_impSmime->extractSignedContents($raw_text); - if (is_a($msg_data, 'PEAR_Error')) { - $this->_status[] = $msg_data->getMessage(); - $mime_message = $mime; + $text = $this->_outputStatus(); + if (!is_null($sig_result)) { + $text .= $this->_outputSMIMESignatureTest($sig_result->result, $sig_result->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; + } elseif (($from = $this->_headers->getValue('from'))) { + $subject = $from; } else { - $mime_message = Horde_Mime_Message::parseMessage($msg_data); + $subject = null; } - } - - $text = $this->_outputStatus(); - if ($sig_result !== null) { - $text .= $this->_outputSMIMESignatureTest($sig_result->result, $sig_result->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; - } elseif (($from = $this->_headers->getValue('from'))) { - $subject = $from; - } else { - $subject = null; - } - if (isset($subpart) && - !empty($subject) && - $GLOBALS['registry']->hasMethod('contacts/addField') && - $GLOBALS['prefs']->getValue('add_source')) { - $this->_status[] = sprintf(_("The S/MIME certificate of %s: "), @htmlspecialchars($subject, ENT_COMPAT, NLS::getCharset())) . - $this->_contents->linkViewJS($subpart, 'view_attach', _("View"), '', null, array('viewkey' => 1)) . '/' . - Horde::link('#', '', null, null, $this->_impSmime->savePublicKeyURL($sig_result->cert) . ' return false;') . _("Save in your Address Book") . ''; - $text .= $this->_outputStatus(); - } + if (isset($subpart) && + !empty($subject) && + $GLOBALS['registry']->hasMethod('contacts/addField') && + $GLOBALS['prefs']->getValue('add_source')) { + $this->_status[] = sprintf(_("The S/MIME certificate of %s: "), @htmlspecialchars($subject, ENT_COMPAT, NLS::getCharset())) . + $this->_contents->linkViewJS($subpart, 'view_attach', _("View"), '', null, array('viewkey' => 1)) . '/' . + Horde::link('#', '', null, null, $this->_impsmime->savePublicKeyURL($sig_result->cert) . ' return false;') . _("Save in your Address Book") . ''; + $text .= $this->_outputStatus(); } } } - if (isset($mime_message)) { - /* We need to stick the output into a IMP_Contents object. */ - $mc = new IMP_Contents($mime_message, array('download' => 'download_attach', 'view' => 'view_attach'), array(&$this->_contents)); - $mc->buildMessage(); - - $text .= '' . $mc->getMessage(true) . '
'; - } else { - $text = $this->_outputStatus(); - } - - return $text; + return array(); } /** @@ -286,18 +236,18 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver return $this->_outputStatus(); } - if (!$this->_impSmime->getPersonalPrivateKey()) { + if (!$this->_impsmime->getPersonalPrivateKey()) { $this->_status[] = _("No personal private key exists so the message is unable to be decrypted."); return $this->_outputStatus(); } /* Make sure we have a passphrase. */ - $passphrase = $this->_impSmime->getPassphrase(); + $passphrase = $this->_impsmime->getPassphrase(); if ($passphrase === false) { if (isset($_SESSION['imp']['viewmode']) && ($_SESSION['imp']['viewmode'] == 'imp')) { // TODO: Fix to work with DIMP - $url = $this->_impSmime->getJSOpenWinCode('open_passphrase_dialog'); + $url = $this->_impsmime->getJSOpenWinCode('open_passphrase_dialog'); $this->_status[] = Horde::link('#', _("You must enter the passphrase for your S/MIME private key to view this message"), null, null, $url . ' return false;') . '' . _("You must enter the passphrase for your S/MIME private key to view this message") . '.'; $msg .= $this->_outputStatus() . ''; @@ -306,7 +256,7 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver } $raw_text = $this->_getRawSMIMEText(); - $decrypted_data = $this->_impSmime->decryptMessage($raw_text); + $decrypted_data = $this->_impsmime->decryptMessage($raw_text); if (is_a($decrypted_data, 'PEAR_Error')) { $this->_status[] = $decrypted_data->getMessage(); @@ -356,8 +306,6 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver */ protected function _getRawSMIMEText() { - $mime = &$this->mime_part; - $mime->setContents($this->_contents->getBody()); if (is_a($this->_contents, 'IMP_Contents') && (($mime->getMIMEId() == 0) || @@ -381,25 +329,6 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver } } - /* Various formatting helper functions. */ - protected function _initStatus($src, $alt = '') - { - if ($this->_icon === null) { - $this->_icon = Horde::img($src, $alt, 'height="16" width="16"', ''); - } - } - - protected function _outputStatus() - { - $output = ''; - if (!empty($this->_status)) { - $output = $this->formatStatusMsg($this->_status, $this->_icon); - } - $this->_icon = null; - $this->_status = array(); - return $output; - } - /** * Generates HTML output for the S/MIME signature test. * @@ -438,51 +367,23 @@ class IMP_Horde_Mime_Viewer_pkcs7 extends Horde_Mime_Viewer_Driver } /** - * Render out attachment information. - * - * @param array $params An array with a reference to a IMP_Contents - * object. - * - * @return string The rendered text in HTML. - */ - public function renderAttachmentInfo($params) - { - $this->_contents = &$params[0]; - - $type = $this->_getSMIMEType(); - switch ($type) { - case 'signed': - $this->_status[] = _("This message contains an attachment that has been digitally signed via S/MIME."); - break; - - case 'encrypted': - $this->_status[] = _("This message contains an attachment that has been encrypted via S/MIME."); - break; - } - - $this->_status[] = sprintf(_("Click %s to view the attachment in a separate window."), $this->_contents->linkViewJS($this->mime_part, 'view_attach', _("HERE"), _("View attachment in a separate window"))); - $this->_initStatus($this->getIcon($this->mime_part->getType()), _("S/MIME")); - return $this->_outputStatus(); - } - - /** - * Deterimne the S/MIME type of the message. + * Determine the S/MIME type of the message. * * @return string Either 'encrypted' or 'signed'. */ protected function _getSMIMEType() { - $type = $this->mime_part->getType(); - if (in_array($type, array('application/pkcs7-mime', 'application/x-pkcs7-mime'))) { - $smime_type = $this->mime_part->getContentTypeParameter('smime-type'); + switch ($this->_mimepart->getType()) { + case 'application/pkcs7-mime': + case 'application/x-pkcs7-mime': + $smime_type = $this->_mimepart->getContentTypeParameter('smime-type'); if ($smime_type == 'signed-data') { return 'signed'; } elseif (!$smime_type || ($smime_type == 'enveloped-data')) { return 'encrypted'; } - } + break; - switch ($type) { case 'multipart/signed': case 'application/pkcs7-signature': case 'application/x-pkcs7-signature':