File: //usr/local/CyberCP/public/snappymail/snappymail/v/2.38.2/app/libraries/RainLoop/Actions/SMime.php
<?php
namespace RainLoop\Actions;
use SnappyMail\SMime\OpenSSL;
use SnappyMail\SMime\Certificate;
use MailSo\Imap\Enumerations\FetchType;
trait SMime
{
private $SMIME = null;
public function SMIME() : OpenSSL
{
if (!$this->SMIME) {
$oAccount = $this->getMainAccountFromToken();
if (!$oAccount) {
return null;
}
$homedir = \rtrim($this->StorageProvider()->GenerateFilePath(
$oAccount,
\RainLoop\Providers\Storage\Enumerations\StorageType::ROOT
), '/') . '/.smime';
\MailSo\Base\Utils::mkdir($homedir);
if (!\is_writable($homedir)) {
throw new \Exception("smime homedir '{$homedir}' not writable");
}
$this->SMIME = new OpenSSL($homedir);
}
return $this->SMIME;
}
public function DoGetSMimeCertificate() : array
{
$result = [
'key' => '',
'pkey' => '',
'cert' => ''
];
return $this->DefaultResponse(\array_values(\array_unique($result)));
}
// Like DoGnupgGetKeys
public function DoSMimeGetCertificates() : array
{
return $this->DefaultResponse(
$this->SMIME()->certificates()
);
}
/**
* Can be used by Identity
*/
public function DoSMimeCreateCertificate() : array
{
$oAccount = $this->getAccountFromToken();
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
$cert = new Certificate();
$cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name();
$cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email();
$result = $cert->createSelfSigned($oPassphrase, $this->GetActionParam('privateKey', ''));
return $this->DefaultResponse($result ?: false);
}
public function DoSMimeExportPrivateKey() : array
{
$SMIME = $this->SMIME();
$SMIME->setPrivateKey(
$this->GetActionParam('privateKey'),
new \SnappyMail\SensitiveString($this->GetActionParam('oldPassphrase', ''))
);
$result = $SMIME->exportPrivateKey(
new \SnappyMail\SensitiveString($this->GetActionParam('newPassphrase', ''))
);
return $this->DefaultResponse($result);
}
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', '');
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
$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, $oPassphrase);
$result = $SMIME->decrypt($sBody);
if ($result) {
$result = ['data' => $result];
if (\str_contains($result['data'], 'multipart/signed')
|| \preg_match('/smime-type=["\']?signed-data/', $result['data'])
) {
$signed = $SMIME->verify($result['data'], null, true);
$result['signed'] = [
'success' => !empty($signed['success'])
];
if (!empty($signed['body'])) {
$result['data'] = $signed['body'];
}
}
}
return $this->DefaultResponse($result ?: false);
}
public function DoSMimeVerifyMessage() : array
{
$sBody = $this->GetActionParam('bodyPart', '');
$sPartId = $this->GetActionParam('partId', '');
$bDetached = !empty($this->GetActionParam('detached', 0));
if (!$sBody && $sPartId) {
$iUid = (int) $this->GetActionParam('uid', 0);
// $sMicAlg = $this->GetActionParam('micAlg', '');
$this->initMailClientConnection();
$oImapClient = $this->ImapClient();
$oImapClient->FolderExamine($this->GetActionParam('folder', ''));
$sBody = $oImapClient->FetchMessagePart($iUid, $sPartId);
}
$result = $this->SMIME()->verify($sBody, null, !$bDetached);
// Import the certificates automatically
$sBody = $this->GetActionParam('sigPart', '');
$sPartId = $this->GetActionParam('sigPartId', '') ?: $sPartId;
if (!$sBody && $sPartId && $oImapClient) {
$sBody = $oImapClient->Fetch(
[FetchType::BODY_PEEK.'['.$sPartId.']'],
$iUid,
true
)[0]->GetFetchValue(FetchType::BODY.'['.$sPartId.']');
}
if ($sBody) {
$sBody = \trim($sBody);
$certificates = [];
\openssl_pkcs7_read(
"-----BEGIN PKCS7-----\n\n{$sBody}\n-----END PKCS7-----",
$certificates
) || $this->logWrite("openssl_pkcs7_read: " . \openssl_error_string(), \LOG_ERR, 'OpenSSL');
foreach ($certificates as $certificate) {
$this->SMIME()->storeCertificate($certificate);
}
}
return $this->DefaultResponse($result);
}
public function DoSMimeImportCertificate() : array
{
return $this->DefaultResponse(
$this->SMIME()->storeCertificate(
$this->GetActionParam('pem', '')
)
);
}
public function DoSMimeImportCertificatesFromMessage() : array
{
/*
$sBody = $this->GetActionParam('sigPart', '');
if (!$sBody) {
$sPartId = $this->GetActionParam('sigPartId', '') ?: $this->GetActionParam('partId', '');
$this->initMailClientConnection();
$oImapClient = $this->ImapClient();
$oImapClient->FolderExamine($this->GetActionParam('folder', ''));
$sBody = $oImapClient->Fetch([
FetchType::BODY_PEEK.'['.$sPartId.']'
], (int) $this->GetActionParam('uid', 0), true)[0]
->GetFetchValue(FetchType::BODY.'['.$sPartId.']');
}
$sBody = \trim($sBody);
$certificates = [];
\openssl_pkcs7_read(
"-----BEGIN PKCS7-----\n\n{$sBody}\n-----END PKCS7-----",
$certificates
);
foreach ($certificates as $certificate) {
$this->SMIME()->storeCertificate($certificate);
}
return $this->DefaultResponse($certificates);
*/
}
}