From 109cba621a91caaa159062d51a4e964a56eb6bb4 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Fri, 6 Jun 2014 14:02:57 -0500
Subject: [PATCH] Allow direct access to tickets with email and num

Starting with osTicket 1.8.1, users must receive an email and follow a link
in the email to get access to the ticket. With this new option, the email
verification step can be avoided in osTicket 1.9, because access is now only
granted to exactly one ticket.
---
 include/class.auth.php                        | 35 +++++++++++++++++--
 include/class.config.php                      |  6 ++++
 include/client/accesslink.inc.php             |  7 +++-
 .../i18n/en_US/help/tips/settings.access.yaml | 11 ++++++
 include/staff/settings-access.inc.php         |  8 +++++
 login.php                                     |  6 ++++
 6 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/include/class.auth.php b/include/class.auth.php
index 02e8eaf52..fe0bba0e6 100644
--- a/include/class.auth.php
+++ b/include/class.auth.php
@@ -1050,6 +1050,14 @@ class AccessLinkAuthentication extends UserAuthenticationBackend {
                 || !($user=User::lookup(array('emails__address' => $email))))
             return false;
 
+        if (!($user = $this->_getTicketUser($ticket, $user)))
+            return false;
+
+        $_SESSION['_auth']['user-ticket'] = $number;
+        return new ClientSession($user);
+    }
+
+    function _getTicketUser($ticket, $user) {
         // Ticket owner?
         if ($ticket->getUserId() == $user->getId())
             $user = $ticket->getOwner();
@@ -1059,13 +1067,36 @@ class AccessLinkAuthentication extends UserAuthenticationBackend {
                 'ticketId' => $ticket->getId()))))
             return false; //Bro, we don't know you!
 
-        return new ClientSession($user);
+        return $user;
     }
 
-    //We are not actually logging in the user....
+    // We are not actually logging in the user....
     function login($user, $bk) {
+        global $cfg;
+
+        if (!$cfg->isClientEmailVerificationRequired()) {
+            return parent::login($user, $bk);
+        }
         return true;
     }
+
+    protected function validate($userid) {
+        $number = $_SESSION['_auth']['user-ticket'];
+
+        if (!($ticket = Ticket::lookupByNumber($number)))
+            return false;
+
+        if (!($user = User::lookup($userid)))
+            return false;
+
+        if (!($user = $this->_getTicketUser($ticket, $user)))
+            return false;
+
+        $user = new ClientSession($user);
+        $user->flagGuest();
+        return $user;
+    }
+
     function supportsInteractiveAuthentication() {
         return false;
     }
diff --git a/include/class.config.php b/include/class.config.php
index 2cdce1351..0616bb96b 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -167,6 +167,7 @@ class OsticketConfig extends Config {
         'accept_unregistered_email' => true,
         'default_help_topic' => 0,
         'help_topic_sort_mode' => 'a',
+        'client_verify_email' => 1,
     );
 
     function OsticketConfig($section=null) {
@@ -579,6 +580,10 @@ class OsticketConfig extends Config {
         return $this->get('client_registration');
     }
 
+    function isClientEmailVerificationRequired() {
+        return $this->get('client_verify_email');
+    }
+
     function isCaptchaEnabled() {
         return (extension_loaded('gd') && function_exists('gd_info') && $this->get('enable_captcha'));
     }
@@ -918,6 +923,7 @@ class OsticketConfig extends Config {
             'pw_reset_window'=>$vars['pw_reset_window'],
             'clients_only'=>isset($vars['clients_only'])?1:0,
             'client_registration'=>$vars['client_registration'],
+            'client_verify_email'=>isset($vars['client_verify_email'])?1:0,
         ));
     }
 
diff --git a/include/client/accesslink.inc.php b/include/client/accesslink.inc.php
index a87d08d58..f40eb7efc 100644
--- a/include/client/accesslink.inc.php
+++ b/include/client/accesslink.inc.php
@@ -3,6 +3,11 @@ if(!defined('OSTCLIENTINC')) die('Access Denied');
 
 $email=Format::input($_POST['lemail']?$_POST['lemail']:$_GET['e']);
 $ticketid=Format::input($_POST['lticket']?$_POST['lticket']:$_GET['t']);
+
+if ($cfg->isClientEmailVerificationRequired())
+    $button = "Email Access Link";
+else
+    $button = "View Ticket";
 ?>
 <h1>Check Ticket Status</h1>
 <p>Please provide us with your email address and a ticket number, and an access
@@ -24,7 +29,7 @@ link will be emailed to you.</p>
             size="30" value="<?php echo $ticketid; ?>"></td>
     </div>
     <p>
-        <input class="btn" type="submit" value="Email Access Link">
+        <input class="btn" type="submit" value="<?php echo $button; ?>">
     </p>
     </div>
     <div style="display:table-cell;padding-left: 2em;padding-right:90px;">
diff --git a/include/i18n/en_US/help/tips/settings.access.yaml b/include/i18n/en_US/help/tips/settings.access.yaml
index 17a861186..1d88a13bf 100644
--- a/include/i18n/en_US/help/tips/settings.access.yaml
+++ b/include/i18n/en_US/help/tips/settings.access.yaml
@@ -100,3 +100,14 @@ registration_method:
             <tr><td>Yes</td><td>Disabled</td>
                 <td>Disable new tickets via web portal</td></tr>
         </tbody></table>
+
+client_verify_email:
+    title: Require Email Verification
+    content: >
+        Disable this option to give your users immediate access to tickets
+        via the "Check Ticket Status" login page in the client portal. If
+        enabled, (which is the default), users will be required to receive
+        an email and follow a link in the email to view the ticket.
+        <br><br>
+        Disabling email verification might allow third-parties (e.g. ticket
+        collaborators) to impersonate the ticket owner.
diff --git a/include/staff/settings-access.inc.php b/include/staff/settings-access.inc.php
index 29e2fc212..e045a4560 100644
--- a/include/staff/settings-access.inc.php
+++ b/include/staff/settings-access.inc.php
@@ -132,6 +132,14 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin() || !$config)
               <i class="help-tip icon-question-sign" href="#client_session_timeout"></i>
             </td>
         </tr>
+        <tr><td>Client Quick Access:</td>
+            <td><input type="checkbox" name="client_verify_email" <?php
+                if ($config['client_verify_email'])
+                    echo 'checked="checked"'; ?>/>
+                Require email verification on "Check Ticket Status" page
+            <i class="help-tip icon-question-sign" href="#client_verify_email"></i>
+            </td>
+        </tr>
     </tbody>
     <thead>
         <tr>
diff --git a/login.php b/login.php
index da849bd9e..d8c4d8101 100644
--- a/login.php
+++ b/login.php
@@ -66,6 +66,12 @@ elseif ($_POST && isset($_POST['lticket'])) {
         $errors['err'] = 'Valid email address and ticket number required';
     elseif (($user = UserAuthenticationBackend::process($_POST['lemail'],
             $_POST['lticket'], $errors))) {
+
+        // If email address verification is not required, then provide
+        // immediate access to the ticket!
+        if (!$cfg->isClientEmailVerificationRequired())
+            Http::redirect('tickets.php');
+
         // We're using authentication backend so we can guard aganist brute
         // force attempts (which doesn't buy much since the link is emailed)
         $user->sendAccessLink();
-- 
GitLab