Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Change password ISPConfig 3.1 #1298

Open
andypl78 opened this issue Dec 28, 2016 · 6 comments
Open

Change password ISPConfig 3.1 #1298

andypl78 opened this issue Dec 28, 2016 · 6 comments

Comments

@andypl78
Copy link

RainLoop version, browser, OS:
Latest

Please add posibility to change password via API ISPConfig 3.1

@OrihuelaConde
Copy link

I don't know how to make a new plugin or how to use the API of ISPConfig 3.1 so I edited the old one to support one Master and one Slave. Hope this help.

Index.php:

<?php

class IspconfigChangePasswordPlugin 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', '');
				$sDsn2 = \trim($this->Config()->Get('plugin', 'pdo_dsn2', ''));
				$sUser2 = (string) $this->Config()->Get('plugin', 'user2', '');
				$sPassword2 = (string) $this->Config()->Get('plugin', 'password2', '');

				if (!empty($sDsn) && 0 < \strlen($sUser) && 0 < \strlen($sPassword))
				{
					include_once __DIR__.'/IspConfigChangePasswordDriver.php';

					$oProvider = new IspConfigChangePasswordDriver();
					$oProvider->SetLogger($this->Manager()->Actions()->Logger());
					$oProvider->SetConfig($sDsn, $sUser, $sPassword, $sDsn2, $sUser2, $sPassword2);
					$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('Master ISPConfig PDO dsn')
				->SetDefaultValue('mysql:host=127.0.0.1;dbname=dbispconfig'),
			\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('Master DB User')
				->SetDefaultValue('root'),
			\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('Master DB Password')
				->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
				->SetDefaultValue(''),
			\RainLoop\Plugins\Property::NewInstance('pdo_dsn2')->SetLabel('Slave ISPConfig PDO dsn')
				->SetDefaultValue('mysql:host=127.0.0.1;dbname=dbispconfig'),
			\RainLoop\Plugins\Property::NewInstance('user2')->SetLabel('Slave DB User')
				->SetDefaultValue('root'),
			\RainLoop\Plugins\Property::NewInstance('password2')->SetLabel('Slave 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: [email protected] [email protected] *@domain2.net')
				->SetDefaultValue('*')
		);
	}
}

IspConfigChangePasswordDriver.php:

<?php

class IspConfigChangePasswordDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
{
	/**
	 * @var string
	 */
	private $sDsn = '';

	/**
	 * @var string
	 */
	private $sUser = '';

	/**
	 * @var string
	 */
	private $sPassword = '';
	
	/**
	 * @var string
	 */
	private $sDsn2 = '';

	/**
	 * @var string
	 */
	private $sUser2 = '';

	/**
	 * @var string
	 */
	private $sPassword2 = '';

	/**
	 * @var string
	 */
	private $sAllowedEmails = '';

	/**
	 * @var \MailSo\Log\Logger
	 */
	private $oLogger = null;

	/**
	 * @param string $sDsn
	 * @param string $sUser
	 * @param string $sPassword
	 * @param string $sDsn2
	 * @param string $sUser2
	 * @param string $sPassword2
	 *
	 * @return \IspConfigChangePasswordDriver
	 */
	public function SetConfig($sDsn, $sUser, $sPassword, $sDsn2, $sUser2, $sPassword2)
	{
		$this->sDsn = $sDsn;
		$this->sUser = $sUser;
		$this->sPassword = $sPassword;
		$this->sDsn2 = $sDsn2;
		$this->sUser2 = $sUser2;
		$this->sPassword2 = $sPassword2;

		return $this;
	}

	/**
	 * @param string $sAllowedEmails
	 *
	 * @return \IspConfigChangePasswordDriver
	 */
	public function SetAllowedEmails($sAllowedEmails)
	{
		$this->sAllowedEmails = $sAllowedEmails;
		return $this;
	}

	/**
	 * @param \MailSo\Log\Logger $oLogger
	 *
	 * @return \IspConfigChangePasswordDriver
	 */
	public function SetLogger($oLogger)
	{
		if ($oLogger instanceof \MailSo\Log\Logger)
		{
			$this->oLogger = $oLogger;
		}

		return $this;
	}

	/**
	 * @param \RainLoop\Model\Account $oAccount
	 *
	 * @return bool
	 */
	public function PasswordChangePossibility($oAccount)
	{
		return $oAccount && $oAccount->Email() &&
			\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
	}

