From fcc7f861b170596c6970aecb1ddc87a3567b112f Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Sat, 30 Jul 2011 11:32:13 -0400
Subject: [PATCH] Log session validation errors; keep error message when redirecting to login after session error

---
 index.php                         |   17 +++++++++++++----
 program/include/rcube_session.php |   21 +++++++++++++++++++--
 config/main.inc.php.dist          |    3 +++
 program/js/app.js                 |    3 ++-
 4 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index db4ab92..750fa25 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -41,6 +41,9 @@
 // Log successful logins to <log_dir>/userlogins or to syslog
 $rcmail_config['log_logins'] = false;
 
+// Log session authentication errors to <log_dir>/session or to syslog
+$rcmail_config['log_session'] = false;
+
 // Log SQL queries to <log_dir>/sql or to syslog
 $rcmail_config['sql_debug'] = false;
 
diff --git a/index.php b/index.php
index 2cf5814..4b887c7 100644
--- a/index.php
+++ b/index.php
@@ -120,7 +120,7 @@
 
     // allow plugins to control the redirect url after login success
     $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail'));
-    unset($redir['abort']);
+    unset($redir['abort'], $redir['_err']);
 
     // send redirect
     $OUTPUT->redirect($redir);
@@ -147,18 +147,24 @@
 // check session and auth cookie
 else if ($RCMAIL->task != 'login' && $_SESSION['user_id'] && $RCMAIL->action != 'send') {
   if (!$RCMAIL->session->check_auth()) {
-    $OUTPUT->show_message('sessionerror', 'error');
     $RCMAIL->kill_session();
+    $session_error = true;
   }
 }
 
 // not logged in -> show login page
 if (empty($RCMAIL->user->ID)) {
+  // log session failures
+  if ($RCMAIL->task != 'login' && !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])) {
+    $RCMAIL->session->log("Aborted session " . $sess_id . "; no valid session data found");
+    $session_error = true;
+  }
+
   if ($OUTPUT->ajax_call)
-    $OUTPUT->redirect(array(), 2000);
+    $OUTPUT->redirect(array('_err' => 'session'), 2000);
 
   if (!empty($_REQUEST['_framed']))
-    $OUTPUT->command('redirect', '?');
+    $OUTPUT->command('redirect', $RCMAIL->url(array('_err' => 'session')));
 
   // check if installer is still active
   if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) {
@@ -171,6 +177,9 @@
       )
     );
   }
+  
+  if ($session_error || $_REQUEST['_err'] == 'session')
+    $OUTPUT->show_message('sessionerror', 'error', null, true, -1);
 
   $RCMAIL->set_task('login');
   $OUTPUT->send('login');
diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php
index a635010..bface28 100644
--- a/program/include/rcube_session.php
+++ b/program/include/rcube_session.php
@@ -42,6 +42,7 @@
   private $prev;
   private $secret = '';
   private $ip_check = false;
+  private $logging = false;
   private $keep_alive = 0;
   private $memcache;
 
@@ -53,6 +54,7 @@
     $this->db = $db;
     $this->start = microtime(true);
     $this->ip = $_SERVER['REMOTE_ADDR'];
+    $this->logging = $config->get('log_session', false);
 
     $lifetime = $config->get('session_lifetime', 1) * 60;
     $this->set_lifetime($lifetime);
@@ -565,12 +567,18 @@
     $this->cookie = $_COOKIE[$this->cookiename];
     $result = $this->ip_check ? $_SERVER['REMOTE_ADDR'] == $this->ip : true;
 
+    if (!$result)
+      $this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . $_SERVER['REMOTE_ADDR']);
+
     if ($result && $this->_mkcookie($this->now) != $this->cookie) {
       // Check if using id from previous time slot
-      if ($this->_mkcookie($this->prev) == $this->cookie)
+      if ($this->_mkcookie($this->prev) == $this->cookie) {
         $this->set_auth_cookie();
-      else
+      }
+      else {
         $result = false;
+        $this->log("Session authentication failed for " . $this->key . "; invalid auth cookie sent");
+      }
     }
 
     return $result;
@@ -598,5 +606,14 @@
     $auth_string = "$this->key,$this->secret,$timeslot";
     return "S" . (function_exists('sha1') ? sha1($auth_string) : md5($auth_string));
   }
+  
+  /**
+   * 
+   */
+  function log($line)
+  {
+    if ($this->logging)
+      write_log('session', $line);
+  }
 
 }
diff --git a/program/js/app.js b/program/js/app.js
index da445a3..a9ed9ad 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -5153,7 +5153,8 @@
       obj.click(function() { return ref.hide_message(obj); });
     }
 
-    window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
+    if (timeout > 0)
+      window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
     return id;
   };
 

--
Gitblit v1.9.1