| Current Path : /var/www/consult-e-syn/public_html/plugins/system/admintools/feature/ |
| Current File : /var/www/consult-e-syn/public_html/plugins/system/admintools/feature/trackfailedlogins.php |
<?php
/**
* @package admintools
* @copyright Copyright (c)2010-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
use FOF40\Date\Date;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Authentication\AuthenticationResponse;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\User\UserHelper;
defined('_JEXEC') || die;
class AtsystemFeatureTrackfailedlogins extends AtsystemFeatureAbstract
{
protected $loadOrder = 410;
/**
* Is this feature enabled?
*
* @return bool
*/
public function isEnabled()
{
return ($this->cparams->getValue('trackfailedlogins', 0) == 1);
}
/**
* Treat failed logins as security exceptions
*
* @param AuthenticationResponse $response
*/
public function onUserLoginFailure($response)
{
// Exit if the IP is blacklisted; logins originating from blacklisted IPs will be blocked anyway
if ($this->parentPlugin->runBooleanFeature('isIPBlocked', false, []))
{
return;
}
$extraInfo = null;
$user = $this->input->getString('username', null);
// Log the username only if we have a user AND we told Admin Tools to store usernames, too
if ($this->cparams->getValue('logusernames', 0) && !empty($user))
{
$extraInfo = 'Username: ' . $user;
}
$this->exceptionsHandler->logAndAutoban('loginfailure', $user, $extraInfo);
$this->deactivateUser($user);
}
private function deactivateUser($username)
{
$userParams = ComponentHelper::getParams('com_users');
// User registration disabled or no user activation - Let's stop here
if (!$userParams->get('allowUserRegistration') || ($userParams->get('useractivation') == 0))
{
return;
}
$ip = AtsystemUtilFilter::getIp();
// If I can't detect the IP there's not point in continuing
if (!$ip)
{
return;
}
$limit = $this->cparams->getValue('deactivateusers_num', 3);
$numfreq = $this->cparams->getValue('deactivateusers_numfreq', 1);
$frequency = $this->cparams->getValue('deactivateusers_frequency', 'hour');
// The user didn't set any limit nor frequency value, let's stop here
if (!$limit || !$numfreq)
{
return;
}
$userid = UserHelper::getUserId($username);
// The user doesn't exists, let's stop here
if (!$userid)
{
return;
}
$user = $this->container->platform->getUser($userid);
// Username doesn't match, the user is blocked or is not active? Let's stop here
if ($user->username != $username || $user->block || !(empty($user->activation)))
{
return;
}
// If I'm here, it means that this is a valid user, let's see if I have to deactivate him
$where = [
'ip' => $ip,
'reason' => 'loginfailure',
];
$deactivate = $this->checkLogFrequency($limit, $numfreq, $frequency, $where);
if (!$deactivate)
{
return;
}
PluginHelper::importPlugin('user');
$db = $this->db;
$randomPassword = class_exists('Joomla\\CMS\\User\\UserHelper') ? UserHelper::genRandomPassword() : UserHelper::genRandomPassword();
$data['activation'] = class_exists('Joomla\\CMS\\Application\\ApplicationHelper') ? ApplicationHelper::getHash($randomPassword) : JApplication::getHash($randomPassword);
$data['block'] = 1;
$data['lastvisitDate'] = version_compare(JVERSION, '3.9999.9999', 'le') ? $db->getNullDate() : null;
// If an admin needs to activate the user, I have to set the activate flag
if ($userParams->get('useractivation') == 2)
{
$user->setParam('activate', 1);
}
if (!$user->bind($data))
{
return;
}
if (!$user->save())
{
return;
}
// Ok, now it's time to send the activation email again
$template = $this->exceptionsHandler->getEmailTemplate('user-reactivate', true);
// Well, this should never happen...
if (!$template)
{
return;
}
$subject = $template[0];
$body = $template[1];
$config = $this->container->platform->getConfig();
try
{
$mailer = Factory::getMailer();
$mailfrom = $config->get('mailfrom');
$fromname = $config->get('fromname');
$uri = Uri::getInstance();
$base = $uri->toString(['scheme', 'user', 'pass', 'host', 'port']);
$activate = $base . Route::_('index.php?option=com_users&task=registration.activate&token=' . $data['activation'], false);
// Send e-mail to the user
if ($userParams->get('useractivation') == 1)
{
$mailer->addRecipient($user->email);
}
// Send e-mail to Super Users
elseif ($userParams->get('useractivation') == 2)
{
// get all admin users
$query = $db->getQuery(true)
->select($db->qn(['name', 'email', 'sendEmail', 'id']))
->from($db->qn('#__users'))
->where($db->qn('sendEmail') . ' = ' . 1);
$rows = $db->setQuery($query)->loadObjectList();
// Send mail to all users with users creating permissions and receiving system emails
foreach ($rows as $row)
{
$usercreator = $this->container->platform->getUser($row->id);
if ($usercreator->authorise('core.create', 'com_users') && !empty($usercreator->email))
{
$mailer->addRecipient($usercreator->email);
}
}
}
else
{
// Future-proof check
return;
}
$tokens = $this->exceptionsHandler->getEmailVariables('', [
'[ACTIVATE]' => '<a href="' . $activate . '">' . $activate . '</a>',
'[USER]' => $user->username . ' (' . $user->name . ' <' . $user->email . '>)',
]);
$subject = str_replace(array_keys($tokens), array_values($tokens), $subject);
$body = str_replace(array_keys($tokens), array_values($tokens), $body);
// This line is required because SpamAssassin is BROKEN
$mailer->Priority = 3;
$mailer->isHtml(true);
$mailer->setSender([$mailfrom, $fromname]);
$mailer->setSubject($subject);
$mailer->setBody($body);
$mailer->Send();
}
catch (Exception $e)
{
// Joomla! 3.5 and later throw an exception when crap happens instead of suppressing it and returning false
}
}
/**
* @param $limit
* @param $numfreq
* @param $frequency
* @param array $extraWhere
*
* @return bool
*/
private function checkLogFrequency($limit, $numfreq, $frequency, array $extraWhere)
{
$db = $this->db;
$mindatestamp = 0;
switch ($frequency)
{
case 'second':
break;
case 'minute':
$numfreq *= 60;
break;
case 'hour':
$numfreq *= 3600;
break;
case 'day':
$numfreq *= 86400;
break;
case 'ever':
$mindatestamp = 946706400; // January 1st, 2000
break;
}
$jNow = new Date();
if ($mindatestamp == 0)
{
$mindatestamp = $jNow->toUnix() - $numfreq;
}
$jMinDate = new Date($mindatestamp);
$minDate = $jMinDate->toSql();
$sql = $db->getQuery(true)
->select('COUNT(*)')
->from($db->qn('#__admintools_log'))
->where($db->qn('logdate') . ' >= ' . $db->q($minDate));
foreach ($extraWhere as $column => $value)
{
$sql->where($db->qn($column) . ' = ' . $db->q($value));
}
$db->setQuery($sql);
try
{
$numOffenses = $db->loadResult();
}
catch (Exception $e)
{
$numOffenses = 0;
}
if ($numOffenses < $limit)
{
return false;
}
return true;
}
}