	/**
	 * @param \RainLoop\Model\Account $oAccount
	 * @param string $sPrevPassword
	 * @param string $sNewPassword
	 *
	 * @return bool
	 */
	public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
	{
		if ($this->oLogger)
		{
			$this->oLogger->Write('ISP: Try to change password for '.$oAccount->Email());
		}

		$bResult = false;
		$bResult2 = false;
		$sNewPass = $this->cryptPassword($sNewPassword);
		$sOldPass = '';
		if (!empty($this->sDsn) && !empty($this->sDsn2) && 0 < \strlen($this->sUser) && 0 < \strlen($this->sUser2) && 0 < \strlen($this->sPassword) && \strlen($this->sPassword2) && $oAccount)
		{
			try
			{
				$oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword);
				$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

				$oStmt = $oPdo->prepare('SELECT password, mailuser_id FROM mail_user WHERE login = ? LIMIT 1');
				if ($oStmt->execute(array($oAccount->IncLogin())))
				{
					$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
					if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['mailuser_id']))
					{
						$sDbPassword = \stripslashes($aFetchResult[0]['password']);
						$sOldPass = $sDbPassword;
						$sDbSalt = '$1$'.\substr($sDbPassword, 3, 8).'$';

						if (\crypt(\stripslashes($sPrevPassword), $sDbSalt) === $sDbPassword)
						{
							$oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?');
							$bResult = (bool) $oStmt->execute(
								array($sNewPass, $aFetchResult[0]['mailuser_id']));
						}
					}
				}
				
				$oPdo = new \PDO($this->sDsn2, $this->sUser2, $this->sPassword2);
				$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

				$oStmt = $oPdo->prepare('SELECT password, mailuser_id FROM mail_user WHERE login = ? LIMIT 1');
				if ($oStmt->execute(array($oAccount->IncLogin())))
				{
					$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
					if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['mailuser_id']))
					{
						$sDbPassword = \stripslashes($aFetchResult[0]['password']);
						$sDbSalt = '$1$'.\substr($sDbPassword, 3, 8).'$';

						if (\crypt(\stripslashes($sPrevPassword), $sDbSalt) === $sDbPassword)
						{
							$oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?');
							$bResult2 = (bool) $oStmt->execute(
								array($sNewPass, $aFetchResult[0]['mailuser_id']));
						}
					}
				}
			}
			catch (\Exception $oException)
			{
				if($bResult && !$bResult2)
				{
					try
					{
						$oPdo = new \PDO($this->sDsn, $this->sUser, $this->sPassword);
						$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

						$oStmt = $oPdo->prepare('SELECT password, mailuser_id FROM mail_user WHERE login = ? LIMIT 1');
						if ($oStmt->execute(array($oAccount->IncLogin())))
						{
							$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
							if (\is_array($aFetchResult) && isset($aFetchResult[0]['password'], $aFetchResult[0]['mailuser_id']))
							{
								$sDbPassword = \stripslashes($aFetchResult[0]['password']);
								$sDbSalt = '$1$'.\substr($sDbPassword, 3, 8).'$';
								$oStmt = $oPdo->prepare('UPDATE mail_user SET password = ? WHERE mailuser_id = ?');
								$oStmt->execute(array($sOldPass, $aFetchResult[0]['mailuser_id']));
							}
						}
					}
					catch (\Exception $oException)
					{
						$this->oLogger->WriteException($oException);
					}
				}
				if ($this->oLogger)
				{
					$this->oLogger->WriteException($oException);
				}
			}
		}

		return $bResult2;
	}

	/**
	 * @param string $sPassword
	 * @return string
	 */
	private function cryptPassword($sPassword)
	{
		$sSalt = '';
		$sBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

		for ($iIndex = 0; $iIndex < 8; $iIndex++)
		{
			$sSalt .= $sBase64[\rand(0, 63)];
		}

		return \crypt($sPassword, '$1$'.$sSalt.'$');
	}
}

@goranculibrk
Copy link

goranculibrk commented Mar 1, 2018

Hi,
did anyone manage to get this to work? I can't get this plugin to work with ISPconfig 3.1

@katiakweb
Copy link

My God ... we are in September of 2019 and this problem still exist? What happened to the amazing developers of this plugin? Help us, please! This plugin doesn't work in multi servers!

@katiakweb
Copy link

Hi,
did anyone manage to get this to work? I can't get this plugin to work with ISPconfig 3.1

Same problem here... I almost broke Google serching for a solution, but I don't found. I tried the @OrihuelaConde code also, but also not work for me. I am using ISPConfig 3.1.15 on 5 Debian 9, multi server, dedicated web, mail, etc...

@gppixelworks
Copy link

My God ... we are in September of 2019 and this problem still exist? What happened to the amazing developers of this plugin? Help us, please! This plugin doesn't work in multi servers!

I'm rather surprised as well.

The plugin works on one of the domains controlled by ISPConfig but not another. The broken domain simply returns, "Could not save password".

@samuelpetrosyan
Copy link

samuelpetrosyan commented Jun 2, 2021

I deployed a fine solution
#2095

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants