function tryLogin($ticketID, $email, $auth = null) { global $ost; $cfg = $ost->getConfig(); # Only consider auth token for GET requests, and for GET requests, # REQUIRE the auth token $auto_login = $_SERVER['REQUEST_METHOD'] == 'GET'; //Check time for last max failed login attempt strike. $loginmsg = 'Invalid login'; # XXX: SECURITY: Max attempts is enforced client-side via the PHP # session cookie. if ($_SESSION['_client']['laststrike']) { if (time() - $_SESSION['_client']['laststrike'] < $cfg->getClientLoginTimeout()) { $loginmsg = 'Excessive failed login attempts'; $errors['err'] = 'You\'ve reached maximum failed login attempts allowed. Try again later or <a href="open.php">open a new ticket</a>'; } else { //Timeout is over. //Reset the counter for next round of attempts after the timeout. $_SESSION['_client']['laststrike'] = null; $_SESSION['_client']['strikes'] = 0; } } //See if we can fetch local ticket id associated with the ID given if (!$errors && is_numeric($ticketID) && Validator::is_email($email) && ($ticket = Ticket::lookupByExtId($ticketID))) { //At this point we know the ticket is valid. //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets?? //Check the email given. # Require auth token for automatic logins if (!$auto_login || $auth === $ticket->getAuthToken()) { if ($ticket->getId() && strcasecmp($ticket->getEmail(), $email) == 0) { //valid match...create session goodies for the client. $user = new ClientSession($email, $ticket->getId()); $_SESSION['_client'] = array(); //clear. $_SESSION['_client']['userID'] = $ticket->getEmail(); //Email $_SESSION['_client']['key'] = $ticket->getExtId(); //Ticket ID --acts as password when used with email. See above. $_SESSION['_client']['token'] = $user->getSessionToken(); $_SESSION['TZ_OFFSET'] = $cfg->getTZoffset(); $_SESSION['TZ_DST'] = $cfg->observeDaylightSaving(); //Log login info... $msg = sprintf("%s/%s logged in [%s]", $ticket->getEmail(), $ticket->getExtId(), $_SERVER['REMOTE_ADDR']); $ost->logDebug('User login', $msg); //Redirect tickets.php session_write_close(); session_regenerate_id(); @header("Location: tickets.php?id=" . $ticket->getExtId()); require_once 'tickets.php'; //Just incase. of header already sent error. exit; } } } //If we get to this point we know the login failed. $_SESSION['_client']['strikes'] += 1; if (!$errors && $_SESSION['_client']['strikes'] > $cfg->getClientMaxLogins()) { $loginmsg = 'Access Denied'; $errors['err'] = 'Forgot your login info? Please <a href="open.php">open a new ticket</a>.'; $_SESSION['_client']['laststrike'] = time(); $alert = 'Excessive login attempts by a client?' . "\n" . 'Email: ' . $_POST['lemail'] . "\n" . 'Ticket#: ' . $_POST['lticket'] . "\n" . 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n" . 'Time:' . date('M j, Y, g:i a T') . "\n\n" . 'Attempts #' . $_SESSION['_client']['strikes']; $ost->logError('Excessive login attempts (client)', $alert, $cfg->alertONLoginError()); } elseif ($_SESSION['_client']['strikes'] % 2 == 0) { //Log every other failed login attempt as a warning. $alert = 'Email: ' . $_POST['lemail'] . "\n" . 'Ticket #: ' . $_POST['lticket'] . "\n" . 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n" . 'TIME: ' . date('M j, Y, g:i a T') . "\n\n" . 'Attempts #' . $_SESSION['_client']['strikes']; $ost->logWarning('Failed login attempt (client)', $alert); } }
function createTicket($mid) { global $ost; if (!($mailinfo = $this->getHeaderInfo($mid))) { return false; } //Make sure the email is NOT already fetched... (undeleted emails) if ($mailinfo['mid'] && ($id = Ticket::getIdByMessageId(trim($mailinfo['mid']), $mailinfo['email']))) { return true; } //Reporting success so the email can be moved or deleted. //Is the email address banned? if ($mailinfo['email'] && EmailFilter::isBanned($mailinfo['email'])) { //We need to let admin know... $ost->logWarning('Ticket denied', 'Banned email - ' . $mailinfo['email']); return true; //Report success (moved or delete) } $emailId = $this->getEmailId(); $var['name'] = $this->mime_decode($mailinfo['name']); $var['email'] = $mailinfo['email']; $var['subject'] = $mailinfo['subject'] ? $this->mime_decode($mailinfo['subject']) : '[No Subject]'; $var['message'] = Format::stripEmptyLines($this->getBody($mid)); $var['header'] = $this->getHeader($mid); $var['emailId'] = $emailId ? $emailId : $ost->getConfig()->getDefaultEmailId(); //ok to default? $var['name'] = $var['name'] ? $var['name'] : $var['email']; //No name? use email $var['mid'] = $mailinfo['mid']; if (!$var['message']) { //An email with just attachments can have empty body. $var['message'] = '(EMPTY)'; } if ($ost->getConfig()->useEmailPriority()) { $var['priorityId'] = $this->getPriority($mid); } $ticket = null; $newticket = true; //Check the subject line for possible ID. if ($var['subject'] && preg_match("[[#][0-9]{1,10}]", $var['subject'], $regs)) { $tid = trim(preg_replace("/[^0-9]/", "", $regs[0])); //Allow mismatched emails?? For now NO. if (!($ticket = Ticket::lookupByExtId($tid)) || strcasecmp($ticket->getEmail(), $var['email'])) { $ticket = null; } } $errors = array(); if ($ticket) { if (!($msgid = $ticket->postMessage($var['message'], 'Email', $var['mid'], $var['header']))) { return false; } } elseif ($ticket = Ticket::create($var, $errors, 'Email')) { $msgid = $ticket->getLastMsgId(); } else { //TODO: Log error.. return null; } //Save attachments if any. if ($msgid && $ost->getConfig()->allowEmailAttachments() && ($struct = imap_fetchstructure($this->mbox, $mid)) && $struct->parts && ($attachments = $this->getAttachments($struct))) { //We're just checking the type of file - not size or number of attachments... // Restrictions are mainly due to PHP file uploads limitations foreach ($attachments as $a) { if ($ost->isFileTypeAllowed($a['name'], $a['mime'])) { $file = array('name' => $a['name'], 'type' => $a['mime'], 'data' => $this->decode($a['encoding'], imap_fetchbody($this->mbox, $mid, $a['index']))); $ticket->saveAttachment($file, $msgid, 'M'); } else { //This should be really a comment on message - NoT an internal note. //TODO: support comments on Messages and Responses. $error = sprintf('Attachment %s [%s] rejected because of file type', $a['name'], $a['mime']); $ticket->postNote('Email Attachment Rejected', $error, false); $ost->logDebug('Email Attachment Rejected (Ticket #' . $ticket->getExtId() . ')', $error); } } } return $ticket; }
function login($ticketID, $email, $auth = null, &$errors = array()) { global $ost; $cfg = $ost->getConfig(); $auth = trim($auth); $email = trim($email); $ticketID = trim($ticketID); # Only consider auth token for GET requests, and for GET requests, # REQUIRE the auth token $auto_login = $_SERVER['REQUEST_METHOD'] == 'GET'; //Check time for last max failed login attempt strike. if ($_SESSION['_client']['laststrike']) { if (time() - $_SESSION['_client']['laststrike'] < $cfg->getClientLoginTimeout()) { $errors['login'] = '******'; $errors['err'] = 'You\'ve reached maximum failed login attempts allowed. Try again later or <a href="open.php">open a new ticket</a>'; $_SESSION['_client']['laststrike'] = time(); //renew the strike. } else { //Timeout is over. //Reset the counter for next round of attempts after the timeout. $_SESSION['_client']['laststrike'] = null; $_SESSION['_client']['strikes'] = 0; } } if ($auto_login && !$auth) { $errors['login'] = '******'; } elseif (!$ticketID || !Validator::is_email($email)) { $errors['login'] = '******'; } //Bail out on error. if ($errors) { return false; } //See if we can fetch local ticket id associated with the ID given if (($ticket = Ticket::lookupByExtId($ticketID, $email)) && $ticket->getId()) { //At this point we know the ticket ID is valid. //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets?? //Check the email given. # Require auth token for automatic logins (GET METHOD). if (!strcasecmp($ticket->getEmail(), $email) && (!$auto_login || $auth === $ticket->getAuthToken())) { //valid match...create session goodies for the client. $user = new ClientSession($email, $ticket->getExtId()); $_SESSION['_client'] = array(); //clear. $_SESSION['_client']['userID'] = $ticket->getEmail(); //Email $_SESSION['_client']['key'] = $ticket->getExtId(); //Ticket ID --acts as password when used with email. See above. $_SESSION['_client']['token'] = $user->getSessionToken(); $_SESSION['TZ_OFFSET'] = $cfg->getTZoffset(); $_SESSION['TZ_DST'] = $cfg->observeDaylightSaving(); $user->refreshSession(); //set the hash. //Log login info... $msg = sprintf('%s/%s logged in [%s]', $ticket->getEmail(), $ticket->getExtId(), $_SERVER['REMOTE_ADDR']); $ost->logDebug('User login', $msg); //Regenerate session ID. $sid = session_id(); //Current session id. session_regenerate_id(TRUE); //get new ID. if (($session = $ost->getSession()) && is_object($session) && $sid != session_id()) { $session->destroy($sid); } return $user; } } //If we get to this point we know the login failed. $errors['login'] = '******'; $_SESSION['_client']['strikes'] += 1; if (!$errors && $_SESSION['_client']['strikes'] > $cfg->getClientMaxLogins()) { $errors['login'] = '******'; $errors['err'] = 'Forgot your login info? Please <a href="open.php">open a new ticket</a>.'; $_SESSION['_client']['laststrike'] = time(); $alert = 'Excessive login attempts by a user.' . "\n" . 'Email: ' . $email . "\n" . 'Ticket#: ' . $ticketID . "\n" . 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n" . 'Time:' . date('M j, Y, g:i a T') . "\n\n" . 'Attempts #' . $_SESSION['_client']['strikes']; $ost->logError('Excessive login attempts (user)', $alert, $cfg->alertONLoginError()); } elseif ($_SESSION['_client']['strikes'] % 2 == 0) { //Log every other failed login attempt as a warning. $alert = 'Email: ' . $email . "\n" . 'Ticket #: ' . $ticketID . "\n" . 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n" . 'TIME: ' . date('M j, Y, g:i a T') . "\n\n" . 'Attempts #' . $_SESSION['_client']['strikes']; $ost->logWarning('Failed login attempt (user)', $alert); } return false; }
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 'secure.inc.php'; if (!is_object($thisclient) || !$thisclient->isValid()) { die('Access denied'); } //Double check again. require_once INCLUDE_DIR . 'class.ticket.php'; $ticket = null; if ($_REQUEST['id']) { if (!($ticket = Ticket::lookupByExtId($_REQUEST['id']))) { $errors['err'] = 'Unknown or invalid ticket ID.'; } elseif (!$ticket->checkClientAccess($thisclient)) { $errors['err'] = 'Unknown or invalid ticket ID.'; //Using generic message on purpose! $ticket = null; } } //Process post...depends on $ticket object above. if ($_POST && is_object($ticket) && $ticket->getId()) { $errors = array(); switch (strtolower($_POST['a'])) { case 'reply': if (!$ticket->checkClientAccess($thisclient)) { //double check perm again! $errors['err'] = 'Access Denied. Possibly invalid ticket ID';
//$_SESSION['_client']=array(); #Uncomment to disable login strikes. //Check time for last max failed login attempt strike. $loginmsg = 'Invalid login'; if ($_SESSION['_client']['laststrike']) { if (time() - $_SESSION['_client']['laststrike'] < $cfg->getClientLoginTimeout()) { $loginmsg = 'Excessive failed login attempts'; $errors['err'] = 'You\'ve reached maximum failed login attempts allowed. Try again later or <a href="open.php">open a new ticket</a>'; } else { //Timeout is over. //Reset the counter for next round of attempts after the timeout. $_SESSION['_client']['laststrike'] = null; $_SESSION['_client']['strikes'] = 0; } } //See if we can fetch local ticket id associated with the ID given if (!$errors && is_numeric($ticketID) && Validator::is_email($email) && ($ticket = Ticket::lookupByExtId($ticketID))) { //At this point we know the ticket is valid. //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets?? //Check the email given. if ($ticket->getId() && strcasecmp($ticket->getEMail(), $email) == 0) { //valid match...create session goodies for the client. $user = new ClientSession($email, $ticket->getId()); $_SESSION['_client'] = array(); //clear. $_SESSION['_client']['userID'] = $ticket->getEmail(); //Email $_SESSION['_client']['key'] = $ticket->getExtId(); //Ticket ID --acts as password when used with email. See above. $_SESSION['_client']['token'] = $user->getSessionToken(); $_SESSION['TZ_OFFSET'] = $cfg->getTZoffset(); $_SESSION['daylight'] = $cfg->observeDaylightSaving();