_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'; } } }