true, 'canModifyUsers' => true, 'canLogout' => true ); /** * * Connect to MySQL DB. * return PDOconnection. */ function newPDO() { $host="127.0.0.1"; $port=3306; $user="MySQLuser"; $pass="MySQLpassword"; $db="vboxDB"; try{ return new PDO("mysql:host=$host;port=$port;dbname=$db;charset=utf8",$user,$pass); }catch (PDOException $e){throw new Exception("Can't connect to MySQL db!",vboxconnector::PHPVB_ERRNO_CONNECT);} } /** * * Select row from username * @param $username the user we search * return row */ function PDO_selectUser($username) { try{ $statement=$this->newPDO()->prepare("SELECT username, password, admin FROM users WHERE username=:username"); $statement->bindValue(":username",$username, PDO::PARAM_STR); $statement->execute(); }catch(PDOException $e){throw new Exception("Can't execute requested query!",vboxconnector::PHPVB_ERRNO_FATAL);} return $statement->fetch(PDO::FETCH_ASSOC); } /** * * Generate a random salt. * @param $lenght the lenght of the salt, default is 8. * * On Linux (in particular Ubuntu), the password is generate with this command: * "echo "${username}:${password}" | chpasswd -S -c $crypt_method | cut -d: -f2". * in this particoular implementation I use MD5. * * Max length is 20 char! */ function generateRandomSalt($length = 8) { return substr(sha1(rand().time()), rand(0,20-$length), $length); } /** * * Revalidate login info and set authCheckHeartbeat session variable. * @param vboxconnector $vbox vboxconnector object instance, THIS VARIABLE WILL NOT USED. */ function heartbeat($vbox) { global $_SESSION; $q=$this->PDO_selectUser(@$_SESSION['user']); $p=isset($q['password'])?$q['password']:0; if($p && $p!=@$_SESSION[uHash]) { $_SESSION['valid']=false; session_destroy(); } else { $_SESSION['admin']=intval(q['admin']); $_SESSION['authCheckHeartbeat']=time(); } if(!isset($_SESSION['valid']) || !$_SESSION['valid']) throw new Exception(trans('Not logged in.','UIUsers'), vboxconnector::PHPVB_ERRNO_FATAL); } /** * * Log in function. Populates $_SESSION * @param string $username user name * @param string $password password */ function login($username, $password) { global $_SESSION; $q=$this->PDO_selectUser($username); $p=isset($q['password'])?$q['password']:0; if($p && password_verify($password,$p)) { $_SESSION['valid'] = true; $_SESSION['user'] = $username; $_SESSION['admin'] = intval($q['admin']); $_SESSION['authCheckHeartbeat'] = time(); $_SESSION['uHash'] = $p; } } /** * * Log out user present in $_SESSION * @param array $response response passed byref by API and populated within function */ function logout(&$response) { global $_SESSION; if(function_exists('session_destroy')) session_destroy(); else unset($_SESSION['valid']); $response['data']['result'] = 1; } /** * * Change password function. * @param string $old old password * @param string $new new password * @return boolean true on success */ function changePassword($old, $new) { global $_SESSION; $p=$this->PDO_selectUser($_SESSION['user']); $p=isset($p['password'])?$p['password']:0; //along the time is changed? if($p && password_verify($old, $p)) { $np=crypt($new, '$1$'.$this->generateRandomSalt().'$'); //look the MD5 format!! //look here for more info: http://php.net/manual/en/faq.passwords.php try{ $sth=$this->newPDO()->prepare("UPDATE users SET password=:password WHERE username=:username"); $sth->bindValue(":password",$np,PDO::PARAM_STR); $sth->bindValue(":username",$_SESSION['user'],PDO::PARAM_STR); $sth->execute(); }catch(PDOException $e){throw new Exception("Can't execute requested query!",vboxconnector::PHPVB_ERRNO_FATAL);} return true; } return false; } /** * * Return a list of users * @return array list of users */ function listUsers() { $response = array(); try{ $sth=$this->newPDO()->prepare("SELECT * FROM users"); $sth->execute(); }catch(PDOException $e){throw new Exception("Can't display users list!",vboxconnector::PHPVB_ERRNO_FATAL);} while(($row=$sth->fetch(PDO::FETCH_ASSOC))!==FALSE) { $response[$row['username']]=array('username'=> $row['username'], 'admin'=> intval($row['admin'])); } return $response; } /** * * Update user information such as password and admin status * @param array $vboxRequest request passed from API representing the ajax request. Contains user, password and administration level. * @param boolean $skipExistCheck Do not check that the user exists first. Essentially, if this is set and the user does not exist, it is added. */ function updateUser($vboxRequest, $skipExistCheck) { global $_SESSION; if(!$_SESSION['admin']) return; $q=$this->PDO_selectUser($vboxRequest['u']); if(!$skipExistCheck && $q) return; $np=($vboxRequest['p'])?crypt($vboxRequest['p'], '$1$'.$this->generateRandomSalt().'$'):0; $query="INSERT INTO `users`(`username`, `password`,`admin`) VALUES (:username, :password, :admin) ON DUPLICATE KEY UPDATE `password`=:password, `admin`=:admin"; $sth=$this->newPDO()->prepare($query); try{ $sth->bindValue(":username",$vboxRequest['u'],PDO::PARAM_STR); $sth->bindValue(":password",($vboxRequest['p']?$np:$q['password']),PDO::PARAM_STR); $sth->bindValue(":admin",($vboxRequest['a']?"1":"0"),PDO::PARAM_STR); $sth->execute(); }catch(PDOException $e){throw new Exception("Can't execute requested query!",vboxconnector::PHPVB_ERRNO_FATAL);} } /** * * Remove the user $user * @param string $user Username to remove */ function deleteUser($user) { $sth=$this->newPDO()->prepare("DELETE FROM users WHERE username=:username"); try{ $sth->bindValue(":username",$user,PDO::PARAM_STR); $sth->execute(); }catch(PDOException $e){throw new Exception("Can't execute requested query!",vboxconnector::PHPVB_ERRNO_FATAL);} } }