⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.50
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-horde
/
imp
/
lib
/
Mime
/
Viewer
/
Edit File: Smime.php
<?php /** * Copyright 2002-2017 Horde LLC (http://www.horde.org/) * * See the enclosed file COPYING for license information (GPL). If you * did not receive this file, see http://www.horde.org/licenses/gpl. * * @category Horde * @copyright 2000-2017 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package IMP */ /** * Renderer for viewing/decrypting of S/MIME v3.2 messages (RFC 5751). * * This class handles the following MIME types: * application/pkcs7-mime * application/x-pkcs7-mime * application/pkcs7-signature (in multipart/signed part) * application/x-pkcs7-signature (in multipart/signed part) * * This class may add the following parameters to the URL: * 'smime_verify_msg' - (boolean) Do verification of S/MIME message. * 'view_smime_key' - (boolean) Display the S/MIME Key. * * @author Mike Cochrane <mike@graftonhall.co.nz> * @author Michael Slusarz <slusarz@horde.org> * @category Horde * @copyright 2000-2017 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package IMP */ class IMP_Mime_Viewer_Smime extends Horde_Mime_Viewer_Base { /** * This driver's display capabilities. * * @var array */ protected $_capability = array( 'full' => false, 'info' => false, 'inline' => true, 'raw' => false ); /** * Metadata for the current viewer/data. * * @var array */ protected $_metadata = array( 'compressed' => false, 'embedded' => true, 'forceinline' => true ); /** * IMP_Crypt_Smime object. * * @var IMP_Crypt_Smime */ protected $_impsmime = null; /** * Init the S/MIME Horde_Crypt object. */ protected function _initSmime() { if (is_null($this->_impsmime) && $GLOBALS['prefs']->getValue('use_smime')) { try { $this->_impsmime = $GLOBALS['injector']->getInstance('IMP_Crypt_Smime'); $this->_impsmime->checkForOpenSSL(); } catch (Horde_Exception $e) { $this->_impsmime = null; } } } /** * Return the rendered inline version of the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInline() { /* Check to see if S/MIME support is available. */ $this->_initSmime(); if ($GLOBALS['injector']->getInstance('Horde_Variables')->view_smime_key) { return $this->_outputSmimeKey(); } $id = $this->_mimepart->getMimeId(); switch ($this->_mimepart->getType()) { case 'multipart/signed': if (!in_array($this->_mimepart->getContentTypeParameter('protocol'), array('application/pkcs7-signature', 'application/x-pkcs7-signature'))) { return array(); } $this->_parseSignedData(true); // Fall-through case 'application/pkcs7-mime': case 'application/x-pkcs7-mime': $cache = $this->getConfigParam('imp_contents')->getViewCache(); if (isset($cache->smime[$id])) { $ret = array( $id => array( 'data' => null, 'status' => $cache->smime[$id]['status'], 'type' => 'text/plain; charset=' . $this->getConfigParam('charset'), 'wrap' => $cache->smime[$id]['wrap'] ) ); if (isset($cache->smime[$id]['sig'])) { $ret[$cache->smime[$id]['sig']] = null; } return $ret; } // Fall-through default: return array(); } } /** * 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() { if (!in_array($this->_mimepart->getType(), array('application/pkcs7-mime', 'application/x-pkcs7-mime'))) { return null; } switch ($this->_getSmimeType($this->_mimepart)) { case 'signed-data': return $this->_parseSignedData(); case 'enveloped-data': return $this->_parseEnvelopedData(); } } /** * Parse enveloped (encrypted) data. * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseEnvelopedData() { $base_id = $this->_mimepart->getMimeId(); /* Initialize inline data. */ $status = new IMP_Mime_Status(_("The data in this part has been encrypted via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array( 'status' => $status, 'wrap' => '' ); /* Is PGP active? */ $this->_initSmime(); if (empty($this->_impsmime)) { $status->addText(_("S/MIME support is not currently enabled so the data is unable to be decrypted.")); return null; } if (!$this->_impsmime->getPersonalPrivateKey()) { $status->addText(_("No personal private key exists so the data is unable to be decrypted.")); return null; } /* Make sure we have a passphrase. */ $passphrase = $this->_impsmime->getPassphrase(); if ($passphrase === false) { $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array( 'type' => 'smimePersonal' )); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase for your S/MIME private key to view this data.") . '</a>'); return null; } $raw_text = $this->_getPartStream($this->_mimepart->getMimeId()); try { $decrypted_data = $this->_impsmime->decryptMessage($this->_mimepart->replaceEOL($raw_text, Horde_Mime_Part::RFC_EOL)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $new_part = Horde_Mime_Part::parseMessage($decrypted_data, array( 'forcemime' => true )); switch ($new_part->getType()) { case 'application/pkcs7-mime': case 'application/x-pkcs7-mime': $signed_data = ($this->_getSmimeType($new_part) === 'signed-data'); break; case 'multipart/signed': $signed_data = true; break; default: $signed_data = false; break; } if ($signed_data) { $hdrs = $this->getConfigParam('imp_contents')->getHeader(); $data = new Horde_Stream_Temp(); $data->add( 'From:' . $hdrs->getValue('from') . "\n" . $decrypted_data ); $new_part->setMetadata('imp-smime-decrypt', $data); $new_part->setContents($decrypted_data, array( 'encoding' => 'binary' )); } return $new_part; } /** * Parse signed data. * * @param boolean $sig_only Only do signature checking? * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseSignedData($sig_only = false) { $partlist = array_keys($this->_mimepart->contentTypeMap()); $base_id = reset($partlist); if (!$data_id = next($partlist)) { $data_id = $base_id; } $sig_id = Horde_Mime::mimeIdArithmetic($data_id, 'next'); /* Initialize inline data. */ $status = new IMP_Mime_Status(_("The data in this part has been digitally signed via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array( 'sig' => $sig_id, 'status' => $status, 'wrap' => 'mimePartWrap' ); if (!$GLOBALS['prefs']->getValue('use_smime')) { $status->addText(_("S/MIME support is not enabled so the digital signature is unable to be verified.")); return null; } $imp_contents = $this->getConfigParam('imp_contents'); $stream = $imp_contents->isEmbedded($base_id) ? $this->_mimepart->getMetadata('imp-smime-decrypt')->stream : $this->_getPartStream($base_id); $raw_text = $this->_mimepart->replaceEOL($stream, Horde_Mime_Part::RFC_EOL); $this->_initSmime(); $sig_result = null; if ($GLOBALS['prefs']->getValue('smime_verify') || $GLOBALS['injector']->getInstance('Horde_Variables')->smime_verify_msg) { try { $sig_result = $this->_impsmime->verifySignature($raw_text); if ($sig_result->verify) { $status->action(IMP_Mime_Status::SUCCESS); } else { $status->action(IMP_Mime_Status::WARNING); } if (!is_array($sig_result->email)) { $sig_result->email = array($sig_result->email); } $email = implode(', ', $sig_result->email); $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $status->addText($sig_result->msg); if (!empty($sig_result->cert)) { $cert = $this->_impsmime->parseCert($sig_result->cert); if (isset($cert['certificate']['subject']['CommonName']) && (strcasecmp($email, $cert['certificate']['subject']['CommonName']) !== 0)) { $email = $cert['certificate']['subject']['CommonName'] . ' (' . trim($email) . ')'; } } if (!empty($sig_result->cert) && isset($sig_result->email) && $GLOBALS['registry']->hasMethod('contacts/addField') && $GLOBALS['prefs']->getValue('add_source')) { $status->addText(sprintf(_("Sender: %s"), $imp_contents->linkViewJS($this->_mimepart, 'view_attach', htmlspecialchars($email), array( 'jstext' => _("View certificate details"), 'params' => array( 'mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1 ) )))); foreach ($sig_result->email as $single_email) { try { $this->_impsmime->getPublicKey($single_email); } catch (Horde_Exception $e) { $imple = $GLOBALS['injector'] ->getInstance('Horde_Core_Factory_Imple') ->create( 'IMP_Ajax_Imple_ImportEncryptKey', array( 'mime_id' => $base_id, 'muid' => strval($imp_contents->getIndicesOb()), 'type' => 'smime' ) ); $status->addText( Horde::link( '#', '', '', '', '', '', '', array('id' => $imple->getDomId()) ) . _("Save the certificate to your Address Book.") . '</a>' ); break; } } } elseif (strlen($email)) { $status->addText(sprintf(_("Sender: %s"), htmlspecialchars($email))); } } catch (Horde_Exception $e) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText($e->getMessage()); } } else { switch ($GLOBALS['registry']->getView()) { case Horde_Registry::VIEW_BASIC: $status->addText(Horde::link(Horde::selfUrlParams()->add('smime_verify_msg', 1)) . _("Click HERE to verify the data.") . '</a>'); break; case Horde_Registry::VIEW_DYNAMIC: $status->addText(Horde::link('#', '', 'smimeVerifyMsg') . _("Click HERE to verify the data.") . '</a>'); break; } } if ($sig_only) { return; } $subpart = $imp_contents->getMIMEPart($sig_id); if (empty($subpart)) { try { $msg_data = $this->_impsmime->extractSignedContents($raw_text); $subpart = Horde_Mime_Part::parseMessage($msg_data, array('forcemime' => true)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } } return $subpart; } /** * Generates HTML output for the S/MIME key. * * @return string The HTML output. */ protected function _outputSmimeKey() { if (empty($this->_impsmime)) { return array(); } $raw_text = $this->_getPartStream($this->_mimepart->getMimeId()); try { $sig_result = $this->_impsmime->verifySignature($this->_mimepart->replaceEOL($raw_text, Horde_Mime_Part::RFC_EOL)); } catch (Horde_Exception $e) { return array(); } return array( $this->_mimepart->getMimeId() => array( 'data' => $this->_impsmime->certToHTML($sig_result->cert), 'type' => 'text/html; charset=' . $this->getConfigParam('charset') ) ); } /** */ protected function _getPartStream($id) { return $id ? $this->getConfigParam('imp_contents')->getBodyPart($id, array('mimeheaders' => true, 'stream' => true))->data : $this->getConfigParam('imp_contents')->fullMessageText(); } /** * Determines the S/MIME type of a part. Uses the smime-type content * parameter (if it exists), and falls back to ASN.1 parsing of data if * it doesn't exist. * * @param Horde_Mime_Part $part MIME part with S/MIME data. * * @return string 'signed-data', 'enveloped-data', or null. */ protected function _getSmimeType(Horde_Mime_Part $part) { if ($type = $part->getContentTypeParameter('smime-type')) { return strtolower($type); } if (!class_exists('File_ASN1')) { return null; } $asn1 = new File_ASN1(); $decoded = $asn1->decodeBER($part->getContents()); foreach ($decoded as $val) { if ($val['type'] == FILE_ASN1_TYPE_SEQUENCE) { foreach ($val['content'] as $val2) { if ($val2['type'] == FILE_ASN1_TYPE_OBJECT_IDENTIFIER) { /* ASN.1 values from STD 70/RFC 5652 - CMS syntax */ switch ($val2['content']) { case '1.2.840.113549.1.7.2': return 'signed-data'; case '1.2.840.113549.1.7.3': return 'enveloped-data'; default: // Other types not supported as of now. return null; } } } } } return null; } }
Simpan