From 75c80484bac38d00f4b45da9b0533131356835bf Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Fri, 30 Aug 2013 15:26:08 +0000
Subject: [PATCH] Don't log the user out after changing account info

Also include
  * username validation -- no spaces or weird chars
  * no longer base64 encoded sha1-hex hash for CSRF token
  * refresh login page every two hours to keep session active
---
 include/class.csrf.php         |  9 ++-------
 include/class.staff.php        |  7 ++++---
 include/class.usersession.php  |  2 +-
 include/class.validator.php    | 13 +++++++++++--
 include/staff/login.header.php |  1 +
 include/staff/login.tpl.php    |  2 +-
 scp/staff.inc.php              |  2 +-
 7 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/include/class.csrf.php b/include/class.csrf.php
index 806217284..cdd04a292 100644
--- a/include/class.csrf.php
+++ b/include/class.csrf.php
@@ -53,16 +53,11 @@ Class CSRF {
         return $this->name;
     }
 
-    function getToken($len=32) {
+    function getToken() {
 
         if(!$this->csrf['token'] || $this->isExpired()) {
 
-            $len = $len>8?$len:32;
-            $r = '';
-            for ($i = 0; $i <= $len; $i++)
-                $r .= chr(mt_rand(0, 255));
-        
-            $this->csrf['token'] = base64_encode(sha1(session_id().$r.SECRET_SALT));
+            $this->csrf['token'] = sha1(session_id().Crypto::randcode(16).SECRET_SALT);
             $this->csrf['time'] = time();
         } else {
             //Reset the timer
diff --git a/include/class.staff.php b/include/class.staff.php
index 4e375bb10..e0220120c 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -657,7 +657,7 @@ class Staff {
         db_query($sql);
         //Now set session crap and lets roll baby!
         $_SESSION['_staff'] = array(); //clear.
-        $_SESSION['_staff']['userID'] = $username;
+        $_SESSION['_staff']['userID'] = $user->getId();
         $user->refreshSession(); //set the hash.
         $_SESSION['TZ_OFFSET'] = $user->getTZoffset();
         $_SESSION['TZ_DST'] = $user->observeDaylight();
@@ -742,8 +742,9 @@ class Staff {
         if(!$vars['lastname'])
             $errors['lastname']='Last name required';
 
-        if(!$vars['username'] || strlen($vars['username'])<2)
-            $errors['username']='Username required';
+        $error = '';
+        if(!$vars['username'] || !Validator::is_username($vars['username'], $error))
+            $errors['username']=($error) ? $error : 'Username required';
         elseif(($uid=Staff::getIdByUsername($vars['username'])) && $uid!=$id)
             $errors['username']='Username already in use';
 
diff --git a/include/class.usersession.php b/include/class.usersession.php
index 5e10df43f..b596934cf 100644
--- a/include/class.usersession.php
+++ b/include/class.usersession.php
@@ -147,7 +147,7 @@ class StaffSession extends Staff {
     
     function StaffSession($var){
         parent::Staff($var);
-        $this->session= new UserSession($var);
+        $this->session= new UserSession($this->getId());
     }
 
     function isValid(){
diff --git a/include/class.validator.php b/include/class.validator.php
index e8bf851a5..f01bcb38c 100644
--- a/include/class.validator.php
+++ b/include/class.validator.php
@@ -111,8 +111,9 @@ class Validator {
                     $this->errors[$k]=$field['error'].' (5 chars min)';
                 break;
             case 'username':
-                if(strlen($this->input[$k])<2)
-                    $this->errors[$k]=$field['error'].' (2 chars min)';
+                $error = '';
+                if (!$this->is_username($this->input[$k], $error))
+                    $this->errors[$k]=$field['error'].": $error";
                 break;
             case 'zipcode':
                 if(!is_numeric($this->input[$k]) || (strlen($this->input[$k])!=5))
@@ -169,6 +170,14 @@ class Validator {
         return false;
     }
 
+    function is_username($username, &$error='') {
+        if (strlen($username)<2)
+            $error = 'At least two (2) characters';
+        elseif (!preg_match('/^[\w._-]+$/', $username))
+            $error = 'Username contains invalid characters';
+        return $error == '';
+    }
+
     function process($fields,$vars,&$errors){
 
         $val = new Validator();
diff --git a/include/staff/login.header.php b/include/staff/login.header.php
index 679a509f9..cf6fbddba 100644
--- a/include/staff/login.header.php
+++ b/include/staff/login.header.php
@@ -5,6 +5,7 @@ defined('OSTSCPINC') or die('Invalid path');
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
     <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <meta http-equiv="refresh" content="7200" />
     <title>osTicket:: SCP Login</title>
     <link rel="stylesheet" href="css/login.css" type="text/css" />
     <meta name="robots" content="noindex" />
diff --git a/include/staff/login.tpl.php b/include/staff/login.tpl.php
index 6d5435732..1f3bb55e0 100644
--- a/include/staff/login.tpl.php
+++ b/include/staff/login.tpl.php
@@ -9,7 +9,7 @@ $info = ($_POST && $errors)?Format::htmlchars($_POST):array();
         <?php csrf_token(); ?>
         <input type="hidden" name="do" value="scplogin">
         <fieldset>
-            <input type="text" name="userid" id="name" value="<?php echo $info['username']; ?>" placeholder="username" autocorrect="off" autocapitalize="off">
+            <input type="text" name="userid" id="name" value="<?php echo $info['userid']; ?>" placeholder="username" autocorrect="off" autocapitalize="off">
             <input type="password" name="passwd" id="pass" placeholder="password" autocorrect="off" autocapitalize="off">
         </fieldset>
         <?php if ($_SESSION['_staff']['strikes'] > 1 && $cfg->allowPasswordReset()) { ?>
diff --git a/scp/staff.inc.php b/scp/staff.inc.php
index 54ff91b99..0c835d46a 100644
--- a/scp/staff.inc.php
+++ b/scp/staff.inc.php
@@ -58,7 +58,7 @@ if(!function_exists('staffLoginPage')) { //Ajax interface can pre-declare the fu
 
 $thisstaff = new StaffSession($_SESSION['_staff']['userID']); //Set staff object.
 //1) is the user Logged in for real && is staff.
-if(!$thisstaff || !is_object($thisstaff) || !$thisstaff->getId() || !$thisstaff->isValid()){
+if(!$thisstaff->getId() || !$thisstaff->isValid()){
     if (isset($_SESSION['_staff']['auth']['msg'])) {
         $msg = $_SESSION['_staff']['auth']['msg'];
         unset($_SESSION['_staff']['auth']['msg']);
-- 
GitLab