diff --git a/api/src/Mail/Smime.php b/api/src/Mail/Smime.php index 6a2ffc4db2..5c20db7bb7 100644 --- a/api/src/Mail/Smime.php +++ b/api/src/Mail/Smime.php @@ -170,4 +170,80 @@ class Smime extends Horde_Crypt_Smime return false; } } + + /** + * Verify a signature using via S/MIME. + * + * @param string $text The multipart/signed data to be verified. + * @param mixed $certs Either a single or array of root certificates. + * + * @return stdClass Object with the following elements: + *
+ * cert - (string) The certificate of the signer stored in the message (in + * PEM format). + * email - (string) The email of the signing person. + * msg - (string) Status string. + * verify - (boolean) True if certificate was verified. + *+ * @throws Horde_Crypt_Exception + * + * + * @TODO: This method is overridden in order to extract content + * from the signed message. There's a pull request opened for this + * modification on horde github, https://github.com/horde/horde/pull/218 + * which in case that gets merged we need to remove this implementation. + */ + public function verify($text, $certs) + { + /* Check for availability of OpenSSL PHP extension. */ + $this->checkForOpenSSL(); + + /* Create temp files for input/output. */ + $input = $this->_createTempFile('horde-smime'); + $output = $this->_createTempFile('horde-smime'); + $content = $this->_createTempFile('horde-smime'); + + /* Write text to file */ + file_put_contents($input, $text); + unset($text); + + $root_certs = array(); + if (!is_array($certs)) { + $certs = array($certs); + } + foreach ($certs as $file) { + if (file_exists($file)) { + $root_certs[] = $file; + } + } + + $ob = new stdClass; + + if (!empty($root_certs) && + (openssl_pkcs7_verify($input, 0, $output) === true)) { + /* Message verified */ + $ob->msg = Horde_Crypt_Translation::t("Message verified successfully."); + $ob->verify = true; + } else { + /* Try again without verfying the signer's cert */ + $result = openssl_pkcs7_verify($input, PKCS7_NOVERIFY, $output); + + if ($result === -1) { + throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - an unknown error has occurred.")); + } elseif ($result === false) { + throw new Horde_Crypt_Exception(Horde_Crypt_Translation::t("Verification failed - this message may have been tampered with.")); + } + + $ob->msg = Horde_Crypt_Translation::t("Message verified successfully but the signer's certificate could not be verified."); + $ob->verify = false; + } + if (openssl_pkcs7_verify($input, PKCS7_NOVERIFY, $output, array(), $output, $content)) + { + $ob->content = file_get_contents($content); + } + $ob->cert = file_get_contents($output); + $ob->email = $this->getEmailFromKey($ob->cert); + + return $ob; + } } diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index f34f758f78..ebb8921bf5 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -2012,7 +2012,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2); if ($htmlOptions !='always_display') $fetchEmbeddedImages = true; $attachments = $this->mail_bo->getMessageAttachments($uid, $partID, null, $fetchEmbeddedImages,true,true,$mailbox); - $smimeData = $this->resolveSmimeAttachment ($attachments, $uid, $partID, $mailbox, $rowID); + $smimeData = $this->resolveSmimeAttachment ($attachments, $uid, $partID, $mailbox, '', $rowID); if (is_array($smimeData)) { $error_msg[] = $smimeData['msg']; @@ -2104,6 +2104,22 @@ $filter['before']= date("d-M-Y", $cutoffdate2); $etpl->exec('mail.mail_ui.displayMessage',$content,$sel_options,$readonlys,$preserv,2); } + /** + * Parse SMIME signed message + * + * @param string $_message signed message + * @param type $_mailbox mailbox + * @return array + */ + function parseSmimeSignedMessage ($_message, $_mailbox) + { + $structure = Horde_Mime_Part::parseMessage($_message, array('forcemime'=>true)); + return array ( + 'attachments' => $this->mail_bo->getMessageAttachments('',null,$structure,true, false,true,$_mailbox), + 'body' => $this->mail_bo->getMessageBody('', '', null, $structure, false, $_mailbox, $calendar_part = null) + ); + } + /** * decrypt given smime encrypted message * @@ -2143,7 +2159,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2); * @param string $_passphrase * @return array */ - function resolveSmimeAttachment (&$attachments, $_uid, $_partID, $_mailbox, $_passphrase='') + function resolveSmimeAttachment (&$attachments, $_uid, $_partID, $_mailbox, $_passphrase='', $_rowID) { $this->smime = new Mail\Smime; @@ -2170,7 +2186,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2); 'certHtml' => $this->smime->certToHTML($cert->cert), 'partID' => $attachment['partID'], 'signed' => true, - 'message' => $message + 'message' => $cert->content != "" ? $cert->content : $message ); } catch (Exception $ex) {