<?php

/**
 * @file
 * Prevents hijacked session from accessing pages protected by the securepages module.
 */

define('SECUREPAGES_SESSID', 'SSL_'. session_name());

/**
 * Implementation of hook_init().
 *
 * If this is and is supposed to be a secure page, and a user has
 * logged in, verify that the secure cookie (set in hook_user below)
 * is a valid token.
 */
function securepages_prevent_hijack_init() {
  $path = isset($_GET['q']) ? $_GET['q'] : '';
  $page_match = securepages_match($path);

  global $user;
  if ($user->uid > 0 && $page_match && securepages_is_secure() && variable_get('securepages_enable', FALSE)) {
    if (! isset($_COOKIE[SECUREPAGES_SESSID]) ||
    ! drupal_valid_token($_COOKIE[SECUREPAGES_SESSID], 'securepages_prevent_hijack')) {
      $username = $user->name;
      session_destroy();
      $user = drupal_anonymous_user();
      sess_regenerate();
      if (! isset($_COOKIE[CHOCOLATECHIP])) {
        watchdog('security',
        t('Session hijack attempt detected for user %user!',
        array('%user' => $user->name)));
        drupal_access_denied();
      } else {
#       drupal_goto('user', 'destination=' . $_GET['q']);
        drupal_goto($_GET['q']);
      }
      exit();
    }
  }
}

/**
 * Implementation of hook_user().
 */
function securepages_prevent_hijack_user($op, &$edit, &$user, $category = NULL) {
  switch ($op) {
  case 'login':
    _securepages_prevent_hijack_cookie();
    break;

  case 'after_update':
    // Regenerate our cookie after password changes.
    if (!empty($edit['pass'])) {
      _securepages_prevent_hijack_cookie();
    }
    break;
  }
}

/**
 * Set a secure cookie (that will only be returned to SSL-protected pages)
 * containing a non-guessable token.
 */
function _securepages_prevent_hijack_cookie() {
  if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $tok = drupal_get_token('securepages_prevent_hijack');
    $cookie_params = session_get_cookie_params();
    $lifetime = 0;
    if ($cookie_params['lifetime'] > 0) {
      $lifetime = $_SERVER['REQUEST_TIME'] + $cookie_params['lifetime'];
    }
    setcookie(SECUREPAGES_SESSID, $tok, $lifetime,
    $cookie_params['path'], $cookie_params['domain'], 1);
  }
  else {
    watchdog('security', 'Secure Pages Prevent Hijack failed to set secure cookie.', NULL, WATCHDOG_CRITICAL);
  }
}

/**
 * Implementation of hook_form_alter().
 */
function securepages_prevent_hijack_form_alter(&$form, &$form_state, $form_id) {
  if (!variable_get('securepages_enable', 0)) {
    return;
  }
  // Refresh the cookie whenever the settings page is submitted.
  if ($form['#id'] == 'securepages-settings') {
    $form['#submit'][] = '_securepages_prevent_hijack_cookie';
  }

  // Secure the login form, so that we always have a secure connection to transmit the
  // initial cookie.  Also, protect the password in transit.
  if ($form['#id'] == 'user-login-form' || $form['#id'] == 'user-login') {
    $url = parse_url($form['#action']);

    $base_path = base_path();
    $path = (!strncmp($url['path'], $base_path, drupal_strlen($base_path)) ? drupal_substr($url['path'], drupal_strlen($base_path)) : $url['path']);
    $options = array('absolute' => TRUE, 'base_url' => securepages_baseurl(TRUE));
    if (isset($url['query'])) {
      $options['query'] = $url['query'];
    }
    $form['#action'] = url($path, $options);
  }
}
