From 18d0ba4acb3afcb57f0a6a2078e46e671d7eefde Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 20 Feb 2024 13:04:12 +0100 Subject: [PATCH] Get S/MIME decrypt working for #259 --- dev/View/User/MailBox/MessageView.js | 33 ++++++++++++++- .../app/libraries/RainLoop/Actions/SMime.php | 41 +++++++++++++++++++ .../templates/Views/User/MailMessageView.html | 4 +- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 5f1317def..d4f997f06 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -54,6 +54,9 @@ import { showScreenPopup } from 'Knoin/Knoin'; import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport'; import { GnuPGUserStore } from 'Stores/User/GnuPG'; import { OpenPGPUserStore } from 'Stores/User/OpenPGP'; +import { IdentityUserStore } from 'Stores/User/Identity'; + +import { AskPopupView } from 'View/Popup/Ask'; const oMessageScrollerDom = () => elementById('messageItem') || {}, @@ -619,11 +622,39 @@ export class MailMessageView extends AbstractViewRight { }); } - smimeDecrypt() { + async smimeDecrypt() { /* + $sCertificate = $this->GetActionParam('signCertificate', ''); + $sPrivateKey = $this->GetActionParam('signPrivateKey', ''); + $sPassphrase = $this->GetActionParam('passphrase', ''); + // TODO: find private key and certificate to decrypt const oMessage = currentMessage(); */ + const message = currentMessage(); + let data = message.smimeEncrypted(); // { partId: "1" } + const addresses = message.from.concat(message.to, message.cc, message.bcc).map(item => item.email), + identity = IdentityUserStore.find(item => addresses.includes(item.email())); + if (data && identity) { + data = { ...data }; // clone + data.folder = message.folder; + data.uid = message.uid; +// data.bodyPart = data.bodyPart?.raw; + data.certificate = identity.smimeCertificate(); + data.privateKey = identity.smimeKey(); + if (identity.smimeKey().includes('-----BEGIN ENCRYPTED PRIVATE KEY-----')) { + const pass = await AskPopupView.password('S/MIME private key', 'CRYPTO/DECRYPT'); + data.passphrase = pass?.password; + } + + Remote.post('SMimeDecryptMessage', null, data).then(response => { + if (response?.Result) { + message.smimeDecrypted(true); + MimeToMessage(response.Result, message); + message.html() ? message.viewHtml() : message.viewPlain(); + } + }); + } } smimeVerify(/*self, event*/) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index bc57d77e7..7f29c173e 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -71,6 +71,47 @@ trait SMime return $this->DefaultResponse($result ?: false); } + public function DoSMimeDecryptMessage() : array + { + $sFolderName = $this->GetActionParam('folder', ''); + $iUid = (int) $this->GetActionParam('uid', 0); + $sPartId = $this->GetActionParam('partId', ''); + $sCertificate = $this->GetActionParam('certificate', ''); + $sPrivateKey = $this->GetActionParam('privateKey', ''); + $sPassphrase = $this->GetActionParam('passphrase', ''); + $this->logMask($sPassphrase); + + $this->initMailClientConnection(); + $oImapClient = $this->ImapClient(); + $oImapClient->FolderExamine($sFolderName); + + if ('TEXT' === $sPartId) { + $oFetchResponse = $oImapClient->Fetch([ + FetchType::BODY_PEEK.'['.$sPartId.']', + // An empty section specification refers to the entire message, including the header. + // But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME]. + FetchType::BODY_HEADER_PEEK + ], $iUid, true)[0]; + $sBody = $oFetchResponse->GetFetchValue(FetchType::BODY_HEADER); + } else { + $oFetchResponse = $oImapClient->Fetch([ + FetchType::BODY_PEEK.'['.$sPartId.']', + // An empty section specification refers to the entire message, including the header. + // But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME]. + FetchType::BODY_PEEK.'['.$sPartId.'.MIME]' + ], $iUid, true)[0]; + $sBody = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.'.MIME]'); + } + $sBody .= $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sPartId.']'); + + $SMIME = $this->SMIME(); + $SMIME->setCertificate($sCertificate); + $SMIME->setPrivateKey($sPrivateKey, $sPassphrase); + $result = $SMIME->decrypt($sBody); + + return $this->DefaultResponse($result ?: false); + } + public function DoSMimeVerifyMessage() : array { $sFolderName = $this->GetActionParam('folder', ''); diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index 73e821ed5..97d0022e7 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -307,10 +307,8 @@