123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- <?php
- require_once "Net/CheckIP.php";
- /**
- * RadAct
- *
- */
- class RadAct{
- /** @var String */
- public $radacctid;
- /** @var String */
- public $acctsessionid;
- /** @var String */
- public $acctuniqueid;
- /** @var String */
- public $username;
- /** @var String */
- public $groupname;
- /** @var String */
- public $realm;
- /** @var String */
- public $nasipaddress;
- /** @var String */
- public $nasportid;
- /** @var String */
- public $nasporttype;
- /** @var String */
- public $acctstarttime;
- /** @var String */
- public $acctstoptime;
- /** @var String */
- public $acctsessiontime;
- /** @var String */
- public $acctauthentic;
- /** @var String */
- public $connectinfo_start;
- /** @var String */
- public $connectinfo_stop;
- /** @var String */
- public $acctinputoctets;
- /** @var String */
- public $acctoutputoctets;
- /** @var String */
- public $calledstationid;
- /** @var String */
- public $callingstationid;
- /** @var String */
- public $acctterminatecause;
- /** @var String */
- public $servicetype;
- /** @var String */
- public $framedprotocol;
- /** @var String */
- public $framedipaddress;
- /** @var String */
- public $acctstartdelay;
- /** @var String */
- public $acctstopdelay;
- /** @var String */
- public $xascendsessionsvrkey;
- }
- /**
- * RadiusClient
- * RadiusClient
- */
- class RadiusClient {
- /** @var String */
- public $nasname;
- /** @var String */
- public $shortname;
- /** @var String */
- public $type;
- /** @var String */
- public $ports;
- /** @var String */
- public $secret;
- /** @var String */
- public $community;
- /** @var String */
- public $description;
- /** @var String */
- public $server;
-
- /** @var String */
- public $acct_enabled;
- }
- /**
- * RadiusRecord
- * RadiusRecord
- */
- class RadiusRecord{
- /** @var String */
- public $user;
- /** @var String */
- public $password;
- /** @var RadiusGroup */
- public $group;
-
- /** @var RadiusProp[] */
- public $reply;
- /** @var RadiusProp[] */
- public $check;
- }
- class RadiusProp{
- /** @var String */
- public $name;
- /** @var String */
- public $value;
- }
- class RadiusGroup{
- /** @var String */
- public $name;
- /** @var RadiusProp[] */
- public $reply;
- /** @var RadiusProp[] */
- public $check;
- public function getCheckArray(){
- $rtr = array();
- foreach($this->check as $r){
- $rtr[$r->name] = $r->value;
- }
- return $rtr;
- }
- public function getReplyArray(){
- $rtr = array();
- foreach($this->reply as $r){
- $rtr[$r->name] = $r->value;
- }
- return $rtr;
- }
- }
- class AccessServiceManager
- {
- private $sql_host = 'mysql';
- private $sql_user = "root";
- private $sql_pass = "";
- private $sql_db = 'freeradius';
- private $delete_group = true;
- private function getSqlCon(){
- $sql_db = $this->sql_db;
- $sql_host = $this->sql_host;
- $sql_user = "root"; //(getenv("MYSQL_USER"))?(getenv("MYSQL_USER")):$this->sql_user;
- $sql_pass = (getenv("MYSQL_ROOT_PASSWORD"))?(getenv("MYSQL_ROOT_PASSWORD")):$this->sql_pass;
- $dbh = new PDO("mysql:host=$sql_host;dbname=$sql_db", $sql_user, $sql_pass);
- return $dbh;
- }
- /**
- *Add a RadiusRecord on the Radius database in case the record exists the record is updated it returns True on success and False if a failure exists
- * @param RadiusRecord
- * @return Boolean
- */
- function addRadiusRecord(RadiusRecord $rr){
- $this->deleteRadiusRecord($rr);
- $this->addRadiusGroup($rr->group);
- syslog(LOG_DEBUG, __FUNCTION__);
- $dbh = $this->getSqlCon();
- $login = $rr->user;
- $Passwd = $rr->password;
- $values[] = "('$login','Password',':=','$Passwd')";
- foreach($rr->check as $k){
- $values[] = sprintf("('$login','%s',':=','%s')", $k->name, $k->value);
- }
- $values = implode(',', $values);
- $sql = "INSERT INTO radcheck (UserName,Attribute,op,Value) VALUES $values;";
- $rtr0 = $dbh->exec($sql);
- syslog(LOG_ALERT, $sql);
- $group = $rr->group;
- $sql="INSERT INTO radusergroup (UserName,GroupName) VALUES ('$login', '$group->name');";
- $rtr1 = $dbh->exec($sql);
- syslog(LOG_DEBUG, $sql);
- $rtr2 = true;
- $replys = array();
- foreach($rr->reply as $k)
- $replys[] = sprintf("('$login','%s','=','%s')", $k->name, $k->value);
- $rtr2 = true;
- if(!empty($replys)){
- $replysValue = implode(',', $replys);
- $sql="INSERT INTO radreply (UserName,Attribute,op,Value) VALUES $replysValue;";
- $rtr2 = $dbh->exec($sql);
- syslog(LOG_ALERT, $sql);
- }
- if($rtr0 and $rtr1 and $rtr2) return true;
- else return false;
- }
-
- protected function getRadiusGroupFromDb($groupName){
- $dbh = $this->getSqlCon();
- $tables = array('reply' => 'radgroupreply', 'check' => 'radgroupcheck');
- $rg_db = new RadiusGroup;
- $rg_db->name = $groupName;
- foreach($tables as $key => $table){
- $sql = sprintf("SELECT id, Attribute, op, Value
- FROM %s WHERE GroupName='%s'", $table, $groupName);
- $rtr = $dbh->query($sql);
- $props = array();
- foreach($rtr as $rr){
- $props[] = $p = new RadiusProp;
- $p->name = $rr['Attribute'];
- $p->value = $rr['Value'];
- }
- $rg_db->$key = $props;
- }
- return $rg_db;
- }
- protected function safeRadiusGroup(RadiusGroup $rg){
- $rg->name = preg_replace("|[^A-Za-z0-9]|", "-", $rg->name);
- return $rg;
- }
-
- /**
- * @param RadiusGroup
- *
- * @return Boolean
- */
- function deleteRadiusGroup(RadiusGroup $rg)
- {
- $rg = $this->safeRadiusGroup($rg);
- $sql = sprintf("SELECT COUNT( * ) AS `Filas` , `groupname` FROM `radusergroup` WHERE groupname = '%s' GROUP BY `groupname`", $rg->name);
- $dbh = $this->getSqlCon();
- $rtr = $dbh->query($sql);
- $total = 0;
- foreach($rtr as $t) $total = $t['Filas'];
- if($total == 0){
- $sql = "DELETE FROM `%s` WHERE GroupName = '%s'";
- foreach(array('radgroupcheck', 'radgroupreply',) as $table)
- $dbh->exec(sprintf($sql,$table, $rg->name));
- }
- //Residuos
- $sql = "DELETE FROM `radgroupcheck` WHERE `GroupName` NOT IN (SELECT DISTINCT (`groupname`) FROM `radusergroup` WHERE 1);";
- $dbh->exec($sql);
- $sql = "DELETE FROM `radgroupreply` WHERE `GroupName` NOT IN (SELECT DISTINCT (`groupname`) FROM `radusergroup` WHERE 1);";
- $dbh->exec($sql);
-
- return true;
- }
-
- /**
- * @param RadiusGroup
- *
- * @return Boolean
- */
- function addRadiusGroup(RadiusGroup $rg)
- {
- $rg = $this->safeRadiusGroup($rg);
- $dbh = $this->getSqlCon();
- $rgDB = $this->getRadiusGroupFromDb($rg->name);
- $props = array('check' => $rg->getCheckArray(), 'reply' => $rg->getReplyArray());
- $propsDB = array('check' => $rgDB->getCheckArray(), 'reply' => $rgDB->getReplyArray());
- foreach(array('check' => array('table' => 'radgroupcheck', 'op' => ':='),
- 'reply' => array('table' => 'radgroupreply', 'op' => '=')) as $op => $config) {
- $table = $config['table'];
- $key = array_keys($props[$op]);
- $keyDB = array_keys($propsDB[$op]);
- $agregar = array_diff($key, $keyDB);
- $borrar = array_diff($keyDB, $key);
- $actualizar = array_diff($key, array_merge($agregar, $borrar));
- if(!empty($borrar)){
- $borrar = array_map(array($dbh, "quote"), $borrar);
- $sql = sprintf("DELETE FROM %s WHERE GroupName='%s' AND Attribute IN (%s);",
- $table, $rg->name, implode(", ", $borrar));
- $dbh->exec($sql);
- }
- if(!empty($agregar)){
- foreach($agregar as $attribute){
- $sql = sprintf("INSERT INTO `%s` ( `GroupName` , `Attribute` , `op` , `Value` ) VALUES (%s, %s, %s, %s);", $table,
- $dbh->quote($rg->name),
- $dbh->quote($attribute),
- $dbh->quote($config['op']),
- $dbh->quote($props[$op][$attribute]));
- $dbh->exec($sql);
- }
- }
- if(!empty($actualizar)){
- foreach($actualizar as $attribute){
- $sql = sprintf("UPDATE `%s` SET `op`='%s', `Value` = %s WHERE GroupName=%s AND Attribute=%s;",
- $table,
- $config['op'],
- $dbh->quote($props[$op][$attribute]), //Value
- $dbh->quote($rg->name), //GroupName
- $dbh->quote($attribute) //GroupName
- );
- $dbh->exec($sql);
- }
- }
- }
-
- return true;
- }
- /**
- *Update a RadiusRecord on the Radius database in case the record dosn't exists the record is updated
- * it returns True on success and False if a failure exists
- * @param RadiusRecord
- * @return boolean
- */
- function updateRadiusRecord(RadiusRecord $rr){
- $this->deleteRadiusRecord($rr);
- return $this->addRadiusRecord($rr);
- }
- /**
- *Delete a RadiusRecord from the Radius database.
- * it returns True on success and False if a failure exists, such as the Record is not found.
- * @param RadiusRecord $rr
- * @return boolean
- */
- function deleteRadiusRecord(RadiusRecord $rr){
- $dbh = $this->getSqlCon();
- $login = $rr->user;
- $Passwd = $rr->password;
- $sql = "DELETE FROM radcheck WHERE UserName='$login';";
- $rtr0 = $dbh->exec($sql);
- if(empty($rr->group)) $rr->group = 'Full';
- $group = $rr->group;
- $sql="DELETE FROM radusergroup WHERE username='$login';";
- $rtr1 = $dbh->exec($sql);
- $rtr2 = true;
-
- $sql="DELETE FROM radreply WHERE UserName='$login';";
- $rtr2 = $dbh->exec($sql);
- $this->deleteRadiusGroup($rr->group);
-
- shell_exec($cmd = sprintf("php /etc/freeradius/close_radius_session.php --username=%s &", $login));
- syslog(LOG_INFO, $cmd);
- $this->disconnectRadiusRecord($rr);
-
- return $rtr0;
- }
-
- /**
- * Send a disconnect message to the nas server on all of the user active connections
- * @param RadiusRecord $rr
- * @return int number of connection succesfully reseted.
- */
- function disconnectRadiusRecord(RadiusRecord $rr){
- $mac_auth = false;
- if(preg_match("/([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i",$rr->user,$matches)){
- $mac_auth = true;
- }
- $dbh = $this->getSqlCon();
- $nasSQL = "SELECT nasname, secret FROM nas";
- $nasInfo = array(); $rtr = 0;
- foreach($dbh->query($nasSQL) as $nas){
- if(preg_match( "/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" .
- "(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $nas['nasname']))
- $ip = $nas['nasname'];
- else $ip = gethostbyname($nas['nasname']);
- $nasInfo[$ip] = $nas['secret'];
- }
- $sql = "SELECT * FROM `radacct` WHERE `username` = ? AND ( `acctstoptime` IS NULL) ORDER BY `radacct`.`radacctid` DESC";
- $stmt = $dbh->prepare($sql);
- $rtr0 = $stmt->execute(array($rr->user));
- $return_var = 0;
- $rads = $stmt->fetchall();
- foreach ($rads as $rad) {
- $force_close = false;
- $user = $rr->user;
- if($mac_auth){
- unset($matches[0]);
- $mac_user1 = implode(":",$matches);
- $mac_user2 = implode("-",$matches);
- if($rad['callingstationid'] == $mac_user1 or $rad['callingstationid'] === $mac_user2 ){
- $user = $rad['callingstationid'];
- }
- }
- if(isset($nasInfo[$rad['nasipaddress']])){
- $cmd = sprintf("/bin/bash " . getcwd()."/scripts/raddisconnect.sh %s %s %s",
- escapeshellarg($rad['nasipaddress']),
- escapeshellarg($nasInfo[$rad['nasipaddress']]),
- escapeshellarg($user));
- if(!empty($rad['framedipaddress'])){
- $cmd = sprintf("%s %s", $cmd, escapeshellarg($rad['framedipaddress']));
- }
- $rtr_cmd= system ( "$cmd", $return_var);
- $radacctid = $rad['radacctid'];
- if($return_var == 0){
- $rtr++;
- syslog(LOG_INFO, basename(__FILE__) . " running cmd (OK) (radacctid $radacctid) ROW {$stmt->rowCount()}" . $cmd);
- }else{
- syslog(LOG_INFO, basename(__FILE__) . " running cmd (FAIL - $return_var) (radacctid $radacctid) ROW {$stmt->rowCount()}" . $cmd);
- $force_close = true;
- }
- }else{
- syslog(LOG_ALERT, sprintf("Can't find the nas %s IP on the nas table.",$rad['nasipaddress']));
- $force_close = true;
- }
- if($force_close){
- $sql = sprintf("UPDATE `radius`.`radacct` SET `acctstoptime` = NOW( ) ,
- `acctterminatecause` = 'unresponsive session (radius WS)' WHERE
- `radacct`.`radacctid` =%d", $rad['radacctid']);
- $dbh->exec($sql);
- }
- }
- return $rtr;
- }
- /**
- *Search all RadiusRecord with the matching pattern
- * @param String $pattern the patter to search for
- * @param Boolean $exact specify if the match shuld be exact otherwise, will match ani username containing the patter
- * @return RadiusRecord[]
- */
- function listRadiusRecord($pattern, $exact = true){
- if(is_null($exact)) $exact = true;
- $dbh = $this->getSqlCon();
- $sql = "SELECT UserName, Value FROM radcheck WHERE Attribute='Password' AND op=':=' AND UserName LIKE '%s'";
- if(!$exact) $pattern = '%' . $pattern . '%';
- $sql = sprintf($sql, $pattern);
- $rtr = array();
- foreach($dbh->query($sql) as $rr){
- $rtr[$rr['UserName']] = $r = new RadiusRecord();
- $r->user = $rr['UserName'];
- $r->password = $rr['Value'];
- }
- $sql = "SELECT UserName, GroupName FROM radusergroup WHERE UserName LIKE '%s'";
- $sql = sprintf($sql, $pattern);
- foreach($dbh->query($sql) as $info){
- if(($rtr[$info['UserName']]))
- {
- $rr = $rtr[$info['UserName']];
- $rr->group = $info['GroupName'];
- }
- }
- $sql = "SELECT UserName, Value FROM radreply WHERE Attribute='Framed-IP-Address' AND op = '=' AND UserName LIKE '%s'";
- $sql = sprintf($sql, $pattern);
- foreach($dbh->query($sql) as $info){
- if(($rtr[$info['UserName']]))
- {
- $rr = $rtr[$info['UserName']];
- $rr->ipAddress = $info['Value'];
- }
- }
- return $rtr;
-
- }
- /**
- * Add (or update) a entry in the NAS (radius Client) table
- * @param RadiusClient $radclient the radcliente, it is identified by its nasname (IP)
- *
- * @return Boolean
- */
- function addRadiusClient(RadiusClient $radcliente)
- {
- $dbh = $this->getSqlCon();
- $stm = $dbh->prepare("DELETE FROM nas WHERE nasname = ?;");
- $rtr = $stm->execute(array($radcliente->nasname));
-
- $sql2 = "INSERT INTO `nas` (`nasname`, `shortname`, `type`, `ports`, `secret`, `community`, `description`, `server`, `acct_enabled`)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
- $stm2 = $dbh->prepare($sql2);
- $rtr2 = $stm2->execute(array(
- $radcliente->nasname, $radcliente->shortname,
- $radcliente->type, $radcliente->ports,
- $radcliente->secret, $radcliente->community,
- $radcliente->description, $radcliente->server,
- $radcliente->acct_enabled
- ));
-
- syslog(shell_exec('sudo kill -9 $(pgrep freeradius)'));
-
- return $rtr2;
- }
- /**
- * delete a entry in the NAS (radius Client) table
- * @param RadiusClient $radclient the radcliente, it is identified by its nasname (IP)
- *
- * @return Boolean
- */
- function deleteRadiusClient(RadiusClient $radcliente)
- {
- $dbh = $this->getSqlCon();
- $stm = $dbh->prepare("DELETE FROM nas WHERE nasname = ?;");
- $rtr = $stm->execute(array($radcliente->nasname));
-
- syslog(shell_exec('sudo kill -9 $(pgrep freeradius)'));
-
- return $rtr;
- }
- /**
- * Find all RadAct
- * @param RadAct $crit, NULL attributes are ignored in the query
- * @param Integer $inicio
- * @param Integer $count
- * @return RadAct[]
- */
- function findRadAct(RadAct $crit, $inicio, $count){
- $sql = "SELECT * FROM radacct";
- $where = array();
- $rtr = array();
- foreach($crit as $key => $val){
- if(!is_null($val))
- $where[] = "$key = '$val'";
- }
- if(!empty($where)){
- $sql .= " WHERE " . implode(' AND ', $where);
- }
- $sql .= " ORDER BY `acctstarttime` DESC";
- $sql .= " LIMIT $inicio, $count";
- $dbh = $this->getSqlCon();
- foreach($dbh->query($sql) as $row){
- $rtr [] = $obj = new RadAct;
- foreach($row as $k => $v) $obj->$k = $v;
- }
- return $rtr;
- }
-
- /**
- * Find RadAct for the $username address
- * @param String $username
- * @return RadAct[]
- */
- function getRadActByUsername($username)
- {
- $radAct = new RadAct();
- $radAct->username = $username;
-
- return $this->findRadAct($radAct, 0, 50);
- }
- }
- require_once "wshelper/common.php";
- $WSClasses = array('AccessServiceManager');
- $WSStructures = array(
- 'RadAct' => 'RadAct',
- 'RadiusGroup' => 'RadiusGroup',
- 'RadiusProp' => 'RadiusProp',
- 'RadiusRecord' => 'RadiusRecord',
- 'RadiusClient' => 'RadiusClient');
- require_once "servicioSoap.php";
|