Index: securepages.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/securepages/securepages.module,v
retrieving revision 1.15.2.4
diff -u -p -r1.15.2.4 securepages.module
--- securepages.module	9 Mar 2008 22:47:53 -0000	1.15.2.4
+++ securepages.module	23 Jul 2008 23:28:57 -0000
@@ -1,6 +1,8 @@
 <?php
 // $Id: securepages.module,v 1.15.2.4 2008/03/09 22:47:53 gordon Exp $
 
+define('SECUREPAGES_SESSID', 'SSL_' . session_name());
+
 /**
  * Implementation of hook_boot()
  */
@@ -40,6 +42,47 @@ function securepages_boot() {
 }
 
 /**
+ * Implementation of hook_init()
+ */
+function securepages_init() {
+  $path = isset($_GET['q']) ? $_GET['q'] : '';
+  $page_match = securepages_match($path);
+  
+  if (variable_get('securepages_prevent_hijack', FALSE) &&
+      $path != 'admin/settings/securepages' &&
+      ! securepages_match('user')) {
+    drupal_set_message('WARNING!  Secure Pages is set to prevent hijacked '.
+		       'sessions from accessing SSL pages but the user login '.
+		       'page is not set to be secured.  Fix your '.
+		       l('Secure Pages settings', 'admin/settings/securepages')
+		       .' now; make sure <em>user*</em> is secure.');
+  }
+
+  // If this is and is supposed to be a secure page, and a user has
+  // logged in, verify that the secure cookie (set in securepages_user
+  // hook below) matching the secure token in $_SESSION is present.
+  global $user;
+  if ($user->uid > 0 && $page_match && $_SERVER['HTTPS'] &&
+      variable_get('securepages_prevent_hijack', FALSE)) {
+    if (is_null($_COOKIE[SECUREPAGES_SESSID]) ||
+	$_COOKIE[SECUREPAGES_SESSID] !== $_SESSION[SECUREPAGES_SESSID]) {
+      watchdog('security', 
+	       t('Session hijack attempt detected for user %user!',
+		 array('%user' => $user->name)));
+
+      menu_set_active_item('');
+      drupal_set_title(t('Access denied by Secure Pages module'));
+      $return = t('<p> The Secure Pages module has detected an invalid '.
+        'session access attempt. Please <a href="!url">log in again</a>.</p>',
+        array('!url' => url('logout', array('query'=>array('destination' => 'user/login')))));
+      print theme('page', $return);
+      module_invoke_all('exit', $url);
+      exit;
+    }
+  }
+}
+
+/**
  * Implementation of hook_menu()
  */
 function securepages_menu() {
@@ -75,6 +118,12 @@ function securepages_settings() {
     '#return_value' => TRUE,
     '#default_value' => variable_get('securepages_switch', FALSE),
   );
+  $form['securepages_prevent_hijack'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Prevent hijacked sessions from accessing SSL pages'),
+    '#return_value' => TRUE,
+    '#default_value' => variable_get('securepages_prevent_hijack', FALSE),
+  );
   $form['securepages_secure'] = array(
     '#type' => 'radios',
     '#title' => t('Pages which will be be secure'),
@@ -143,6 +192,33 @@ function securepages_link_alter(&$node, 
   }
 }
 
+ /**
+ * Implementation of hook_user()
+ */
+function securepages_user($op, &$edit, &$user, $category = NULL) {
+  switch ($op) {
+  case 'login':
+    if (variable_get('securepages_prevent_hijack', FALSE)) {
+      if (! $_SERVER['HTTPS']) {
+	// Admin asked us to prevent hijacks but we have a non-secure login.
+	watchdog('security', t('Secure Pages detected non-SSL login '.
+			       'with hijack-prevention enabled.'));
+      }
+
+      // The user has just logged in.  Set a secure cookie (that will
+      // only be returned to SSL-protected pages) containing a
+      // non-guessable token, and store that token in the $_SESSION.
+      $tok = md5(mt_rand() . $edit['pass'] . mt_rand());
+      $_SESSION[SECUREPAGES_SESSID] = "$tok";
+      $cookie_params = session_get_cookie_params();
+      setcookie(SECUREPAGES_SESSID, $tok, time() + $cookie_params[lifetime],
+        $cookie_params[path], $cookie_params[domain], 1);
+
+    }
+    break;
+  }
+}
+
 /**
  * securepage_goto()
  *
