mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-01-08 07:48:02 +08:00
Add files via upload
This commit is contained in:
parent
a8a1efb071
commit
6d88a93975
5 changed files with 391 additions and 0 deletions
293
plugins/froxlor-change-password/FroxlorChangePasswordDriver.php
Normal file
293
plugins/froxlor-change-password/FroxlorChangePasswordDriver.php
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?php
|
||||
|
||||
class FroxlorChangePasswordDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDsn = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sUser = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sPassword = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sAllowedEmails = '';
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
private $oLogger = null;
|
||||
|
||||
/**
|
||||
* @param string $sDsn
|
||||
* @param string $sUser
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return \FroxlorChangePasswordDriver
|
||||
*/
|
||||
public function SetConfig($sDsn, $sUser, $sPassword)
|
||||
{
|
||||
$this->sDsn = $sDsn;
|
||||
$this->sUser = $sUser;
|
||||
$this->sPassword = $sPassword;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sAllowedEmails
|
||||
*
|
||||
* @return \FroxlorChangePasswordDriver
|
||||
*/
|
||||
public function SetAllowedEmails($sAllowedEmails)
|
||||
{
|
||||
$this->sAllowedEmails = $sAllowedEmails;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*
|
||||
* @return \FroxlorChangePasswordDriver
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
if ($oLogger instanceof \MailSo\Log\Logger)
|
||||
{
|
||||
$this->oLogger = $oLogger;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PasswordChangePossibility($oAccount)
|
||||
{
|
||||
return $oAccount && $oAccount->Email() &&
|
||||
\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sPrevPassword
|
||||
* @param string $sNewPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
|
||||
{
|
||||
if ($this->oLogger) {
|
||||
$this->oLogger->Write('Froxlor: Try to change password for '.$oAccount->Email());
|
||||
}
|
||||
|
||||
$bResult = false;
|
||||
if (!empty($this->sDsn) && 0 < \strlen($this->sUser) && 0 < \strlen($this->sPassword) && $oAccount)
|
||||
{
|
||||
try
|
||||
{
|
||||
$oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword);
|
||||
$oPdo->setAttribute(\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->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetchResult) && isset($aFetchResult[0]['password_enc'], $aFetchResult[0]['id']))
|
||||
{
|
||||
$sDbPassword = \stripslashes($aFetchResult[0]['password_enc']);
|
||||
|
||||
if ( $this->validatePasswordLogin( $sDbPassword, $sPrevPassword ) ) {
|
||||
$sEncNewPassword = $this->cryptPassword($sNewPassword, 3);
|
||||
$oStmt = $oPdo->prepare('UPDATE mail_users SET password_enc = ?,password = ? WHERE id = ?');
|
||||
$bResult = (bool) $oStmt->execute(
|
||||
array($sEncNewPassword, $sNewPassword, $aFetchResult[0]['id']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->WriteException($oException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPassword
|
||||
* @return string
|
||||
*/
|
||||
private function cryptPassword($sPassword, $type = 3)
|
||||
{
|
||||
return $this->makeCryptPassword($sPassword,$type);
|
||||
}
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Michal Wojcik <m.wojcik@sonet3.pl>
|
||||
* @author Michael Kaufmann <mkaufmann@nutime.de>
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Functions
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make crypted password from clear text password
|
||||
*
|
||||
* @author Michal Wojcik <m.wojcik@sonet3.pl>
|
||||
* @author Michael Kaufmann <mkaufmann@nutime.de>
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
*
|
||||
* 0 - default crypt (depenend on system configuration)
|
||||
* 1 - MD5 $1$
|
||||
* 2 - BLOWFISH $2a$ | $2y$07$ (on php 5.3.7+)
|
||||
* 3 - SHA-256 $5$ (default)
|
||||
* 4 - SHA-512 $6$
|
||||
*
|
||||
* @param string $password Password to be crypted
|
||||
*
|
||||
* @return string encrypted password
|
||||
*/
|
||||
private function makeCryptPassword ($password,$type = 3) {
|
||||
switch ($type) {
|
||||
case 0:
|
||||
$cryptPassword = \crypt($password);
|
||||
break;
|
||||
case 1:
|
||||
$cryptPassword = \crypt($password, '$1$' . $this->generatePassword(true). $this->generatePassword(true));
|
||||
break;
|
||||
case 2:
|
||||
if (\version_compare(\phpversion(), '5.3.7', '<')) {
|
||||
$cryptPassword = \crypt($password, '$2a$' . $this->generatePassword(true). $this->generatePassword(true));
|
||||
} else {
|
||||
// Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$",
|
||||
// a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z"
|
||||
$cryptPassword = \crypt(
|
||||
$password,
|
||||
'$2y$07$' . \substr($this->generatePassword(true).$this->generatePassword(true).$this->generatePassword(true), 0, 22)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
$cryptPassword = \crypt($password, '$5$' . $this->generatePassword(true). $this->generatePassword(true));
|
||||
break;
|
||||
case 4:
|
||||
$cryptPassword = \crypt($password, '$6$' . $this->generatePassword(true). $this->generatePassword(true));
|
||||
break;
|
||||
default:
|
||||
$cryptPassword = \crypt($password);
|
||||
break;
|
||||
}
|
||||
|
||||
return $cryptPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random password
|
||||
*
|
||||
* @param boolean $isSalt
|
||||
* optional, create a hash for a salt used in makeCryptPassword because crypt() does not like some special characters in its salts, default is false
|
||||
*/
|
||||
private function generatePassword($isSalt = false)
|
||||
{
|
||||
$alpha_lower = 'abcdefghijklmnopqrstuvwxyz';
|
||||
$alpha_upper = \strtoupper($alpha_lower);
|
||||
$numeric = '0123456789';
|
||||
$special = '!?<>§$%&+#=';
|
||||
$length = 10;
|
||||
|
||||
$pw = $this->special_shuffle($alpha_lower);
|
||||
$n = \floor(($length) / 4);
|
||||
$pw .= \mb_substr($this->special_shuffle($alpha_upper), 0, $n);
|
||||
$pw .= \mb_substr($this->special_shuffle($numeric), 0, $n);
|
||||
$pw = \mb_substr($pw, - $length);
|
||||
return $this->special_shuffle($pw);
|
||||
}
|
||||
|
||||
/**
|
||||
* multibyte-character safe shuffle function
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function special_shuffle($str = null)
|
||||
{
|
||||
$len = \mb_strlen($str);
|
||||
$sploded = array();
|
||||
while ($len -- > 0) {
|
||||
$sploded[] = \mb_substr($str, $len, 1);
|
||||
}
|
||||
\shuffle($sploded);
|
||||
return \join('', $sploded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function validatePasswordLogin
|
||||
*
|
||||
* compare user password-hash with given user-password
|
||||
* and check if they are the same
|
||||
* additionally it updates the hash if the system settings changed
|
||||
* or if the very old md5() sum is used
|
||||
*
|
||||
* @param array $userinfo user-data from table
|
||||
* @param string $password the password to validate
|
||||
* @param string $table either panel_customers or panel_admins
|
||||
* @param string $uid user-id-field in $table
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function validatePasswordLogin($pwd_hash, $password = null) {
|
||||
|
||||
$systype = 3; // SHA256
|
||||
$update_hash = false;
|
||||
// check for good'ole md5
|
||||
if (\strlen($pwd_hash) == 32 && \ctype_xdigit($pwd_hash)) {
|
||||
$pwd_check = \md5($password);
|
||||
$update_hash = true;
|
||||
} else {
|
||||
// cut out the salt from the hash
|
||||
$pwd_salt = \str_replace(\substr(\strrchr($pwd_hash, "$"), 1), "", $pwd_hash);
|
||||
// create same hash to compare
|
||||
$pwd_check = \crypt($password, $pwd_salt);
|
||||
// check whether the hash needs to be updated
|
||||
$hash_type_chk = \substr($pwd_hash, 0, 3);
|
||||
if (($systype == 1 && $hash_type_chk != '$1$') || // MD5
|
||||
($systype == 2 && $hash_type_chk != '$2$') || // BLOWFISH
|
||||
($systype == 3 && $hash_type_chk != '$5$') || // SHA256
|
||||
($systype == 4 && $hash_type_chk != '$6$') // SHA512
|
||||
) {
|
||||
$update_hash = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $pwd_check;
|
||||
}
|
||||
|
||||
|
||||
}
|
20
plugins/froxlor-change-password/LICENSE
Normal file
20
plugins/froxlor-change-password/LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Bob Kromonos Achten
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
plugins/froxlor-change-password/README
Normal file
1
plugins/froxlor-change-password/README
Normal file
|
@ -0,0 +1 @@
|
|||
Plugin that adds functionality to change the email account password (Froxlor).
|
1
plugins/froxlor-change-password/VERSION
Normal file
1
plugins/froxlor-change-password/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
1.0
|
76
plugins/froxlor-change-password/index.php
Normal file
76
plugins/froxlor-change-password/index.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
class FroxlorchangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||
{
|
||||
public function Init()
|
||||
{
|
||||
$this->addHook('main.fabrica', 'MainFabrica');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Supported()
|
||||
{
|
||||
if (!extension_loaded('pdo') || !class_exists('PDO'))
|
||||
{
|
||||
return 'The PHP exention PDO (mysql) must be installed to use this plugin';
|
||||
}
|
||||
|
||||
$aDrivers = \PDO::getAvailableDrivers();
|
||||
if (!is_array($aDrivers) || !in_array('mysql', $aDrivers))
|
||||
{
|
||||
return 'The PHP exention PDO (mysql) must be installed to use this plugin';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param mixed $oProvider
|
||||
*/
|
||||
public function MainFabrica($sName, &$oProvider)
|
||||
{
|
||||
switch ($sName)
|
||||
{
|
||||
case 'change-password':
|
||||
|
||||
$sDsn = \trim($this->Config()->Get('plugin', 'pdo_dsn', ''));
|
||||
$sUser = (string) $this->Config()->Get('plugin', 'user', '');
|
||||
$sPassword = (string) $this->Config()->Get('plugin', 'password', '');
|
||||
|
||||
if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword))
|
||||
{
|
||||
include_once __DIR__.'/FroxlorChangePasswordDriver.php';
|
||||
|
||||
$oProvider = new FroxlorChangePasswordDriver();
|
||||
$oProvider->SetLogger($this->Manager()->Actions()->Logger());
|
||||
$oProvider->SetConfig($sDsn, $sUser, $sPassword);
|
||||
$oProvider->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function configMapping()
|
||||
{
|
||||
return array(
|
||||
\RainLoop\Plugins\Property::NewInstance('pdo_dsn')->SetLabel('Froxlor PDO dsn')
|
||||
->SetDefaultValue('mysql:host=127.0.0.1;dbname=froxlor'),
|
||||
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('DB User')
|
||||
->SetDefaultValue('root'),
|
||||
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('DB Password')
|
||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
|
||||
->SetDefaultValue(''),
|
||||
\RainLoop\Plugins\Property::NewInstance('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('*')
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue