- Модуль: security
- Путь к файлу: ~/bitrix/modules/security/classes/general/iprule.php
- Класс: CSecurityIPRule
- Вызов: CSecurityIPRule::OnPageStart
static function OnPageStart($use_query = false)
{
//ToDo: good candidate for refactoring
global $DB, $CACHE_MANAGER;
if(
!CSecuritySystemInformation::isCliMode()
&& CSecurityIPRule::GetActiveCount()
)
{
if(CSecurityIPRule::CheckAntiFile())
return;
$bMatch = false;
$uri = $_SERVER['REQUEST_URI'];
if (($pos = mb_strpos($uri, '?')) !== false)
$uri = mb_substr($uri, 0, $pos);
$uri = urldecode($uri);
$uri = preg_replace('#/+#', '/', $uri);
//Block any invalid uri
if (!static::isValidUri($uri))
include($_SERVER['DOCUMENT_ROOT'].'/bitrix/admin/security_403.php'); //die inside
//Normalize on Windows, because my. == my
if (CSecuritySystemInformation::isRunOnWin())
$uri = preg_replace('#(. )+[/\]+#', '/', $uri);
$ip2check = CSecurityIPRule::ip2number($_SERVER["REMOTE_ADDR"]);
if(!$use_query && CACHED_b_sec_iprule !== false)
{
$cache_id = "b_sec_iprule";
if($CACHE_MANAGER->Read(CACHED_b_sec_iprule, $cache_id, "b_sec_iprule"))
{
$arRules = $CACHE_MANAGER->Get($cache_id);
}
else
{
$arRules = array();
$rs = $DB->Query("
SELECT
r.ID,
r.ADMIN_SECTION,
r.SITE_ID,
r.ACTIVE_FROM_TIMESTAMP,
r.ACTIVE_TO_TIMESTAMP
FROM
b_sec_iprule r
WHERE
r.ACTIVE='Y'
AND (
r.ACTIVE_TO IS NULL
OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction()."
)
");
while($ar = $rs->Fetch())
{
$ar["ACTIVE_FROM_TIMESTAMP"] = intval($ar["ACTIVE_FROM_TIMESTAMP"]);
$ar["ACTIVE_TO_TIMESTAMP"] = intval($ar["ACTIVE_TO_TIMESTAMP"]);
$ar["INCL_MASKS"] = array();
$ar["EXCL_MASKS"] = array();
$ar["INCL_IPS"] = array();
$ar["EXCL_IPS"] = array();
$arRules[$ar["ID"]] = $ar;
}
$rs = $DB->Query("
SELECT
im.IPRULE_ID,
im.PREG_MASK
FROM
b_sec_iprule r
INNER JOIN b_sec_iprule_incl_mask im on im.IPRULE_ID = r.ID
WHERE
r.ACTIVE='Y'
AND (
r.ACTIVE_TO IS NULL
OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction()."
)
");
while($ar = $rs->Fetch())
if(array_key_exists($ar["IPRULE_ID"], $arRules))
$arRules[$ar["IPRULE_ID"]]["INCL_MASKS"][] = $ar["PREG_MASK"];
foreach($arRules as $ID => $ar)
if(count($ar["INCL_MASKS"]) <= 0)
unset($arRules[$ID]);
$rs = $DB->Query("
SELECT
em.IPRULE_ID,
em.PREG_MASK
FROM
b_sec_iprule r
INNER JOIN b_sec_iprule_excl_mask em on em.IPRULE_ID = r.ID
WHERE
r.ACTIVE='Y'
AND (
r.ACTIVE_TO IS NULL
OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction()."
)
");
while($ar = $rs->Fetch())
if(array_key_exists($ar["IPRULE_ID"], $arRules))
$arRules[$ar["IPRULE_ID"]]["EXCL_MASKS"][] = $ar["PREG_MASK"];
$rs = $DB->Query("
SELECT
ii.IPRULE_ID,
ii.IP_START,
ii.IP_END
FROM
b_sec_iprule r
INNER JOIN b_sec_iprule_incl_ip ii on ii.IPRULE_ID = r.ID
WHERE
r.ACTIVE='Y'
AND (
r.ACTIVE_TO IS NULL
OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction()."
)
");
while($ar = $rs->Fetch())
if(array_key_exists($ar["IPRULE_ID"], $arRules))
$arRules[$ar["IPRULE_ID"]]["INCL_IPS"][] = array(
doubleval($ar["IP_START"]),
doubleval($ar["IP_END"]),
);
foreach($arRules as $ID => $ar)
if(count($ar["INCL_IPS"]) <= 0)
unset($arRules[$ID]);
$rs = $DB->Query("
SELECT
ei.IPRULE_ID,
ei.IP_START,
ei.IP_END
FROM
b_sec_iprule r
INNER JOIN b_sec_iprule_excl_ip ei on ei.IPRULE_ID = r.ID
WHERE
r.ACTIVE='Y'
AND (
r.ACTIVE_TO IS NULL
OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction()."
)
");
while($ar = $rs->Fetch())
if(array_key_exists($ar["IPRULE_ID"], $arRules))
$arRules[$ar["IPRULE_ID"]]["EXCL_IPS"][] = array(
doubleval($ar["IP_START"]),
doubleval($ar["IP_END"]),
);
$CACHE_MANAGER->Set($cache_id, $arRules);
}
foreach($arRules as $arRule)
{
//Check if this rule is active
if(
($arRule["ACTIVE_FROM_TIMESTAMP"] <= 0 || $arRule["ACTIVE_FROM_TIMESTAMP"] <= time())
&& ($arRule["ACTIVE_TO_TIMESTAMP"] <= 0 || $arRule["ACTIVE_TO_TIMESTAMP"] >= time())
)
{
$bMatch = true;
}
else
{
$bMatch = false;
}
//Check if site does match
if($bMatch)
{
if(defined("ADMIN_SECTION") && ADMIN_SECTION===true)
$bMatch = $arRule["ADMIN_SECTION"] == "Y";
else
$bMatch = (!$arRule["SITE_ID"] || $arRule["SITE_ID"] == SITE_ID);
}
else
{
continue;
}
//Check if IP in blocked
if($bMatch)
{
$bMatch = false;
foreach($arRule["INCL_IPS"] as $arIP)
{
if($ip2check >= $arIP[0] && $ip2check <= $arIP[1])
{
$bMatch = true;
break;
}
}
//IP is in blocked range so check if it is excluded
if($bMatch)
{
foreach($arRule["EXCL_IPS"] as $arIP)
{
if($ip2check >= $arIP[0] && $ip2check <= $arIP[1])
{
$bMatch = false;
break;
}
}
}
}
else
{
continue;
}
//IP does match to blocking condition let's check path
if($bMatch)
{
$bMatch = false;
foreach($arRule["INCL_MASKS"] as $mask)
{
if(preg_match("#^".$mask."$#", $uri))
{
$bMatch = true;
break;
}
}
//Check path for exclusion
if($bMatch)
{
foreach($arRule["EXCL_MASKS"] as $mask)
{
if(preg_match("#^".$mask."$#", $uri))
{
$bMatch = false;
break;
}
}
}
}
else
{
continue;
}
//Found blocking rule
if($bMatch)
break;
}
}
else
{
$strSql = "
SELECT r.ID
FROM
b_sec_iprule r
INNER JOIN b_sec_iprule_incl_mask im on im.IPRULE_ID = r.ID
LEFT JOIN b_sec_iprule_excl_mask em on em.IPRULE_ID = r.ID AND '".$DB->ForSQL($uri)."' like em.LIKE_MASK
INNER JOIN b_sec_iprule_incl_ip ii on ii.IPRULE_ID = r.ID
LEFT JOIN b_sec_iprule_excl_ip ei on ei.IPRULE_ID = r.ID AND ".$ip2check." between ei.IP_START and ei.IP_END
WHERE
r.ACTIVE = 'Y'
AND (r.ACTIVE_FROM IS NULL OR r.ACTIVE_FROM <= ".$DB->CurrentTimeFunction().")
AND (r.ACTIVE_TO IS NULL OR r.ACTIVE_TO >= ".$DB->CurrentTimeFunction().")
".(defined("ADMIN_SECTION") && ADMIN_SECTION===true?
"AND r.ADMIN_SECTION = 'Y'":
"AND (r.SITE_ID IS NULL OR r.SITE_ID = '".$DB->ForSQL(SITE_ID)."')"
)."
AND '".$DB->ForSQL($uri)."' like im.LIKE_MASK
AND em.IPRULE_ID is null
AND ".$ip2check." between ii.IP_START and ii.IP_END
AND ei.IPRULE_ID is null
";
$rs = $DB->Query($strSql);
if($arRule = $rs->Fetch())
$bMatch = true;
else
$bMatch = false;
}
if($bMatch)
include($_SERVER["DOCUMENT_ROOT"]."/bitrix/admin/security_403.php");
}
}