$_POST['name'], 'pass' => $_POST['pass']); $function = '_securesite_plain_auth'; break; } // Are credentials different from current user? if ((!isset($user->name) || $edit['name'] !== $user->name) && (!isset($_SESSION['securesite_guest']) || $edit['name'] !== $_SESSION['securesite_guest'])) { $function($edit); } } /** * Menu callback; handle restricted pages. */ function _securesite_403() { global $user; if (empty($user->uid) && !isset($_SESSION['securesite_guest']) && $_GET['q'] != 'logout') { _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); } else { $path = drupal_get_normal_path(variable_get('securesite_403', '')); menu_set_active_item($path); return menu_execute_active_handler($path); } } /** * Perform digest authentication. */ function _securesite_digest_auth($edit) { global $user; $realm = variable_get('securesite_realm', variable_get('site_name', 'Drupal')); $header = _securesite_digest_validate($status, array('data' => $_SERVER['PHP_AUTH_DIGEST'], 'method' => $_SERVER['REQUEST_METHOD'], 'uri' => request_uri(), 'realm' => $realm)); $account = user_load(array('name' => $edit['name'], 'status' => 1)); if (empty($account->uid)) { // Not a registered user. See if we have guest user credentials. switch ($status) { case 1: drupal_set_header('HTTP/1.1 400 Bad Request'); _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); break; case 0: // Password is correct. Log user in. drupal_set_header($header); $edit['pass'] = variable_get('securesite_guest_pass', ''); default: _securesite_guest_login($edit); break; } } else { switch ($status) { case 0: // Password is correct. Log user in. $user = $account; user_authenticate_finalize($edit); drupal_set_header($header); _securesite_user_login(); break; case 2: // Password not stored. Request credentials using next most secure authentication method. $mechanism = _securesite_mechanism(); $types = variable_get('securesite_type', array(SECURESITE_BASIC)); rsort($types); foreach ($types as $type) { if ($type < $mechanism) { break; } } watchdog('user', 'Secure log-in failed for %user.', array('%user' => $edit['name'])); drupal_set_message(t('Secure log-in failed. Please try again.'), 'error'); _securesite_dialog($type); break; case 1: drupal_set_header('HTTP/1.1 400 Bad Request'); default: // Authentication failed. Request credentials using most secure authentication method. watchdog('user', 'Log-in attempt failed for %user.', array('%user' => $edit['name'])); drupal_set_message(t('Unrecognized user name and/or password.'), 'error'); _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); break; } } } /** * Get the result of digest validation. * * @param $status: Will be set to the return status of the validation script * @param $edit: An array of parameters to pass to the validation script * @return * An HTTP header string. */ function _securesite_digest_validate(&$status, $edit = NULL) { static $header; if (isset($edit)) { if (is_array($edit)) { $values = array(); foreach ($edit as $key => $value) { $values[] = escapeshellarg("$key=$value"); } $script = variable_get('securesite_digest_script', drupal_get_path('module', 'securesite') .'/digest_md5/digest_md5.php'); $response = exec($script .' '. implode(' ', $values), $output, $status); if (isset($edit['data']) && empty($status)) { $header = "Authentication-Info: $response"; } else { $header = "WWW-Authenticate: Digest $response"; } } else { $header = $edit; } } return $header; } /** * Perform plain authentication. */ function _securesite_plain_auth($edit) { global $user; $account = user_load(array('name' => $edit['name'], 'status' => 1)); if (empty($account->uid)) { // Not a registered user. See if we have guest user credentials. _securesite_guest_login($edit); } else { // The LDAP auth module can't use the regular external user log-in system, so we // have to call its log-in function directly. if (module_exists('ldapauth')) { ldapauth_authenticate($edit); } else { user_authenticate($edit); } if (!empty($user->uid)) { _securesite_user_login(); } else { // Request credentials using most secure authentication method. watchdog('user', 'Log-in attempt failed for %user.', array('%user' => $edit['name'])); drupal_set_message(t('Unrecognized user name and/or password.'), 'error'); _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); } } } /** * Log in authenticated user. */ function _securesite_user_login() { global $user; if (user_access('access secured pages')) { unset($_SESSION['securesite_guest']); // Clear the guest session. $_SESSION['securesite_login'] = TRUE; // Mark the session so Secure Site will be triggered on log-out. // Prevent a log-in/log-out loop by redirecting off the log-out page. if ($_GET['q'] == 'logout') { drupal_goto(); } } // Not an authorized user. else { // Load the anonymous user. $user = drupal_anonymous_user(); drupal_set_message(t('Unauthorized user.'), 'error'); _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); } } /** * Log in guest user. */ function _securesite_guest_login($edit) { $guest_name = variable_get('securesite_guest_name', ''); $guest_pass = variable_get('securesite_guest_pass', ''); // Check anonymous user permission and credentials. if (user_access('access secured pages') && (empty($guest_name) || $edit['name'] == $guest_name) && (empty($guest_pass) || $edit['pass'] == $guest_pass)) { // Mark this session to prevent re-login (note: guests can't log out). $_SESSION['securesite_guest'] = $edit['name']; $_SESSION['securesite_login'] = TRUE; // Prevent a 403 error by redirecting off the logout page. if ($_GET['q'] == 'logout') { drupal_goto(); } } else { if (empty($edit['name'])) { watchdog('user', 'Log-in attempt failed for anonymous user.'); } else { watchdog('user', 'Log-in attempt failed for %user.', array('%user' => $edit['name'])); } drupal_set_message(' '. t('Unrecognized user name and/or password.') ."\n ", 'error'); _securesite_dialog(array_pop(variable_get('securesite_type', array(SECURESITE_BASIC)))); } } /** * Determine if Secure Site authentication should be forced. */ function _securesite_forced() { global $base_path; // Do we require credentials to display this page? if (php_sapi_name() == 'cli') { return FALSE; } else { switch (variable_get('securesite_enabled', SECURESITE_DISABLED)) { case SECURESITE_ALWAYS: return TRUE; case SECURESITE_OFFLINE: return variable_get('site_offline', FALSE); case SECURESITE_403: if (variable_get('site_403', '') != 'securesite_403') { variable_set('securesite_403', variable_get('site_403', '')); variable_set('site_403', 'securesite_403'); } default: return FALSE; } } } /** * Display authentication dialog and send password reset mails. */ function _securesite_dialog($type) { global $base_path; // Has the password reset form been submitted? if (isset($_POST['form_id']) && $_POST['form_id'] == 'securesite_user_pass') { $content = _securesite_page(); } // Are we on a password reset page? elseif (strpos($_GET['q'], 'user/reset/') === 0 || module_exists('i18n') && i18n_selection_mode() != 'off' && strpos($_GET['q'], i18n_selection_mode('params') .'/user/reset/') === 0) { $args = explode('/', $_GET['q']); if (module_exists('i18n') && i18n_selection_mode() != 'off' && i18n_selection_mode('params') != '') { // Remove the language argument. array_shift($args); } // The password reset function doesn't work well if it doesn't have all the // required parameters or if the UID parameter isn't valid if (count($args) < 5 || user_load(array('uid' => $args[2], 'status' => 1)) == FALSE) { $error = t('You have tried to use an invalid one-time log-in link.'); $reset = variable_get('securesite_reset_form', t('Enter your user name or e-mail address.')); if (empty($reset)) { drupal_set_message($error, 'error'); $content = ''; } else { $error .= ' '. t('Please request a new one using the form below.'); drupal_set_message($error, 'error'); $content = drupal_get_form('securesite_user_pass'); } } } else { // Display log-in dialog. switch ($type) { case SECURESITE_DIGEST: $header = _securesite_digest_validate($status); if (empty($header)) { $realm = variable_get('securesite_realm', variable_get('site_name', 'Drupal')); $header = _securesite_digest_validate($status, array('realm' => $realm, 'fakerealm' => _securesite_fake_realm())); } if (strpos($header, 'WWW-Authenticate') === 0) { drupal_set_header($header); drupal_set_header('HTTP/1.1 401 Unauthorized'); } else { drupal_set_header($header); } $content = _securesite_page('

