This commit is contained in:
the-djmaze 2022-05-30 13:12:01 +02:00
parent fe9d0da14a
commit 5cc738e2ba
2 changed files with 127 additions and 0 deletions

View file

@ -0,0 +1,107 @@
<?php
class ChangePasswordFroxlorDriver
{
const
NAME = 'Froxlor',
DESCRIPTION = 'Change passwords in Froxlor.';
/**
* @var \RainLoop\Config\Plugin
*/
private $oConfig = null;
/**
* @var \MailSo\Log\Logger
*/
private $oLogger = null;
function __construct(\RainLoop\Config\Plugin $oConfig, \MailSo\Log\Logger $oLogger)
{
$this->oConfig = $oConfig;
$this->oLogger = $oLogger;
}
public static function isSupported() : bool
{
return \class_exists('PDO', false)
// The PHP extension PDO (mysql) must be installed to use this plugin
&& \in_array('mysql', \PDO::getAvailableDrivers());
}
public static function configMapping() : array
{
return array(
\RainLoop\Plugins\Property::NewInstance('froxlor_dsn')->SetLabel('Froxlor PDO dsn')
->SetDefaultValue('mysql:host=localhost;dbname=froxlor;charset=utf8'),
\RainLoop\Plugins\Property::NewInstance('froxlor_user')->SetLabel('User'),
\RainLoop\Plugins\Property::NewInstance('froxlor_password')->SetLabel('Password')
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD),
\RainLoop\Plugins\Property::NewInstance('froxlor_allowed_emails')->SetLabel('Allowed emails')
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
->SetDefaultValue('*')
);
}
public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool
{
if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'froxlor_allowed_emails', ''))) {
return false;
}
try
{
if ($this->oLogger) {
$this->oLogger->Write('froxlor: Try to change password for '.$oAccount->Email());
}
$oPdo = new \PDO(
$this->oConfig->Get('plugin', 'froxlor_dsn', ''),
$this->oConfig->Get('plugin', 'froxlor_user', ''),
$this->oConfig->Get('plugin', 'froxlor_password', ''),
array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
)
);
$oStmt = $oPdo->prepare('SELECT password_enc, id FROM mail_users WHERE username = ? LIMIT 1');
if ($oStmt->execute(array($oAccount->IncLogin()))) {
$aFetchResult = $oStmt->fetch(\PDO::FETCH_ASSOC);
if (!empty($aFetchResult['id'])) {
$sDbPassword = $aFetchResult['password_enc'];
$sDbSalt = \substr($sDbPassword, 0, \strrpos($sDbPassword, '$'));
if (\crypt($sPrevPassword, $sDbSalt) === $sDbPassword) {
$oStmt = $oPdo->prepare('UPDATE mail_users SET password_enc = ? WHERE id = ?');
return !!$oStmt->execute(array(
$this->cryptPassword($sNewPassword),
$aFetchResult['id']
));
}
}
}
}
catch (\Exception $oException)
{
if ($this->oLogger) {
$this->oLogger->WriteException($oException);
}
}
return false;
}
private function cryptPassword(string $sPassword) : string
{
if (\defined('CRYPT_SHA512') && CRYPT_SHA512) {
$sSalt = '$6$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$';
} elseif (\defined('CRYPT_SHA256') && CRYPT_SHA256) {
$sSalt = '$5$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$';
} else {
$sSalt = '$1$' . \bin2hex(\random_bytes(6)) . '$';
}
return \crypt($sPassword, $sSalt);
}
}

View file

@ -0,0 +1,20 @@
<?php
use \RainLoop\Exceptions\ClientException;
class ChangePasswordPoppassdPlugin extends \RainLoop\Plugins\AbstractPlugin
{
const
NAME = 'Change Password Froxlor',
AUTHOR = 'Euphonique',
VERSION = '1.0',
RELEASE = '2022-05-30',
REQUIRED = '2.15.3',
CATEGORY = 'Security',
DESCRIPTION = 'Extension to allow users to change their passwords through Froxlor';
public function Supported() : string
{
return 'Use Change Password plugin';
}
}