| Current Path : /home/poneycluc/www/plugins/system/bfnetwork/bfnetwork/ |
| Current File : /home/poneycluc/www/plugins/system/bfnetwork/bfnetwork/bfAdmintools.php |
<?php
/*
* @package bfNetwork
* @copyright Copyright (C) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Blue Flame Digital Solutions Ltd. All rights reserved.
* @license GNU General Public License version 3 or later
*
* @see https://mySites.guru/
* @see https://www.phil-taylor.com/
*
* @author Phil Taylor / Blue Flame Digital Solutions Limited.
*
* bfNetwork is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* bfNetwork is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package. If not, see http://www.gnu.org/licenses/
*
* If you have any questions regarding this code, please contact phil@phil-taylor.com
*/
/*
* Akeeba Admin Tools Professional integration: detect when Admin Tools' WAF has blocked the
* mySites.guru worker/proxy IP, and clear that block so audits, snapshots, backups and updates
* can reach the site again.
*
* Admin Tools auto-bans an IP after repeated "security exceptions". Because every mySites.guru
* call to this site arrives from the same egress IP, the WAF can auto-ban us, after which every
* remote call silently fails. This helper removes our IP from all of Admin Tools' block state and
* adds it to the permanent allow-list so it is never auto-banned again.
*
* IP block state lives across these Admin Tools tables (real #__admintools_* tables, so the
* connector's $db resolves #__ to the live prefix):
* ipblock (id, ip, description) - manual permanent block list
* ipautoban (ip PK, reason, until) - WAF auto-ban (the one that locks us out)
* ipautobanhistory (id, ip, reason, until) - tally that drives re-banning
* ipallow (id, ip, description) - permanent allow-list (never auto-banned)
*
* Every query is wrapped so a missing/half-installed Admin Tools can never fatal the snapshot.
*
* If we have got here then we have already passed through decrypting the encrypted header and so
* we are sure we are now secure and no one else can run the code below.
*/
final class bfAdmintools
{
/**
* Description stamped on the allow-list entry we add for the worker IP.
*/
private const ALLOW_DESCRIPTION = 'mySites.guru management IP - auto allow-listed';
/**
* @var object
*/
private $db;
public function __construct($db)
{
$this->db = $db;
}
/**
* Is the Admin Tools component installed and enabled on this site?
*/
public function isInstalled(): bool
{
try {
$this->db->setQuery(
"SELECT COUNT(*) FROM #__extensions WHERE element = 'com_admintools' AND type = 'component' AND enabled = 1"
);
return (int) $this->db->loadResult() > 0;
} catch (\Throwable $e) {
return false;
}
}
/**
* Is the given IP currently blocked by Admin Tools? True if it appears in either the manual
* block list or the WAF auto-ban list.
*/
public function isIpBlocked(string $ip): bool
{
$ip = trim($ip);
if ($ip === '') {
return false;
}
$quoted = $this->db->quote($ip);
foreach (['ipblock', 'ipautoban'] as $table) {
try {
$this->db->setQuery('SELECT COUNT(*) FROM #__admintools_' . $table . ' WHERE ip = ' . $quoted);
if ((int) $this->db->loadResult() > 0) {
return true;
}
} catch (\Throwable $e) {
// Table missing or unreadable - treat as not blocked for this table.
continue;
}
}
return false;
}
/**
* Remove the given IP from every Admin Tools block table, then add it to the permanent
* allow-list (idempotently) so it cannot be auto-banned again.
*
* @return array
*/
public function unblockIp(string $ip): array
{
$ip = trim($ip);
$result = [
'ipblock' => 0,
'ipautoban' => 0,
'ipautobanhistory' => 0,
'allowlisted' => false,
'ip' => $ip,
];
if ($ip === '') {
return $result;
}
$quoted = $this->db->quote($ip);
foreach (['ipblock', 'ipautoban', 'ipautobanhistory'] as $table) {
try {
$this->db->setQuery('DELETE FROM #__admintools_' . $table . ' WHERE ip = ' . $quoted);
$this->db->execute();
$result[$table] = (int) $this->db->getAffectedRows();
} catch (\Throwable $e) {
// Table missing - nothing to delete.
continue;
}
}
$result['allowlisted'] = $this->allowListIp($ip);
return $result;
}
/**
* Add the IP to the Admin Tools allow-list if it is not already there. Returns true when the
* IP is present in the allow-list afterwards (whether we added it or it was already there).
*/
private function allowListIp(string $ip): bool
{
$quoted = $this->db->quote($ip);
try {
$this->db->setQuery('SELECT COUNT(*) FROM #__admintools_ipallow WHERE ip = ' . $quoted);
if ((int) $this->db->loadResult() > 0) {
return true;
}
$this->db->setQuery(
'INSERT INTO #__admintools_ipallow (ip, description) VALUES ('
. $quoted . ', ' . $this->db->quote(self::ALLOW_DESCRIPTION) . ')'
);
$this->db->execute();
return true;
} catch (\Throwable $e) {
return false;
}
}
}