|
| 1 | +<?php |
| 2 | + |
| 3 | +class ChangePasswordDriverISPConfig |
| 4 | +{ |
| 5 | + const |
| 6 | + NAME = 'ISPConfig', |
| 7 | + DESCRIPTION = 'Change passwords in ISPConfig.'; |
| 8 | + |
| 9 | + /** |
| 10 | + * @var \RainLoop\Config\Plugin |
| 11 | + */ |
| 12 | + private $oConfig = null; |
| 13 | + |
| 14 | + /** |
| 15 | + * @var \MailSo\Log\Logger |
| 16 | + */ |
| 17 | + private $oLogger = null; |
| 18 | + |
| 19 | + function __construct(\RainLoop\Config\Plugin $oConfig, \MailSo\Log\Logger $oLogger) |
| 20 | + { |
| 21 | + $this->oConfig = $oConfig; |
| 22 | + $this->oLogger = $oLogger; |
| 23 | + } |
| 24 | + |
| 25 | + public static function isSupported() : bool |
| 26 | + { |
| 27 | + return \class_exists('PDO', false) |
| 28 | + // The PHP extension PDO (mysql) must be installed to use this plugin |
| 29 | + && \in_array('mysql', \PDO::getAvailableDrivers()); |
| 30 | + } |
| 31 | + |
| 32 | + public static function configMapping() : array |
| 33 | + { |
| 34 | + return array( |
| 35 | + \RainLoop\Plugins\Property::NewInstance('ispconfig_dsn')->SetLabel('ISPConfig PDO dsn') |
| 36 | + ->SetDefaultValue('mysql:host=localhost;dbname=dbispconfig;charset=utf8'), |
| 37 | + \RainLoop\Plugins\Property::NewInstance('ispconfig_user')->SetLabel('User'), |
| 38 | + \RainLoop\Plugins\Property::NewInstance('ispconfig_password')->SetLabel('Password') |
| 39 | + ->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD), |
| 40 | + \RainLoop\Plugins\Property::NewInstance('ispconfig_allowed_emails')->SetLabel('Allowed emails') |
| 41 | + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT) |
| 42 | + -> SetDescription( 'Allowed emails, space as delimiter, wildcard supported. Example: [email protected] [email protected] *@domain2.net') |
| 43 | + ->SetDefaultValue('*') |
| 44 | + ); |
| 45 | + } |
| 46 | + |
| 47 | + public function ChangePassword(\RainLoop\Model\Account $oAccount, string $sPrevPassword, string $sNewPassword) : bool |
| 48 | + { |
| 49 | + if (!\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->oConfig->Get('plugin', 'ispconfig_allowed_emails', ''))) { |
| 50 | + return false; |
| 51 | + } |
| 52 | + |
| 53 | + try |
| 54 | + { |
| 55 | + if ($this->oLogger) { |
| 56 | + $this->oLogger->Write('ISPConfig: Try to change password for '.$oAccount->Email()); |
| 57 | + } |
| 58 | + |
| 59 | + $oPdo = new \PDO( |
| 60 | + $this->oConfig->Get('plugin', 'ispconfig_dsn', ''), |
| 61 | + $this->oConfig->Get('plugin', 'ispconfig_user', ''), |
| 62 | + $this->oConfig->Get('plugin', 'ispconfig_password', ''), |
| 63 | + array( |
| 64 | + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION |
| 65 | + ) |
| 66 | + ); |
| 67 | + |
| 68 | + $oStmt = $oPdo->prepare('SELECT password, mailuser_id FROM mail_user WHERE login = ? LIMIT 1'); |
| 69 | + if ($oStmt->execute(array($oAccount->IncLogin()))) { |
| 70 | + $aFetchResult = $oStmt->fetch(\PDO::FETCH_ASSOC); |
| 71 | + if (!empty($aFetchResult['mailuser_id'])) { |
| 72 | + $sDbPassword = $aFetchResult['password']; |
| 73 | + $sDbSalt = \substr($sDbPassword, 0, \strrpos($sDbPassword, '$')); |
| 74 | + if (\crypt($sPrevPassword, $sDbSalt) === $sDbPassword) { |
| 75 | + $oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?'); |
| 76 | + return !!$oStmt->execute(array( |
| 77 | + $this->cryptPassword($sNewPassword), |
| 78 | + $aFetchResult['mailuser_id'] |
| 79 | + )); |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + catch (\Exception $oException) |
| 85 | + { |
| 86 | + if ($this->oLogger) { |
| 87 | + $this->oLogger->WriteException($oException); |
| 88 | + } |
| 89 | + } |
| 90 | + return false; |
| 91 | + } |
| 92 | + |
| 93 | + private function cryptPassword(string $sPassword) : string |
| 94 | + { |
| 95 | + if (\defined('CRYPT_SHA512') && CRYPT_SHA512) { |
| 96 | + $sSalt = '$6$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$'; |
| 97 | + } elseif (\defined('CRYPT_SHA256') && CRYPT_SHA256) { |
| 98 | + $sSalt = '$5$rounds=5000$' . \bin2hex(\random_bytes(8)) . '$'; |
| 99 | + } else { |
| 100 | + $sSalt = '$1$' . \bin2hex(\random_bytes(6)) . '$'; |
| 101 | + } |
| 102 | + return \crypt($sPassword, $sSalt); |
| 103 | + } |
| 104 | +} |
0 commit comments