download this file: class.network.tcpwrap.php view text/plain: class.network.tcpwrap.php file encoding: UTF-8 [goback]
<?php
## this file name is 'class.network.tcpwrap.php'
##
## simple check ipaddress math of tcpwrapper /etc/hosts.allow or /etc/hosts.deny
## such as PECL/tcpwrap
##
## - support php4.2.x(J5K/admin UI), php5.x
##
## - san2@2009.06.26: support case-insensitive in daemon_list
## - san2@2009.06.23: daemon match bug fixed
## - san2@2009.06.22: new build
##
## - example
## tcpwrap::match(NULL,$_SERVER['REMOTE_ADDR']);
## or
## tcpwrap::match('sshd',$_SERVER['REMOTE_ADDR']);
##
## - return value
## 0: no match, FALSE
## 1: match, TRUE
##
class tcpwrap
{
## public, check to allow
##
function &match($daemon, $client)
{
$denyrule = tcpwrap::_match('/etc/hosts.deny',$daemon,$client);
if(!$denyrule || $denyrule=='allow') return TRUE;
$allowrule = tcpwrap::_match('/etc/hosts.allow',$daemon,$client);
return ($allowrule=='allow') ? TRUE : FALSE;
}
## private, core
## hosts_access(5) daemon_list : client_list [ : shell_command ]
## hosts_options(5) daemon_list : client_list : option : option ...
##
function &_match($file, $daemon, $client)
{
if(!file_exists($file)) return -1;
if(!$fp = fopen($file,'r')) return -1;
$baserule = preg_match('/\.allow$/',$file) ? 'allow' : 'deny';
$daemon = strtoupper(trim($daemon)); // rewrite
$client = trim($client); // rewrite
while($line = fgets($fp,1024))
{
list($line) = explode('#',trim($line));
if(!$line = trim($line)) continue;
if(preg_match('/(.+)\\\$/',$line,$m))
{
$pline .= $m[1].' ';
continue;
}
$tmp = explode(':',$pline.$line);
$size = sizeof($tmp);
$dlists = trim($tmp[0]);
$clists = trim($tmp[1]);
## match rlue
if($size > 2)
{
$rule = strtolower(trim($tmp[$size-1]));
$rule = preg_match("/^(allow|deny)$/",$rule) ? $rule : $baserule;
}
else $rule = $baserule;
## check daemon list
##
if($daemon && $daemon!='ALL')
{
list($dmatch,$dexcept) = tcpwrap::__get_matchlist(strtoupper($dlists));
if($dexcept && in_array($daemon,$dexcept)) continue;
if(!in_array('ALL',$dmatch) && !in_array($daemon,$dmatch)) continue;
}
list($match,$except) = tcpwrap::__get_matchlist($clists);
if($except && tcpwrap::__ipmatch($client,$except)) continue;
if(tcpwrap::__ipmatch($client,$match))
{
$r = $rule;
break;
}
$pline = '';
}
@fclose($fp);
return $r ? $r : FALSE;
}
## private, get daemon list
##
function &__get_matchlist($str)
{
$rr = $ee = array();
$arr = explode(',',preg_replace('/[\s]+/',' ',$str));
foreach($arr AS $v)
{
list($u,$e) = explode('EXCEPT',trim($v));
$rr = array_merge($rr, explode(' ',trim($u)));
if($e) $ee = array_merge($ee, explode(' ',trim($e)));
}
return array($rr,$ee);
}
function &__ipmatch($ip, $arr)
{
if(!is_array($arr)) $arr = array($arr);
if(in_array($ip,$arr)) return TRUE;
$ipbit = tcpwrap::inet_atob($ip);
foreach($arr AS $v)
{
if($v == 'ALL')
{
return TRUE;
break;
}
else if(preg_match(';/;',$v)) // network/netmask
{
list($net,$mask) = explode('/',$v);
$mbit = tcpwrap::inet_atob($mask);
$unet = ($ipbit & $mbit);
$unet = tcpwrap::inet_btoa("$unet"); // required double quota "
if($unet == $net)
{
return TRUE;
break;
}
}
else if(preg_match(';\.$;',$v))
{
if(preg_match("/^$v/",$ip)) // $v = str_replace('.','\.',$v);
{
return TRUE;
break;
}
}
}
return; // false
}
## check /etc/hosts hosts
## such as getent
##
function &__getent_hosts($ipaddr)
{
return;
}
function &inet_atob($ipaddr)
{
return sprintf('%032b',ip2long($ipaddr));
}
function &inet_btoa($bits)
{
return long2ip(bindec("$bits"));
}
} // eof clss
## EOF
?>