mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-08 17:07:03 +03:00
#89 DoMessagePgpVerify() succeeds with GnuPG
This commit is contained in:
parent
bf84684965
commit
d35473841f
3 changed files with 101 additions and 62 deletions
|
|
@ -658,82 +658,67 @@ trait Messages
|
||||||
$iUid = (int) $this->GetActionParam('Uid', 0);
|
$iUid = (int) $this->GetActionParam('Uid', 0);
|
||||||
$sBodyPartId = $this->GetActionParam('BodyPartId', '');
|
$sBodyPartId = $this->GetActionParam('BodyPartId', '');
|
||||||
$sSigPartId = $this->GetActionParam('SigPartId', '');
|
$sSigPartId = $this->GetActionParam('SigPartId', '');
|
||||||
$sMicAlg = $this->GetActionParam('MicAlg', '');
|
// $sMicAlg = $this->GetActionParam('MicAlg', '');
|
||||||
|
|
||||||
$oAccount = $this->initMailClientConnection();
|
$oAccount = $this->initMailClientConnection();
|
||||||
|
|
||||||
$oImapClient = $this->MailClient()->ImapClient();
|
$oImapClient = $this->MailClient()->ImapClient();
|
||||||
$oImapClient->FolderExamine($sFolderName);
|
$oImapClient->FolderExamine($sFolderName);
|
||||||
|
|
||||||
$aFetchResponse = $oImapClient->Fetch([
|
$oFetchResponse = $oImapClient->Fetch([
|
||||||
// An empty section specification refers to the entire message, including the header.
|
// 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].
|
// But Dovecot does not return it with BODY.PEEK[1], so we also use BODY.PEEK[1.MIME].
|
||||||
FetchType::BODY_PEEK.'['.$sBodyPartId.'.MIME]',
|
FetchType::BODY_PEEK.'['.$sBodyPartId.'.MIME]',
|
||||||
FetchType::BODY_PEEK.'['.$sBodyPartId.']',
|
FetchType::BODY_PEEK.'['.$sBodyPartId.']',
|
||||||
FetchType::BODY_PEEK.'['.$sSigPartId.']',
|
FetchType::BODY_PEEK.'['.$sSigPartId.']'
|
||||||
FetchType::BuildBodyCustomHeaderRequest([
|
], $iUid, true)[0];
|
||||||
\MailSo\Mime\Enumerations\Header::FROM_,
|
|
||||||
], true)
|
|
||||||
], $iUid, true);
|
|
||||||
|
|
||||||
$oFetchResponse = $aFetchResponse[0];
|
|
||||||
|
|
||||||
$sKey = '';
|
|
||||||
$sFrom = $oFetchResponse->GetFetchValue('BODY[HEADER.FIELDS (FROM)]');
|
|
||||||
$aFrom = [];
|
|
||||||
if (\preg_match('/[^\\s<>]+@[^\\s<>]+/', $sFrom, $aFrom)) {
|
|
||||||
$sFrom = $aFrom[0];
|
|
||||||
}
|
|
||||||
if ($sFrom) {
|
|
||||||
/* // Check expired/revoked
|
|
||||||
$aKey = $this->StorageProvider()->Get(
|
|
||||||
$oAccount,
|
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::PGP,
|
|
||||||
\sha1($sFrom)
|
|
||||||
);
|
|
||||||
if ($aKey) {
|
|
||||||
$sKey = $aKeys[0]['key'];
|
|
||||||
} else
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
$aKeys = \SnappyMail\PGP\Keyservers::index($sFrom);
|
|
||||||
if ($aKeys) {
|
|
||||||
$sKey = \SnappyMail\PGP\Keyservers::get($aKeys[0]['keyid']);
|
|
||||||
if ($sKey) {
|
|
||||||
$aKeys[0]['key'] = $sKey;
|
|
||||||
/*
|
|
||||||
$this->StorageProvider()->Put(
|
|
||||||
$oAccount,
|
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::PGP,
|
|
||||||
\sha1($sFrom),
|
|
||||||
$aKeys[0]
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = [
|
$result = [
|
||||||
'MIME' => \trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sBodyPartId.'.MIME]')),
|
'Text' => \preg_replace('/\\R/s', "\r\n",
|
||||||
'Body' => \trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sBodyPartId.']')),
|
$oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sBodyPartId.'.MIME]')
|
||||||
'Signature' => \trim($oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sSigPartId.']')),
|
. $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sBodyPartId.']')
|
||||||
'From' => $sFrom,
|
),
|
||||||
'PubKey' => $sKey
|
'Signature' => preg_replace('/[^\x00-\x7F]/', '',
|
||||||
|
$oFetchResponse->GetFetchValue(FetchType::BODY.'['.$sSigPartId.']')
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: this fails
|
if (\class_exists('gnupg')) {
|
||||||
if ($result['PubKey'] && \class_exists('gnupg')) {
|
$info = $this->GnuPG()->verify($result['Text'], $result['Signature'])[0];
|
||||||
$pgp_dir = $this->StorageProvider()->GenerateFilePath($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::PGP);
|
|
||||||
$gpg = new \gnupg(['home_dir' => \dirname($pgp_dir) . '/.gnupg']);
|
/**
|
||||||
$gpg->import($result['PubKey']);
|
* https://code.woboq.org/qt5/include/gpg-error.h.html
|
||||||
$info = $gpg->verify(
|
* status:
|
||||||
\trim(\trim($result['MIME']) . "\r\n\r\n" . \trim($result['Body'])),
|
0 = GPG_ERR_NO_ERROR
|
||||||
$result['Signature']
|
9 = GPG_ERR_NO_PUBKEY
|
||||||
);
|
117440513 = General error
|
||||||
$result['gnupg'] = $info;
|
117440520 = Bad signature
|
||||||
|
*/
|
||||||
|
|
||||||
|
$summary = [
|
||||||
|
GNUPG_SIGSUM_VALID => 'The signature is fully valid.',
|
||||||
|
GNUPG_SIGSUM_GREEN => 'The signature is good but one might want to display some extra information. Check the other bits.',
|
||||||
|
GNUPG_SIGSUM_RED => 'The signature is bad. It might be useful to check other bits and display more information, i.e. a revoked certificate might not render a signature invalid when the message was received prior to the cause for the revocation.',
|
||||||
|
GNUPG_SIGSUM_KEY_REVOKED => 'The key or at least one certificate has been revoked.',
|
||||||
|
GNUPG_SIGSUM_KEY_EXPIRED => 'The key or one of the certificates has expired. It is probably a good idea to display the date of the expiration.',
|
||||||
|
GNUPG_SIGSUM_SIG_EXPIRED => 'The signature has expired.',
|
||||||
|
GNUPG_SIGSUM_KEY_MISSING => 'Can’t verify due to a missing key or certificate.',
|
||||||
|
GNUPG_SIGSUM_CRL_MISSING => 'The CRL (or an equivalent mechanism) is not available.',
|
||||||
|
GNUPG_SIGSUM_CRL_TOO_OLD => 'Available CRL is too old.',
|
||||||
|
GNUPG_SIGSUM_BAD_POLICY => 'A policy requirement was not met.',
|
||||||
|
GNUPG_SIGSUM_SYS_ERROR => 'A system error occurred.',
|
||||||
|
// GNUPG_SIGSUM_TOFU_CONFLICT = 'A TOFU conflict was detected.',
|
||||||
|
];
|
||||||
|
|
||||||
|
$result['Result'] = [
|
||||||
|
'fingerprint' => $info['fingerprint'],
|
||||||
|
'validity' => $info['validity'],
|
||||||
|
'status' => $info['status'],
|
||||||
|
'summary' => $info['summary'],
|
||||||
|
'message' => \implode("\n", \array_filter($summary, function($k) use ($info) {
|
||||||
|
return $info['summary'] & $k;
|
||||||
|
}, ARRAY_FILTER_USE_KEY))
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->DefaultResponse(__FUNCTION__, $result);
|
return $this->DefaultResponse(__FUNCTION__, $result);
|
||||||
|
|
|
||||||
53
snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php
Normal file
53
snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RainLoop\Actions;
|
||||||
|
|
||||||
|
trait Pgp
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws \MailSo\Base\Exceptions\Exception
|
||||||
|
*/
|
||||||
|
public function GnuPG() : ?\gnupg
|
||||||
|
{
|
||||||
|
if (\class_exists('gnupg')) {
|
||||||
|
$pgp_dir = $this->StorageProvider()->GenerateFilePath(
|
||||||
|
$this->getAccountFromToken(),
|
||||||
|
\RainLoop\Providers\Storage\Enumerations\StorageType::PGP
|
||||||
|
);
|
||||||
|
return new \gnupg(['home_dir' => \dirname($pgp_dir) . '/.gnupg']);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function DoImportKey() : array
|
||||||
|
{
|
||||||
|
$sKeyId = $this->GetActionParam('KeyId', '');
|
||||||
|
$sPublicKey = $this->GetActionParam('PublicKey', '');
|
||||||
|
$sEmail = $this->GetActionParam('Email', '');
|
||||||
|
|
||||||
|
if (!$sPublicKey) {
|
||||||
|
try {
|
||||||
|
if (!$sKeyId) {
|
||||||
|
if (\preg_match('/[^\\s<>]+@[^\\s<>]+/', $sEmail, $aMatch)) {
|
||||||
|
$sEmail = $aMatch[0];
|
||||||
|
}
|
||||||
|
if ($sEmail) {
|
||||||
|
$aKeys = \SnappyMail\PGP\Keyservers::index($sEmail);
|
||||||
|
if ($aKeys) {
|
||||||
|
$sKeyId = $aKeys[0]['keyid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($sKeyId) {
|
||||||
|
$sPublicKey = \SnappyMail\PGP\Keyservers::get($sKeyId);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sPublicKey
|
||||||
|
? $this->DefaultResponse(__FUNCTION__, $this->GnuPG()->import($sPublicKey))
|
||||||
|
: $this->FalseResponse(__FUNCTION__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ trait User
|
||||||
use Filters;
|
use Filters;
|
||||||
use Folders;
|
use Folders;
|
||||||
use Messages;
|
use Messages;
|
||||||
|
use Pgp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \RainLoop\Providers\Suggestions
|
* @var \RainLoop\Providers\Suggestions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue