mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
ChangePassword extensions use \SnappyMail\SensitiveString
This commit is contained in:
parent
9427b36633
commit
8c033f53fa
13 changed files with 70 additions and 56 deletions
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordFroxlorDriver
|
||||
{
|
||||
const
|
||||
|
|
@ -44,7 +46,7 @@ class ChangePasswordFroxlorDriver
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'froxlor_allowed_emails', ''))) {
|
||||
return false;
|
||||
|
|
@ -72,12 +74,12 @@ class ChangePasswordFroxlorDriver
|
|||
if (!empty($aFetchResult['id'])) {
|
||||
$sDbPassword = $aFetchResult['password_enc'];
|
||||
$sDbSalt = \substr($sDbPassword, 0, \strrpos($sDbPassword, '$'));
|
||||
if (\crypt($sPrevPassword, $sDbSalt) === $sDbPassword) {
|
||||
if (\crypt($oPrevPassword, $sDbSalt) === $sDbPassword) {
|
||||
|
||||
$oStmt = $oPdo->prepare('UPDATE mail_users SET password_enc = ? WHERE id = ?');
|
||||
|
||||
return !!$oStmt->execute(array(
|
||||
$this->cryptPassword($sNewPassword),
|
||||
$this->cryptPassword($oNewPassword),
|
||||
$aFetchResult['id']
|
||||
));
|
||||
}
|
||||
|
|
@ -93,7 +95,7 @@ class ChangePasswordFroxlorDriver
|
|||
return false;
|
||||
}
|
||||
|
||||
private function cryptPassword(string $sPassword) : string
|
||||
private function cryptPassword(SensitiveString $oPassword) : string
|
||||
{
|
||||
if (\defined('CRYPT_SHA512') && CRYPT_SHA512) {
|
||||
$sSalt = '$6$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$';
|
||||
|
|
@ -102,6 +104,6 @@ class ChangePasswordFroxlorDriver
|
|||
} else {
|
||||
$sSalt = '$1$' . \bin2hex(\random_bytes(6)) . '$';
|
||||
}
|
||||
return \crypt($sPassword, $sSalt);
|
||||
return \crypt($oPassword, $sSalt);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
|
||||
class ChangePasswordFroxlorPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password Froxlor',
|
||||
AUTHOR = 'Euphonique',
|
||||
VERSION = '1.0',
|
||||
RELEASE = '2022-05-30',
|
||||
REQUIRED = '2.15.3',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords through Froxlor';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordHestiaDriver
|
||||
{
|
||||
const
|
||||
|
|
@ -39,7 +41,7 @@ class ChangePasswordHestiaDriver
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'hestia_allowed_emails', ''))) {
|
||||
return false;
|
||||
|
|
@ -53,8 +55,8 @@ class ChangePasswordHestiaDriver
|
|||
$HTTP = \SnappyMail\HTTP\Request::factory();
|
||||
$postvars = array(
|
||||
'email' => $oAccount->Email(),
|
||||
'password' => $sPrevPassword,
|
||||
'new' => $sNewPassword,
|
||||
'password' => (string) $oPrevPassword,
|
||||
'new' => (string) $oNewPassword,
|
||||
);
|
||||
$response = $HTTP->doRequest('POST', 'https://'.$sHost.':'.$sPort.'/reset/mail/', \http_build_query($postvars));
|
||||
if (!$response) {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
|
||||
class ChangePasswordHestiaPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password Hestia',
|
||||
AUTHOR = 'Jaap Marcus',
|
||||
VERSION = '1.2',
|
||||
RELEASE = '2023-05-16',
|
||||
REQUIRED = '2.16.3',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords through HestiaCP';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use MailSo\Net\ConnectSettings;
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordHMailServerDriver
|
||||
{
|
||||
|
|
@ -37,7 +38,7 @@ class ChangePasswordHMailServerDriver
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'hmailserver_emails', ''))) {
|
||||
return false;
|
||||
|
|
@ -62,7 +63,7 @@ class ChangePasswordHMailServerDriver
|
|||
if ($oHmailDomain) {
|
||||
$oHmailAccount = $oHmailDomain->Accounts->ItemByAddress($sEmail);
|
||||
if ($oHmailAccount) {
|
||||
$oHmailAccount->Password = $sNewPassword;
|
||||
$oHmailAccount->Password = (string) $oNewPassword;
|
||||
$oHmailAccount->Save();
|
||||
$bResult = true;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
|
||||
class ChangePasswordHMailServerPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password hMailServer',
|
||||
VERSION = '2.1',
|
||||
RELEASE = '2024-03-12',
|
||||
REQUIRED = '2.35.3',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords through hMailServer';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordISPConfigDriver
|
||||
{
|
||||
const
|
||||
|
|
@ -44,7 +46,7 @@ class ChangePasswordISPConfigDriver
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'ispconfig_allowed_emails', ''))) {
|
||||
return false;
|
||||
|
|
@ -71,10 +73,10 @@ class ChangePasswordISPConfigDriver
|
|||
if (!empty($aFetchResult['mailuser_id'])) {
|
||||
$sDbPassword = $aFetchResult['password'];
|
||||
$sDbSalt = \substr($sDbPassword, 0, \strrpos($sDbPassword, '$'));
|
||||
if (\crypt($sPrevPassword, $sDbSalt) === $sDbPassword) {
|
||||
if (\crypt($oPrevPassword, $sDbSalt) === $sDbPassword) {
|
||||
$oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?');
|
||||
return !!$oStmt->execute(array(
|
||||
$this->cryptPassword($sNewPassword),
|
||||
$this->cryptPassword($oNewPassword),
|
||||
$aFetchResult['mailuser_id']
|
||||
));
|
||||
}
|
||||
|
|
@ -90,7 +92,7 @@ class ChangePasswordISPConfigDriver
|
|||
return false;
|
||||
}
|
||||
|
||||
private function cryptPassword(string $sPassword) : string
|
||||
private function cryptPassword(SensitiveString $oPassword) : string
|
||||
{
|
||||
if (\defined('CRYPT_SHA512') && CRYPT_SHA512) {
|
||||
$sSalt = '$6$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$';
|
||||
|
|
@ -99,6 +101,6 @@ class ChangePasswordISPConfigDriver
|
|||
} else {
|
||||
$sSalt = '$1$' . \bin2hex(\random_bytes(6)) . '$';
|
||||
}
|
||||
return \crypt($sPassword, $sSalt);
|
||||
return \crypt($oPassword, $sSalt);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
|
||||
class ChangePasswordISPConfigPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password ISPConfig',
|
||||
VERSION = '2.19',
|
||||
RELEASE = '2023-04-11',
|
||||
REQUIRED = '2.23.0',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords through ISPConfig';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use MailSo\Net\ConnectSettings;
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordPoppassdDriver extends \MailSo\Net\NetClient
|
||||
{
|
||||
|
|
@ -33,7 +34,7 @@ class ChangePasswordPoppassdDriver extends \MailSo\Net\NetClient
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'poppassd_allowed_emails', ''))) {
|
||||
return false;
|
||||
|
|
@ -55,7 +56,7 @@ class ChangePasswordPoppassdDriver extends \MailSo\Net\NetClient
|
|||
try
|
||||
{
|
||||
$this->sendRequestWithCheck('user', $oAccount->IncLogin(), true);
|
||||
$this->sendRequestWithCheck('pass', $sPrevPassword, true);
|
||||
$this->sendRequestWithCheck('pass', $oPrevPassword, true);
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
|
|
@ -65,7 +66,7 @@ class ChangePasswordPoppassdDriver extends \MailSo\Net\NetClient
|
|||
$this->bIsLoggined = true;
|
||||
|
||||
if ($this->bIsLoggined) {
|
||||
$this->sendRequestWithCheck('newpass', $sNewPassword);
|
||||
$this->sendRequestWithCheck('newpass', $oNewPassword);
|
||||
} else {
|
||||
$this->writeLogException(
|
||||
new \RuntimeException('Required login'),
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
|
||||
class ChangePasswordPoppassdPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password Poppassd',
|
||||
VERSION = '2.20',
|
||||
RELEASE = '2023-12-08',
|
||||
REQUIRED = '2.28.0',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords through Poppassd';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordDriverLDAP
|
||||
{
|
||||
const
|
||||
|
|
@ -55,7 +57,7 @@ class ChangePasswordDriverLDAP
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
$sDomain = \MailSo\Base\Utils::getEmailAddressDomain($oAccount->Email());
|
||||
$sUserDn = \strtr($this->sUserDnFormat, array(
|
||||
|
|
@ -89,25 +91,25 @@ class ChangePasswordDriverLDAP
|
|||
throw new \Exception('ldap_start_tls error '.\ldap_errno($oCon).': '.\ldap_error($oCon));
|
||||
}
|
||||
|
||||
if (!\ldap_bind($oCon, $sUserDn, $sPrevPassword)) {
|
||||
if (!\ldap_bind($oCon, $sUserDn, $oPrevPassword)) {
|
||||
throw new \Exception('ldap_bind error '.\ldap_errno($oCon).': '.\ldap_error($oCon));
|
||||
}
|
||||
|
||||
$sSshaSalt = '';
|
||||
$sPrefix = '{'.\strtoupper($this->sPasswordEncType).'}';
|
||||
$sEncodedNewPassword = $sNewPassword;
|
||||
$sEncodedNewPassword = $oNewPassword;
|
||||
switch ($sPrefix)
|
||||
{
|
||||
case '{SSHA}':
|
||||
$sSshaSalt = $this->getSalt(4);
|
||||
case '{SHA}':
|
||||
$sEncodedNewPassword = $sPrefix.\base64_encode(\hash('sha1', $sNewPassword.$sSshaSalt, true).$sSshaSalt);
|
||||
$sEncodedNewPassword = $sPrefix.\base64_encode(\hash('sha1', $oNewPassword.$sSshaSalt, true).$sSshaSalt);
|
||||
break;
|
||||
case '{MD5}':
|
||||
$sEncodedNewPassword = $sPrefix.\base64_encode(\md5($sNewPassword, true));
|
||||
$sEncodedNewPassword = $sPrefix.\base64_encode(\md5($oNewPassword, true));
|
||||
break;
|
||||
case '{CRYPT}':
|
||||
$sEncodedNewPassword = $sPrefix.\crypt($sNewPassword, $this->getSalt(2));
|
||||
$sEncodedNewPassword = $sPrefix.\crypt($oNewPassword, $this->getSalt(2));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordDriverPDO
|
||||
{
|
||||
const
|
||||
|
|
@ -58,7 +60,7 @@ class ChangePasswordDriverPDO
|
|||
);
|
||||
}
|
||||
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
|
||||
public function ChangePassword(\RainLoop\Model\Account $oAccount, SensitiveString $oPrevPassword, SensitiveString $oNewPassword) : bool
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -85,8 +87,8 @@ class ChangePasswordDriverPDO
|
|||
|
||||
$placeholders = array(
|
||||
':email' => $sEmail,
|
||||
':oldpass' => $encrypt_prefix . \ChangePasswordPlugin::encrypt($encrypt, $sPrevPassword),
|
||||
':newpass' => $encrypt_prefix . \ChangePasswordPlugin::encrypt($encrypt, $sNewPassword),
|
||||
':oldpass' => $encrypt_prefix . \ChangePasswordPlugin::encrypt($encrypt, $oPrevPassword),
|
||||
':newpass' => $encrypt_prefix . \ChangePasswordPlugin::encrypt($encrypt, $oNewPassword),
|
||||
':domain' => \MailSo\Base\Utils::getEmailAddressDomain($sEmail),
|
||||
':username' => \MailSo\Base\Utils::getEmailAddressLocalPart($sEmail),
|
||||
':login_name' => $oAccount->IncLogin()
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
<?php
|
||||
|
||||
use \RainLoop\Exceptions\ClientException;
|
||||
use RainLoop\Exceptions\ClientException;
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
const
|
||||
NAME = 'Change Password',
|
||||
VERSION = '2.20',
|
||||
RELEASE = '2024-03-12',
|
||||
REQUIRED = '2.35.3',
|
||||
VERSION = '2.36',
|
||||
RELEASE = '2024-03-17',
|
||||
REQUIRED = '2.36.0',
|
||||
CATEGORY = 'Security',
|
||||
DESCRIPTION = 'Extension to allow users to change their passwords';
|
||||
|
||||
|
|
@ -149,15 +150,16 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|||
if ($sPrevPassword !== $oAccount->IncPassword()) {
|
||||
throw new ClientException(static::CurrentPasswordIncorrect, null, $oActions->StaticI18N('NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT'));
|
||||
}
|
||||
$oPrevPassword = new \SnappyMail\SensitiveString($sPrevPassword);
|
||||
|
||||
$sNewPassword = $this->jsonParam('NewPassword');
|
||||
if ($this->Config()->Get('plugin', 'pass_min_length', 10) > \strlen($sNewPassword)) {
|
||||
throw new ClientException(static::NewPasswordShort, null, $oActions->StaticI18N('NOTIFICATIONS/NEW_PASSWORD_SHORT'));
|
||||
}
|
||||
|
||||
if ($this->Config()->Get('plugin', 'pass_min_strength', 70) > static::PasswordStrength($sNewPassword)) {
|
||||
throw new ClientException(static::NewPasswordWeak, null, $oActions->StaticI18N('NOTIFICATIONS/NEW_PASSWORD_WEAK'));
|
||||
}
|
||||
$oNewPassword = new \SnappyMail\SensitiveString($sNewPassword);
|
||||
|
||||
$bResult = false;
|
||||
$oConfig = $this->Config();
|
||||
|
|
@ -171,7 +173,7 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|||
$oConfig,
|
||||
$oLogger
|
||||
);
|
||||
if (!$oDriver->ChangePassword($oAccount, $sPrevPassword, $sNewPassword)) {
|
||||
if (!$oDriver->ChangePassword($oAccount, $oPrevPassword, $oNewPassword)) {
|
||||
throw new ClientException(static::CouldNotSaveNewPassword);
|
||||
}
|
||||
$bResult = true;
|
||||
|
|
@ -196,7 +198,7 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|||
throw new ClientException(static::CouldNotSaveNewPassword);
|
||||
}
|
||||
|
||||
$oAccount->SetPassword($sNewPassword);
|
||||
$oAccount->SetPassword($oNewPassword);
|
||||
if ($oAccount instanceof \RainLoop\Model\MainAccount) {
|
||||
$oActions->SetAuthToken($oAccount);
|
||||
}
|
||||
|
|
@ -204,7 +206,7 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|||
return $this->jsonResponse(__FUNCTION__, $oActions->AppData(false));
|
||||
}
|
||||
|
||||
public static function encrypt(string $algo, string $password)
|
||||
public static function encrypt(string $algo, SensitiveString $password)
|
||||
{
|
||||
switch (\strtolower($algo))
|
||||
{
|
||||
|
|
@ -233,7 +235,7 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
|||
private static function PasswordStrength(string $sPassword) : int
|
||||
{
|
||||
$i = \strlen($sPassword);
|
||||
$max = min(100, $i * 8);
|
||||
$max = \min(100, $i * 8);
|
||||
$s = 0;
|
||||
while (--$i) {
|
||||
$s += ($sPassword[$i] != $sPassword[$i-1] ? 1 : -0.5);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue