Skip to content

Commit

Permalink
Merge branch 'pu/cw/bypassAreaLocks' into '2024.11'
Browse files Browse the repository at this point in the history
tweak(Tinebase): support to bypass areaLocks by IP

See merge request tine20/tine20!6587
  • Loading branch information
pschuele committed Feb 17, 2025
2 parents 1053c1b + c373be9 commit 9d6572d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 14 deletions.
11 changes: 10 additions & 1 deletion tine20/Tinebase/AreaLock.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ protected function _hasValidAuth(string $area): bool
. __LINE__ . ' Config not found for area ' . $area);
return false;
}

if (Tinebase_Auth_MFA::checkMFABypass()) {
return true;
}

/** @var Tinebase_Model_AreaLockConfig $config */
foreach($configs as $config) {
if (!$config->getBackend()->hasValidAuth()) {
Expand All @@ -272,13 +277,17 @@ protected function _hasValidAuth(string $area): bool
}

/**
* @param string $area
* @return array<Tinebase_DateTime>
*/
protected function _getAuthValidity(string $area): array
{
$bypass = Tinebase_Auth_MFA::checkMFABypass();
$result = [];
foreach ($this->getAreaConfigs($area) as $config) {
$result[$config->{Tinebase_Model_AreaLockConfig::FLD_AREA_NAME}] = $config->getBackend()->getAuthValidity();
$result[$config->{Tinebase_Model_AreaLockConfig::FLD_AREA_NAME}] = $bypass
? Tinebase_DateTime::now()->addYear(1)
: $config->getBackend()->getAuthValidity();
}
return $result;
}
Expand Down
20 changes: 20 additions & 0 deletions tine20/Tinebase/Auth/MFA.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* @author Paul Mehrer <[email protected]>
*/

use \IPLib\Factory;

/**
* SecondFactor Auth Facade
*
Expand Down Expand Up @@ -135,6 +137,24 @@ private function __construct(Tinebase_Model_MFA_Config $config)
$this->_config = $config;
}

public static function checkMFABypass(): bool
{
// mfa free netmasks:
if (($_SERVER['HTTP_X_REAL_IP'] ?? false) &&
!empty($byPassMasks = Tinebase_Config::getInstance()->{Tinebase_Config::MFA_BYPASS_NETMASKS}) &&
($ip = Factory::parseAddressString($_SERVER['HTTP_X_REAL_IP']))
) {
foreach ($byPassMasks as $netmask) {
if (Factory::parseRangeString($netmask)?->contains($ip)) {
// bypassing
return true;
}
}
}

return false;
}

/**
* don't clone. Use the singleton.
*/
Expand Down
17 changes: 4 additions & 13 deletions tine20/Tinebase/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
*
*/

use \IPLib\Factory;
use \Psr\Http\Message\RequestInterface;

/**
Expand Down Expand Up @@ -926,19 +925,11 @@ public function _validateSecondFactor(Tinebase_Model_AccessLog $accessLog, Tineb
$areaLock = Tinebase_AreaLock::getInstance();
$userConfigIntersection = new Tinebase_Record_RecordSet(Tinebase_Model_MFA_UserConfig::class);
if ($areaLock->hasLock(Tinebase_Model_AreaLockConfig::AREA_LOGIN)) {
// mfa free netmasks:
if (($_SERVER['HTTP_X_REAL_IP'] ?? false) &&
!empty($byPassMasks = Tinebase_Config::getInstance()->{Tinebase_Config::MFA_BYPASS_NETMASKS}) &&
($ip = Factory::parseAddressString($_SERVER['HTTP_X_REAL_IP']))) {
foreach ($byPassMasks as $netmask) {
if (Factory::parseRangeString($netmask)?->contains($ip)) {
// bypassing
if ($this->_forceUnlockLoginArea) {
$areaLock->forceUnlock(Tinebase_Model_AreaLockConfig::AREA_LOGIN);
}
return;
}
if (Tinebase_Auth_MFA::checkMFABypass()) {
if ($this->_forceUnlockLoginArea) {
$areaLock->forceUnlock(Tinebase_Model_AreaLockConfig::AREA_LOGIN);
}
return;
}

/** @var Tinebase_Model_AreaLockConfig $areaConfig */
Expand Down

0 comments on commit 9d6572d

Please sign in to comment.