diff --git a/include/ajax.content.php b/include/ajax.content.php index 7ba1a1d4c31adfb467e87d01ed856b8e547c909a..197d75ffe50c622296ca0bb22335874773fb499b 100644 --- a/include/ajax.content.php +++ b/include/ajax.content.php @@ -15,9 +15,9 @@ **********************************************************************/ if(!defined('INCLUDE_DIR')) die('!'); - + class ContentAjaxAPI extends AjaxController { - + function log($id) { if($id && ($log=Log::lookup($id))) { @@ -77,6 +77,8 @@ class ContentAjaxAPI extends AjaxController { <tr><td>%{assignee}</td><td>Assigned staff/team</td></tr> <tr><td>%{assigner}</td><td>Staff assigning the ticket</td></tr> <tr><td>%{url}</td><td>osTicket\'s base url (FQDN)</td></tr> + <tr><td>%{reset_link}</td> + <td>Reset link used by the password reset feature</td></tr> </table> </td> </tr> diff --git a/include/class.config.php b/include/class.config.php index 3aaf9d7164102e7ff6275cb0ecd4f94cb36db36d..3726309876cf198d317e81e7988a7aa9f53476d5 100644 --- a/include/class.config.php +++ b/include/class.config.php @@ -474,6 +474,30 @@ class OsticketConfig extends Config { return ($this->get('staff_ip_binding')); } + /** + * Configuration: allow_pw_reset + * + * TRUE if the <a>Forgot my password</a> link and system should be + * enabled, and FALSE otherwise. + */ + function allowPasswordReset() { + return $this->get('allow_pw_reset'); + } + + /** + * Configuration: pw_reset_window + * + * Number of minutes for which the password reset token is valid. + * + * Returns: Number of seconds the password reset token is valid. The + * number of minutes from the database is automatically converted + * to seconds here. + */ + function getPwResetWindow() { + // pw_reset_window is stored in minutes. Return value in seconds + return $this->get('pw_reset_window') * 60; + } + function isCaptchaEnabled() { return (extension_loaded('gd') && function_exists('gd_info') && $this->get('enable_captcha')); } @@ -744,6 +768,8 @@ class OsticketConfig extends Config { $f['datetime_format']=array('type'=>'string', 'required'=>1, 'error'=>'Datetime format required'); $f['daydatetime_format']=array('type'=>'string', 'required'=>1, 'error'=>'Day, Datetime format required'); $f['default_timezone_id']=array('type'=>'int', 'required'=>1, 'error'=>'Default Timezone required'); + $f['pw_reset_window']=array('type'=>'int', 'required'=>1, 'min'=>1, + 'error'=>'Valid password reset window required'); if(!Validator::process($f, $vars, $errors) || $errors) @@ -766,6 +792,8 @@ class OsticketConfig extends Config { 'client_max_logins'=>$vars['client_max_logins'], 'client_login_timeout'=>$vars['client_login_timeout'], 'client_session_timeout'=>$vars['client_session_timeout'], + 'allow_pw_reset'=>isset($vars['allow_pw_reset'])?1:0, + 'pw_reset_window'=>$vars['pw_reset_window'], 'time_format'=>$vars['time_format'], 'date_format'=>$vars['date_format'], 'datetime_format'=>$vars['datetime_format'], diff --git a/include/class.staff.php b/include/class.staff.php index a4edb4f7abd7e9a104d5ba182f87ff74dc9d62e4..19bd71bf02da54c1ee1fd6c36ac356c32f0ca7aa 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -15,6 +15,7 @@ **********************************************************************/ include_once(INCLUDE_DIR.'class.ticket.php'); include_once(INCLUDE_DIR.'class.dept.php'); +include_once(INCLUDE_DIR.'class.error.php'); include_once(INCLUDE_DIR.'class.team.php'); include_once(INCLUDE_DIR.'class.group.php'); include_once(INCLUDE_DIR.'class.passwd.php'); @@ -401,6 +402,7 @@ class Staff { //Staff profile update...unfortunately we have to separate it from admin update to avoid potential issues function updateProfile($vars, &$errors) { + global $cfg; $vars['firstname']=Format::striptags($vars['firstname']); $vars['lastname']=Format::striptags($vars['lastname']); @@ -437,7 +439,17 @@ class Staff { elseif($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2'])) $errors['passwd2']='Password(s) do not match'; - if(!$vars['cpasswd']) + if (($rtoken = $_SESSION['_staff']['reset-token'])) { + $_config = new Config('pwreset'); + if ($_config->get($rtoken) != $this->getId()) + $errors['err'] = + 'Invalid reset token. Logout and try again'; + elseif (!($ts = $_config->lastModified($rtoken)) + && ($cfg->getPwResetWindow() < (time() - strtotime($ts)))) + $errors['err'] = + 'Invalid reset token. Logout and try again'; + } + elseif(!$vars['cpasswd']) $errors['cpasswd']='Current password required'; elseif(!$this->cmp_passwd($vars['cpasswd'])) $errors['cpasswd']='Invalid current password!'; @@ -470,8 +482,10 @@ class Staff { .' ,default_paper_size='.db_input($vars['default_paper_size']); - if($vars['passwd1']) + if($vars['passwd1']) { $sql.=' ,change_passwd=0, passwdreset=NOW(), passwd='.db_input(Passwd::hash($vars['passwd1'])); + $this->cancelResetTokens(); + } $sql.=' WHERE staff_id='.db_input($this->getId()); @@ -576,7 +590,7 @@ class Staff { } function lookup($id) { - return ($id && is_numeric($id) && ($staff= new Staff($id)) && $staff->getId()==$id)?$staff:null; + return ($id && ($staff= new Staff($id)) && $staff->getId()) ? $staff : null; } function login($username, $passwd, &$errors, $strike=true) { @@ -600,31 +614,10 @@ class Staff { if($errors) return false; if(($user=new StaffSession(trim($username))) && $user->getId() && $user->check_passwd($passwd)) { - //update last login && password reset stuff. - $sql='UPDATE '.STAFF_TABLE.' SET lastlogin=NOW() '; - if($user->isPasswdResetDue() && !$user->isAdmin()) - $sql.=',change_passwd=1'; - $sql.=' WHERE staff_id='.db_input($user->getId()); - db_query($sql); - //Now set session crap and lets roll baby! - $_SESSION['_staff'] = array(); //clear. - $_SESSION['_staff']['userID'] = $username; - $user->refreshSession(); //set the hash. - $_SESSION['TZ_OFFSET'] = $user->getTZoffset(); - $_SESSION['TZ_DST'] = $user->observeDaylight(); - - //Log debug info. - $ost->logDebug('Staff login', - sprintf("%s logged in [%s]", $user->getUserName(), $_SERVER['REMOTE_ADDR'])); //Debug. - - //Regenerate session id. - $sid=session_id(); //Current id - session_regenerate_id(TRUE); - //Destroy old session ID - needed for PHP version < 5.1.0 TODO: remove when we move to php 5.3 as min. requirement. - if(($session=$ost->getSession()) && is_object($session) && $sid!=session_id()) - $session->destroy($sid); + self::_do_login($user, $username); Signal::send('auth.login.succeeded', $user); + $user->cancelResetTokens(); return $user; } @@ -651,6 +644,36 @@ class Staff { return false; } + function _do_login($user, $username) { + global $ost; + + //update last login && password reset stuff. + $sql='UPDATE '.STAFF_TABLE.' SET lastlogin=NOW() '; + if($user->isPasswdResetDue() && !$user->isAdmin()) + $sql.=',change_passwd=1'; + $sql.=' WHERE staff_id='.db_input($user->getId()); + db_query($sql); + //Now set session crap and lets roll baby! + $_SESSION['_staff'] = array(); //clear. + $_SESSION['_staff']['userID'] = $username; + $user->refreshSession(); //set the hash. + $_SESSION['TZ_OFFSET'] = $user->getTZoffset(); + $_SESSION['TZ_DST'] = $user->observeDaylight(); + + //Log debug info. + $ost->logDebug('Staff login', + sprintf("%s logged in [%s]", $user->getUserName(), $_SERVER['REMOTE_ADDR'])); //Debug. + + //Regenerate session id. + $sid=session_id(); //Current id + session_regenerate_id(TRUE); + //Destroy old session ID - needed for PHP version < 5.1.0 TODO: remove when we move to php 5.3 as min. requirement. + if(($session=$ost->getSession()) && is_object($session) && $sid!=session_id()) + $session->destroy($sid); + + return $user; + } + function create($vars, &$errors) { if(($id=self::save(0, $vars, $errors)) && $vars['teams'] && ($staff=Staff::lookup($id))) { $staff->updateTeams($vars['teams']); @@ -660,6 +683,43 @@ class Staff { return $id; } + function cancelResetTokens() { + // TODO: Drop password-reset tokens from the config table for + // this user id + $sql = 'DELETE FROM '.CONFIG_TABLE.' WHERE `namespace`="pwreset" + AND `value`='.db_input($this->getId()); + db_query($sql); + unset($_SESSION['_staff']['reset-token']); + } + + function sendResetEmail() { + global $ost, $cfg; + + if(!($tpl = $this->getDept()->getTemplate())) + $tpl= $ost->getConfig()->getDefaultTemplate(); + + $token = Misc::randCode(48); // 290-bits + if (!($template = $tpl->getMsgTemplate('staff.pwreset'))) + return new Error('Unable to retrieve password reset email template'); + + $msg = $ost->replaceTemplateVariables($template->asArray(), array( + 'url' => $ost->getConfig()->getBaseUrl(), + 'token' => $token, + 'reset_link' => sprintf( + "%s/scp/pwreset.php?token=%s", + $ost->getConfig()->getBaseUrl(), + $token), + )); + + if(!($email=$cfg->getAlertEmail())) + $email =$cfg->getDefaultEmail(); + + $_config = new Config('pwreset'); + $_config->set($token, $this->getId()); + + $email->send($this->getEmail(), $msg['subj'], $msg['body']); + } + function save($id, $vars, &$errors) { $vars['username']=Format::striptags($vars['username']); @@ -736,8 +796,9 @@ class Staff { .' ,signature='.db_input($vars['signature']) .' ,notes='.db_input($vars['notes']); - if($vars['passwd1']) + if($vars['passwd1']) { $sql.=' ,passwd='.db_input(Passwd::hash($vars['passwd1'])); + } if(isset($vars['change_passwd'])) $sql.=' ,change_passwd=1'; diff --git a/include/class.template.php b/include/class.template.php index c85297d2fd5f23f1cfb8b1b0df82bfc852369478..c270b41bf8376f13c2803f51bcdb9bc288443a1a 100644 --- a/include/class.template.php +++ b/include/class.template.php @@ -56,6 +56,9 @@ class EmailTemplateGroup { 'ticket.overdue'=>array( 'name'=>'Overdue Ticket Alert', 'desc'=>'Alert sent to staff on stale or overdue tickets.'), + 'staff.pwreset' => array( + 'name' => 'Staff Password Reset', + 'desc' => 'Notice sent to staff with the password reset link.'), ); function EmailTemplateGroup($id){ diff --git a/include/staff/login.header.php b/include/staff/login.header.php new file mode 100644 index 0000000000000000000000000000000000000000..679a509f96baa7f581bf8463048d3b642531d51a --- /dev/null +++ b/include/staff/login.header.php @@ -0,0 +1,22 @@ +<?php +defined('OSTSCPINC') or die('Invalid path'); +?> +<!DOCTYPE html> +<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" /> + <title>osTicket:: SCP Login</title> + <link rel="stylesheet" href="css/login.css" type="text/css" /> + <meta name="robots" content="noindex" /> + <meta http-equiv="cache-control" content="no-cache" /> + <meta http-equiv="pragma" content="no-cache" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> + <script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script> + <script type="text/javascript"> + $(document).ready(function() { + $("input:not(.dp):visible:enabled:first").focus(); + }); + </script> +</head> +<body id="loginBody"> + diff --git a/include/staff/login.tpl.php b/include/staff/login.tpl.php index b8b136eb56d01282e8b15dbd4c0f11085e437eaa..6d5435732128d556219c0230bdfb66004bdc21e7 100644 --- a/include/staff/login.tpl.php +++ b/include/staff/login.tpl.php @@ -1,26 +1,7 @@ -<?php -defined('OSTSCPINC') or die('Invalid path'); - +<?php +include_once(INCLUDE_DIR.'staff/login.header.php'); $info = ($_POST && $errors)?Format::htmlchars($_POST):array(); ?> -<!DOCTYPE html> -<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" /> - <title>osTicket:: SCP Login</title> - <link rel="stylesheet" href="css/login.css" type="text/css" /> - <meta name="robots" content="noindex" /> - <meta http-equiv="cache-control" content="no-cache" /> - <meta http-equiv="pragma" content="no-cache" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> - <script type="text/javascript" src="../js/jquery-1.7.2.min.js"></script> - <script type="text/javascript"> - $(document).ready(function() { - $("input:not(.dp):visible:enabled:first").focus(); - }); - </script> -</head> -<body id="loginBody"> <div id="loginBox"> <h1 id="logo"><a href="index.php">osTicket Staff Control Panel</a></h1> <h3><?php echo Format::htmlchars($msg); ?></h3> @@ -28,9 +9,12 @@ $info = ($_POST && $errors)?Format::htmlchars($_POST):array(); <?php csrf_token(); ?> <input type="hidden" name="do" value="scplogin"> <fieldset> - <input type="text" name="username" id="name" value="<?php echo $info['username']; ?>" placeholder="username" autocorrect="off" autocapitalize="off"> + <input type="text" name="userid" id="name" value="<?php echo $info['username']; ?>" 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()) { ?> + <h3 style="display:inline"><a href="pwreset.php">Forgot my password</a></h3> + <?php } ?> <input class="submit" type="submit" name="submit" value="Log In"> </form> </div> diff --git a/include/staff/profile.inc.php b/include/staff/profile.inc.php index 073a7c8a44229e1b18bf7b7b4cc738d8689d8396..2543c80d1cfa68444199a894f117c1521774afb4 100644 --- a/include/staff/profile.inc.php +++ b/include/staff/profile.inc.php @@ -190,6 +190,7 @@ $info['id']=$staff->getId(); <em><strong>Password</strong>: To reset your password, provide your current password and a new password below. <span class="error"> <?php echo $errors['passwd']; ?></span></em> </th> </tr> + <?php if (!isset($_SESSION['_staff']['reset-token'])) { ?> <tr> <td width="180"> Current Password: @@ -199,6 +200,7 @@ $info['id']=$staff->getId(); <span class="error"> <?php echo $errors['cpasswd']; ?></span> </td> </tr> + <?php } ?> <tr> <td width="180"> New Password: diff --git a/include/staff/pwreset.login.php b/include/staff/pwreset.login.php new file mode 100644 index 0000000000000000000000000000000000000000..6f93f1f0118093aefd5eb7b67568a560d2fb9066 --- /dev/null +++ b/include/staff/pwreset.login.php @@ -0,0 +1,26 @@ +<?php +include_once(INCLUDE_DIR.'staff/login.header.php'); +defined('OSTSCPINC') or die('Invalid path'); +$info = ($_POST)?Format::htmlchars($_POST):array(); +?> + +<div id="loginBox"> + <h1 id="logo"><a href="index.php">osTicket Staff Password Reset</a></h1> + <h3><?php echo Format::htmlchars($msg); ?></h3> + + <form action="pwreset.php" method="post"> + <?php csrf_token(); ?> + <input type="hidden" name="do" value="newpasswd"/> + <input type="hidden" name="token" value="<?php echo $_REQUEST['token']; ?>"/> + <fieldset> + <input type="text" name="userid" id="name" value="<?php echo + $info['userid']; ?>" placeholder="username or email" + autocorrect="off" autocapitalize="off"/> + </fieldset> + <input class="submit" type="submit" name="submit" value="Login"/> + </form> +</div> + +<div id="copyRights">Copyright © <a href='http://www.osticket.com' target="_blank">osTicket.com</a></div> +</body> +</html> diff --git a/include/staff/pwreset.php b/include/staff/pwreset.php new file mode 100644 index 0000000000000000000000000000000000000000..6aadeb2fcf10dbb308ed7ec3f548f4afd6c94ee8 --- /dev/null +++ b/include/staff/pwreset.php @@ -0,0 +1,25 @@ +<?php +include_once(INCLUDE_DIR.'staff/login.header.php'); +defined('OSTSCPINC') or die('Invalid path'); +$info = ($_POST && $errors)?Format::htmlchars($_POST):array(); +?> + +<div id="loginBox"> + <h1 id="logo"><a href="index.php">osTicket Staff Password Reset</a></h1> + <h3><?php echo Format::htmlchars($msg); ?></h3> + <form action="pwreset.php" method="post"> + <?php csrf_token(); ?> + <input type="hidden" name="do" value="sendmail"> + <fieldset> + <input type="text" name="userid" id="name" value="<?php echo + $info['userid']; ?>" placeholder="username" autocorrect="off" + autocapitalize="off"> + </fieldset> + <input class="submit" type="submit" name="submit" value="Send Email"/> + </form> + +</div> + +<div id="copyRights">Copyright © <a href='http://www.osticket.com' target="_blank">osTicket.com</a></div> +</body> +</html> diff --git a/include/staff/pwreset.sent.php b/include/staff/pwreset.sent.php new file mode 100644 index 0000000000000000000000000000000000000000..832b78ef57470c4045ed615c152dc228eb414e79 --- /dev/null +++ b/include/staff/pwreset.sent.php @@ -0,0 +1,22 @@ +<?php +include_once(INCLUDE_DIR.'staff/login.header.php'); +defined('OSTSCPINC') or die('Invalid path'); +$info = ($_POST && $errors)?Format::htmlchars($_POST):array(); +?> + +<div id="loginBox"> + <h1 id="logo"><a href="index.php">osTicket Staff Password Reset</a></h1> + <h3>A confirmation email has been sent</h3> + <h3 style="color:black;"><em> + A password reset email was sent to the email on file for your account. + Follow the link in the email to reset your password. + </em></h3> + + <form action="index.php" method="get"> + <input class="submit" type="submit" name="submit" value="Login"/> + </form> +</div> + +<div id="copyRights">Copyright © <a href='http://www.osticket.com' target="_blank">osTicket.com</a></div> +</body> +</html> diff --git a/include/staff/settings-system.inc.php b/include/staff/settings-system.inc.php index 6fade6d964b1fab6cca118fa0b8cff86841aa417..8915c8b4f87048d60cfba3a4d0fe3e2ca697dc62 100644 --- a/include/staff/settings-system.inc.php +++ b/include/staff/settings-system.inc.php @@ -112,7 +112,12 @@ $gmtime = Misc::gmtime(); </select> </td> </tr> - <tr><td>Password Reset Policy:</th> + <tr> + <th colspan="2"> + <em><b>Authentication Settings</b></em> + </th> + </tr> + <tr><td>Password Change Policy:</th> <td> <select name="passwd_reset_period"> <option value="0"> — None —</option> @@ -126,10 +131,20 @@ $gmtime = Misc::gmtime(); <font class="error"> <?php echo $errors['passwd_reset_period']; ?></font> </td> </tr> - <tr><td>Bind Staff Session to IP:</td> + <tr><td>Allow Password Resets:</th> <td> - <input type="checkbox" name="staff_ip_binding" <?php echo $config['staff_ip_binding']?'checked="checked"':''; ?>> - <em>(binds staff session to originating IP address upon login)</em> + <input type="checkbox" name="allow_pw_reset" <?php echo $config['allow_pw_reset']?'checked="checked"':''; ?>> + <em>Enables the <u>Forgot my password</u> link on the staff + control panel</em> + </td> + </tr> + <tr><td>Password Reset Window:</th> + <td> + <input type="text" name="pw_reset_window" size="6" value="<?php + echo $config['pw_reset_window']; ?>"> + Maximum time <em>in minutes</em> a password reset token can + be valid. + <font class="error"> <?php echo $errors['pw_reset_window']; ?></font> </td> </tr> <tr><td>Staff Excessive Logins:</td> @@ -182,6 +197,12 @@ $gmtime = Misc::gmtime(); Maximum idle time in minutes before a client must log in again (enter 0 to disable). </td> </tr> + <tr><td>Bind Staff Session to IP:</td> + <td> + <input type="checkbox" name="staff_ip_binding" <?php echo $config['staff_ip_binding']?'checked="checked"':''; ?>> + <em>(binds staff session to originating IP address upon login)</em> + </td> + </tr> <tr> <th colspan="2"> <em><b>Date and Time Options</b>: Please refer to <a href="http://php.net/date" target="_blank">PHP Manual</a> for supported parameters.</em> diff --git a/include/staff/tpl.inc.php b/include/staff/tpl.inc.php index 8c1ede75e5e4ed12092c08201d22a0aebeaa2cc2..58e0b57fcef0b42d326818b22652efe976ee2ce9 100644 --- a/include/staff/tpl.inc.php +++ b/include/staff/tpl.inc.php @@ -6,6 +6,7 @@ if (is_a($template, EmailTemplateGroup)) { $id = 0; $tpl_id = $template->getId(); $name = $template->getName(); + $group = $template; $selected = $_REQUEST['code_name']; $action = 'implement'; $extras = array('code_name'=>$selected, 'tpl_id'=>$tpl_id); @@ -15,6 +16,7 @@ if (is_a($template, EmailTemplateGroup)) { $id = $template->getId(); $tpl_id = $template->getTplId(); $name = $template->getGroup()->getName(); + $group = $template->getGroup(); $selected = $template->getCodeName(); $action = 'updatetpl'; $extras = array(); @@ -33,7 +35,7 @@ $tpl=$msgtemplates[$info['tpl']]; <select id="tpl_options" name="id" style="width:300px;"> <option value="">— Select Setting Group —</option> <?php - foreach($template->getGroup()->getTemplates() as $cn=>$t) { + foreach($group->getTemplates() as $cn=>$t) { $nfo=$t->getDescription(); if (!$nfo['name']) continue; @@ -41,6 +43,10 @@ $tpl=$msgtemplates[$info['tpl']]; echo sprintf('<option value="%s" %s>%s</option>', $t->getId(),$sel,$nfo['name']); } + if ($id == 0) { ?> + <option selected="selected" value="<?php echo $id; ?>"><?php + echo $msgtemplates[$selected]['name']; ?></option> + <?php } ?> </select> <input type="submit" value="Go"> diff --git a/scp/login.php b/scp/login.php index fcefaafd666660cdaf2d44c5e32e4b0bcfaeab37..2f3cf2236e9f4996bb10b94764fb6d0a14d99d22 100644 --- a/scp/login.php +++ b/scp/login.php @@ -24,7 +24,7 @@ $msg = $_SESSION['_staff']['auth']['msg']; $msg = $msg?$msg:'Authentication Required'; if($_POST) { //$_SESSION['_staff']=array(); #Uncomment to disable login strikes. - if(($user=Staff::login($_POST['username'], $_POST['passwd'], $errors))){ + if(($user=Staff::login($_POST['userid'], $_POST['passwd'], $errors))){ $dest=($dest && (!strstr($dest,'login.php') && !strstr($dest,'ajax.php')))?$dest:'index.php'; @header("Location: $dest"); require_once('index.php'); //Just incase header is messed up. diff --git a/scp/pwreset.php b/scp/pwreset.php new file mode 100644 index 0000000000000000000000000000000000000000..a8efb2f6ef86715463398d01143d907a0313e10e --- /dev/null +++ b/scp/pwreset.php @@ -0,0 +1,88 @@ +<?php +/********************************************************************* + pwreset.php + + Handles step 2, 3 and 5 of password resetting + 1. Fail to login (2+ fail login attempts) + 2. Visit password reset form and enter username or email + 3. Receive an email with a link and follow it + 4. Visit password reset form again, with the link + 5. Enter the username or email address again and login + 6. Password change is now required, user changes password and + continues on with the session + + Peter Rotich <peter@osticket.com> + Jared Hancock <jared@osticket.com> + Copyright (c) 2006-2013 osTicket + http://www.osticket.com + + Released under the GNU General Public License WITHOUT ANY WARRANTY. + See LICENSE.TXT for details. + + vim: expandtab sw=4 ts=4 sts=4: +**********************************************************************/ +require_once('../main.inc.php'); +if(!defined('INCLUDE_DIR')) die('Fatal Error. Kwaheri!'); + +require_once(INCLUDE_DIR.'class.staff.php'); +require_once(INCLUDE_DIR.'class.csrf.php'); + +$tpl = 'pwreset.php'; +if($_POST) { + if (!$ost->checkCSRFToken()) { + Http::response(400, 'Valid CSRF Token Required'); + exit; + } + switch ($_POST['do']) { + case 'sendmail': + if (($staff=Staff::lookup($_POST['userid']))) { + if (!$staff->sendResetEmail()) { + $tpl = 'pwreset.sent.php'; + } + } + else + $msg = 'Unable to verify username ' + .Format::htmlchars($_POST['userid']); + break; + case 'newpasswd': + // TODO: Compare passwords + $tpl = 'pwreset.login.php'; + $_config = new Config('pwreset'); + if (($staff = new StaffSession($_POST['userid'])) && + !$staff->getId()) + $msg = 'Invalid user-id given'; + elseif (!($id = $_config->get($_POST['token'])) + || $id != $staff->getId()) + $msg = 'Invalid reset token'; + elseif (!($ts = $_config->lastModified($_POST['token'])) + && ($ost->getConfig()->getPwResetWindow() < (time() - strtotime($ts)))) + $msg = 'Invalid reset token'; + elseif (!$staff->forcePasswdRest()) + $msg = 'Unable to reset password'; + else { + Staff::_do_login($staff, $_POST['userid']); + $_SESSION['_staff']['reset-token'] = $_POST['token']; + header('Location: index.php'); + exit(); + } + break; + } +} +elseif ($_GET['token']) { + $msg = 'Re-enter your username or email'; + $_config = new Config('pwreset'); + if (($id = $_config->get($_GET['token'])) + && ($staff = Staff::lookup($id))) + $tpl = 'pwreset.login.php'; + else + header('Location: index.php'); +} +elseif ($cfg->allowPasswordReset()) { + $msg = 'Enter your username or email address below'; +} +else { + $_SESSION['_staff']['auth']['msg']='Password resets are disabled'; + return header('Location: index.php'); +} +define("OSTSCPINC",TRUE); //Make includes happy! +include_once(INCLUDE_DIR.'staff/'. $tpl); diff --git a/scp/staff.inc.php b/scp/staff.inc.php index 577fdd12c6a124a0d98dd50b792d080ab40f983e..503c3cd413be64319882c255f9595029cbd0615d 100644 --- a/scp/staff.inc.php +++ b/scp/staff.inc.php @@ -1,7 +1,7 @@ <?php /************************************************************************* staff.inc.php - + File included on every staff page...handles logins (security) and file path issues. Peter Rotich <peter@osticket.com> @@ -42,13 +42,14 @@ require_once(INCLUDE_DIR.'class.nav.php'); require_once(INCLUDE_DIR.'class.csrf.php'); /* First order of the day is see if the user is logged in and with a valid session. - * User must be valid staff beyond this point + * User must be valid staff beyond this point * ONLY super admins can access the helpdesk on offline state. */ if(!function_exists('staffLoginPage')) { //Ajax interface can pre-declare the function to trap expired sessions. function staffLoginPage($msg) { + global $ost, $cfg; $_SESSION['_staff']['auth']['dest']=THISURI; $_SESSION['_staff']['auth']['msg']=$msg; require(SCP_DIR.'login.php'); @@ -59,7 +60,15 @@ 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()){ - $msg=(!$thisstaff || !$thisstaff->isValid())?'Authentication Required':'Session timed out due to inactivity'; + if (isset($_SESSION['_staff']['auth']['msg'])) { + $msg = $_SESSION['_staff']['auth']['msg']; + unset($_SESSION['_staff']['auth']['msg']); + } + elseif ($thisstaff && !$thisstaff->isValid()) + $msg = 'Session timed out due to inactivity'; + else + $msg = 'Authentication Required'; + staffLoginPage($msg); exit; } @@ -88,7 +97,7 @@ if ($_POST && !$ost->checkCSRFToken()) { exit; } -//Add token to the header - used on ajax calls [DO NOT CHANGE THE NAME] +//Add token to the header - used on ajax calls [DO NOT CHANGE THE NAME] $ost->addExtraHeader('<meta name="csrf_token" content="'.$ost->getCSRFToken().'" />'); /******* SET STAFF DEFAULTS **********/