'. t('Reload the page to try logging in again.') .'

'); break; case SECURESITE_BASIC: drupal_set_header('WWW-Authenticate: Basic realm="'. _securesite_fake_realm() .'"'); drupal_set_header('HTTP/1.1 401 Unauthorized'); $content = _securesite_page('

'. t('Reload the page to try logging in again.') .'

'); break; case SECURESITE_FORM: // Form authentication doesn't work for cron. if (request_uri() != $base_path .'cron.php') { $content = _securesite_page(); } break; } } if (isset($content)) { drupal_add_css(drupal_get_path('module', 'securesite') .'/securesite.css'); print theme('securesite_page', $content); module_invoke_all('exit'); exit(); } } /** * Opera and Internet Explorer save credentials indefinitely and will keep * attempting to use them even when they have failed multiple times. We add a * random string to the realm to allow users to log out. */ function _securesite_fake_realm() { $realm = variable_get('securesite_realm', variable_get('site_name', 'Drupal')); $user_agent = (isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : ''); if ($user_agent != str_replace(array('msie', 'opera'), '', $user_agent)) { $realm .= ' - '. mt_rand(10, 999); } return $realm; } /** * Display fallback HTML for HTTP authentication dialogs. Safari will not load * this. Opera will not load this after log-out unless the page has been * reloaded and the authentication dialog has been displayed twice. */ function _securesite_page($message = NULL) { $reset = variable_get('securesite_reset_form', t('Enter your user name or e-mail address.')); if (in_array(SECURESITE_FORM, variable_get('securesite_type', array(SECURESITE_BASIC)))) { $output = drupal_get_form('securesite_user_login'); $output .= empty($reset) ? '' : "
\n". drupal_get_form('securesite_user_pass'); } else { if (!empty($reset) && _securesite_forced()) { $output = drupal_get_form('securesite_user_pass'); } else { $output = $message; } } return $output; } /** * Process variables for securesite-page.tpl.php * * The $variables array contains the following arguments: * - $messages * * @see securesite-page.tpl.php */ function template_preprocess_securesite_page(&$variables) { $variables['messages'] = theme('status_messages'); } /** * We use our own version of the log-in form for theming. We do not use the * default validate and submit functions because we may allow anonymous users. * * @ingroup forms * @see user_login() */ function securesite_user_login() { $form['name'] = array( '#type' => 'textfield', '#title' => t('User name'), '#maxlength' => USERNAME_MAX_LENGTH, '#size' => 15, ); $form['pass'] = array( '#type' => 'password', '#title' => t('Password'), '#maxlength' => 60, '#size' => 15, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Log in'), ); if (module_exists('openid')) { global $base_path; $style = ''; drupal_set_html_head($style); } drupal_alter('form', $form, NULL, 'user_login'); return $form; } /** * Process variables for securesite-user-login.tpl.php * * The $variables array contains the following arguments: * - $title * - $messages * * @see securesite-user-login.tpl.php */ function template_preprocess_securesite_user_login(&$variables) { $variables['title'] = variable_get('securesite_login_form', t('Enter your user name and password.')); $variables['messages'] = ''; // If the reset form exists and was submitted, status messages should be displayed there. $reset = variable_get('securesite_reset_form', t('Enter your user name or e-mail address.')); if (empty($reset) || !isset($_POST['form_id']) || isset($_POST['form_id']) && $_POST['form_id'] != 'securesite_user_pass') { $variables['messages'] = theme('status_messages'); } } /** * We use our own version of the password reset form for theming. * * @ingroup forms * @see user_pass_validate * @see user_pass_submit */ function securesite_user_pass() { module_load_include('inc', 'user', 'user.pages'); $form = user_pass(); drupal_alter('form', $form, NULL, 'user_pass'); $form['#redirect'] = FALSE; $form['#validate'][] = 'user_pass_validate'; $form['#submit'][] = 'user_pass_submit'; return $form; } /** * Process variables for securesite-user-pass.tpl.php * * The $variables array contains the following arguments: * - $title * - $messages * * @see securesite-user-pass.tpl.php */ function template_preprocess_securesite_user_pass(&$variables) { $variables['title'] = variable_get('securesite_reset_form', t('Enter your user name or e-mail address.')); $variables['messages'] = theme('status_messages'); $variables['form']['name']['#required'] = FALSE; }