Skip to content

Commit c725f9e

Browse files
author
the-djmaze
committed
Resolve RainLoop#2150
1 parent 63e15ff commit c725f9e

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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

Comments
 (0)