Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a feature to prevent duplicate POSTs #870

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
@header('Location: index.php');
//just incase redirect fails
die('Action denied (400)!');
} elseif ($_POST && !$ost->checkActivityToken()) {
$errors['err'] = 'Cowardly refusing to repeat previous activity';
}

/* Client specific defaults */
Expand Down
24 changes: 24 additions & 0 deletions include/class.osticket.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,30 @@ function checkCSRFToken($name='') {
return false;
}

function checkActivityToken($name='__activity__') {
global $thisstaff, $thisclient;
$user = null;

if (defined('OSTSTAFFINC') && $thisstaff) {
$user = $thisstaff;
}
elseif (defined('OSTCLIENTINC') && $thisclient) {
$user = $thisclient;
}
if (isset($_POST[$name]) && $user) {
// Ensure the token matches the current token for the user. If
// they don't match, this is likely a stale form post
$pass = ($user->getActivityToken() == $_POST[$name]);
// Regardless, the same token CANNOT be used in a future post
$user->rollActivityToken();
return $pass;
}
else {
// Token not found. Pass by default
return true;
}
}

function getLinkToken() {
return md5($this->getCSRFToken().SECRET_SALT.session_id());
}
Expand Down
43 changes: 41 additions & 2 deletions include/class.usersession.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ class UserSession {
var $browser = '';
var $ip = '';
var $validated=FALSE;
var $activity;

function UserSession($userid){

$this->browser=(!empty($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : $_ENV['HTTP_USER_AGENT'];
$this->ip=(!empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : getenv('REMOTE_ADDR');
$this->session_id=session_id();
$this->userID=$userid;
$this->activity = &$_SESSION['activity:token'];
}

function isStaff(){
Expand All @@ -57,6 +59,17 @@ function refreshSession(){
//nothing to do...clients need to worry about it.
}

function getActivityToken() {
if (!$this->activity)
$this->rollActivityToken();

return $this->activity;
}

function rollActivityToken() {
$this->activity = sha1(session_id().microtime(true).$this->ip);
}

function sessionToken(){

$time = time();
Expand Down Expand Up @@ -137,7 +150,14 @@ function getSessionToken() {

function getIP(){
return $this->session->getIP();
}
}

function getActivityToken() {
return $this->session->getActivityToken();
}
function rollActivityToken() {
return $this->session->rollActivityToken();
}
}


Expand Down Expand Up @@ -175,7 +195,26 @@ function getSessionToken() {
function getIP(){
return $this->session->getIP();
}


function getActivityToken() {
return $this->session->getActivityToken();
}
function rollActivityToken() {
return $this->session->rollActivityToken();
}
}

function activity_token() {
global $thisstaff, $thisclient;

if (defined('OSTSTAFFINC') && $thisstaff) { ?>
<input type="hidden" name="__activity__" value="<?php
echo $thisstaff->getActivityToken(); ?>"/>
<?php }
elseif (defined('OSTCLIENTINC') && $thisclient) { ?>
<input type="hidden" name="__activity__" value="<?php
echo $thisclient->getActivityToken(); ?>"/>
<?php }
}

?>
1 change: 1 addition & 0 deletions include/client/open.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<p>Please fill in the form below to open a new ticket.</p>
<form id="ticketForm" method="post" action="open.php" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="a" value="open">
<table width="800" cellpadding="1" cellspacing="0" border="0">
<tr>
Expand Down
1 change: 1 addition & 0 deletions include/client/view.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<?php } ?>
<form id="reply" action="tickets.php?id=<?php echo $ticket->getExtId(); ?>#reply" name="reply" method="post" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<h2>Post a Reply</h2>
<input type="hidden" name="id" value="<?php echo $ticket->getExtId(); ?>">
<input type="hidden" name="a" value="reply">
Expand Down
1 change: 1 addition & 0 deletions include/staff/ticket-open.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
?>
<form action="tickets.php?a=open" method="post" id="save" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="do" value="create">
<input type="hidden" name="a" value="open">
<h2>Open New Ticket</h2>
Expand Down
7 changes: 7 additions & 0 deletions include/staff/ticket-view.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@
if($thisstaff->canPostReply()) { ?>
<form id="reply" action="tickets.php?id=<?php echo $ticket->getId(); ?>#reply" name="reply" method="post" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="msgId" value="<?php echo $msgId; ?>">
<input type="hidden" name="a" value="reply">
Expand Down Expand Up @@ -516,6 +517,7 @@
} ?>
<form id="note" action="tickets.php?id=<?php echo $ticket->getId(); ?>#note" name="note" method="post" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="locktime" value="<?php echo $cfg->getLockTime(); ?>">
<input type="hidden" name="a" value="postnote">
Expand Down Expand Up @@ -622,6 +624,7 @@
if($thisstaff->canTransferTickets()) { ?>
<form id="transfer" action="tickets.php?id=<?php echo $ticket->getId(); ?>#transfer" name="transfer" method="post" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="ticket_id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="a" value="transfer">
<table border="0" cellspacing="0" cellpadding="3">
Expand Down Expand Up @@ -680,6 +683,7 @@
if($thisstaff->canAssignTickets()) { ?>
<form id="assign" action="tickets.php?id=<?php echo $ticket->getId(); ?>#assign" name="assign" method="post" enctype="multipart/form-data">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="a" value="assign">
<table border="0" cellspacing="0" cellpadding="3">
Expand Down Expand Up @@ -770,6 +774,7 @@
<hr/>
<form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="post" id="print-form" name="print-form">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="a" value="print">
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<fieldset class="notes">
Expand Down Expand Up @@ -810,6 +815,7 @@
<?php echo sprintf('Are you sure you want to <b>%s</b> this ticket?', $ticket->isClosed()?'REOPEN':'CLOSE'); ?>
<form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="post" id="status-form" name="status-form">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="a" value="process">
<input type="hidden" name="do" value="<?php echo $ticket->isClosed()?'reopen':'close'; ?>">
Expand Down Expand Up @@ -863,6 +869,7 @@
<div>Please confirm to continue.</div>
<form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="post" id="confirm-form" name="confirm-form">
<?php csrf_token(); ?>
<?php activity_token(); ?>
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<input type="hidden" name="a" value="process">
<input type="hidden" name="do" id="action" value="">
Expand Down
3 changes: 1 addition & 2 deletions open.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
require('client.inc.php');
define('SOURCE','Web'); //Ticket source.
$ticket = null;
$errors=array();
if($_POST):
if($_POST && !$errors):
$vars = $_POST;
$vars['deptId']=$vars['emailId']=0; //Just Making sure we don't accept crap...only topicId is expected.
if($thisclient) {
Expand Down
2 changes: 2 additions & 0 deletions scp/staff.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ function staffLoginPage($msg) {
} elseif($cfg->isHelpDeskOffline()) {
$sysnotice='<strong>System is set to offline mode</strong> - Client interface is disabled and ONLY admins can access staff control panel.';
$sysnotice.=' <a href="settings.php">Enable</a>.';
} elseif ($_POST && !$ost->checkActivityToken()) {
$errors['err'] = 'Cowardly refusing to repeat previous activity';
}

$nav = new StaffNav($thisstaff);
Expand Down
2 changes: 1 addition & 1 deletion tickets.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}

//Process post...depends on $ticket object above.
if($_POST && is_object($ticket) && $ticket->getId()):
if($_POST && is_object($ticket) && $ticket->getId() && !$errors):
$errors=array();
switch(strtolower($_POST['a'])){
case 'reply':
Expand Down