Skip to content
Snippets Groups Projects
Commit d66bd0f9 authored by hotspoons's avatar hotspoons
Browse files

Initial checkin

parents
Branches 6.x-1.x
Tags 6.x-1.0
No related merge requests found
To install this module, extract the module archive into the
sites/all/modules directory, then activate the module. This module requires the
LDAP integration module ( http://drupal.org/project/ldap_integration ), version
6.x-1.x-dev, published February 25, 2011 or newer.
This module also requires that your web server provides an authentication
mechanism for LDAP. The only authentication mechanism used in development
was mod_auth_sspi for Apache/Windows, but so long as the web server's LDAP
authentication mechanism is configured to provide the $_SERVER variable
$_SERVER['REMOTE_USER'] or $_SERVER['REDIRECT_REMOTE_USER'] corresponding
directly to a user's LDAP user name, this should work all the same. This
will require some sort of LDAP authentication mechanism; mod_auth_sspi is
available here: http://mod-auth-sspi.sourceforge.net/, while mod_ntlm is
available here: http://modntlm.sourceforge.net/, and mod_auth_ntlm_winbind is
available here: http://samba.org/ftp/unpacked/lorikeet/mod_auth_ntlm_winbind/.
If a Linux distribution is being used, Apache authentication modules are likely
available within the distro's package manager.
Unless an administrator wishes to require that all visitors be authenticated,
NTLM and/or basic authentication should be set up only on the path
user/login/sso, which will authentify the visitor but not deny access to view
the site if the visitor is not authenticated. An administrator may wish to
require LDAP authentication to view any portion of the site; this can be
achieved by changing the location directive below to "/". An administrator may
also wish to automatically log in visitors to Drupal; this can be achieved by
checking "Turn on automated single sign-on" in the modules' configuration page.
An example of an Apache configuration for a named virtualhost configuration
using mod_auth_sspi on Windows is as follows:
httpd.conf:
_______________________________________________________________________________
_______________________________________________________________________________
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
# Pass NTLM authentication to Apache
LoadModule sspi_auth_module modules/mod_auth_sspi.so
<IfModule !mod_auth_sspi.c>
LoadModule sspi_auth_module modules/mod_auth_sspi.so
</IfModule>
_______________________________________________________________________________
_______________________________________________________________________________
httpd-vhosts.conf:
_______________________________________________________________________________
_______________________________________________________________________________
NameVirtualHost example.com
<VirtualHost example.com>
DocumentRoot "D:/www/example.com/htdocs"
ServerName example.com
<directory "D:/www/example.com/htdocs">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order Allow,Deny
Allow from all
</directory>
<Location /user/login/sso>
AuthType SSPI
AuthName "Example.com - Login using your LDAP user name and password"
SSPIAuth On
SSPIAuthoritative On
### The domain used to authenticate with LDAP; this should match the domain
### configured in the LDAP integration configuration within Drupal
SSPIDomain ad.example.com
SSPIOmitDomain On
SSPIOfferBasic On
Require valid-user
#SSPIBasicPreferred On
#SSPIofferSSPI off
</Location>
</VirtualHost>
_______________________________________________________________________________
_______________________________________________________________________________
After enabling and configuring an LDAP authentication module with Apache,
visit user/login/sso in the Drupal installation on example.com. With or without
the ldap sso Drupal module enabled, the browser should prompt for a user name
and password if using Internet Explorer 8+ or a non-Microsoft browser.
Internet Explorer 7 by default will pass NTLM authentication credentials to
local websites, and IE8+ and Firefox can be configured to do this as well.
If prompted for credentials on that path, enter a valid LDAP user name,
omitting the domain, as well as a password. If the credentials are correct,
or if NTLM credentials are passed automatically by the browser and successfully
authenticated, a Drupal 404 "Page not found" message will be displayed if the
module is not enabled; an "access is denied" message will be displayed if the
module is enabled and the browser is already logged in; and if the ldap_sso
module is fully configured and there is no existing session, the browser will
display the message "You have been successfully authenticated" after
redirecting to the sites' home page.
The LDAP Single Sign-On module provides an administrator with the ability to
configure a Drupal site to use either NTLMSSP (e.g. seamless automatic login
using LDAP / Active Directory credentials passed automatically by supported
and properly configured browsers) or basic digest authentication as a fallback
to authenticate Drupal users. The net effect is that either automatically, or
by visiting a link, a user is authenticated and logged into a Drupal site
without requiring the user to manually enter credentials on suitably configured
installations.
The module was created to provide Drupal intranet applications full integration
with Active Directory and Windows workstations in enterprise environments. It
leverages the LDAP integration module for all Drupal to LDAP/Active Directory
communications, while relies on a web server to provide a $_SERVER
variable containing an authenticated user's login name; this name is queried
by Drupal to allow or deny access to the system.
For more information on configuring Apache to provide NTLM / LDAP
authentication, see INSTALL.txt.
This module requires that the LDAP integration module be installed and fully
configured for proper operation.
After enabling the LDAP Single Sign-On module, it can be configured by
visiting the path admin/settings/ldap/sso as an administrator. Available
options include:
"Turn on automated single sign-on":
Automatically redirects unauthenticated visitors to the sign on page upon
visiting the site, providing a seamless login for browsers configured to
pass NTLM credentials automatically.
"Cookie lifetime":
To ensure users aren't automatically logged back in after logging out, a
cookie is set to ensure no automatic redirection occurs if automated single
sign-on is enabled. This sets the lifetime of the cookie.
"Authentication mechanism":
If different server variables or other authentication mechanisms are used,
they will be selected here. Currently, only mod_auth_sspi is supported, but
other implementations of NTLM authentications can be supported in the
future.
After enabling the LDAP SSO module, a new menu item will be available in the
navigation menu titled "Log In", pointing to user/login/sso. If the
administrator does not wish to use seamless login, they can place this menu
item in a menu accessible to anonymous visitors, and visitors can log in by
visiting this path.
; $Id$
name = Single Sign On
description = LDAP Single Sign On
version = 6.x-1.x-dev
core = 6.x
package = LDAP integration
dependencies[] = ldapauth
\ No newline at end of file
<?php
// $Id: ldap_sso.module
/**
* Implementation of hook_user().
*/
function ldap_sso_user($op, &$edit, &$account, $category = NULL) {
switch ($op) {
case 'load':
if($account->uid == 0 && $GLOBALS['user']->uid == $account->uid){
if(!(isset($_COOKIE['seamless_login'])) || $_COOKIE['seamless_login'] == 'auto login'){
if((arg(0) == 'user' && !(is_numeric(arg(1)))) ||
arg(0) == 'logout' ||
//Special case for preview, since for some reason the anonymous user is
//loaded when previewing a node, triggering this logic branch
//probably not needed any more since I now compare the current global
//user ID to the ID passed here to determine if we need to enter
//this logic or not.
((
(arg(0) == 'node' && arg(1) == 'add') ||
(arg(0) == 'node' && arg(2) == 'edit')
)
&& $_POST['op'] == 'Preview')){
return;
}
else{
if(variable_get('ldap_sso_seamless_login', 0) == 1 && ($_COOKIE['seamless_login_attempted'] != 'true')){
setcookie("seamless_login_attempted", 'true', time()+variable_get('ldap_sso_cookie_expire', (315360000)), base_path(), "");
$_SESSION['seamless_login_attempted'] = $_COOKIE['seamless_login_attempted'];
$destination = 'destination='. rawurlencode($_GET['q']);
drupal_goto('user/login/sso', $destination);
}
else{
return;
}
}
}
}
break;
case 'logout':
if(variable_get('ldap_sso_seamless_login', 0) == 1){
setcookie("seamless_login", 'do not auto login', time()+variable_get('ldap_sso_cookie_expire', (315360000)), base_path(), "");
$_SESSION['seamless_login'] = $_COOKIE['seamless_login'];
}
break;
}
}
/**
* Implementation of hook_menu().
*
* @return An array of menu items.
*/
function ldap_sso_menu() {
$items = array();
$items['user/login/sso'] = array(
'title' => t('Log In'),
'page callback' => 'ldap_sso_user_login',
'access callback' => '_ldap_sso_user_access',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/settings/ldap/sso'] = array(
'title' => 'LDAP Single Sign-On',
'page callback' => 'ldap_sso_admin',
'page arguments' => array(),
'access arguments' => array('administer ldap modules'),
'weight' => 0,
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Menu callback; present an administrative comment listing.
*/
function ldap_sso_admin($callback_arg = '') {
$output = drupal_get_form('ldap_sso_form');
return $output;
}
function ldap_sso_form($form_state){
$period = array(0 => t('Immediately')) + drupal_map_assoc(array(3600, 86400, 604800, 2592000, 31536000, 315360000), 'format_interval') + array(-1 => t('Never'));
$form['ldap_sso_seamless_login'] = array(
'#type' => 'checkbox',
'#title' => t('Turn on automated single sign-on'),
'#description' => t('This requires that you '.
'have operational NTLM authentication turned on for at least
the path user/login/sso, or for the whole domain.'),
'#default_value' => variable_get('ldap_sso_seamless_login', 0),
);
$form['ldap_sso_cookie_expire'] = array(
'#type' => 'select',
'#title' => t('Cookie Lifetime'),
'#description' => t('If using the seamless login, a cookie is necessary to prevent automatic login after a user manually logs out. Select the lifetime of the cookie.'),
'#default_value' => variable_get('ldap_sso_cookie_expire', (315360000)),
'#options' => $period,
);
$form['ldap_sso_ldap_implementation'] = array(
'#type' => 'select',
'#title' => t('Authentication Mechanism'),
'#description' => t('Select the type of authentication mechanism you are using.'),
'#default_value' => variable_get('ldap_sso_ldap_implementation', 'mod_auth_sspi'),
'#options' => array ('mod_auth_sspi' => t('mod_auth_sspi'),
//'mod_auth_ntlm_winbind' => t('mod_auth_ntlm_winbind'),
//'mod_ntlm' => t('mod_ntlm')
),
);
return system_settings_form($form);
}
/**
* Implements hook_theme().
*/
function ldap_sso_theme() {
return array(
'ldap_sso_login_message' => array(
'arguments' => array('message' => NULL),
),
'ldap_sso_message_not_found' => array(
'arguments' => array('message' => NULL),
),
'ldap_sso_message_not_authenticated' => array(
'arguments' => array('message' => NULL),
),
);
}
function theme_ldap_sso_login_message($message){
return $message;
}
function theme_ldap_sso_message_not_found($message){
return $message;
}
function theme_ldap_sso_message_not_authenticated($message){
return $message;
}
//Deny access if uid > 0
function _ldap_sso_user_access() {
if (!$GLOBALS['user']->uid || !empty($GLOBALS['menu_admin']))
return true;
else
return false;
}
function _ldap_sso_user_logout_access() {
return !(_ldap_sso_user_access());
}
/**
* A proxy function for the actual authentication routine. This is in place
* so various implementations of grabbing NTLM credentials can be used and
* selected from an administration page. This is the real gatekeeper since
* this assumes that any NTLM authentication from the underlying web server
* is good enough, and only checks that there are values in place for the
* user name, and anything else that is set for a particular implementation. In
* the case that there is no credentials set by the underlying web server, the
* user is redirected to the normal user login form.
*
* @return false
*/
function ldap_sso_user_login() {
$implementation = variable_get('ldap_sso_ldap_implementation', 'mod_auth_sspi');
switch($implementation) {
case 'mod_auth_sspi' :
$remote_user = $_SERVER['REMOTE_USER'] ? $_SERVER['REMOTE_USER'] : $_SERVER['REDIRECT_REMOTE_USER'];
break;
}
if($remote_user){
$user = ldap_sso_authenticate($remote_user);
if($user && $user->uid > 0){
if(variable_get('ldap_sso_seamless_login', 0) == 1){
setcookie("seamless_login", 'auto login', time()+variable_get('ldap_sso_cookie_expire', 315360000), base_path(), "");
$_SESSION['seamless_login'] = $_COOKIE['seamless_login'];
setcookie("seamless_login_attempted", '');
unset($_SESSION['seamless_login_attempted']);
}
drupal_set_message(t(theme('ldap_sso_login_message',
'You have been successfully authenticated')));
drupal_goto('home');
}
else{
if(variable_get('ldap_sso_seamless_login', 0) == 1){
setcookie("seamless_login", 'do not auto login', time()+variable_get('ldap_sso_cookie_expire', 315360000), base_path(), "");
$_SESSION['seamless_login'] = $_COOKIE['seamless_login'];
}
drupal_set_message(theme('ldap_sso_message_not_found',
t('Sorry, your LDAP credentials were not found, '.
'or the LDAP is not available. You may log in '.
'with other credentials on the !user_login_form.', array('!user_login_form' => l(t('user login form'), 'user/login')))), 'error');
drupal_goto('user/login');
}
}
else{
if(variable_get('ldap_sso_seamless_login', 0) == 1){
setcookie("seamless_login", 'do not auto login', time()+variable_get('ldap_sso_cookie_expire', 315360000), base_path(), "");
$_SESSION['seamless_login'] = $_COOKIE['seamless_login'];
}
drupal_set_message(t(theme('ldap_sso_message_not_authenticated',
'You were not authenticated by the server. You may log in with your credentials below.')), 'error');
drupal_goto('user/login');
}
}
/**
* Implementation of hook_perm().
*
* @return array An array of valid permissions for the ldap_sso module
*/
function ldap_sso_perm() {
return array('administer ldap sso');
}
/**
* Main user authentication function.
*
* This is a facimile of ldapauth_authenticate() from the ldapauth module;
* the main differences are that since we are trusting that the web server's
* authentication mechanism, this only performs a lookup in LDAP on the user's
* name to make sure they exist, and avoids passwords except where required,
* such as storing the user's password in the user table.
*
* If successful, sets the global $user object.
*/
function ldap_sso_authenticate($name) {
module_load_include('module', 'ldapauth');
ldapauth_init();
global $user, $_ldapauth_ldap;
$result = db_query("SELECT sid FROM {ldapauth} WHERE status = 1 ORDER BY weight");
while ($row = db_fetch_object($result)) {
// Initialize LDAP.
if (!_ldapauth_init($row->sid))
continue;
}
if(!($_ldapauth_ldap)){
drupal_set_message(t('There was an error contacting the LDAP server'), 'error');
return false;
}
$pass = user_password(20);
// The user_login_name_validate() is not called if the user is being authenticated
// from the httpauth or services modules, therefore call it here.
$form_state = array('values' => array('name' => $name));
user_login_name_validate(NULL, $form_state);
$account = user_load(array('name' => $name, 'status' => 1));
if ($account && drupal_is_denied('mail', $account->mail)) {
form_set_error('name', t('The name %name is registered using a reserved e-mail address and therefore could not be logged in.', array('%name' => $account->name)));
}
// If there is any validations errors, we do not query LDAP.
if (form_get_errors())
return;
//Replace authentication with a lookup on the user's credentials. This is
//assuming that the webserver's authentication mechanism is a good enough
//gate keeper.
$ldap_user = _ldapauth_user_lookup($name);
//drupal_set_message('<pre>'.var_export($ldap_user, true). '</pre>');
if (!$account) {
// Register this new user.
if ($ldap_user) {
// If mail attribute is missing, set the name as mail.
$init = $mail = key_exists(($_ldapauth_ldap->getOption('mail_attr') ? $_ldapauth_ldap->getOption('mail_attr') : LDAPAUTH_DEFAULT_MAIL_ATTR), $ldap_user) ? $ldap_user[$_ldapauth_ldap->getOption('mail_attr')][0] : $name;
// Check if the e-mail is not denied.
if (drupal_is_denied('mail', $mail)) {
form_set_error('name', t('The name %name is registered using a reserved e-mail address and therefore could not be logged in.', array('%name' => $name)));
return;
}
// Generate a random drupal password. LDAP password will be used anyways.
$pass_new = $pass;
$userinfo = array('name' => $name, 'pass' => $pass_new, 'mail' => $mail, 'init' => $init, 'status' => 1, 'authname_ldapauth' => $name, 'ldap_authentified' => TRUE, 'ldap_dn' => $ldap_user['dn'], 'ldap_config' => $_ldapauth_ldap->getOption('sid'));
$user = user_save('', $userinfo);
//Set a session variable, so elsewhere we can provide terms & conditions and the such
$_SESSION['new_account_created'] = 1;
watchdog('ldapauth', 'New external user %name created from the LDAP server %server.', array('%name' => $name, '%server' => $_ldapauth_ldap->getOption('name')), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit'));
}
}
else {
// Login existing user.
$data = array(
'ldap_dn' => $ldap_user['dn'],
'ldap_config' => $_ldapauth_ldap->getOption('sid'),
);
if (!isset($account->ldap_authentified)) {
// LDAP and local user conflict.
if (LDAPAUTH_LOGIN_CONFLICT == LDAPAUTH_CONFLICT_LOG) {
watchdog('ldapauth', 'LDAP user with DN %dn has a naming conflict with a local drupal user %name', array('%dn' => $dn, '%name' => $account->name), WATCHDOG_ERROR);
drupal_set_message(t('Another user already exists in the system with the same login name. You should contact the system administrator in order to solve this conflict.'), 'error');
return;
}
else {
$data['ldap_authentified'] = TRUE;
$data['authname_ldapauth'] = $name;
}
}
// Successfull login.
// Save the new login data.
if (LDAPAUTH_LOGIN_PROCESS == LDAPAUTH_AUTH_MIXED && LDAPAUTH_SYNC_PASSWORDS)
$data['pass'] = $pass;
$user = user_save($account, $data);
}
// Save user's authentication data to the session.
$_SESSION['ldap_login']['dn'] = $dn;
$_SESSION['ldap_login']['pass'] = $pass;
user_authenticate_finalize($form_values);
return $user;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment