mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-27 18:18:28 +08:00
Make better use of SnappyMail\SensitiveString
This commit is contained in:
parent
0f7505baba
commit
7cacc9b503
18 changed files with 84 additions and 147 deletions
|
@ -91,7 +91,6 @@ class SnappyMailHelper
|
||||||
*/
|
*/
|
||||||
if ($doLogin && $aCredentials[1] && $aCredentials[2]) {
|
if ($doLogin && $aCredentials[1] && $aCredentials[2]) {
|
||||||
try {
|
try {
|
||||||
$oActions->Logger()->AddSecret($aCredentials[2]);
|
|
||||||
$oAccount = $oActions->LoginProcess($aCredentials[1], $aCredentials[2]);
|
$oAccount = $oActions->LoginProcess($aCredentials[1], $aCredentials[2]);
|
||||||
if ($oAccount) {
|
if ($oAccount) {
|
||||||
// Must be here due to bug #1241
|
// Must be here due to bug #1241
|
||||||
|
@ -202,9 +201,10 @@ class SnappyMailHelper
|
||||||
return \SnappyMail\Crypt::EncryptUrlSafe($sPassword, $sSalt);
|
return \SnappyMail\Crypt::EncryptUrlSafe($sPassword, $sSalt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function decodePassword(string $sPassword, string $sSalt)/* : mixed */
|
public static function decodePassword(string $sPassword, string $sSalt) : ?\SnappyMail\SensitiveString
|
||||||
{
|
{
|
||||||
static::loadApp();
|
static::loadApp();
|
||||||
return \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt);
|
$result = \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt);
|
||||||
|
return $result ? new \SnappyMail\SensitiveString($result) : $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ trait Accounts
|
||||||
$aAccounts = $this->GetAccounts($oMainAccount);
|
$aAccounts = $this->GetAccounts($oMainAccount);
|
||||||
|
|
||||||
$sEmail = \trim($this->GetActionParam('email', ''));
|
$sEmail = \trim($this->GetActionParam('email', ''));
|
||||||
$sPassword = $this->GetActionParam('password', '');
|
$oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('password', ''));
|
||||||
$sName = \trim($this->GetActionParam('name', ''));
|
$sName = \trim($this->GetActionParam('name', ''));
|
||||||
$bNew = !empty($this->GetActionParam('new', 1));
|
$bNew = !empty($this->GetActionParam('new', 1));
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ trait Accounts
|
||||||
throw new ClientException(Notifications::AccountDoesNotExist);
|
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bNew || $sPassword) {
|
if ($bNew || \strlen($oPassword)) {
|
||||||
$oNewAccount = $this->LoginProcess($sEmail, $sPassword, false);
|
$oNewAccount = $this->LoginProcess($sEmail, $oPassword, false);
|
||||||
$aAccounts[$sEmail] = $oNewAccount->asTokenArray($oMainAccount);
|
$aAccounts[$sEmail] = $oNewAccount->asTokenArray($oMainAccount);
|
||||||
} else {
|
} else {
|
||||||
$aAccounts[$sEmail] = \RainLoop\Model\AdditionalAccount::convertArray($aAccounts[$sEmail]);
|
$aAccounts[$sEmail] = \RainLoop\Model\AdditionalAccount::convertArray($aAccounts[$sEmail]);
|
||||||
|
|
|
@ -60,9 +60,9 @@ trait AdminDomains
|
||||||
public function DoAdminDomainMatch() : array
|
public function DoAdminDomainMatch() : array
|
||||||
{
|
{
|
||||||
$sEmail = $this->GetActionParam('username');
|
$sEmail = $this->GetActionParam('username');
|
||||||
$sPassword = '********';
|
$oPassword = new \SnappyMail\SensitiveString('********');
|
||||||
$sLogin = '';
|
$sLogin = '';
|
||||||
$this->resolveLoginCredentials($sEmail, $sPassword, $sLogin);
|
$this->resolveLoginCredentials($sEmail, $oPassword, $sLogin);
|
||||||
$oDomain = \str_contains($sEmail, '@')
|
$oDomain = \str_contains($sEmail, '@')
|
||||||
? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true)
|
? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true)
|
||||||
: null;
|
: null;
|
||||||
|
|
|
@ -1065,8 +1065,7 @@ trait Messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sPassphrase = $this->GetActionParam('signPassphrase', '');
|
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('signPassphrase', ''));
|
||||||
$this->logMask($sPassphrase);
|
|
||||||
|
|
||||||
$sFingerprint = $this->GetActionParam('signFingerprint', '');
|
$sFingerprint = $this->GetActionParam('signFingerprint', '');
|
||||||
if ($sFingerprint) {
|
if ($sFingerprint) {
|
||||||
|
@ -1084,7 +1083,7 @@ trait Messages
|
||||||
$oMessage->SubParts->Clear();
|
$oMessage->SubParts->Clear();
|
||||||
$oMessage->Attachments()->Clear();
|
$oMessage->Attachments()->Clear();
|
||||||
|
|
||||||
$GPG->addSignKey($sFingerprint, $sPassphrase);
|
$GPG->addSignKey($sFingerprint, $oPassphrase);
|
||||||
$GPG->setsignmode(GNUPG_SIG_MODE_DETACH);
|
$GPG->setsignmode(GNUPG_SIG_MODE_DETACH);
|
||||||
$sSignature = $GPG->signStream($fp);
|
$sSignature = $GPG->signStream($fp);
|
||||||
if (!$sSignature) {
|
if (!$sSignature) {
|
||||||
|
@ -1127,7 +1126,7 @@ trait Messages
|
||||||
|
|
||||||
$SMIME = $this->SMIME();
|
$SMIME = $this->SMIME();
|
||||||
$SMIME->setCertificate($sCertificate);
|
$SMIME->setCertificate($sCertificate);
|
||||||
$SMIME->setPrivateKey($sPrivateKey, $sPassphrase);
|
$SMIME->setPrivateKey($sPrivateKey, $oPassphrase);
|
||||||
$sSignature = $SMIME->sign($tmp, $detached);
|
$sSignature = $SMIME->sign($tmp, $detached);
|
||||||
|
|
||||||
if (!$sSignature) {
|
if (!$sSignature) {
|
||||||
|
|
|
@ -113,10 +113,9 @@ trait Pgp
|
||||||
return $this->FalseResponse();
|
return $this->FalseResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sPassphrase = $this->GetActionParam('passphrase', '');
|
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
|
||||||
$this->logMask($sPassphrase);
|
|
||||||
|
|
||||||
$GPG->addDecryptKey($this->GetActionParam('keyId', ''), $sPassphrase);
|
$GPG->addDecryptKey($this->GetActionParam('keyId', ''), $oPassphrase);
|
||||||
|
|
||||||
$sData = $this->GetActionParam('data', '');
|
$sData = $this->GetActionParam('data', '');
|
||||||
$oPart = null;
|
$oPart = null;
|
||||||
|
@ -160,12 +159,13 @@ trait Pgp
|
||||||
|
|
||||||
public function DoGnupgExportKey() : array
|
public function DoGnupgExportKey() : array
|
||||||
{
|
{
|
||||||
$sPassphrase = $this->GetActionParam('passphrase', '');
|
$oPassphrase = $this->GetActionParam('isPrivate', '')
|
||||||
$this->logMask($sPassphrase);
|
? new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''))
|
||||||
|
: null;
|
||||||
$GPG = $this->GnuPG();
|
$GPG = $this->GnuPG();
|
||||||
return $this->DefaultResponse($GPG ? $GPG->export(
|
return $this->DefaultResponse($GPG ? $GPG->export(
|
||||||
$this->GetActionParam('keyId', ''),
|
$this->GetActionParam('keyId', ''),
|
||||||
$sPassphrase
|
$oPassphrase
|
||||||
) : false);
|
) : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,11 +176,10 @@ trait Pgp
|
||||||
if ($GPG) {
|
if ($GPG) {
|
||||||
$sName = $this->GetActionParam('name', '');
|
$sName = $this->GetActionParam('name', '');
|
||||||
$sEmail = $this->GetActionParam('email', '');
|
$sEmail = $this->GetActionParam('email', '');
|
||||||
$sPassphrase = $this->GetActionParam('passphrase', '');
|
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
|
||||||
$this->logMask($sPassphrase);
|
|
||||||
$fingerprint = $GPG->generateKey(
|
$fingerprint = $GPG->generateKey(
|
||||||
$sName ? "{$sName} <{$sEmail}>" : $sEmail,
|
$sName ? "{$sName} <{$sEmail}>" : $sEmail,
|
||||||
$sPassphrase
|
$oPassphrase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return $this->DefaultResponse($fingerprint);
|
return $this->DefaultResponse($fingerprint);
|
||||||
|
|
|
@ -53,19 +53,18 @@ trait SMime
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be use by Identity
|
* Can be used by Identity
|
||||||
*/
|
*/
|
||||||
public function DoSMimeCreateCertificate() : array
|
public function DoSMimeCreateCertificate() : array
|
||||||
{
|
{
|
||||||
$oAccount = $this->getAccountFromToken();
|
$oAccount = $this->getAccountFromToken();
|
||||||
|
|
||||||
$sPassphrase = $this->GetActionParam('passphrase', '');
|
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
|
||||||
$this->logMask($sPassphrase);
|
|
||||||
|
|
||||||
$cert = new Certificate();
|
$cert = new Certificate();
|
||||||
$cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name();
|
$cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name();
|
||||||
$cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email();
|
$cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email();
|
||||||
$result = $cert->createSelfSigned($sPassphrase, $this->GetActionParam('privateKey', ''));
|
$result = $cert->createSelfSigned($oPassphrase, $this->GetActionParam('privateKey', ''));
|
||||||
return $this->DefaultResponse($result ?: false);
|
return $this->DefaultResponse($result ?: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +75,7 @@ trait SMime
|
||||||
$sPartId = $this->GetActionParam('partId', '');
|
$sPartId = $this->GetActionParam('partId', '');
|
||||||
$sCertificate = $this->GetActionParam('certificate', '');
|
$sCertificate = $this->GetActionParam('certificate', '');
|
||||||
$sPrivateKey = $this->GetActionParam('privateKey', '');
|
$sPrivateKey = $this->GetActionParam('privateKey', '');
|
||||||
$sPassphrase = $this->GetActionParam('passphrase', '');
|
$oPassphrase = new \SnappyMail\SensitiveString($this->GetActionParam('passphrase', ''));
|
||||||
$this->logMask($sPassphrase);
|
|
||||||
|
|
||||||
$this->initMailClientConnection();
|
$this->initMailClientConnection();
|
||||||
$oImapClient = $this->ImapClient();
|
$oImapClient = $this->ImapClient();
|
||||||
|
@ -104,7 +102,7 @@ trait SMime
|
||||||
|
|
||||||
$SMIME = $this->SMIME();
|
$SMIME = $this->SMIME();
|
||||||
$SMIME->setCertificate($sCertificate);
|
$SMIME->setCertificate($sCertificate);
|
||||||
$SMIME->setPrivateKey($sPrivateKey, $sPassphrase);
|
$SMIME->setPrivateKey($sPrivateKey, $oPassphrase);
|
||||||
$result = $SMIME->decrypt($sBody);
|
$result = $SMIME->decrypt($sBody);
|
||||||
|
|
||||||
return $this->DefaultResponse($result ?: false);
|
return $this->DefaultResponse($result ?: false);
|
||||||
|
|
|
@ -36,10 +36,10 @@ trait User
|
||||||
public function DoLogin() : array
|
public function DoLogin() : array
|
||||||
{
|
{
|
||||||
$sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', ''));
|
$sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', ''));
|
||||||
$sPassword = $this->GetActionParam('Password', '');
|
$oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', ''));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$oAccount = $this->LoginProcess($sEmail, $sPassword);
|
$oAccount = $this->LoginProcess($sEmail, $oPassword);
|
||||||
} catch (\Throwable $oException) {
|
} catch (\Throwable $oException) {
|
||||||
$this->loginErrorDelay();
|
$this->loginErrorDelay();
|
||||||
throw $oException;
|
throw $oException;
|
||||||
|
|
|
@ -22,10 +22,7 @@ trait UserAuth
|
||||||
/**
|
/**
|
||||||
* @throws \RainLoop\Exceptions\ClientException
|
* @throws \RainLoop\Exceptions\ClientException
|
||||||
*/
|
*/
|
||||||
public function resolveLoginCredentials(string &$sEmail,
|
public function resolveLoginCredentials(string &$sEmail, \SnappyMail\SensitiveString $oPassword, string &$sLogin): void
|
||||||
#[\SensitiveParameter]
|
|
||||||
string &$sPassword,
|
|
||||||
string &$sLogin): void
|
|
||||||
{
|
{
|
||||||
$sEmail = \MailSo\Base\Utils::Trim($sEmail);
|
$sEmail = \MailSo\Base\Utils::Trim($sEmail);
|
||||||
if ($this->Config()->Get('login', 'login_lowercase', true)) {
|
if ($this->Config()->Get('login', 'login_lowercase', true)) {
|
||||||
|
@ -101,43 +98,40 @@ trait UserAuth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sPassword = (string) $oPassword;
|
||||||
$this->Plugins()->RunHook('login.credentials.step-2', array(&$sEmail, &$sPassword));
|
$this->Plugins()->RunHook('login.credentials.step-2', array(&$sEmail, &$sPassword));
|
||||||
|
$this->logMask($sPassword);
|
||||||
|
|
||||||
$sLogin = $sEmail;
|
$sLogin = $sEmail;
|
||||||
if ($this->Config()->Get('login', 'login_lowercase', true)) {
|
if ($this->Config()->Get('login', 'login_lowercase', true)) {
|
||||||
$sLogin = \mb_strtolower($sLogin);
|
$sLogin = \mb_strtolower($sLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logMask($sPassword);
|
|
||||||
$this->Plugins()->RunHook('login.credentials', array(&$sEmail, &$sLogin, &$sPassword));
|
$this->Plugins()->RunHook('login.credentials', array(&$sEmail, &$sLogin, &$sPassword));
|
||||||
$this->logMask($sPassword);
|
$this->logMask($sPassword);
|
||||||
|
|
||||||
|
$oPassword->setValue($sPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \RainLoop\Exceptions\ClientException
|
* @throws \RainLoop\Exceptions\ClientException
|
||||||
*/
|
*/
|
||||||
public function LoginProcess(string &$sEmail,
|
public function LoginProcess(string &$sEmail, \SnappyMail\SensitiveString $oPassword, bool $bMainAccount = true): Account
|
||||||
#[\SensitiveParameter]
|
|
||||||
string &$sPassword,
|
|
||||||
bool $bMainAccount = true
|
|
||||||
): Account
|
|
||||||
{
|
{
|
||||||
$sInputEmail = $sEmail;
|
$sInputEmail = $sEmail;
|
||||||
|
|
||||||
$this->logMask($sPassword);
|
|
||||||
|
|
||||||
$sLogin = '';
|
$sLogin = '';
|
||||||
$this->resolveLoginCredentials($sEmail, $sPassword, $sLogin);
|
$this->resolveLoginCredentials($sEmail, $oPassword, $sLogin);
|
||||||
|
|
||||||
if (!\str_contains($sEmail, '@') || !\strlen($sPassword)) {
|
if (!\str_contains($sEmail, '@') || !\strlen($oPassword)) {
|
||||||
throw new ClientException(Notifications::InvalidInputArgument);
|
throw new ClientException(Notifications::InvalidInputArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oAccount = null;
|
$oAccount = null;
|
||||||
try {
|
try {
|
||||||
$oAccount = $bMainAccount
|
$oAccount = $bMainAccount
|
||||||
? MainAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, true)
|
? MainAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $oPassword, true)
|
||||||
: AdditionalAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $sPassword, true);
|
: AdditionalAccount::NewInstanceFromCredentials($this, $sEmail, $sLogin, $oPassword, true);
|
||||||
if (!$oAccount) {
|
if (!$oAccount) {
|
||||||
throw new ClientException(Notifications::AuthError);
|
throw new ClientException(Notifications::AuthError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,17 +111,15 @@ class ActionsAdmin extends Actions
|
||||||
public function DoAdminLogin() : array
|
public function DoAdminLogin() : array
|
||||||
{
|
{
|
||||||
$sLogin = trim($this->GetActionParam('Login', ''));
|
$sLogin = trim($this->GetActionParam('Login', ''));
|
||||||
$sPassword = $this->GetActionParam('Password', '');
|
$oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', ''));
|
||||||
|
|
||||||
$this->logMask($sPassword);
|
|
||||||
|
|
||||||
$totp = $this->Config()->Get('security', 'admin_totp', '');
|
$totp = $this->Config()->Get('security', 'admin_totp', '');
|
||||||
|
|
||||||
// \explode(':',`getent shadow root`)[1];
|
// \explode(':',`getent shadow root`)[1];
|
||||||
if (!\strlen($sLogin) || !\strlen($sPassword) ||
|
if (!\strlen($sLogin) || !\strlen($oPassword) ||
|
||||||
!$this->Config()->Get('security', 'allow_admin_panel', true) ||
|
!$this->Config()->Get('security', 'allow_admin_panel', true) ||
|
||||||
$sLogin !== $this->Config()->Get('security', 'admin_login', '') ||
|
$sLogin !== $this->Config()->Get('security', 'admin_login', '') ||
|
||||||
!$this->Config()->ValidatePassword($sPassword)
|
!$this->Config()->ValidatePassword($oPassword)
|
||||||
|| ($totp && !\SnappyMail\TOTP::Verify($totp, $this->GetActionParam('TOTP', ''))))
|
|| ($totp && !\SnappyMail\TOTP::Verify($totp, $this->GetActionParam('TOTP', ''))))
|
||||||
{
|
{
|
||||||
$this->LoggerAuthHelper(null, $this->getAdditionalLogParamsByUserLogin($sLogin, true), true);
|
$this->LoggerAuthHelper(null, $this->getAdditionalLogParamsByUserLogin($sLogin, true), true);
|
||||||
|
@ -183,17 +181,13 @@ class ActionsAdmin extends Actions
|
||||||
$bResult = false;
|
$bResult = false;
|
||||||
$oConfig = $this->Config();
|
$oConfig = $this->Config();
|
||||||
|
|
||||||
$sPassword = $this->GetActionParam('Password', '');
|
$oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('Password', ''));
|
||||||
$this->logMask($sPassword);
|
|
||||||
|
|
||||||
$sNewPassword = $this->GetActionParam('newPassword', '');
|
$oNewPassword = new \SnappyMail\SensitiveString($this->GetActionParam('newPassword', ''));
|
||||||
if (\strlen($sNewPassword)) {
|
|
||||||
$this->logMask($sNewPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
$passfile = APP_PRIVATE_DATA.'admin_password.txt';
|
$passfile = APP_PRIVATE_DATA.'admin_password.txt';
|
||||||
|
|
||||||
if ($oConfig->ValidatePassword($sPassword)) {
|
if ($oConfig->ValidatePassword($oPassword)) {
|
||||||
$sLogin = \trim($this->GetActionParam('Login', ''));
|
$sLogin = \trim($this->GetActionParam('Login', ''));
|
||||||
if (\strlen($sLogin)) {
|
if (\strlen($sLogin)) {
|
||||||
$oConfig->Set('security', 'admin_login', $sLogin);
|
$oConfig->Set('security', 'admin_login', $sLogin);
|
||||||
|
@ -201,9 +195,9 @@ class ActionsAdmin extends Actions
|
||||||
|
|
||||||
$oConfig->Set('security', 'admin_totp', $this->GetActionParam('TOTP', ''));
|
$oConfig->Set('security', 'admin_totp', $this->GetActionParam('TOTP', ''));
|
||||||
|
|
||||||
if (\strlen($sNewPassword)) {
|
if (\strlen($oNewPassword)) {
|
||||||
$oConfig->SetPassword($sNewPassword);
|
$oConfig->SetPassword($oNewPassword);
|
||||||
if (\is_file($passfile) && \trim(\file_get_contents($passfile)) !== $sNewPassword) {
|
if (\is_file($passfile) && \trim(\file_get_contents($passfile)) !== (string) $oNewPassword) {
|
||||||
\unlink($passfile);
|
\unlink($passfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,25 +120,14 @@ class Application extends \RainLoop\Config\AbstractConfig
|
||||||
parent::Set($sSectionKey, $sParamKey, $mParamValue);
|
parent::Set($sSectionKey, $sParamKey, $mParamValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetPassword(
|
public function SetPassword(\SnappyMail\SensitiveString $oPassword) : void
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $sPassword
|
|
||||||
) : void
|
|
||||||
{
|
{
|
||||||
$this->Set('security', 'admin_password', \password_hash($sPassword, PASSWORD_DEFAULT));
|
$this->Set('security', 'admin_password', \password_hash($oPassword, PASSWORD_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ValidatePassword(
|
public function ValidatePassword(\SnappyMail\SensitiveString $oPassword) : bool
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $sPassword
|
|
||||||
) : bool
|
|
||||||
{
|
{
|
||||||
$sConfigPassword = (string) $this->Get('security', 'admin_password', '');
|
return \strlen($oPassword) && \password_verify($oPassword, $this->Get('security', 'admin_password', ''));
|
||||||
if (32 == \strlen($sPassword) && \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword) {
|
|
||||||
$this->SetPassword($sPassword);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return \strlen($sPassword) && \password_verify($sPassword, $sConfigPassword);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Save() : bool
|
public function Save() : bool
|
||||||
|
|
|
@ -15,7 +15,7 @@ abstract class Account implements \JsonSerializable
|
||||||
|
|
||||||
private string $sLogin = '';
|
private string $sLogin = '';
|
||||||
|
|
||||||
private ?SensitiveString $sPassword = null;
|
private ?SensitiveString $oPassword = null;
|
||||||
|
|
||||||
private string $sSmtpLogin = '';
|
private string $sSmtpLogin = '';
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ abstract class Account implements \JsonSerializable
|
||||||
|
|
||||||
public function IncPassword() : string
|
public function IncPassword() : string
|
||||||
{
|
{
|
||||||
return $this->sPassword ? $this->sPassword->getValue() : '';
|
return $this->oPassword ? $this->oPassword->getValue() : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function OutLogin() : string
|
public function OutLogin() : string
|
||||||
|
@ -66,16 +66,13 @@ abstract class Account implements \JsonSerializable
|
||||||
$this->sEmail,
|
$this->sEmail,
|
||||||
$this->sLogin,
|
$this->sLogin,
|
||||||
// \json_encode($this->Domain()),
|
// \json_encode($this->Domain()),
|
||||||
// $this->sPassword
|
// $this->oPassword
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetPassword(
|
public function SetPassword(SensitiveString $oPassword) : void
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $sPassword
|
|
||||||
) : void
|
|
||||||
{
|
{
|
||||||
$this->sPassword = new SensitiveString($sPassword);
|
$this->oPassword = $oPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetSmtpPassword(
|
public function SetSmtpPassword(
|
||||||
|
@ -125,12 +122,11 @@ abstract class Account implements \JsonSerializable
|
||||||
|
|
||||||
public static function NewInstanceFromCredentials(\RainLoop\Actions $oActions,
|
public static function NewInstanceFromCredentials(\RainLoop\Actions $oActions,
|
||||||
string $sEmail, string $sLogin,
|
string $sEmail, string $sLogin,
|
||||||
#[\SensitiveParameter]
|
SensitiveString $oPassword,
|
||||||
string $sPassword,
|
|
||||||
bool $bThrowException = false): ?self
|
bool $bThrowException = false): ?self
|
||||||
{
|
{
|
||||||
$oAccount = null;
|
$oAccount = null;
|
||||||
if ($sEmail && $sLogin && $sPassword) {
|
if ($sEmail && $sLogin && \strlen($oPassword)) {
|
||||||
$oDomain = $oActions->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true);
|
$oDomain = $oActions->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true);
|
||||||
if ($oDomain) {
|
if ($oDomain) {
|
||||||
if ($oDomain->ValidateWhiteList($sEmail, $sLogin)) {
|
if ($oDomain->ValidateWhiteList($sEmail, $sLogin)) {
|
||||||
|
@ -138,7 +134,7 @@ abstract class Account implements \JsonSerializable
|
||||||
|
|
||||||
$oAccount->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
$oAccount->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||||
$oAccount->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin);
|
$oAccount->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin);
|
||||||
$oAccount->SetPassword($sPassword);
|
$oAccount->SetPassword($oPassword);
|
||||||
$oAccount->oDomain = $oDomain;
|
$oAccount->oDomain = $oDomain;
|
||||||
|
|
||||||
$oActions->Plugins()->RunHook('filter.account', array($oAccount));
|
$oActions->Plugins()->RunHook('filter.account', array($oAccount));
|
||||||
|
@ -194,25 +190,22 @@ abstract class Account implements \JsonSerializable
|
||||||
$oActions,
|
$oActions,
|
||||||
$aAccountHash['email'],
|
$aAccountHash['email'],
|
||||||
$aAccountHash['login'],
|
$aAccountHash['login'],
|
||||||
$aAccountHash['pass'],
|
new SensitiveString($aAccountHash['pass']),
|
||||||
$bThrowExceptionOnFalse
|
$bThrowExceptionOnFalse
|
||||||
);
|
);
|
||||||
if ($oAccount) {
|
if ($oAccount) {
|
||||||
if (isset($aAccountHash['name'])) {
|
if (isset($aAccountHash['name'])) {
|
||||||
$oAccount->sName = $aAccountHash['name'];
|
$oAccount->sName = $aAccountHash['name'];
|
||||||
}
|
}
|
||||||
$oActions->logMask($oAccount->IncPassword());
|
|
||||||
// init smtp user/password
|
// init smtp user/password
|
||||||
if (isset($aAccountHash['smtp'])) {
|
if (isset($aAccountHash['smtp'])) {
|
||||||
$oAccount->sSmtpLogin = $aAccountHash['smtp']['user'];
|
$oAccount->sSmtpLogin = $aAccountHash['smtp']['user'];
|
||||||
$oAccount->SetSmtpPassword($aAccountHash['smtp']['pass']);
|
$oAccount->SetSmtpPassword($aAccountHash['smtp']['pass']);
|
||||||
$oActions->logMask($oAccount->sSmtpPassword);
|
|
||||||
}
|
}
|
||||||
// init proxy user/password
|
// init proxy user/password
|
||||||
if (isset($aAccountHash['proxy'])) {
|
if (isset($aAccountHash['proxy'])) {
|
||||||
$oAccount->sProxyAuthUser = $aAccountHash['proxy']['user'];
|
$oAccount->sProxyAuthUser = $aAccountHash['proxy']['user'];
|
||||||
$oAccount->SetProxyAuthPassword($aAccountHash['proxy']['pass']);
|
$oAccount->SetProxyAuthPassword($aAccountHash['proxy']['pass']);
|
||||||
$oActions->logMask($oAccount->sProxyAuthPassword);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +233,7 @@ abstract class Account implements \JsonSerializable
|
||||||
$oImapClient->Connect($oSettings);
|
$oImapClient->Connect($oSettings);
|
||||||
$oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $oSettings));
|
$oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $oSettings));
|
||||||
|
|
||||||
$oSettings->Password = $this->sPassword;
|
$oSettings->Password = $this->oPassword;
|
||||||
return $this->netClientLogin($oImapClient, $oPlugins);
|
return $this->netClientLogin($oImapClient, $oPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +257,7 @@ abstract class Account implements \JsonSerializable
|
||||||
throw new RequireCredentialsException
|
throw new RequireCredentialsException
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
$oSettings->Password = $this->sSmtpPassword ?: $this->sPassword;
|
$oSettings->Password = $this->sSmtpPassword ?: $this->oPassword;
|
||||||
return $this->netClientLogin($oSmtpClient, $oPlugins);
|
return $this->netClientLogin($oSmtpClient, $oPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +272,7 @@ abstract class Account implements \JsonSerializable
|
||||||
$oSieveClient->Connect($oSettings);
|
$oSieveClient->Connect($oSettings);
|
||||||
$oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $oSettings));
|
$oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $oSettings));
|
||||||
|
|
||||||
$oSettings->Password = $this->sPassword;
|
$oSettings->Password = $this->oPassword;
|
||||||
return $this->netClientLogin($oSieveClient, $oPlugins);
|
return $this->netClientLogin($oSieveClient, $oPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,16 +120,6 @@ class ServiceActions
|
||||||
$aPost[$key] = '*******';
|
$aPost[$key] = '*******';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
switch ($sMethodName)
|
|
||||||
{
|
|
||||||
case 'DoLogin':
|
|
||||||
case 'DoAdminLogin':
|
|
||||||
case 'DoAccountAdd':
|
|
||||||
$this->oActions->logMask($this->oActions->GetActionParam('Password', ''));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
$this->oActions->logWrite(Utils::jsonEncode($aPost), \LOG_INFO, 'POST');
|
$this->oActions->logWrite(Utils::jsonEncode($aPost), \LOG_INFO, 'POST');
|
||||||
} else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) {
|
} else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) {
|
||||||
$this->oActions->SetActionParams(array(
|
$this->oActions->SetActionParams(array(
|
||||||
|
@ -561,14 +551,14 @@ class ServiceActions
|
||||||
(0 === $aData['Time'] || \time() - 10 < $aData['Time']))
|
(0 === $aData['Time'] || \time() - 10 < $aData['Time']))
|
||||||
{
|
{
|
||||||
$sEmail = \trim($aData['Email']);
|
$sEmail = \trim($aData['Email']);
|
||||||
$sPassword = $aData['Password'];
|
$oPassword = new \SnappyMail\SensitiveString($aData['Password']);
|
||||||
|
|
||||||
$aAdditionalOptions = (isset($aData['AdditionalOptions']) && \is_array($aData['AdditionalOptions']))
|
$aAdditionalOptions = (isset($aData['AdditionalOptions']) && \is_array($aData['AdditionalOptions']))
|
||||||
? $aData['AdditionalOptions'] : [];
|
? $aData['AdditionalOptions'] : [];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oAccount = $this->oActions->LoginProcess($sEmail, $sPassword);
|
$oAccount = $this->oActions->LoginProcess($sEmail, $oPassword);
|
||||||
|
|
||||||
if ($aAdditionalOptions) {
|
if ($aAdditionalOptions) {
|
||||||
$bNeedToSettings = false;
|
$bNeedToSettings = false;
|
||||||
|
|
|
@ -284,10 +284,7 @@ abstract class Base
|
||||||
/**
|
/**
|
||||||
* Add a key for decryption
|
* Add a key for decryption
|
||||||
*/
|
*/
|
||||||
public function addDecryptKey(string $fingerprint,
|
public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase
|
|
||||||
) : bool
|
|
||||||
{
|
{
|
||||||
$this->decryptKeys[$fingerprint] = $passphrase;
|
$this->decryptKeys[$fingerprint] = $passphrase;
|
||||||
// $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase;
|
// $this->decryptKeys[\substr($fingerprint, -16)] = $passphrase;
|
||||||
|
@ -306,10 +303,7 @@ abstract class Base
|
||||||
/**
|
/**
|
||||||
* Add a key for signing
|
* Add a key for signing
|
||||||
*/
|
*/
|
||||||
public function addSignKey(string $fingerprint,
|
public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase
|
|
||||||
) : bool
|
|
||||||
{
|
{
|
||||||
$this->signKeys[$fingerprint] = $passphrase;
|
$this->signKeys[$fingerprint] = $passphrase;
|
||||||
// $this->signKeys[\substr($fingerprint, -16)] = $passphrase;
|
// $this->signKeys[\substr($fingerprint, -16)] = $passphrase;
|
||||||
|
@ -356,10 +350,7 @@ abstract class Base
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPassphrase($keyId,
|
public function addPassphrase($keyId, \SnappyMail\SensitiveString $passphrase)
|
||||||
#[\SensitiveParameter]
|
|
||||||
$passphrase
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
$this->passphrases[$keyId] = $passphrase;
|
$this->passphrases[$keyId] = $passphrase;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -95,7 +95,7 @@ class PGP extends Base
|
||||||
$fclose = $this->setOutput($output);
|
$fclose = $this->setOutput($output);
|
||||||
|
|
||||||
if ($this->decryptKeys) {
|
if ($this->decryptKeys) {
|
||||||
$_ENV['PINENTRY_USER_DATA'] = \json_encode($this->decryptKeys);
|
$_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->decryptKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->exec(['--decrypt','--skip-verify']);
|
$result = $this->exec(['--decrypt','--skip-verify']);
|
||||||
|
@ -241,7 +241,7 @@ class PGP extends Base
|
||||||
throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId);
|
throw new \Exception(($private ? 'Private' : 'Public') . ' key not found: ' . $keyId);
|
||||||
}
|
}
|
||||||
if ($private && $this->passphrases) {
|
if ($private && $this->passphrases) {
|
||||||
$_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases);
|
$_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases));
|
||||||
}
|
}
|
||||||
$result = $this->exec([
|
$result = $this->exec([
|
||||||
$private ? '--export-secret-keys' : '--export',
|
$private ? '--export-secret-keys' : '--export',
|
||||||
|
@ -362,7 +362,7 @@ class PGP extends Base
|
||||||
$arguments = ['--import'];
|
$arguments = ['--import'];
|
||||||
|
|
||||||
if ($this->passphrases) {
|
if ($this->passphrases) {
|
||||||
$_ENV['PINENTRY_USER_DATA'] = \json_encode($this->passphrases);
|
$_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->passphrases));
|
||||||
} else {
|
} else {
|
||||||
$arguments[] = '--batch';
|
$arguments[] = '--batch';
|
||||||
}
|
}
|
||||||
|
@ -629,7 +629,7 @@ class PGP extends Base
|
||||||
foreach ($this->signKeys as $fingerprint => $pass) {
|
foreach ($this->signKeys as $fingerprint => $pass) {
|
||||||
$arguments[] = '--local-user ' . \escapeshellarg($fingerprint);
|
$arguments[] = '--local-user ' . \escapeshellarg($fingerprint);
|
||||||
}
|
}
|
||||||
$_ENV['PINENTRY_USER_DATA'] = \json_encode($this->signKeys);
|
$_ENV['PINENTRY_USER_DATA'] = \json_encode(\array_map('strval', $this->signKeys));
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->exec($arguments);
|
$result = $this->exec($arguments);
|
||||||
|
|
|
@ -86,10 +86,7 @@ class GnuPG
|
||||||
/**
|
/**
|
||||||
* Add a key for decryption
|
* Add a key for decryption
|
||||||
*/
|
*/
|
||||||
public function addDecryptKey(string $fingerprint,
|
public function addDecryptKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase
|
|
||||||
) : bool
|
|
||||||
{
|
{
|
||||||
return $this->handler()->adddecryptkey($fingerprint, $passphrase);
|
return $this->handler()->adddecryptkey($fingerprint, $passphrase);
|
||||||
}
|
}
|
||||||
|
@ -105,10 +102,7 @@ class GnuPG
|
||||||
/**
|
/**
|
||||||
* Add a key for signing
|
* Add a key for signing
|
||||||
*/
|
*/
|
||||||
public function addSignKey(string $fingerprint,
|
public function addSignKey(string $fingerprint, \SnappyMail\SensitiveString $passphrase) : bool
|
||||||
#[\SensitiveParameter]
|
|
||||||
?string $passphrase
|
|
||||||
) : bool
|
|
||||||
{
|
{
|
||||||
return $this->handler()->addsignkey($fingerprint, $passphrase);
|
return $this->handler()->addsignkey($fingerprint, $passphrase);
|
||||||
}
|
}
|
||||||
|
@ -226,10 +220,7 @@ class GnuPG
|
||||||
/**
|
/**
|
||||||
* Exports a key
|
* Exports a key
|
||||||
*/
|
*/
|
||||||
public function export(string $fingerprint,
|
public function export(string $fingerprint, ?\SnappyMail\SensitiveString $passphrase = null) /*: string|false*/
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase = ''
|
|
||||||
) /*: string|false*/
|
|
||||||
{
|
{
|
||||||
if ($passphrase) {
|
if ($passphrase) {
|
||||||
return $this->getGPG()
|
return $this->getGPG()
|
||||||
|
@ -276,10 +267,7 @@ class GnuPG
|
||||||
/**
|
/**
|
||||||
* Generates a key
|
* Generates a key
|
||||||
*/
|
*/
|
||||||
public function generateKey(string $uid,
|
public function generateKey(string $uid, \SnappyMail\SensitiveString $passphrase) /*: string|false*/
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase
|
|
||||||
) /*: string|false*/
|
|
||||||
{
|
{
|
||||||
$GPG = $this->getGPG(false);
|
$GPG = $this->getGPG(false);
|
||||||
return $GPG ? $GPG->generateKey($uid, $passphrase) : false;
|
return $GPG ? $GPG->generateKey($uid, $passphrase) : false;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace SnappyMail;
|
namespace SnappyMail;
|
||||||
|
|
||||||
class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ implements \Stringable
|
class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */ implements \Stringable, \JsonSerializable
|
||||||
{
|
{
|
||||||
private string $value, $nonce;
|
private string $value, $nonce;
|
||||||
private static ?string $key = null;
|
private static ?string $key = null;
|
||||||
|
@ -28,6 +28,7 @@ class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */
|
||||||
string $value
|
string $value
|
||||||
) : void
|
) : void
|
||||||
{
|
{
|
||||||
|
\strlen($value) && \RainLoop\Api::Actions()->logMask($value);
|
||||||
if (\is_callable('sodium_crypto_secretbox')) {
|
if (\is_callable('sodium_crypto_secretbox')) {
|
||||||
$this->nonce = \random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
$this->nonce = \random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||||
if (!static::$key) {
|
if (!static::$key) {
|
||||||
|
@ -60,6 +61,12 @@ class SensitiveString /* extends SensitiveParameterValue | SensitiveParameter */
|
||||||
return $this->getValue();
|
return $this->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[\ReturnTypeWillChange]
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
throw new \Exception("JSON serialization of 'SnappyMail\\SensitiveString' is not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
public function __debugInfo(): array
|
public function __debugInfo(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -112,11 +112,7 @@ class Certificate
|
||||||
return \openssl_get_cipher_methods($aliases);
|
return \openssl_get_cipher_methods($aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createSelfSigned(
|
public function createSelfSigned(\SnappyMail\SensitiveString $passphrase, ?string $privateKey = null) : array
|
||||||
#[\SensitiveParameter]
|
|
||||||
string $passphrase = '',
|
|
||||||
?string $privateKey = null
|
|
||||||
) : array
|
|
||||||
{
|
{
|
||||||
$options = array(
|
$options = array(
|
||||||
'config' => __DIR__ . '/openssl.cnf',
|
'config' => __DIR__ . '/openssl.cnf',
|
||||||
|
|
|
@ -132,8 +132,7 @@ class OpenSSL
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPrivateKey(/*OpenSSLAsymmetricKey|string*/$privateKey,
|
public function setPrivateKey(/*OpenSSLAsymmetricKey|string*/$privateKey,
|
||||||
#[\SensitiveParameter]
|
?\SnappyMail\SensitiveString $passphrase = null
|
||||||
?string $passphrase = null
|
|
||||||
) : void
|
) : void
|
||||||
{
|
{
|
||||||
$this->privateKey = \openssl_pkey_get_private($privateKey, $passphrase);
|
$this->privateKey = \openssl_pkey_get_private($privateKey, $passphrase);
|
||||||
|
|
Loading…
Reference in a new issue