| 1 |
<?php |
<?php |
| 2 |
// $Id: ldapgroups.module,v 1.38 2009/07/27 16:28:19 miglius Exp $ |
// $Id: ldapgroups.module,v 1.39 2009/07/28 14:03:05 miglius Exp $ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* @file |
* @file |
| 15 |
// Core API hooks |
// Core API hooks |
| 16 |
|
|
| 17 |
/** |
/** |
|
* Implements hook_init(). |
|
|
*/ |
|
|
function ldapgroups_init() { |
|
|
require_once(drupal_get_path('module', 'ldapgroups') .'/includes/LDAPInterface.inc'); |
|
|
} |
|
|
|
|
|
/** |
|
| 18 |
* Implementation of hook_menu(). |
* Implementation of hook_menu(). |
| 19 |
*/ |
*/ |
| 20 |
function ldapgroups_menu() { |
function ldapgroups_menu() { |
| 53 |
function ldapgroups_user($op, &$edit, &$account, $category = NULL) { |
function ldapgroups_user($op, &$edit, &$account, $category = NULL) { |
| 54 |
switch ($op) { |
switch ($op) { |
| 55 |
case 'login': |
case 'login': |
| 56 |
|
require_once(drupal_get_path('module', 'ldapgroups') .'/includes/LDAPInterface.inc'); |
| 57 |
|
require_once(drupal_get_path('module', 'ldapgroups') .'/ldapgroups.inc'); |
| 58 |
ldapgroups_user_login($account); |
ldapgroups_user_login($account); |
| 59 |
break; |
break; |
| 60 |
} |
} |
| 61 |
} |
} |
| 62 |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
// hook_user() functions |
|
|
|
|
|
/** |
|
|
* Implements hook_user() login operation. |
|
|
*/ |
|
|
function ldapgroups_user_login(&$account) { |
|
|
$authmap = user_get_authmaps($account->name); |
|
|
if (!isset($authmap['ldapauth'])) { |
|
|
// This user is not authenticated via lapauth. |
|
|
return; |
|
|
} |
|
|
|
|
|
// Setup the global $_ldapgroups_ldap object. |
|
|
if (!_ldapgroups_ldap_init($account)) |
|
|
return; |
|
|
|
|
|
// First, we figure out the appropriate groups. |
|
|
$groups = _ldapgroups_detect_groups($account); |
|
|
|
|
|
// Apply groups restrictions. |
|
|
if (count($groups_allow = _ldapgroups_ldap_info($account, 'ldapgroups_groups')) > 0 && count(array_intersect($groups, $groups_allow)) == 0) { |
|
|
$account = user_load(0); |
|
|
return; |
|
|
} |
|
|
|
|
|
// Then, we take every mapped role from the user, later below |
|
|
// we'll grant back those deserved. |
|
|
$account->ldap_drupal_roles = isset($account->ldap_drupal_roles) ? $account->ldap_drupal_roles : array(); |
|
|
foreach ($account->ldap_drupal_roles as $role) { |
|
|
_ldapgroups_deny_role($account, $role); |
|
|
} |
|
|
|
|
|
// Are there LDAP groups for the user? |
|
|
if ($groups === FALSE) |
|
|
return TRUE; |
|
|
|
|
|
// Next, we apply site-specific rules. |
|
|
$groups = _ldapgroups_filter($account, $groups); |
|
|
|
|
|
// At this point, the roles are in the full DN format. |
|
|
$roles = array(); |
|
|
if (!empty($groups)) { |
|
|
$ldapgroups_mappings = _ldapgroups_ldap_info($account, 'ldapgroups_mappings'); |
|
|
foreach ($groups as $group) { |
|
|
$role = _ldapgroups_mapping($account, $group); |
|
|
_ldapgroups_create_role($role); |
|
|
_ldapgroups_grant_role($account, $role); |
|
|
$roles[] = $role; |
|
|
} |
|
|
} |
|
|
|
|
|
// Store roles in the user object so we know which ones |
|
|
// were granted here. |
|
|
user_save($account, array('ldap_drupal_roles' => $roles)); |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
// Auxiliary functions |
|
|
|
|
|
/** |
|
|
* Detect user groups from the LDAP. |
|
|
* |
|
|
* @param $user |
|
|
* A user object. |
|
|
* |
|
|
* @return |
|
|
* An array of user groups. |
|
|
*/ |
|
|
function _ldapgroups_detect_groups($user) { |
|
|
global $_ldapgroups_ldap; |
|
|
|
|
|
// Nothing to do if the user is not LDAP authentified |
|
|
// or there are no groups configured. |
|
|
if (!(_ldapgroups_ldap_info($user, 'ldapgroups_in_dn') || _ldapgroups_ldap_info($user, 'ldapgroups_in_attr') || _ldapgroups_ldap_info($user, 'ldapgroups_as_entries'))) |
|
|
return FALSE; |
|
|
|
|
|
// First try to connect with the stored user's DN and password. |
|
|
// If unsuccessful, connect with the BINDDN and BINDPW stored in the database for this config. |
|
|
$dn = isset($_SESSION['ldap_login']['dn']) ? $_SESSION['ldap_login']['dn'] : ''; |
|
|
$pass = isset($_SESSION['ldap_login']['pass']) ? $_SESSION['ldap_login']['pass'] : ''; |
|
|
|
|
|
// If I try to connect using a blank dn and pass, I dont get an error until ldap_read, |
|
|
// so I just check to see if they would be blank, based on ldap_forget_passwords, and |
|
|
// make it read from the database. |
|
|
if (LDAPAUTH_FORGET_PASSWORDS || !$_ldapgroups_ldap->connect($dn, $pass)) { |
|
|
$row2 = db_fetch_object(db_query("SELECT binddn, bindpw FROM {ldapauth} WHERE sid = %d", $_ldapgroups_ldap->getOption('sid'))); |
|
|
$dn = $row2->binddn; |
|
|
$pass = $row2->bindpw; |
|
|
if (!$_ldapgroups_ldap->connect($dn, $pass)) { |
|
|
watchdog('ldapgroups', "User login: user %name data could not be read in the LDAP directory", array('%name' => $user->name), WATCHDOG_WARNING); |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
|
|
|
// Strategy 1: group extracted from user's DN. |
|
|
$dn_groups = array(); |
|
|
if (_ldapgroups_ldap_info($user, 'ldapgroups_in_dn')) { |
|
|
$pairs = explode(',', $user->ldap_dn); |
|
|
foreach ($pairs as $p) { |
|
|
$pair = explode('=', $p); |
|
|
if (drupal_strtolower(trim($pair[0])) == drupal_strtolower(_ldapgroups_ldap_info($user, 'ldapgroups_dn_attribute'))) |
|
|
$dn_groups[] = trim($pair[1]); |
|
|
} |
|
|
} |
|
|
|
|
|
// Strategy 2: groups in user attributes. |
|
|
$attrib_groups = array(); |
|
|
if (_ldapgroups_ldap_info($user, 'ldapgroups_in_attr')) { |
|
|
foreach (_ldapgroups_ldap_info($user, 'ldapgroups_attr') as $attribute) |
|
|
$attrib_groups = array_merge($attrib_groups, $_ldapgroups_ldap->retrieveMultiAttribute($user->ldap_dn, $attribute)); |
|
|
} |
|
|
|
|
|
// Strategy 3: groups as entries. |
|
|
$entries_groups = array(); |
|
|
$ldapgroups_entries_attribute = _ldapgroups_ldap_info($user, 'ldapgroups_entries_attribute'); |
|
|
if (_ldapgroups_ldap_info($user, 'ldapgroups_as_entries')) { |
|
|
foreach (_ldapgroups_ldap_info($user, 'ldapgroups_entries') as $branch) { |
|
|
$entries = $_ldapgroups_ldap->search($branch, $ldapgroups_entries_attribute .'='. $user->ldap_dn, array($ldapgroups_entries_attribute)); |
|
|
if (empty($entries) || $entries['count'] == 0) |
|
|
$entries = $_ldapgroups_ldap->search($branch, $ldapgroups_entries_attribute .'='. $user->name, array($ldapgroups_entries_attribute)); |
|
|
foreach ($entries as $entry) { |
|
|
if (isset($entry['dn'])) |
|
|
$entries_groups[] = $entry['dn']; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
$_ldapgroups_ldap->disconnect(); |
|
|
return array_unique(array_merge($dn_groups, $attrib_groups, $entries_groups)); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Grant a user with a role. |
|
|
* |
|
|
* @param $user |
|
|
* A user object. |
|
|
* @param $rolename |
|
|
* A name of the role. |
|
|
* |
|
|
* @return |
|
|
*/ |
|
|
function _ldapgroups_grant_role($user, $rolename) { |
|
|
$result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename); |
|
|
if ($row = db_fetch_object($result)) { |
|
|
$result = db_query("SELECT * FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid); |
|
|
if (!db_fetch_object($result)) { |
|
|
db_query("INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)", $user->uid, $row->rid); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Deny a user with a role. |
|
|
* |
|
|
* @param $user |
|
|
* A user object. |
|
|
* @param $rolename |
|
|
* A name of the role. |
|
|
* |
|
|
* @return |
|
|
*/ |
|
|
function _ldapgroups_deny_role($user, $rolename) { |
|
|
$result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename); |
|
|
if ($row = db_fetch_object($result)) { |
|
|
$result = db_query("SELECT * FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid); |
|
|
if (db_fetch_object($result)) { |
|
|
db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $user->uid, $row->rid); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Create a new role. |
|
|
* |
|
|
* @param $rolename |
|
|
* A name of the role. |
|
|
* |
|
|
* @return |
|
|
*/ |
|
|
function _ldapgroups_create_role($rolename) { |
|
|
$result = db_query("SELECT * FROM {role} WHERE name = '%s'", $rolename); |
|
|
if (!($row = db_fetch_object($result))) |
|
|
db_query("INSERT INTO {role} (name) VALUES ('%s')", $rolename); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Filters groups only to a explicitely defined groups. |
|
|
* |
|
|
* @param $groups |
|
|
* An array of the LDAP groups. |
|
|
* |
|
|
* @return |
|
|
* An array of the filtered groups. |
|
|
*/ |
|
|
function _ldapgroups_filter($account, $groups) { |
|
|
if (_ldapgroups_ldap_info($account, 'ldapgroups_mappings_filter') && count(_ldapgroups_ldap_info($account, 'ldapgroups_mappings') > 0)) { |
|
|
$groups_new = array(); |
|
|
foreach ($groups as $group) { |
|
|
foreach (_ldapgroups_ldap_info($account, 'ldapgroups_mappings') as $group_approved => $role) { |
|
|
if (strcasecmp($group_approved, $group) == 0) |
|
|
$groups_new[] = $group; |
|
|
} |
|
|
} |
|
|
$groups = $groups_new; |
|
|
} |
|
|
|
|
|
if ($code = _ldapgroups_ldap_info($account, 'ldapgroups_filter_php')) |
|
|
$groups = eval($code); |
|
|
|
|
|
return $groups; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Maps LDAP group name to a Drupal role. |
|
|
* |
|
|
* @param $user |
|
|
* A user object. |
|
|
* @param $group |
|
|
* A LDAP group name. |
|
|
* |
|
|
* @return |
|
|
* An Drupal role. |
|
|
*/ |
|
|
function _ldapgroups_mapping($user, $group) { |
|
|
$ldapgroups_mappings = _ldapgroups_ldap_info($user, 'ldapgroups_mappings'); |
|
|
if (isset($ldapgroups_mappings[$group])) |
|
|
return $ldapgroups_mappings[$group]; |
|
|
else if (preg_match('/^[^=]+=([^,]+),.*$/', $group, $matches)) |
|
|
return $matches[1]; |
|
|
else |
|
|
return $group; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Initiates the LDAPInterfase class. |
|
|
* |
|
|
* @param $sid |
|
|
* A server ID or user object. |
|
|
* |
|
|
* @return |
|
|
*/ |
|
|
function _ldapgroups_ldap_init($sid) { |
|
|
global $_ldapgroups_ldap; |
|
|
|
|
|
if (!($sid = is_object($sid) ? (isset($sid->ldap_config) ? $sid->ldap_config : NULL) : $sid)) |
|
|
return; |
|
|
|
|
|
static $servers = array(); |
|
|
if (!isset($servers[$sid])) |
|
|
$servers[$sid] = db_fetch_object(db_query("SELECT * FROM {ldapauth} WHERE status = 1 AND sid = %d", $sid)); |
|
|
|
|
|
if ($servers[$sid]) { |
|
|
$_ldapgroups_ldap = new LDAPInterface(); |
|
|
$_ldapgroups_ldap->setOption('sid', $sid); |
|
|
$_ldapgroups_ldap->setOption('name', $servers[$sid]->name); |
|
|
$_ldapgroups_ldap->setOption('server', $servers[$sid]->server); |
|
|
$_ldapgroups_ldap->setOption('port', $servers[$sid]->port); |
|
|
$_ldapgroups_ldap->setOption('tls', $servers[$sid]->tls); |
|
|
$_ldapgroups_ldap->setOption('encrypted', $servers[$sid]->encrypted); |
|
|
$_ldapgroups_ldap->setOption('basedn', $servers[$sid]->basedn); |
|
|
$_ldapgroups_ldap->setOption('user_attr', $servers[$sid]->user_attr); |
|
|
return $_ldapgroups_ldap; |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Retrieve the saved ldapgroups saved setting. |
|
|
* |
|
|
* @param $sid |
|
|
* A server ID or user object. |
|
|
* @param $req |
|
|
* An attribute name. |
|
|
* |
|
|
* @return |
|
|
* The attribute value. |
|
|
*/ |
|
|
function _ldapgroups_ldap_info($sid, $req) { |
|
|
if (!($sid = is_object($sid) ? (isset($sid->ldap_config) ? $sid->ldap_config : NULL) : $sid)) |
|
|
return; |
|
|
|
|
|
static $servers = array(); |
|
|
if (!isset($servers[$sid])) |
|
|
$servers[$sid] = db_fetch_object(db_query("SELECT * FROM {ldapauth} WHERE sid = %d", $sid)); |
|
|
|
|
|
switch ($req) { |
|
|
case 'ldapgroups_in_dn': |
|
|
return $servers[$sid]->ldapgroups_in_dn; |
|
|
case 'ldapgroups_dn_attribute': |
|
|
return !empty($servers[$sid]->ldapgroups_dn_attribute) ? $servers[$sid]->ldapgroups_dn_attribute : LDAPGROUPS_DEFAULT_DN_ATTRIBUTE; |
|
|
case 'ldapgroups_in_attr': |
|
|
return $servers[$sid]->ldapgroups_in_attr; |
|
|
case 'ldapgroups_attr': |
|
|
return !empty($servers[$sid]->ldapgroups_attr) ? unserialize($servers[$sid]->ldapgroups_attr) : array(); |
|
|
case 'ldapgroups_as_entries': |
|
|
return $servers[$sid]->ldapgroups_as_entries; |
|
|
case 'ldapgroups_entries': |
|
|
return !empty($servers[$sid]->ldapgroups_entries) ? unserialize($servers[$sid]->ldapgroups_entries) : array(); |
|
|
case 'ldapgroups_entries_attribute': |
|
|
return !empty($servers[$sid]->ldapgroups_entries_attribute) ? $servers[$sid]->ldapgroups_entries_attribute : LDAPGROUPS_DEFAULT_ENTRIES_ATTRIBUTE; |
|
|
case 'ldapgroups_mappings': |
|
|
return !empty($servers[$sid]->ldapgroups_mappings) ? unserialize($servers[$sid]->ldapgroups_mappings) : array(); |
|
|
case 'ldapgroups_mappings_filter': |
|
|
return $servers[$sid]->ldapgroups_mappings_filter; |
|
|
case 'ldapgroups_filter_php': |
|
|
return $servers[$sid]->ldapgroups_filter_php; |
|
|
case 'ldapgroups_groups': |
|
|
return !empty($servers[$sid]->ldapgroups_groups) ? unserialize($servers[$sid]->ldapgroups_groups) : array(); |
|
|
} |
|
|
} |
|
|
|
|