Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

831 lines (734 sloc) 27.44 kB
<?php /*
ocPortal
Copyright (c) ocProducts, 2004-2012
See text/EN/licence.txt for full licencing information.
NOTE TO PROGRAMMERS:
Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
**** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****
*/
/*EXTRA FUNCTIONS: (sha1)|(ldap\_.+)*/
/**
* @license http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
* @copyright ocProducts Ltd
* @package ldap
*/
/*
Note: when we say 'cn' we mean whatever member_property() is. It might not actually be the 'cn' (isn't for Active Directory).
Group membership mechanism is hard-coded for Linux and Active Directory LDAP:
- Linux, using gidnumber on user record (secondary memberships for member) and memberuid on group record (primary memberships for group)
- Active Directory, using memberof on user record
We assume groups are always referenced as 'cn'.
When looping over results, we always have to skip non-numeric keys, which are for meta-data returned within result set (e.g. 'count'). Ugly, I know - you'd think LDAP would be neater ;).
*/
/**
* Standard code module initialisation function.
*/
function init__ocf_ldap()
{
if (!defined('LDAP_OPT_DIAGNOSTIC_MESSAGE')) define('LDAP_OPT_DIAGNOSTIC_MESSAGE',0x0032);
}
/**
* Escape, ready for an LDAP query.
*
* @param string The value.
* @param boolean Whether this is for use in a DN string.
* @return string The escaped value.
*/
function ldap_escape($str,$for_dn=false)
{
// see:
// RFC2254
// http://msdn.microsoft.com/en-us/library/ms675768(VS.85).aspx
// http://www-03.ibm.com/systems/i/software/ldap/underdn.html
$meta_chars=$for_dn?array(',','=','+','<','>',';','\\','"','#'):array('*','(',')','\\',chr(0));
$quoted_meta_chars=array();
foreach ($meta_chars as $key=>$value)
$quoted_meta_chars[$key]='\\'.str_pad(dechex(ord($value)),2,'0');
$ret=str_replace($meta_chars,$quoted_meta_chars,$str);
require_code('character_sets');
return convert_to_internal_encoding($ret,get_charset(),'utf8');
}
/**
* Unescape data from LDAP. Technically this is not unescaping, it's just a character set conversion, but function is named to provide symmetry with ldap_escape which does both escaping and character set conversion.
*
* @param string The escaped value.
* @return string The value.
*/
function ldap_unescape($str)
{
require_code('character_sets');
return convert_to_internal_encoding($str,'utf8',get_charset());
}
/**
* Set up the OCF LDAP connection.
*/
function ocf_ldap_connect()
{
global $LDAP_CONNECTION;
$LDAP_CONNECTION=ldap_connect(get_option('ldap_hostname'));
if ((get_option('ldap_is_windows')=='1') && (function_exists('ldap_set_option')))
{
ldap_set_option($LDAP_CONNECTION,LDAP_OPT_REFERRALS,0);
}
ldap_set_option($LDAP_CONNECTION,LDAP_OPT_PROTOCOL_VERSION,intval(get_option('ldap_version')));
ocf_ldap_bind();
}
/**
* Where in the LDAP hierarchy to search for groups.
*
* @return string The property.
*/
function member_search_qualifier()
{
$v=get_option('ldap_member_search_qualifier');
if ($v=='') return $v;
return $v.',';
}
/**
* The property in LDAP used for logins.
*
* @return string The property.
*/
function member_property()
{
return get_option('ldap_member_property');
}
/**
* The LDAP class indicating an account.
*
* @return string The property.
*/
function get_member_class()
{
return get_option('ldap_member_class');
}
/**
* Where in the LDAP hierarchy to search for members.
*
* @return string The property.
*/
function group_search_qualifier()
{
$v=get_option('ldap_group_search_qualifier');
if ($v=='') return $v;
return $v.',';
}
/**
* The group naming property LDAP will be using.
*
* @return string The property.
*/
function group_property()
{
return 'cn';
}
/**
* The LDAP class indicating a group.
*
* @return string The property.
*/
function get_group_class()
{
return get_option('ldap_group_class');
}
/**
* The LDAP group that maps to the default ocPortal group.
*
* @return string The group.
*/
function get_mapped_users_group()
{
return 'users';
}
/**
* The LDAP group that maps to the first administrative group in ocPortal (db_get_first_id()+1).
*
* @return string The group.
*/
function get_mapped_admin_group()
{
if (get_option('ldap_is_windows')=='0')
{
return 'admin';
}
require_code('lang'); // If in AJAX mode
return do_lang('ADMINISTRATORS');
}
/**
* Find whether a member of a certain username WOULD be bound to LDAP authentication (an exceptional situation, only for sites that use it).
*
* @param string The username.
* @return boolean The answer.
*/
function ocf_is_ldap_member_potential($cn)
{
global $LDAP_CONNECTION;
if (is_null($LDAP_CONNECTION)) return false;
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))',array(member_property()));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
$answer=(array_key_exists(0,$entries));
ldap_free_result($results);
return $answer;
}
/**
* Performs the OCF LDAP connection bind, used to do general querying (not a user login).
*/
function ocf_ldap_bind()
{
global $LDAP_CONNECTION;
$cn=get_option('ldap_bind_rdn');
if ($cn=='') // Anonymous bind
{
$test=@ldap_bind($LDAP_CONNECTION); // This sometimes causes errors, and isn't always needed. Hence error output is suppressed
if (get_param_integer('keep_ldap_debug',0)==1)
{
if ($test===false)
{
require_code('site');
$extended_error='';
ldap_get_option($LDAP_CONNECTION,LDAP_OPT_DIAGNOSTIC_MESSAGE,$extended_error);
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION).'; '.$extended_error),'warn');
fatal_exit(ldap_error($LDAP_CONNECTION));
}
}
} else
{
$login=ldap_get_login_string($cn);
/*
Example for Active Directory, if domain is chris4.com
$login='cn=Administrator,cn=Users,dc=chris4,dc=com'; // Log in using full name (cn) [in this case, same as username, but not always]
$login='Administrator@chris4.com'; // Log in using username (sAMAccountName)
*/
$test=@ldap_bind($LDAP_CONNECTION,$login,get_option('ldap_bind_password')); // This sometimes causes errors, and isn't always needed. Hence error output is suppressed
if ($test===false)
{
require_code('site');
$extended_error='';
ldap_get_option($LDAP_CONNECTION,LDAP_OPT_DIAGNOSTIC_MESSAGE,$extended_error);
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION).'; '.$extended_error),'warn');
if (get_param_integer('keep_ldap_debug',0)==1)
fatal_exit(ldap_error($LDAP_CONNECTION));
}
}
}
/**
* Find whether a member exists on the LDAP server.
*
* @param SHORT_TEXT The username.
* @return boolean The answer.
*/
function ocf_is_on_ldap($cn)
{
global $LDAP_CONNECTION;
$path=member_search_qualifier().get_option('ldap_base_dn');
$query='(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))';
$results=@ldap_search($LDAP_CONNECTION,$path,$query,array(member_property()),1);
if ($results===false)
{
require_code('site');
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION)),'warn');
if (get_param_integer('keep_ldap_debug',0)==1)
fatal_exit(ldap_error($LDAP_CONNECTION));
return false;
}
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
$is_on=array_key_exists(0,$entries);
ldap_free_result($results);
return $is_on;
}
/**
* Find the LDAP servers password for a certain member.
*
* @param string The username.
* @return ?string The password (NULL: no such user).
*/
function ocf_get_ldap_hash($cn)
{
global $LDAP_CONNECTION;
$results=@ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))',array('userpassword'));
if ($results===false)
{
require_code('site');
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION)),'warn');
if (get_param_integer('keep_ldap_debug',0)==1)
fatal_exit(ldap_error($LDAP_CONNECTION));
return NULL;
}
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if (!array_key_exists(0,$entries))
{
ldap_free_result($results);
return NULL;
}
if (!array_key_exists('userpassword',$entries[0]))
{
require_code('site');
attach_message(do_lang_tempcode('LDAP_CANNOT_CHECK_PASSWORDS'),'warn');
return uniqid('');
}
$pass=$entries[0]['userpassword'][0];
ldap_free_result($results);
return $pass;
}
/**
* Convert a plain-text password into a hashed password.
*
* @param string The username (we use this to extract the hash algorithm being used by the member).
* @param string The password.
* @return string The hashed password.
*/
function ocf_ldap_hash($cn,$password)
{
global $LDAP_CONNECTION;
$stored=ocf_get_ldap_hash($cn);
if (is_null($stored)) return '!!!'; // User is valid locally, but not on LDAP
$type_pos=strpos($stored,'}');
$type=substr($stored,1,$type_pos-1);
if ((strtolower($type)=='crypt') && (strlen($stored)==41)) $type='md5crypt';
if ((strtolower($type)=='crypt') && (strlen($stored)==45)) $type='blowfish';
switch (strtolower($type))
{
case '':
return $password;
case 'crypt':
$salt=substr($stored,$type_pos+4,2);
return '{'.$type.'}'.crypt($password,$salt);
case 'md5':
return '{'.$type.'}'.base64_encode(pack('H*',md5($password)));
case 'blowfish':
$salt=substr($stored,$type_pos+4,13);
return '{'.$type.'}'.crypt($password,'$2$'.$salt);
case 'md5crypt':
$salt=substr($stored,$type_pos+4,9);
return '{'.$type.'}'.crypt($password,'$1$'.$salt);
case 'sha':
return '{'.$type.'}'.base64_encode(pack('H*',sha1($password)));
}
return '!!'; // Unknown password type
}
/**
* Get an LDAP login string to do a bind against.
*
* @param string The username.
* @return string The login string.
*/
function ldap_get_login_string($cn)
{
$pre=get_option('ldap_login_qualifier');
if ($pre!='')
{
$login=$pre.$cn;
} else
{
if (member_property()=='sAMAccountName')
{
$login=$cn.'@'.preg_replace('#^dc=#','',str_replace(',dc=','.',strtolower(get_option('ldap_base_dn'))));
} else
{
if (strpos($cn,'=')===false)
{
$login=member_property().'='.$cn.','.member_search_qualifier().get_option('ldap_base_dn');
} else
{
$login=$cn;
}
}
}
return $login;
}
/**
* Authorise an LDAP login.
*
* @param string The username.
* @param ?string The password (NULL: no such user).
* @return array Part of the member row to put back in and authorise normally (hackerish, but it works kind of like a filter / stage in a chain).
*/
function ocf_ldap_authorise_login($cn,$password)
{
global $LDAP_CONNECTION;
if (get_option('ldap_none_bind_logins')=='1')
{
$try=ocf_ldap_hash($cn,$password);
$there=ocf_get_ldap_hash($cn);
$good=($try==$there);
if ($good)
{
return array('m_pass_hash_salted'=>$password,'m_password_compat_scheme'=>'md5'); // A bit of a hack: actually we are doing a plain text check, and the 'hashed' passwords were both never hashed: still works
}
return array('m_pass_hash_salted'=>'!!!','m_password_compat_scheme'=>'md5'); // Access will be denied
}
$login=ldap_get_login_string($cn);
$test=@ldap_bind($LDAP_CONNECTION,$login,$password);
if ($test!==false) // Note, for Windows Active Directory the CN is the full user name, not the login name. Therefore users log in with this.
{
ocf_ldap_bind(); // Rebind under normal name, so we're not stuck on this user's bind
// We only get here if we are authorised. As to not complicate ocPortal's authentication chain, we trick it by setting our db password to that of our given password, ONLY once LDAP login is confirmed.
return array('m_pass_hash_salted'=>$password,'m_password_compat_scheme'=>'md5'); // A bit of a hack: actually we are doing a plain text check, and the 'hashed' passwords were both never hashed: still works
}
if (get_param_integer('keep_ldap_debug',0)==1)
{
if ($test===false)
{
require_code('site');
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION)),'warn');
fatal_exit(ldap_error($LDAP_CONNECTION));
}
}
ocf_ldap_bind(); // Rebind under normal name, so we're not stuck on this failed bind
return array('m_pass_hash_salted'=>'!!!','m_password_compat_scheme'=>'md5'); // Access will be denied
}
/**
* Find the ocPortal member-ID for an LDAP username.
*
* @param string The username.
* @return ?integer The ocPortal member-ID (NULL: none).
*/
function ocf_member_ldapcn_to_ocfid($cn)
{
$ret=$GLOBALS['FORUM_DB']->query_value_null_ok('f_members','id',array('m_username'=>$cn,'m_password_compat_scheme'=>'ldap'));
if (is_null($ret))
$ret=$GLOBALS['FORUM_DB']->query_value_null_ok('f_members','id',array('m_username'=>$cn,'m_password_compat_scheme'=>'httpauth'));
return $ret;
}
/**
* Find the LDAP username for an ocPortal member-ID.
*
* @param integer The ocPortal member-ID.
* @return ?SHORT_TEXT The username (NULL: none).
*/
function ocf_member_ocfid_to_ldapcn($id)
{
$ret=$GLOBALS['FORUM_DB']->query_value_null_ok('f_members','m_username',array('id'=>$id,'m_password_compat_scheme'=>'ldap'));
if (is_null($ret))
$ret=$GLOBALS['FORUM_DB']->query_value_null_ok('f_members','m_username',array('id'=>$id,'m_password_compat_scheme'=>'httpauth'));
return $ret;
}
/**
* Get a list of usergroups on the LDAP server.
*
* @return array The list of user-groups (string).
*/
function ocf_get_all_ldap_groups()
{
global $LDAP_CONNECTION;
$groups=array();
$results=@ldap_search($LDAP_CONNECTION,group_search_qualifier().get_option('ldap_base_dn'),'objectclass='.get_group_class(),array(group_property())); // We do ldap_search as Active Directory can be fussy when looking at large sets, like all members
if ($results===false)
{
require_code('site');
attach_message(make_string_tempcode('LDAP: '.ldap_error($LDAP_CONNECTION)),'warn');
if (get_param_integer('keep_ldap_debug',0)==1)
fatal_exit(ldap_error($LDAP_CONNECTION));
return array();
}
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
foreach ($entries as $key=>$entry)
{
if ($key==='dn') // May come out as 'dn'
{
$group_cn=ocf_long_cn_to_short_cn(ldap_unescape($entry['dn']),'dn');
$groups[]=$group_cn;
}
if (!is_numeric($key)) continue;
if (!array_key_exists(group_property(),$entry)) continue;
$group_cn=ocf_long_cn_to_short_cn(ldap_unescape($entry[group_property()][0]),group_property());
$groups[]=$group_cn;
}
ldap_free_result($results);
return array_unique($groups);
}
/**
* Find the ocPortal-ID for a named LDAP usergroup.
*
* @param string The usergroup.
* @return ?GROUP The ocPortal-ID (NULL: none).
*/
function ocf_group_ldapcn_to_ocfid($cn)
{
if ($cn==get_mapped_admin_group()) return db_get_first_id()+1;
if ($cn==get_mapped_users_group()) return get_first_default_group();
ocf_ensure_groups_cached('*');
global $USER_GROUPS_CACHED;
foreach ($USER_GROUPS_CACHED as $id=>$group)
{
if ($group['g__name']==$cn) return $id;
}
return NULL;
}
/**
* Find the named LDAP usergroup for an OCF ID. Note that the returned MAY NOT ACTUALLY EXIST!
*
* @param GROUP The OCF ID.
* @return ?SHORT_TEXT The named LDAP usergroup (NULL: none).
*/
function ocf_group_ocfid_to_ldapcn($id)
{
if ($id==db_get_first_id()+1) return get_mapped_admin_group();
if ($id==get_first_default_group()) return get_mapped_users_group();
ocf_ensure_groups_cached(array($id));
global $USER_GROUPS_CACHED;
return $USER_GROUPS_CACHED[$id]['g__name'];
}
/**
* Get the e-mail of a member in LDAP.
*
* @param ID_TEXT The CN of the member.
* @return SHORT_TEXT Guessed e-mail address (blank: couldn't find).
*/
function ocf_ldap_guess_email($cn)
{
global $LDAP_CONNECTION;
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))');
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
ldap_free_result($results);
if (!array_key_exists(0,$entries)) return '';
foreach (array('mail','email') as $mail_property)
{
if (array_key_exists($mail_property,$entries[0])) return is_array($entries[0][$mail_property])?$entries[0][$mail_property][0]:$entries[0][$mail_property];
}
return '';
}
/**
* (LDAP helper for ocf_get_group_members_raw) Get a list of members in a group (or more full details if $non_validated is true).
*
* @param array The list is written into this.
* @param GROUP The ID of the usergroup.
* @param boolean Whether to include those in the usergroup as a primary member.
* @param boolean Whether to include those applied to join the usergroup, but not validated in.
* @param boolean Whether to include those in the usergroup as a secondary member.
*/
function ocf_get_group_members_raw_ldap(&$members,$group_id,$include_primaries,$non_validated,$include_secondaries)
{
global $LDAP_CONNECTION;
$gid=NULL;
$cn=ocf_group_ocfid_to_ldapcn($group_id);
if (get_option('ldap_is_windows')=='0')
{
// Members under group (secondary)
if (($include_secondaries) && (!is_null($cn)))
{
$results=ldap_search($LDAP_CONNECTION,group_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_group_class().')('.group_property().'='.ldap_escape($cn).'))',array('memberuid','gidnumber'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if ((array_key_exists(0,$entries)) && (array_key_exists('memberuid',$entries[0]))) // Might not exist in LDAP
{
foreach ($entries[0]['memberuid'] as $key=>$member)
{
if (!is_numeric($key)) continue;
$member_id=ocf_member_ldapcn_to_ocfid(ldap_unescape($member));
if (!is_null($member_id))
{
if ($non_validated) $members[]=array('gm_member_id'=>$member_id,'gm_validated'=>1,'m_username'=>ldap_unescape($member)); else $members[]=$member_id;
}
}
$gid=$entries[0]['gidnumber']; // Picked up for performance reasons
ldap_free_result($results);
}
}
if (is_null($gid))
$gid=ocf_group_ldapcn_to_ldapgid($cn);
// Groups under member (primary)
if (($include_primaries) && (!is_null($gid)))
{
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')(gidnumber='.ldap_escape(strval($gid)).'))',array(member_property()));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
foreach ($entries as $key=>$member) // There will only be one, but I wrote a loop so lets use a loop
{
if (!is_numeric($key)) continue;
if (!array_key_exists(member_property(),$member)) continue;
if (!array_key_exists(0,$member[member_property()])) continue;
$member_id=ocf_member_ldapcn_to_ocfid(ldap_unescape($member[member_property()][0]));
if (!is_null($member_id))
if ($non_validated) $members[]=array('m_username'=>ldap_unescape($member[member_property()][0]),'gm_member_id'=>$member_id,'gm_validated'=>1); else $members[]=$member_id;
}
ldap_free_result($results);
}
} else
{
if (!is_null($cn))
{
// Groups under member (Active Directory makes no distinction)
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.group_property().'='.ldap_escape($cn).'))',array('memberof')); // We do ldap_search as Active Directory can be fussy when looking at large sets, like all members
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if ((array_key_exists(0,$entries)) && (array_key_exists('memberof',$entries[0]))) // Might not exist in LDAP
{
foreach ($entries[0]['memberof'] as $key=>$member)
{
if (!is_numeric($key)) continue;
$member_id=ocf_member_ldapcn_to_ocfid(ldap_unescape(ocf_long_cn_to_short_cn($member,member_property())));
if (!is_null($member_id))
{
if ((($include_primaries) && ($include_secondaries)) ||
(($include_primaries) && (!$include_secondaries) && (ocf_ldap_get_member_primary_group($member_id)==$gid)) ||
((!$include_primaries) && ($include_secondaries) && (ocf_ldap_get_member_primary_group($member_id)!=$gid))
)
{
if ($non_validated)
{
$members[]=array('gm_member_id'=>$member_id,'gm_validated'=>1,'m_username'=>ldap_unescape(ocf_long_cn_to_short_cn($member,member_property())));
} else $members[]=$member_id;
}
}
}
ldap_free_result($results);
}
}
}
}
/**
* (LDAP helper for ocf_get_members_groups) Get a list of the usergroups a member is in (keys say the usergroups, values are irrelevant).
*
* @param ?MEMBER The member to find the usergroups of (NULL: current member).
* @return array The list (e.g. array(1=>1,2=>1,3=>1) for someone in (1,2,3)). The keys are all that matters, values are arbitrary.
*/
function ocf_get_members_groups_ldap($member_id)
{
$groups=array();
global $LDAP_CONNECTION;
$cn=ocf_member_ocfid_to_ldapcn($member_id);
if (get_option('ldap_is_windows')=='0')
{
// Members under group (secondary)
$results=ldap_search($LDAP_CONNECTION,group_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')(memberuid='.ldap_escape($cn).'))',array(group_property()),1);
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
foreach ($entries as $key=>$entry)
{
if ($key==='dn') // May come out as 'dn'
{
$group_cn=ocf_long_cn_to_short_cn(ldap_unescape($entry['dn']),'dn');
$group_id=ocf_group_ldapcn_to_ocfid($group_cn);
if (!is_null($group_id))
$groups[$group_id]=1;
}
if (!is_numeric($key)) continue;
if (!array_key_exists(group_property(),$entry)) continue;
if (!array_key_exists(0,$entry[group_property()])) continue;
$group_cn=ocf_long_cn_to_short_cn(ldap_unescape($entry[group_property()][0]),group_property());
$group_id=ocf_group_ldapcn_to_ocfid($group_cn);
if (!is_null($group_id))
$groups[$group_id]=1;
}
ldap_free_result($results);
// Groups under member (primary)
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))',array('gidnumber'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
$group_id_use=NULL;
foreach ($entries as $key=>$group) // There will only be one, but I wrote a loop so lets use a loop
{
if (!is_numeric($key)) continue;
$group_id=ocf_group_ldapgid_to_ocfid($group['gidnumber'][0]);
if (!is_null($group_id)) $group_id_use=$group_id;
}
ldap_free_result($results);
if (is_null($group_id_use)) $group_id_use=get_first_default_group();
$groups[$group_id_use]=1;
} else
{
// Groups under member (Active Directory makes no distinction)
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape($cn).'))',array('memberof'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
$group_id_use=NULL;
if ((array_key_exists(0,$entries)) && (array_key_exists('memberof',$entries[0]))) // Might not exist in LDAP
{
foreach ($entries[0]['memberof'] as $key=>$group) // There will only be one, but I wrote a loop so lets use a loop
{
if (!is_numeric($key)) continue;
$group_id=ocf_group_ldapcn_to_ocfid(ocf_long_cn_to_short_cn($group,group_property()));
if (!is_null($group_id)) $groups[$group_id]=1;
}
}
ldap_free_result($results);
if (count($groups)==0) $groups=array_flip(ocf_get_all_default_groups(true));
}
return $groups;
}
/**
* Get the primary usergroup of a member in LDAP.
*
* @param MEMBER The member.
* @return GROUP The.
*/
function ocf_ldap_get_member_primary_group($member_id)
{
global $PRIMARY_GROUP_MEMBERS;
global $LDAP_CONNECTION;
if (get_option('ldap_is_windows')=='0')
{
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape(ocf_member_ocfid_to_ldapcn($member_id)).'))',array('gidnumber'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
$gid=array_key_exists(0,$entries)?$entries[0]['gidnumber'][0]:NULL;
ldap_free_result($results);
if (!is_null($gid)) $gid=ocf_group_ldapgid_to_ocfid($gid);
if (is_null($gid)) $gid=get_first_default_group();
} else
{
// Whilst Windows has primaryGroupID, it has an ID that refers outside of LDAP, so is of no use to us. We use the last a member is in as the primary
$results=ldap_search($LDAP_CONNECTION,member_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_member_class().')('.member_property().'='.ldap_escape(ocf_member_ocfid_to_ldapcn($member_id)).'))',array('memberof'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if ((array_key_exists(0,$entries)) && (array_key_exists('memberof',$entries[0]))) // Might not exist in LDAP
{
$group=$entries[0]['memberof'][count($entries[0]['memberof'])-2]; // Last is -2 due to count index
$cn=ocf_long_cn_to_short_cn($group,group_property());
$gid=ocf_group_ldapcn_to_ocfid($cn);
if (is_null($gid)) $gid=get_first_default_group();
} else
{
$gid=get_first_default_group();
}
ldap_free_result($results);
}
$PRIMARY_GROUP_MEMBERS[$member_id]=$gid;
return $gid;
}
/**
* Find the ocPortal-ID for an LDAP usergroup-ID. POSIX Only.
*
* @param integer The LDAP ID.
* @return ?GROUP The ocPortal-ID (NULL: could not find).
*/
function ocf_group_ldapgid_to_ocfid($gid)
{
global $LDAP_CONNECTION;
$results=ldap_search($LDAP_CONNECTION,group_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_group_class().')(gidnumber='.ldap_escape(strval($gid)).'))',array(group_property()),1);
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if (!array_key_exists(0,$entries)) return NULL;
if (array_key_exists(0,$entries[0][group_property()]))
{
$long_cn=$entries[0][group_property()][0];
$cn=ocf_long_cn_to_short_cn($long_cn,group_property());
} else
{
$long_cn=$entries[0]['dn']; // Might come out as DN
$cn=ocf_long_cn_to_short_cn($long_cn,'dn');
}
return ocf_group_ldapcn_to_ocfid($cn);
}
/**
* Find the LDAP ID for a named LDAP usergroup. POSIX Only.
*
* @param string The named LDAP usergroup.
* @return ?integer The LDAP usergroup ID (NULL: none).
*/
function ocf_group_ldapcn_to_ldapgid($cn)
{
global $LDAP_CONNECTION;
$results=ldap_search($LDAP_CONNECTION,group_search_qualifier().get_option('ldap_base_dn'),'(&(objectclass='.get_group_class().')('.group_property().'='.ldap_escape($cn).'))',array('gidnumber'));
$entries=ldap_get_entries($LDAP_CONNECTION,$results);
if (!array_key_exists(0,$entries)) return NULL;
return $entries[0]['gidnumber'][0];
}
/**
* Converts an active directory style long-CN to a short one.
*
* @param string The long one.
* @param string The type (e.g. CN, DN).
* @return string The short one.
*/
function ocf_long_cn_to_short_cn($long,$type)
{
$matches=array();
if (preg_match('#^(dn|cn|'.str_replace('#','\#',preg_quote($type)).')=([^,]+)(,.*)?$#i',$long,$matches)!=0)
{
return $matches[2];
}
return $long;
}
Jump to Line
Something went wrong with that request. Please try again.