diff options
Diffstat (limited to 'admin/Library/Users/CheckAdmin.php')
-rwxr-xr-x | admin/Library/Users/CheckAdmin.php | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/admin/Library/Users/CheckAdmin.php b/admin/Library/Users/CheckAdmin.php new file mode 100755 index 0000000..9a47b16 --- /dev/null +++ b/admin/Library/Users/CheckAdmin.php @@ -0,0 +1,369 @@ +<?php + +// All EasyGiant code 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. +// See COPYRIGHT.txt and LICENSE.txt. + +if (!defined('EG')) die('Direct access not allowed!'); + +class Users_CheckAdmin { + + public $status = array(); + + protected $_sessionsTable; //table containing all the sessions + protected $_usersTable; //table containing all the users + protected $_groupsTable; //table containing all the groups + protected $_manyToManyTable; //table for many to many relationships + protected $_accessesTable; //table containing all the accesses to admin side + protected $uid = null; + protected $_token = null; //token used in order to defense against CSRF (cross sire request forgeries) + protected $_login; //login action + protected $_main; //main action + protected $_retype; //retype (the password) action + protected $_db; //reference to the database layer class + protected $_params = array(); //the parameters of the object + + public function __construct($params = null) { + $this->_params = $params; + + $this->_sessionsTable = $params['sessionsTable']; + $this->_usersTable = $params['usersTable']; + $this->_groupsTable = $params['groupsTable']; + $this->_manyToManyTable = $params['manyToManyTable']; + $this->_accessesTable = $params['accessesTable']; + $this->_login = Url::getRoot(null) . $params['users_controller'] . '/' . $params['users_login_action'] ; + $this->_main = Url::getRoot(null) . $params['panel_controller'] . '/' . $params['panel_main_action'] ; + $this->_retype = Url::getRoot(null) . $params['users_controller'] . '/' . $params['hijacking_action'] ; + $this->_db = Factory_Db::getInstance($params['database_type']); + } + + private function acquireCookie() { #obtain cookie + #cookie + $this->uid = NULL; + global $_COOKIE; + $this->uid = isset($_COOKIE[$this->_params['cookie_name']]) ? sanitizeAlnum($_COOKIE[$this->_params['cookie_name']]) : null; + } + + private function cleanSessions() + { + #cancello le sessioni scadute + $row = $this->_db->select($this->_sessionsTable,'creation_date',"uid='".$this->uid."'"); + if ($row) + { + if ($row[0][$this->_sessionsTable]['creation_date']) + { + if($row[0][$this->_sessionsTable]['creation_date'] + $this->_params['session_expire'] <= time()) + { + setcookie($this->_params['cookie_name'],'',time()-3600,$this->_params['cookie_path']); + } + } + } + $this->_db->del($this->_sessionsTable,"creation_date + " . $this->_params['session_expire'] . " <= ".time()); + } + + public function checkStatus() + { #controlla se l'utente è già loggato + $this->acquireCookie(); #ottengo il cookie + $this->cleanSessions(); #elimino le sessioni vecchie + $row=$this->_db->select($this->_usersTable.','.$this->_sessionsTable,$this->_usersTable.'.id_user,username,token,user_agent',$this->_usersTable.".id_user=".$this->_sessionsTable.".id_user and uid='".$this->uid."'"); + if (count($row) === 1 and $row !== false) + { + $this->status['user']=$row[0][$this->_usersTable]['username']; + $this->status['status']='logged'; + $this->status['id_user']=$row[0][$this->_usersTable]['id_user']; + $this->status['user_agent'] = $row[0][$this->_sessionsTable]['user_agent']; + $this->status['token'] = $row[0][$this->_sessionsTable]['token']; + $this->obtainGroups(); + } else { + $this->status['user']='sconosciuto'; + $this->status['status']='not-logged'; + $this->status['id_user']=''; + $this->status['user_agent']=''; + $this->status['token'] = ''; + $this->status['groups'] = array(); + } + } + + public function redirect($val,$time = 3) { #fa il redirect dell'utente + if ($val === 'logged') { + header('Refresh: '.$time.';url='.$this->_main); + if ($time !== 0) echo "You are already logged, ".$this->status['user'].".."; + } else if ($val === 'accepted') { + header('Refresh: '.$time.';url='.$this->_main); + if ($time !== 0) echo "Hi ".$this->status['user'].".."; + } else if ($val === 'login-error') { + header('Refresh: '.$time.';url='.$this->_login); + if ($time !== 0) echo "Wrong username or password..."; + } else if ($val === 'not-logged') { + header('Refresh: '.$time.';url='.$this->_login); + if ($time !== 0) echo "Limited access... sorry"; + } else if ($val === 'not-authorized') { + header('Refresh: '.$time.';url='.$this->_main); + if ($time !== 0) echo "Your account doesn't allow you to manage this page.. sorry!"; + } else if ($val === 'stolen') { + header('Refresh: '.$time.';url='.$this->_login); + if ($time !== 0) echo "Your session have been probably intercepted! Please login another time."; + } else if ($val === 'retype') { + header('Refresh: '.$time.';url='.$this->_retype); + if ($time !== 0) echo "Your session have been probably intercepted. Please type your password another time."; + } else if ($val === 'wait') { + header('Refresh: '.$time.';url='.$this->_login); + if ($time !== 0) echo "You have to wait ".$this->_params['time_after_failure']." seconds before you can try to login another time"; + } + exit; + } + + //obtain the group of the user + private function obtainGroups() + { + $tables = $this->_usersTable.','.$this->_groupsTable.','.$this->_manyToManyTable; + $fields = $this->_groupsTable.'.name'; + $where = $this->_usersTable.'.id_user='.$this->_manyToManyTable.'.id_user and '.$this->_groupsTable.'.id_group='.$this->_manyToManyTable.'.id_group and '.$this->_usersTable.'.id_user='.$this->status['id_user']; + $groups = $this->_db->select($tables,$fields,$where); + $this->status['groups'] = array(); + foreach ($groups as $group) + { + $this->status['groups'][] = $group[$this->_groupsTable]['name']; + } + } + + //$groups: string with name of groups separated by comma; ex: base,root,users + public function checkAccess($groups) + { + $groupsArray = explode (',',$groups); + foreach ($this->status['groups'] as $group) + { + if (in_array($group,$groupsArray)) return true; + } + return false; + } + + //check that the user is logged and, if present, check the group of the user (if loggeg) + //$groups: comma-separated list of groups whose users can access the page + //$time: time before the redirect is carried out + public function check($groups = null, $time = 3) + { + $this->checkStatus(); + if (strcmp($this->status['status'],'not-logged') === 0) + { + $this->redirect('not-logged',$time); + } + else if (strcmp($this->status['status'],'logged') === 0) + { + if ($this->_params['hijacking_check']) + { + if (!$this->checkHijacking()) + { + if ($this->_params['on_hijacking_event'] === 'forceout') + { + $this->logout(); + $this->redirect('stolen',$time); + } + else if ($this->_params['on_hijacking_event'] === 'redirect') + { + $this->redirect('retype',$time); + } + } + } +// $this->obtainGroups(); + if (isset($groups)) + { + $permission = $this->checkAccess($groups); + if (!$permission) $this->redirect('not-authorized',$time); + } + } + } + + //check if someone have stolen your uid + private function checkHijacking() + { + if (array_key_exists('user_agent',$this->status)) + { + if (strcmp($this->status['user_agent'],'') !== 0) + { + if (strcmp($this->status['user_agent'],getUserAgent()) === 0) + { + return true; + } + } + } + return false; + } + + //check CSRF + //$token: token to check + public function checkCSRF($token) + { + if (strcmp($this->status['token'],'') !== 0) + { + if (strcmp($this->status['token'],$token) === 0) + { + return true; + } + } + return false; + } + + //get an array containing all the users currently logged + public function getUsersLogged() + { + $usersLogged = array(); + $data=$this->_db->select($this->_usersTable.','.$this->_sessionsTable,'DISTINCT '.$this->_usersTable.'.username',$this->_usersTable.".id_user=".$this->_sessionsTable.".id_user"); + foreach ($data as $row) + { + $usersLogged[] = $row[$this->_usersTable]['username']; + } + return $usersLogged; + } + + //get the password of the current user + public function getPassword() + { + $row=$this->_db->select($this->_usersTable,'password',"id_user=".$this->status['id_user']); + if ($row !== false) + { + return $row[0][$this->_usersTable]['password']; + } + else + { + return false; + } + } + + private function checkPassword($user,$pwd) { #check username and password + + if (!in_array($this->_params['password_hash'],Params::$allowedHashFunc)) + { + throw new Exception('Error in '.__METHOD__.' : the hash func has to be '.implode(' or ',Params::$allowedHashFunc)); + } + //calculate the hash of the password + $pwd = call_user_func($this->_params['password_hash'],$pwd); + + $row=$this->_db->select($this->_usersTable,$this->_usersTable.'.id_user,username,password',"username=\"".$user."\" and password=\"".$pwd."\" and has_confirmed=0"); + if (count($row) === 1 and $row !== false) + { + $this->status['user'] = $row[0][$this->_usersTable]['username']; + $this->status['status'] = 'accepted'; + $this->status['id_user'] = $row[0][$this->_usersTable]['id_user']; + } + else + { + $this->status['user'] = 'unknown'; + $this->status['status'] = 'login-error'; + $this->status['id_user'] = ''; + if ($this->_db->recordExists($this->_usersTable,'username',$user)) + { + $this->_db->update($this->_usersTable,'last_failure',array(time()),'username="'.$user.'"'); + } + } + } + + //check that enough time is passed since the last failure of the user + private function checkLastFailure($user) + { + //current time + $now = time(); + //max time + $max = $now - $this->_params['time_after_failure']; + $data = $this->_db->select($this->_usersTable,'last_failure','username="'.$user.'"'); + if (count($data) === 1 and $data !== false) + { + if ($data[0][$this->_usersTable]['last_failure'] < $max) + { + return true; + } + return false; + } + else + { + return true; + } + } + + public function login($user,$pwd) + { + $user = sanitizeAll($user); + $this->checkStatus(); + //check if already logged + if ($this->status['status'] === 'logged') + { +// $this->redirect('logged'); + return 'logged'; + } + else + { + if ($this->checkLastFailure($user)) + { + $this->checkPassword($user,$pwd); + if ($this->status['status']==='accepted') + { + $this->uid = md5(randString(10).uniqid(mt_rand(),true)); + $this->_token = md5(randString(12)); + $userAgent = getUserAgent(); + $this->_db->insert($this->_sessionsTable,'id_user,uid,token,creation_date,user_agent',array($this->status['id_user'],$this->uid,$this->_token,time(),$userAgent)); + setcookie($this->_params['cookie_name'],$this->uid,0,$this->_params['cookie_path']); #magic cookie + $this->updateAccesses(); + + $this->_db->del($this->_sessionsTable,'id_user='.$this->status['id_user'].' AND uid != "'.$this->uid.'"'); + +// $this->redirect('accepted'); + return 'accepted'; + } + else if ($this->status['status']==='login-error') + { +// $this->redirect('login-error'); + return 'login-error'; + } + } + else + { +// $this->redirect('wait'); + return 'wait'; + } + } +// $this->redirect('login-error'); + return 'login-error'; + } + + private function updateAccesses() + { + $ip=getIp(); #ip + $date=date('d'). "-" . date('m') . "-" . date('Y'); #date + $ora=date('H') . ":" . date('i'); #time + $values=array($ip,$date,$ora,$this->status['user']); + $res=$this->_db->insert($this->_accessesTable,'ip,data,ora,username',$values); + } + + //force out an user + //$id: the id of the user + public function forceOut($id) + { + $id = (int)$id; + if ($this->_db->del($this->_sessionsTable,'id_user='.$id)) + { + return true; + } + return false; + } + + public function logout() + { + $this->checkStatus(); + if ($this->status['status'] === 'logged') + { + setcookie ($this->_params['cookie_name'], "", time() - 3600,$this->_params['cookie_path']); + if ($this->_db->del($this->_sessionsTable,'id_user='.$this->status['id_user'])) + { + return 'was-logged'; + } + else + { + return 'error'; + } + } + else + { + return 'not-logged'; + } + } + +}
\ No newline at end of file |