From e49405cd8514d3d85b0b97e8da79d32c35fb97ff Mon Sep 17 00:00:00 2001 From: djmaze Date: Wed, 19 May 2021 15:26:10 +0200 Subject: [PATCH] Improved broken PGP implementation --- dev/Stores/User/Message.js | 15 +- dev/Stores/User/Pgp.js | 4 +- dev/Styles/MessageView.less | 6 +- .../libraries/MailSo/Imap/FetchResponse.php | 27 +-- .../app/libraries/MailSo/Mail/MailClient.php | 59 ++--- .../app/libraries/MailSo/Mail/Message.php | 219 +++++------------- .../libraries/RainLoop/Actions/Response.php | 1 + 7 files changed, 101 insertions(+), 230 deletions(-) diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index dad13f42a..1a570831e 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -435,7 +435,6 @@ export const MessageUserStore = new class { id = '', plain = '', resultHtml = '', - pgpSigned = false, messagesDom = this.messagesBodiesDom(), selectedMessage = this.selectorMessageSelected(), message = this.message(); @@ -495,27 +494,17 @@ export const MessageUserStore = new class { if ((message.isPgpSigned() || message.isPgpEncrypted()) && PgpUserStore.capaOpenPGP()) { plain = pString(json.Plain); - - const isPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(plain); - if (!isPgpEncrypted) { - pgpSigned = - /-----BEGIN PGP SIGNED MESSAGE-----/.test(plain) && /-----BEGIN PGP SIGNATURE-----/.test(plain); - } - const pre = createElement('pre'); - if (pgpSigned && message.isPgpSigned()) { + if (message.isPgpSigned()) { pre.className = 'b-plain-openpgp signed'; pre.textContent = plain; - } else if (isPgpEncrypted && message.isPgpEncrypted()) { + } else if (message.isPgpEncrypted()) { pre.className = 'b-plain-openpgp encrypted'; pre.textContent = plain; } else { pre.innerHTML = resultHtml; } resultHtml = pre.outerHTML; - - message.isPgpSigned(pgpSigned); - message.isPgpEncrypted(isPgpEncrypted); } else { resultHtml = '
' + resultHtml + '
'; } diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index 89d4baddf..85dc32633 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -355,10 +355,10 @@ export const PgpUserStore = new class { verControl = Element.fromHTML('
🔒
'); if (encrypted) { verControl.title = i18n('MESSAGE/PGP_ENCRYPTED_MESSAGE_DESC'); - verControl.addEventHandler('click', domControlEncryptedClickHelper(this, dom, domText, recipients)); + verControl.addEventListener('click', domControlEncryptedClickHelper(this, dom, domText, recipients)); } else { verControl.title = i18n('MESSAGE/PGP_SIGNED_MESSAGE_DESC'); - verControl.addEventHandler('click', domControlSignedClickHelper(this, dom, domText)); + verControl.addEventListener('click', domControlSignedClickHelper(this, dom, domText)); } dom.before(verControl, createElement('div')); diff --git a/dev/Styles/MessageView.less b/dev/Styles/MessageView.less index 2da9f6dc6..7971ce0f9 100644 --- a/dev/Styles/MessageView.less +++ b/dev/Styles/MessageView.less @@ -438,19 +438,21 @@ display: inline-block; cursor: pointer; - color: #777; + opacity: 0.5; &:hover { - color: #111; + opacity: 1; } &.success { color: green; cursor: help; + opacity: 1; } &.error { color: red; + opacity: 1; } } } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FetchResponse.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FetchResponse.php index 32bf8d00d..00a1d0b75 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FetchResponse.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FetchResponse.php @@ -104,31 +104,24 @@ class FetchResponse */ public function GetFetchValue(string $sFetchItemName) { - $mReturn = null; - $bNextIsValue = false; - - if (Enumerations\FetchType::INDEX === $sFetchItemName) - { - $mReturn = $this->oImapResponse->ResponseList[1]; + if (Enumerations\FetchType::INDEX === $sFetchItemName) { + return $this->oImapResponse->ResponseList[1]; } - else if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3])) - { - foreach ($this->oImapResponse->ResponseList[3] as $mItem) - { - if ($bNextIsValue) - { - $mReturn = $mItem; - break; + + if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3])) { + $bNextIsValue = false; + foreach ($this->oImapResponse->ResponseList[3] as $mItem) { + if ($bNextIsValue) { + return $mItem; } - if ($sFetchItemName === $mItem) - { + if ($sFetchItemName === $mItem) { $bNextIsValue = true; } } } - return $mReturn; + return null; } public function GetHeaderFieldsValue(string $sRfc822SubMimeIndex = '') : string diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 751dbae41..e066a7ec7 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -281,31 +281,6 @@ class MailClient $oBodyStructure = null; $oMessage = null; - $aBodyPeekMimeIndexes = array(); - $aSignatureMimeIndexes = array(); - - $aFetchResponse = $this->oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid); - if (0 < \count($aFetchResponse) && isset($aFetchResponse[0])) - { - $oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure(); - if ($oBodyStructure) - { - foreach ($oBodyStructure->SearchHtmlOrPlainParts() as $oPart) - { - $aBodyPeekMimeIndexes[] = array($oPart->PartID(), $oPart->Size()); - } - - $aSignatureParts = $oBodyStructure->SearchByContentType('application/pgp-signature'); - if (is_array($aSignatureParts) && 0 < \count($aSignatureParts)) - { - foreach ($aSignatureParts as $oPart) - { - $aSignatureMimeIndexes[] = $oPart->PartID(); - } - } - } - } - $aFetchItems = array( \MailSo\Imap\Enumerations\FetchType::INDEX, \MailSo\Imap\Enumerations\FetchType::UID, @@ -315,25 +290,31 @@ class MailClient $this->getEnvelopeOrHeadersRequestString() ); - if (0 < \count($aBodyPeekMimeIndexes)) + $aFetchResponse = $this->oImapClient->Fetch(array(\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid); + if (0 < \count($aFetchResponse) && isset($aFetchResponse[0])) { - foreach ($aBodyPeekMimeIndexes as $aTextMimeData) + $oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure(); + if ($oBodyStructure) { - $sLine = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$aTextMimeData[0].']'; - if (0 < $iBodyTextLimit && $iBodyTextLimit < $aTextMimeData[1]) + foreach ($oBodyStructure->SearchHtmlOrPlainParts() as $oPart) { - $sLine .= "<0.{$iBodyTextLimit}>"; + $sLine = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$oPart->PartID().']'; + if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size()) + { + $sLine .= "<0.{$iBodyTextLimit}>"; + } + + $aFetchItems[] = $sLine; } - $aFetchItems[] = $sLine; - } - } - - if (0 < \count($aSignatureMimeIndexes)) - { - foreach ($aSignatureMimeIndexes as $sTextMimeIndex) - { - $aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$sTextMimeIndex.']'; + $aSignatureParts = $oBodyStructure->SearchByContentType('application/pgp-signature'); + if (is_array($aSignatureParts) && 0 < \count($aSignatureParts)) + { + foreach ($aSignatureParts as $oPart) + { + $aFetchItems[] = \MailSo\Imap\Enumerations\FetchType::BODY_PEEK.'['.$oPart->PartID().']'; + } + } } } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php index a3c232b01..6150ca569 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php @@ -31,157 +31,61 @@ class Message implements \JsonSerializable $iHeaderTimeStampInUTC = 0, $sHeaderDate = '', $aFlags = [], - $aFlagsLowerCase = []; + $aFlagsLowerCase = [], - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oFrom; + /** + * @var \MailSo\Mime\EmailCollection + */ + $oFrom = null, + $oSender = null, + $oReplyTo = null, + $oDeliveredTo = null, + $oTo = null, + $oCc = null, + $oBcc = null, - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oSender; + $sInReplyTo = '', - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oReplyTo; + $sPlain = '', + $sHtml = '', - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oDeliveredTo; + /** + * @var AttachmentCollection + */ + $oAttachments = null, - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oTo; + /** + * @var array + */ + $aDraftInfo = null, - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oCc; + $sReferences = '', - /** - * @var \MailSo\Mime\EmailCollection - */ - private $oBcc; + /** + * @var int + */ + $iSensitivity, + $iPriority, - /** - * @var string - */ - private $sInReplyTo; + $sDeliveryReceipt = '', - /** - * @var string - */ - private $sPlain; + $sReadReceipt = '', - /** - * @var string - */ - private $sHtml; + $aUnsubsribeLinks = array(), - /** - * @var AttachmentCollection - */ - private $oAttachments; + $aThreads = array(), - /** - * @var array - */ - private $aDraftInfo; + $bTextPartIsTrimmed = false, - /** - * @var string - */ - private $sReferences; - - /** - * @var int - */ - private $iSensitivity; - - /** - * @var int - */ - private $iPriority; - - /** - * @var string - */ - private $sDeliveryReceipt; - - /** - * @var string - */ - private $sReadReceipt; - - /** - * @var array - */ - private $aUnsubsribeLinks; - - /** - * @var array - */ - private $aThreads; - - /** - * @var bool - */ - private $bTextPartIsTrimmed; - - /** - * @var string - */ - private $sPgpSignature; - - /** - * @var bool - */ - private $bPgpSigned; - - /** - * @var bool - */ - private $bPgpEncrypted; + $sPgpSignature = '', + $sPgpSignatureMicAlg = '', + $bPgpSigned = false, + $bPgpEncrypted = false; function __construct() { - $this->oFrom = null; - $this->oSender = null; - $this->oReplyTo = null; - $this->oDeliveredTo = null; - $this->oTo = null; - $this->oCc = null; - $this->oBcc = null; - - $this->sPlain = ''; - $this->sHtml = ''; - - $this->oAttachments = null; - $this->aDraftInfo = null; - - $this->sInReplyTo = ''; - $this->sReferences = ''; - $this->aUnsubsribeLinks = array(); - $this->iSensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING; $this->iPriority = \MailSo\Mime\Enumerations\MessagePriority::NORMAL; - $this->sDeliveryReceipt = ''; - $this->sReadReceipt = ''; - - $this->aThreads = array(); - - $this->bTextPartIsTrimmed = false; - - $this->sPgpSignature = ''; - $this->bPgpSigned = false; - $this->bPgpEncrypted = false; - - return $this; } public function Plain() : string @@ -199,6 +103,11 @@ class Message implements \JsonSerializable return $this->sPgpSignature; } + public function PgpSignatureMicAlg() : string + { + return $this->sPgpSignatureMicAlg; + } + public function isPgpSigned() : bool { return $this->bPgpSigned; @@ -611,6 +520,24 @@ class Message implements \JsonSerializable $this->sInReplyTo = $oFetchResponse->GetFetchEnvelopeValue(8, ''); } + // Content-Type: multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature" + if ('multipart/signed' === \strtolower($this->sContentType) + && 'application/pgp-signature' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL))) + { + $aPgpSignatureParts = $oBodyStructure ? $oBodyStructure->SearchByContentType('application/pgp-signature') : null; + if ($this->bPgpSigned = !empty($aPgpSignatureParts)) { + $sPgpSignatureText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$aPgpSignatureParts[0]->PartID().']'); + if (\is_string($sPgpSignatureText) && 0 < \strlen($sPgpSignatureText) && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) { + $this->sPgpSignature = \trim($sPgpSignatureText); + $this->sPgpSignatureMicAlg = (string) $oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'micalg'); + } + } + } + + // Content-Type: multipart/encrypted; protocol="application/pgp-encrypted" + $this->bPgpEncrypted = ('multipart/encrypted' === \strtolower($this->sContentType) + && 'application/pgp-encrypted' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL))); + $aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : null; if ($aTextParts) { @@ -674,39 +601,17 @@ class Message implements \JsonSerializable } $aMatch = array(); - if (\preg_match('/-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0])) + if (!$this->bPgpSigned && \preg_match('/-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0])) { $this->sPgpSignature = \trim($aMatch[0]); $this->bPgpSigned = true; } - $aMatch = array(); - if (\preg_match('/-----BEGIN PGP MESSAGE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0])) - { - $this->bPgpEncrypted = true; - } + $this->bPgpEncrypted = !$this->bPgpEncrypted && false !== \stripos($this->sPlain, '-----BEGIN PGP MESSAGE-----'); unset($aHtmlParts, $aPlainParts, $aMatch); } -// if (empty($this->sPgpSignature) && 'multipart/signed' === \strtolower($this->sContentType) && -// 'application/pgp-signature' === \strtolower($oHeaders->ParameterValue( -// \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, -// \MailSo\Mime\Enumerations\Parameter::PROTOCOL -// ))) -// { -// $aPgpSignatureParts = $oBodyStructure ? $oBodyStructure->SearchByContentType('application/pgp-signature') : null; -// if (\is_array($aPgpSignatureParts) && 0 < \count($aPgpSignatureParts) && isset($aPgpSignatureParts[0])) -// { -// $sPgpSignatureText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$aPgpSignatureParts[0]->PartID().']'); -// if (\is_string($sPgpSignatureText) && 0 < \strlen($sPgpSignatureText) && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) -// { -// $this->sPgpSignature = \trim($sPgpSignatureText); -// $this->bPgpSigned = true; -// } -// } -// } - if ($oBodyStructure) { $aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts(); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php index e34c43f94..f26a3bf2e 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php @@ -323,6 +323,7 @@ trait Response $mResult['isPgpSigned'] = $mResponse->isPgpSigned(); $mResult['isPgpEncrypted'] = $mResponse->isPgpEncrypted(); $mResult['PgpSignature'] = $mResponse->PgpSignature(); + $mResult['PgpSignatureMicAlg'] = $mResponse->PgpSignatureMicAlg(); unset($sHtml, $sPlain);