* if( is_muli_line_attr( "postalAddress" ) )
* echo "";
* else
* echo "";
*
*
* @param string $attr_name The name of the attribute of interestd (case insensivite)
* @param string $val (optional) The current value of the attribute (speeds up the
* process by searching for carriage returns already in the attribute value)
* @param int $server_id (optional) The ID of the server of interest. If specified,
* is_multi_line_attr() will read the schema from the server to determine if
* the attr is multi-line capable. (note that schema reads can be expensive,
* but that impact is lessened due to PLA's new caching mechanism)
* @return bool
* @todo Move this to an LDAPServer object method.
*/
function is_multi_line_attr( $attr_name, $val=null, $server_id=null ) {
debug_log(sprintf('is_multi_line_attr(): Entered with (%s,%s,%s)',$attr_name,$val,$server_id),2);
global $config, $ldapservers;
$multi_line_attributes = $config->GetValue('appearance','multi_line_attributes');
$multi_line_syntax_oids = $config->GetValue('appearance','multi_line_syntax_oids');
# Set default return
$return = false;
// First, check the optional val param for a \n or a \r
if (! is_null($val) && (false !== strpos($val,"\n") || false !== strpos($val,"\r")))
$return = true;
// Next, compare strictly by name first
else
foreach ($multi_line_attributes as $multi_line_attr_name)
if (strcasecmp($multi_line_attr_name,$attr_name) == 0) {
$return = true;
break;
}
// If unfound, compare by syntax OID
if (! $return && ! is_null($server_id)) {
$ldapserver = $ldapservers->Instance($server_id);
$schema_attr = get_schema_attribute($ldapserver,$attr_name);
if ($schema_attr) {
$syntax_oid = $schema_attr->getSyntaxOID();
if ($syntax_oid)
foreach($multi_line_syntax_oids as $multi_line_syntax_oid)
if ($multi_line_syntax_oid == $syntax_oid) {
$return = true;
break;
}
}
}
debug_log(sprintf('is_multi_line_attr(): Returning (%s)',$return),1);
return $return;
}
/**
* Fetches the user setting for $view_deref from config.php. The returned value
* will be one of the four LDAP_DEREF_* constancts defined by the PHP LDAP API. If
* the user has failed to configure this setting or configured an inappropriate
* value, the constant DEFAULT_VIEW_DEREF_SETTING is returned.
*
* @return int
* @deprecated
*/
function get_view_deref_setting() {
global $config;
return $config->GetValue('deref','view');
}
/**
* Fetches whether the user has configured phpLDAPadmin to obfuscate passwords
* with "*********" when displaying them.
*
* This is configured in config.php thus:
*
* $obfuscate_password_display = true;
*
*
* @param string $enc Password encoding type
* @return bool
*/
function obfuscate_password_display($enc=null) {
debug_log(sprintf('obfuscate_password_display(): Entered with ()'),2);
global $config;
if ($config->GetValue('appearance','obfuscate_password_display'))
$return = true;
elseif (! $config->GetValue('appearance','show_clear_password') && (is_null($enc) || $enc == 'clear'))
$return = true;
else
$return = false;
debug_log(sprintf('obfuscate_password_display(): Returning (%s)',$return),1);
return $return;
}
/**
* Returns an HTML-beautified version of a DN.
* Internally, this function makes use of pla_explode_dn() to break the
* the DN into its components. It then glues them back together with
* "pretty" HTML. The returned HTML is NOT to be used as a real DN, but
* simply displayed.
*
* @param string $dn The DN to pretty-print.
* @return string
*/
function pretty_print_dn( $dn ) {
debug_log(sprintf('pretty_print_dn(): Entered with (%s)',$dn),2);
$dn = pla_explode_dn( $dn );
foreach( $dn as $i => $element ) {
$element = htmlspecialchars( $element );
$element = explode( '=', $element, 2 );
$element = implode( '=', $element );
$dn[$i] = $element;
}
$dn = implode( ',', $dn );
return $dn;
}
/**
* Returns true if the attribute specified is required to take as input a DN.
* Some examples include 'distinguishedName', 'member' and 'uniqueMember'.
* @param int $server_id The ID of the server of interest
* (required since this operation demands a schema lookup)
* @param string $attr_name The name of the attribute of interest (case insensitive)
* @return bool
* @todo Move this to an LDAPServer object method.
*/
function is_dn_attr( $ldapserver, $attr_name ) {
debug_log(sprintf('is_dn_attr(): Entered with (%s,%s)',$ldapserver->server_id,$attr_name),2);
// Simple test first
$dn_attrs = array( "aliasedObjectName" );
foreach( $dn_attrs as $dn_attr )
if( 0 == strcasecmp( $attr_name, $dn_attr ) )
return true;
// Now look at the schema OID
$attr_schema = get_schema_attribute( $ldapserver, $attr_name );
if( ! $attr_schema )
return false;
$syntax_oid = $attr_schema->getSyntaxOID();
if( '1.3.6.1.4.1.1466.115.121.1.12' == $syntax_oid )
return true;
if( '1.3.6.1.4.1.1466.115.121.1.34' == $syntax_oid )
return true;
$syntaxes = get_schema_syntaxes( $ldapserver );
if( ! isset( $syntaxes[ $syntax_oid ] ) )
return false;
$syntax_desc = $syntaxes[ $syntax_oid ]->getDescription();
if( false !== strpos( strtolower($syntax_desc), 'distinguished name' ) )
return true;
return false;
}
/**
* Given a string, this function returns true if the string has the format
* of a DN (ie, looks like "cn=Foo,dc=example,dc=com"). Returns false otherwise.
* The purpose of this function is so that developers can examine a string and
* know if it looks like a DN, and draw a hyperlink as needed.
*
* (See unit_test.php for test cases)
*
* @param string $attr The attribute to examine for "DNness"
* @see unit_test.php
* @return bool
*/
function is_dn_string( $str ) {
debug_log(sprintf('is_dn_string(): Entered with (%s)',$str),2);
// Try to break the string into its component parts if it can be done
// ie, "uid=Manager" "dc=example" and "dc=com"
$parts = pla_explode_dn( $str );
if( ! is_array( $parts ) )
return false;
if( 0 == count( $parts ) )
return false;
// Foreach of the "parts", look for an "=" character,
// and make sure neither the left nor the right is empty
foreach( $parts as $part ) {
if( false === strpos( $part, "=" ) )
return false;
$sub_parts = explode( "=", $part, 2 );
$left = $sub_parts[0];
$right = $sub_parts[1];
if( 0 == strlen( trim( $left ) ) || 0 == strlen( trim( $right ) ) )
return false;
if( false !== strpos( $left, '#' ) )
return false;
}
// We survived the above rigor. This is a bonified DN string.
return true;
}
/**
* Get whether a string looks like an email address (user@example.com).
*
* @param string $str The string to analyze.
* @return bool Returns true if the specified string looks like
* an email address or false otherwise.
*/
function is_mail_string( $str ) {
debug_log(sprintf('is_mail_string(): Entered with (%s)',$str),2);
$mail_regex = "/^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$/";
if( preg_match( $mail_regex, $str ) )
return true;
else
return false;
}
/**
* Get whether a string looks like a web URL (http://www.example.com/)
*
* @param string $str The string to analyze.
* @return bool Returns true if the specified string looks like
* a web URL or false otherwise.
*/
function is_url_string( $str ) {
debug_log(sprintf('is_url_string(): Entered with (%s)',$str),2);
$url_regex = '/(ftp|https?):\/\/+[\w\.\-\/\?\=\&]*\w+/';
if( preg_match( $url_regex, $str ) )
return true;
else
return false;
}
/**
* Utility wrapper for setting cookies, which takes into consideration
* phpLDAPadmin configuration values. On success, true is returned. On
* failure, false is returned.
*
* @param string $name The name of the cookie to set.
* @param string $val The value of the cookie to set.
* @param int $expire (optional) The duration in seconds of this cookie. If unspecified, $cookie_time
* is used from config.php
* @param string $dir (optional) The directory value of this cookie (see php.net/setcookie)
*
* @see setcookie
* @return bool
*/
function pla_set_cookie( $name, $val, $expire=null, $dir=null ) {
debug_log(sprintf('pla_set_cookie(): Entered with (%s,%s,%s,%s)',$name,$val,$expire,$dir),2);
global $config;
# Set default return
$return = false;
if ($expire == null) {
$cookie_time = $config->GetValue('session','cookie_time');
$expire = $cookie_time == 0 ? null : time() + $cookie_time;
}
if ($dir == null)
$dir = dirname( $_SERVER['PHP_SELF'] );
if (@setcookie($name,$val,$expire,$dir)) {
$_COOKIE[$name] = $val;
$return = true;
}
debug_log(sprintf('pla_set_cookie(): Returning (%s)',$return),1);
return $return;
}
/**
* Responsible for setting two cookies/session-vars to indicate that a user has logged in,
* one for the logged in DN and one for the logged in password.
*
* This function is only used if 'auth_type' is set to 'cookie' or 'session'. The values
* written have the name "pla_login_dn_X" and "pla_login_pass_X" where X is the
* ID of the server to which the user is attempting login.
*
* Note that as with all cookie/session operations this function must be called BEFORE
* any output is sent to the browser.
*
* On success, true is returned. On failure, false is returned.
*
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @param string $dn The DN with which the user has logged in.
* @param string $password The password of the user logged in.
* @param bool $anon_bind Indicates that this is an anonymous bind such that
* a password of "0" is stored.
* @return bool
* @see unset_login_dn
*/
function set_login_dn($ldapserver,$dn,$password,$anon_bind) {
debug_log(sprintf('set_login_dn(): Entered with (%s,%s,%s,%s)',
$ldapserver->server_id,$dn,$password,$anon_bind),2);
if (! $ldapserver->auth_type)
return false;
switch( $ldapserver->auth_type )
{
case 'cookie':
$cookie_dn_name = sprintf("pla_login_dn_%s",$ldapserver->server_id);
$cookie_pass_name = sprintf("pla_login_pass_%s",$ldapserver->server_id);
// we set the cookie password to 0 for anonymous binds.
if( $anon_bind ) {
$dn = 'anonymous';
$password = '0';
}
$res1 = pla_set_cookie( $cookie_dn_name, pla_blowfish_encrypt( $dn ) );
$res2 = pla_set_cookie( $cookie_pass_name, pla_blowfish_encrypt( $password ) );
if( $res1 && $res2 )
return true;
else
return false;
break;
case 'session':
$sess_var_dn_name = sprintf("pla_login_dn_%s",$ldapserver->server_id);
$sess_var_pass_name = sprintf("pla_login_pass_%s",$ldapserver->server_id);
// we set the cookie password to 0 for anonymous binds.
if( $anon_bind ) {
$dn = 'anonymous';
$password = '0';
}
$_SESSION[ $sess_var_dn_name ] = pla_blowfish_encrypt( $dn );
$_SESSION[ $sess_var_pass_name ] = pla_blowfish_encrypt ( $password );
return true;
break;
default:
global $lang;
pla_error( sprintf( $lang['unknown_auth_type'], htmlspecialchars( $ldapserver->auth_type ) ) );
break;
}
}
/**
* Log a user out of the LDAP server.
*
* Removes the cookies/session-vars set by set_login_dn()
* after a user logs out using "auth_type" of "session" or "cookie".
* Returns true on success, false on failure.
*
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @return bool True on success, false on failure.
* @see set_login_dn
*/
function unset_login_dn( $ldapserver ) {
debug_log(sprintf('unset_login_dn(): Entered with (%s)',$ldapserver->server_id),2);
if (! $ldapserver->auth_type)
return false;
switch( $ldapserver->auth_type )
{
case 'cookie':
$logged_in_dn = get_logged_in_dn( $ldapserver );
if( ! $logged_in_dn )
return false;
$logged_in_pass = get_logged_in_pass( $ldapserver );
$anon_bind = $logged_in_dn == 'anonymous' ? true : false;
// set cookie with expire time already passed to erase cookie from client
$expire = time()-3600;
$cookie_dn_name = sprintf("pla_login_dn_%s",$ldapserver->server_id);
$cookie_pass_name = sprintf("pla_login_pass_%s",$ldapserver->server_id);
if( $anon_bind ) {
$res1 = pla_set_cookie( $cookie_dn_name, 'anonymous', $expire );
$res2 = pla_set_cookie( $cookie_pass_name, '0', $expire );
} else {
$res1 = pla_set_cookie( $cookie_dn_name, pla_blowfish_encrypt( $logged_in_dn ), $expire );
$res2 = pla_set_cookie( $cookie_pass_name, pla_blowfish_encrypt( $logged_in_pass ), $expire );
}
# Need to unset the cookies too, since they are still set if further processing occurs (eg: Timeout)
unset($_COOKIE[$cookie_dn_name]);
unset($_COOKIE[$cookie_pass_name]);
if( ! $res1 || ! $res2 )
return false;
else
return true;
break;
case 'session':
// unset session variables
$session_var_dn_name = sprintf("pla_login_dn_%s",$ldapserver->server_id);
$session_var_pass_name = sprintf("pla_login_pass_%s",$ldapserver->server_id);
if( array_key_exists( $session_var_dn_name, $_SESSION ) )
unset( $_SESSION[ $session_var_dn_name ] );
if( array_key_exists( $session_var_pass_name, $_SESSION ) )
unset( $_SESSION[ "$session_var_pass_name" ] );
session_write_close();
return true;
break;
default:
global $lang;
pla_error( sprintf( $lang['unknown_auth_type'], htmlspecialchars( $auth_type ) ) );
break;
}
}
/**
* Get a customized file for a server
* We don't need any caching, because it's done by PHP
*
* @param int $server_id The ID of the server
* @param string $filename The requested filename
*
* @return string The customized filename, if exists, or the standard one
*/
function get_custom_file($server_id,$filename,$path) {
debug_log(sprintf('get_custom_file(): Entered with (%s,%s,%s)',$server_id,$filename,$path),2);
global $ldapservers;
# Set default return
$return = $path.$filename;
$custom = $ldapservers->GetValue($server_id,'custom','pages_prefix');
if (! is_null($custom) && is_file(realpath($path.$custom.$filename)))
$return = $path.$custom.$filename;
debug_log(sprintf('get_custom_file(): Returning (%s)',$return),1);
return $return;
}
/**
* Call a customized function
*
* @param int $server_id The ID of the server
* @param string $filename The requested function
*
* @return any The result of the called function
*/
function call_custom_function( $server_id, $function ) {
debug_log(sprintf('call_custom_function(): Entered with (%s,%s)',$server_id,$function),2);
global $ldapservers;
# Set default return
$return = $function;
$custom = $ldapservers->GetValue($server_id,'custom','pages_prefix');
if (! is_null($custom) && function_exists($custom.$function))
$return = $custom.$filename;
debug_log(sprintf('get_custom_file(): Returning (%s)',$return),1);
return call_user_func($return );
}
/**
* Compares 2 DNs. If they are equivelant, returns 0, otherwise,
* returns their sorting order (similar to strcmp()):
* Returns < 0 if dn1 is less than dn2.
* Returns > 0 if dn1 is greater than dn2.
*
* The comparison is performed starting with the top-most element
* of the DN. Thus, the following list:
*
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* dc=example,dc=com
* cn=Fred,ou=people,dc=example,dc=org
* cn=Dave,ou=people,dc=example,dc=org
*
* Will be sorted thus using usort( $list, "pla_compare_dns" ):
*
* dc=com
* dc=example,dc=com
* ou=people,dc=example,dc=com
* cn=Admin,ou=People,dc=example,dc=com
* cn=Joe,ou=people,dc=example,dc=com
* cn=Dave,ou=people,dc=example,dc=org
* cn=Fred,ou=people,dc=example,dc=org
*
*
* @param string $dn1 The first of two DNs to compare
* @param string $dn2 The second of two DNs to compare
* @return int
*/
function pla_compare_dns( $dn1, $dn2 ) {
debug_log(sprintf('pla_compare_dns(): Entered with (%s,%s)',$dn1,$dn2),2);
// If they are obviously the same, return immediately
if( 0 === strcasecmp( $dn1, $dn2 ) )
return 0;
$dn1_parts = pla_explode_dn( pla_reverse_dn($dn1) );
$dn2_parts = pla_explode_dn( pla_reverse_dn($dn2) );
assert( is_array( $dn1_parts ) );
assert( is_array( $dn2_parts ) );
// Foreach of the "parts" of the smaller DN
for( $i=0; $i
* $show_hints = true;
*
*
* @return bool
* @deprecated
*/
function show_hints() {
global $config;
return $config->GetValue('appearance','show_hints');
}
/**
* Determines if the user has enabled auto uidNumbers for the specified server ID.
*
* @param int $server_id The id of the server of interest.
* @return bool True if auto uidNumbers are enabled, false otherwise.
*/
function auto_uid_numbers_enabled($server_id) {
debug_log(sprintf('auto_uid_numbers_enabled(): Entered with (%s)',$server_id),2);
global $ldapservers;
return $ldapservers->GetValue($server_id,'auto_number','enable');
}
/**
* For hosts who have 'enable_auto_uid_numbers' set to true, this function will
* get the next available uidNumber using the host's preferred mechanism
* (uidpool or search). The uidpool mechanism uses a user-configured entry in
* the LDAP server to store the last used uidNumber. This mechanism simply fetches
* and increments and returns that value. The search mechanism is more complicated
* and slow. It searches all entries that have uidNumber set, finds the smalles and
* "fills in the gaps" by incrementing the smallest uidNumber until an unused value
* is found. Both mechanisms do NOT prevent race conditions or toe-stomping, so
* care must be taken when actually creating the entry to check that the uidNumber
* returned here has not been used in the mean time. Note that the two different
* mechanisms may (will!) return different values as they use different algorithms
* to arrive at their result. Do not be alarmed if (when!) this is the case.
*
* Also note that both algorithms are susceptible to a race condition. If two admins
* are adding users simultaneously, the users may get identical uidNumbers with this
* function.
*
* See config.php.example for more notes on the two auto uidNumber mechanisms.
*
* @param object $ldapserver The LDAP Server Object of interest.
* @return int
*
* @todo take advantage of multiple connections with new LDAPServer object.
* @todo rename this function as its a generic get_next_number function now.
* @todo Must turn off auto_uid|gid in template if config is disabled.
*/
function get_next_uid_number($ldapserver,$startbase='',$type='uid') {
global $config; $config->custom->debug['level'] = 9; $config->custom->debug['syslog'] = true;
debug_log(sprintf('get_next_uid_number(): Entered with (%s,%s,%s)',$ldapserver->server_id,$startbase,$type),2);
global $ldapservers,$servers,$lang;
if (! auto_uid_numbers_enabled($ldapserver->server_id))
return false;
# Based on the configured mechanism, go get the next available uidNumber!
$mechanism = $ldapservers->GetValue($ldapserver->server_id,'auto_number','mechanism');
switch ($mechanism) {
// @todo: This is being deprecated - unless somebody wants it?
case 'uidpool' :
if( ! isset( $servers[ $ldapserver->server_id ][ 'auto_uid_number_uid_pool_dn' ] ) )
pla_error( sprintf( $lang['uidpool_not_set'], $ldapserver->name ) );
$uid_pool_dn = $servers[ $ldapserver->server_id ][ 'auto_uid_number_uid_pool_dn' ];
if( ! dn_exists( $ldapserver, $uid_pool_dn ) )
pla_error( sprintf( $lang['uidpool_not_exist'] , $uid_pool_dn ) );
$next_uid_number = get_object_attr( $ldapserver, $uid_pool_dn, 'uidNumber' );
$next_uid_number = intval( $next_uid_number[ 0 ] );
$next_uid_number++;
return $next_uid_number;
break;
case 'search' :
if (! $startbase) {
$base_dn = $ldapservers->GetValue($ldapserver->server_id,'auto_number','search_base');
if (is_null($base_dn))
pla_error( sprintf( $lang['specified_uidpool'] , $ldapserver->name ) );
} else {
$base_dn = $startbase;
}
$filter = "(|(uidNumber=*)(gidNumber=*))";
$results = array();
# Check see and use our alternate uid_dn and password if we have it.
if (! is_null($ldapservers->GetValue($ldapserver->server_id,'auto_number','dn')) &&
! is_null($ldapservers->GetValue($ldapserver->server_id,'auto_number','pass'))) {
$con = @ldap_connect($ldapserver->host,$ldapserver->port);
@ldap_set_option($con,LDAP_OPT_PROTOCOL_VERSION,3);
@ldap_set_option($con,LDAP_OPT_REFERRALS,0);
# Bind with the alternate ID.
$res = @ldap_bind($con,
$ldapservers->GetValue($ldapserver->server_id,'auto_number','dn'),
$ldapservers->GetValue($ldapserver->server_id,'auto_number','pass'));
if (! $res)
pla_error(sprintf($lang['auto_uid_invalid_credential'],$ldapserver->name));
$search = @ldap_search($con,$base_dn,$filter,array('uidNumber','gidNumber'),0,0,0,
$config->GetValue('deref','search'));
if (! $search)
pla_error(sprintf($lang['bad_auto_uid_search_base'],$ldapserver->name));
$search = @ldap_get_entries($con,$search);
$res = @ldap_unbind($con);
for ($i = 0;$i < $search['count']; $i++ ) {
$attrs = $search[$i];
switch ($type) {
case 'uid' :
if (isset($attrs['uidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['uidnumber'][0];
}
break;
case 'gid' :
if (isset($attrs['gidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['gidnumber'][0];
}
break;
}
$results[] = $entry;
}
} else {
$search = pla_ldap_search( $ldapserver, $filter, $base_dn, array('uidNumber','gidNumber'));
foreach ($search as $dn => $attrs) {
switch ($type) {
case 'uid' :
if (isset($attrs['uidNumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['uidNumber'];
}
break;
case 'gid' :
if (isset($attrs['gidNumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['gidNumber'];
}
break;
}
$results[] = $entry;
}
}
# construct a list of used numbers
$autonum = array();
foreach ($results as $result)
$autonum[] = $result['uniqnumber'];
$autonum = array_unique($autonum);
if (count($autonum) == 0)
return false;
sort($autonum);
foreach($autonum as $uid)
$uid_hash[$uid] = 1;
# start with the least existing autoNumber and add 1
if ($ldapservers->GetValue($ldapserver->server_id,'auto_number','min'))
$minNumber = $ldapservers->GetValue($ldapserver->server_id,'auto_number','min');
else
$minNumber = intval($autonum[0]) + 1;
# this loop terminates as soon as we encounter the next available minNumber
while (isset($uid_hash[$minNumber]))
$minNumber++;
return $minNumber;
break;
# No other cases allowed. The user has an error in the configuration
default :
pla_error( sprintf( $lang['auto_uid_invalid_value'] , $mechanism) );
}
}
/**
* Used to determine if the specified attribute is indeed a jpegPhoto. If the
* specified attribute is one that houses jpeg data, true is returned. Otherwise
* this function returns false.
*
* @param int $server_id The ID of the server hosuing the attribute of interest
* @param string $attr_name The name of the attribute to test.
* @return bool
* @see draw_jpeg_photos
* @todo Move this to an LDAPServer object method.
*/
function is_jpeg_photo( $ldapserver, $attr_name ) {
debug_log(sprintf('is_jpeg_photo(): Entered with (%s,%s)',$ldapserver->server_id,$attr_name),2);
// easy quick check
if( 0 == strcasecmp( $attr_name, 'jpegPhoto' ) ||
0 == strcasecmp( $attr_name, 'photo' ) )
return true;
// go to the schema and get the Syntax OID
// require_once realpath( 'schema_functions.php' );
$schema_attr = get_schema_attribute( $ldapserver, $attr_name );
if( ! $schema_attr )
return false;
$oid = $schema_attr->getSyntaxOID();
$type = $schema_attr->getType();
if( 0 == strcasecmp( $type, 'JPEG' ) )
return true;
if( $oid == '1.3.6.1.4.1.1466.115.121.1.28' )
return true;
return false;
}
/**
* Given an attribute name and server ID number, this function returns
* whether the attrbiute contains boolean data. This is useful for
* developers who wish to display the contents of a boolean attribute
* with a drop-down.
*
* @param int $server_id The ID of the server of interest (required since
* this action requires a schema lookup on the server)
* @param string $attr_name The name of the attribute to test.
* @return bool
* @todo Move this to an LDAPServer object method.
*/
function is_attr_boolean( $ldapserver, $attr_name ) {
debug_log(sprintf('is_attr_boolean(): Entered with (%s,%s)',$ldapserver->server_id,$attr_name),2);
$type = ( $schema_attr = get_schema_attribute( $ldapserver, $attr_name ) ) ?
$schema_attr->getType() : null;
if( 0 == strcasecmp( 'boolean', $type ) ||
0 == strcasecmp( 'isCriticalSystemObject', $attr_name ) ||
0 == strcasecmp( 'showInAdvancedViewOnly', $attr_name ) )
return true;
else
return false;
}
/**
* Given an attribute name and server ID number, this function returns
* whether the attrbiute may contain binary data. This is useful for
* developers who wish to display the contents of an arbitrary attribute
* but don't want to dump binary data on the page.
*
* @param int $server_id The ID of the server of interest (required since
* this action requires a schema lookup on the server)
* @param string $attr_name The name of the attribute to test.
* @return bool
*
* @see is_jpeg_photo
* @todo Move this to an LDAPServer object method.
*/
function is_attr_binary( $ldapserver, $attr_name ) {
debug_log(sprintf('is_attr_binary(): Entered with (%s,%s)',$ldapserver->server_id,$attr_name),2);
$attr_name = strtolower( $attr_name );
/**
* Determining if an attribute is binary can be an expensive operation.
* We cache the results for each attr name on each server in the $attr_cache
* to speed up subsequent calls. The $attr_cache looks like this:
*
* Array
* 0 => Array
* 'objectclass' => false
* 'cn' => false
* 'usercertificate' => true
* 1 => Array
* 'jpegphoto' => true
* 'cn' => false
*/
static $attr_cache;
if( isset( $attr_cache[ $ldapserver->server_id ][ $attr_name ] ) )
return $attr_cache[ $ldapserver->server_id ][ $attr_name ];
if( $attr_name == 'userpassword' ) {
$attr_cache[ $ldapserver->server_id ][ $attr_name ] = false;
return false;
}
// Quick check: If the attr name ends in ";binary", then it's binary.
if( 0 == strcasecmp( substr( $attr_name, strlen( $attr_name ) - 7 ), ";binary" ) ) {
$attr_cache[ $ldapserver->server_id ][ $attr_name ] = true;
return true;
}
// See what the server schema says about this attribute
$schema_attr = get_schema_attribute( $ldapserver, $attr_name );
if( ! $schema_attr ) {
// Strangely, some attributeTypes may not show up in the server
// schema. This behavior has been observed in MS Active Directory.
$type = null;
$syntax = null;
} else {
$type = $schema_attr->getType();
$syntax = $schema_attr->getSyntaxOID();
}
if( 0 == strcasecmp( $type, 'Certificate' ) ||
0 == strcasecmp( $type, 'Binary' ) ||
0 == strcasecmp( $attr_name, 'usercertificate' ) ||
0 == strcasecmp( $attr_name, 'usersmimecertificate' ) ||
0 == strcasecmp( $attr_name, 'networkaddress' ) ||
0 == strcasecmp( $attr_name, 'objectGUID' ) ||
0 == strcasecmp( $attr_name, 'objectSID' ) ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.10' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.28' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.5' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.8' ||
$syntax == '1.3.6.1.4.1.1466.115.121.1.9' ) {
$attr_cache[ $ldapserver->server_id ][ $attr_name ] = true;
return true;
} else {
$attr_cache[ $ldapserver->server_id ][ $attr_name ] = false;
return false;
}
}
/**
* Returns true if the specified attribute is configured as read only
* in config.php with the $read_only_attrs array.
* Attributes are configured as read-only in config.php thus:
*
* $read_only_attrs = array( "objectClass", "givenName" );
*
*
* @param string $attr The name of the attribute to test.
* @return bool
* @todo Move this to an LDAPServer object method.
*/
function is_attr_read_only( $ldapserver, $attr ) {
debug_log(sprintf('is_attr_read_only(): Entered with (%s,%s)',$ldapserver->server_id,$attr),2);
global $read_only_attrs, $read_only_except_dn;
$attr = trim( $attr );
if( '' === $attr )
return false;
if( ! isset( $read_only_attrs ) )
return false;
if( ! is_array( $read_only_attrs) )
return false;
// Is the user excluded?
if (isset($read_only_except_dn) && userIsMember($ldapserver, get_logged_in_dn( $ldapserver ),$read_only_except_dn))
return false;
foreach( $read_only_attrs as $attr_name )
if( 0 == strcasecmp( $attr, trim($attr_name) ) )
return true;
return false;
}
/**
* Returns true if the specified attribute is configured as hidden
* in config.php with the $hidden_attrs array or the $hidden_attrs_ro
* array.
* Attributes are configured as hidden in config.php thus:
*
* $hidden_attrs = array( "objectClass", "givenName" );
*
* or
*
* $hidden_attrs_ro = array( "objectClass", "givenName", "shadowWarning",
* "shadowLastChange", "shadowMax", "shadowFlag",
* "shadowInactive", "shadowMin", "shadowExpire" );
*
*
* @param string $attr The name of the attribute to test.
* @return bool
*/
function is_attr_hidden( $ldapserver, $attr ) {
debug_log(sprintf('is_attr_hidden(): Entered with (%s,%s)',$ldapserver->server_id,$attr),2);
global $hidden_attrs, $hidden_attrs_ro, $hidden_except_dn;
$attr = trim( $attr );
if( '' === $attr )
return false;
if( ! isset( $hidden_attrs ) )
return false;
if( ! is_array( $hidden_attrs) )
return false;
if( ! isset( $hidden_attrs_ro ) )
$hidden_attrs_ro = $hidden_attrs;
if( ! is_array( $hidden_attrs_ro) )
$hidden_attrs_ro = $hidden_attrs;
// Is the user excluded?
if (isset($hidden_except_dn) && userIsMember($ldapserver, get_logged_in_dn( $ldapserver ),$hidden_except_dn))
return false;
if( $ldapserver->isReadOnly() ) {
foreach( $hidden_attrs_ro as $attr_name )
if( 0 == strcasecmp( $attr, trim($attr_name) ) )
return true;
} else {
foreach( $hidden_attrs as $attr_name )
if( 0 == strcasecmp( $attr, trim($attr_name) ) )
return true;
}
return false;
}
/**
* Returns true if the specified server is configured to be displayed
* in read only mode. If a user has logged in via anonymous bind, and
* config.php specifies anonymous_bind_implies_read_only as true, then
* this also returns true. Servers can be configured read-only in
* config.php thus:
*
* $server[$i]['read_only'] = true;
*
*
* @param int $server_id The ID of the server of interest from the $servers array in config.php
* @return bool
* @deprecated
*/
function is_server_read_only( $server_id ) {
global $servers;
if( isset( $servers[$server_id]['read_only'] ) &&
$servers[$server_id]['read_only'] == true )
return true;
global $anonymous_bind_implies_read_only;
if( "anonymous" == get_logged_in_dn( $server_id ) &&
isset( $anonymous_bind_implies_read_only ) &&
$anonymous_bind_implies_read_only == true )
return true;
return false;
}
/**
* Given a DN and server ID, this function reads the DN's objectClasses and
* determines which icon best represents the entry. The results of this query
* are cached in a session variable so it is not run every time the tree
* browser changes, just when exposing new DNs that were not displayed
* previously. That means we can afford a little bit of inefficiency here
* in favor of coolness. :)
*
* This function returns a string like "country.png". All icon files are assumed
* to be contained in the /images/ directory of phpLDAPadmin.
*
* Developers are encouraged to add new icons to the images directory and modify
* this function as needed to suit their types of LDAP entries. If the modifications
* are general to an LDAP audience, the phpLDAPadmin team will gladly accept them
* as a patch.
*
* @param int $server_id The ID of the LDAP server housing the DN of interest.
* @param string $dn The DN of the entry whose icon you wish to fetch.
*
* @return string
*/
function get_icon( $ldapserver, $dn ) {
debug_log(sprintf('get_icon(): Entered with (%s,%s)',$ldapserver->server_id,$dn),2);
// fetch and lowercase all the objectClasses in an array
$object_classes = get_object_attr( $ldapserver, $dn, 'objectClass', true );
if( $object_classes === null || $object_classes === false || ! is_array( $object_classes ) )
$object_classes = array();
foreach( $object_classes as $i => $class )
$object_classes[$i] = strtolower( $class );
$rdn = get_rdn( $dn );
$rdn_parts = explode( '=', $rdn, 2 );
$rdn_value = isset( $rdn_parts[0] ) ? $rdn_parts[0] : null;
$rdn_attr = isset( $rdn_parts[1] ) ? $rdn_parts[1] : null;
unset( $rdn_parts );
// return icon filename based upon objectClass value
if( in_array( 'sambaaccount', $object_classes ) &&
'$' == $rdn{ strlen($rdn) - 1 } )
return 'nt_machine.png';
if( in_array( 'sambaaccount', $object_classes ) )
return 'nt_user.png';
elseif( in_array( 'person', $object_classes ) ||
in_array( 'organizationalperson', $object_classes ) ||
in_array( 'inetorgperson', $object_classes ) ||
in_array( 'account', $object_classes ) ||
in_array( 'posixaccount', $object_classes ) )
return 'user.png';
elseif( in_array( 'organization', $object_classes ) )
return 'o.png';
elseif( in_array( 'organizationalunit', $object_classes ) )
return 'ou.png';
elseif( in_array( 'organizationalrole', $object_classes ) )
return 'uid.png';
elseif( in_array( 'dcobject', $object_classes ) ||
in_array( 'domainrelatedobject', $object_classes ) ||
in_array( 'domain', $object_classes ) ||
in_array( 'builtindomain', $object_classes ))
return 'dc.png';
elseif( in_array( 'alias', $object_classes ) )
return 'go.png';
elseif( in_array( 'room', $object_classes ) )
return 'door.png';
elseif( in_array( 'device', $object_classes ) )
return 'device.png';
elseif( in_array( 'document', $object_classes ) )
return 'document.png';
elseif( in_array( 'country', $object_classes ) ) {
$tmp = pla_explode_dn( $dn );
$cval = explode( '=', $tmp[0], 2 );
$cval = isset( $cval[1] ) ? $cval[1] : false;
if( $cval && false === strpos( $cval, ".." ) &&
file_exists( realpath( sprintf("./images/countries/%s.png",strtolower($cval)) ) ) )
return sprintf("countries/%s.png",strtolower($cval));
else
return 'country.png';
}
elseif( in_array( 'jammvirtualdomain', $object_classes ) )
return 'mail.png';
elseif( in_array( 'locality', $object_classes ) )
return 'locality.png';
elseif( in_array( 'posixgroup', $object_classes ) ||
in_array( 'groupofnames', $object_classes ) ||
in_array( 'group', $object_classes ) )
return 'ou.png';
elseif( in_array( 'applicationprocess', $object_classes ) )
return 'process.png';
elseif( in_array( 'groupofuniquenames', $object_classes ) )
return 'uniquegroup.png';
elseif( in_array( 'iphost', $object_classes ) )
return 'host.png';
elseif( in_array( 'nlsproductcontainer', $object_classes ) )
return 'n.png';
elseif( in_array( 'ndspkikeymaterial', $object_classes ) )
return 'lock.png';
elseif( in_array( 'server', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'volume', $object_classes ) )
return 'hard-drive.png';
elseif( in_array( 'ndscatcatalog', $object_classes ) )
return 'catalog.png';
elseif( in_array( 'resource', $object_classes ) )
return 'n.png';
elseif( in_array( 'ldapgroup', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'ldapserver', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'nisserver', $object_classes ) )
return 'ldap-server.png';
elseif( in_array( 'rbscollection', $object_classes ) )
return 'ou.png';
elseif( in_array( 'dfsconfiguration', $object_classes ) )
return 'nt_machine.png';
elseif( in_array( 'applicationsettings', $object_classes ) )
return 'server-settings.png';
elseif( in_array( 'aspenalias', $object_classes ) )
return 'mail.png';
elseif( in_array( 'container', $object_classes ) )
return 'folder.png';
elseif( in_array( 'ipnetwork', $object_classes ) )
return 'network.png';
elseif( in_array( 'samserver', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'lostandfound', $object_classes ) )
return 'find.png';
elseif( in_array( 'infrastructureupdate', $object_classes ) )
return 'server-small.png';
elseif( in_array( 'filelinktracking', $object_classes ) )
return 'files.png';
elseif( in_array( 'automountmap', $object_classes ) ||
in_array( 'automount', $object_classes ) )
return 'hard-drive.png';
elseif( 0 === strpos( $rdn_value, "ipsec" ) ||
0 == strcasecmp( $rdn_value, "IP Security" ) ||
0 == strcasecmp( $rdn_value, "MSRADIUSPRIVKEY Secret" ) ||
0 === strpos( $rdn_value, "BCKUPKEY_" ) )
return 'lock.png';
elseif( 0 == strcasecmp( $rdn_value, "MicrosoftDNS" ) )
return 'dc.png';
// Oh well, I don't know what it is. Use a generic icon.
else
return 'object.png';
}
/**
* Does the same thing as get_icon(), but it tries to fetch the icon name from the
* tree_icons session variable first. If not found, resorts to get_icon() and stores
* the icon nmae in the tree_icons session before returing the icon.
*
* @param int $server_id The ID of the server housing the DN of interest.
* @param string $dn The DN of the entry of interest.
*
* @return string
*
* @see get_icon
*/
function get_icon_use_cache( $ldapserver, $dn ) {
debug_log(sprintf('get_icon_use_cache(): Entered with (%s,%s)',$ldapserver->server_id,$dn),2);
initialize_session_tree();
if( array_key_exists( 'tree_icons', $_SESSION ) ) {
if( array_key_exists( $ldapserver->server_id, $_SESSION['tree_icons'] ) &&
array_key_exists( $dn, $_SESSION['tree_icons'][$ldapserver->server_id] ) ) {
return $_SESSION['tree_icons'][ $ldapserver->server_id ][ $dn ];
} else {
$icon = get_icon( $ldapserver, $dn );
$_SESSION['tree_icons'][ $ldapserver->server_id ][ $dn ] = $icon;
return $icon;
}
}
}
/**
* Given a server_id, returns whether or not we have enough information
* to authenticate against the server. For example, if the user specifies
* auth_type of 'cookie' in the config for that server, it checks the $_COOKIE array to
* see if the cookie username and password is set for the server. If the auth_type
* is 'session', the $_SESSION array is checked.
*
* There are three cases for this function depending on the auth_type configured for
* the specified server. If the auth_type is form or http, then get_logged_in_dn() is
* called to verify that the user has logged in. If the auth_type is config, then the
* $servers array in config.php is checked to ensure that the user has specified
* login information. In any case, if phpLDAPadmin has enough information to login
* to the server, true is returned. Otherwise false is returned.
*
* @param int $server_id
* @return bool
* @see get_logged_in_dn
* @deprecated
*/
function have_auth_info( $server_id )
{
global $servers, $ldapservers;
$ldapserver = $ldapservers->Instance($server_id);
$server = $servers[$server_id];
// For session or cookie auth_types, we check the session or cookie to see if a user has logged in.
if( isset( $server['auth_type'] ) && ( in_array( $server['auth_type'], array( 'session', 'cookie' ) ) ) ) {
// we don't look at get_logged_in_pass() cause it may be null for anonymous binds
// get_logged_in_dn() will never return null if someone is really logged in.
if( get_logged_in_dn( $ldapserver ) )
return true;
else
return false;
}
// whether or not the login_dn or pass is specified, we return
// true here. (if they are blank, we do an anonymous bind anyway)
elseif( ! isset( $server['auth_type'] ) || $server['auth_type'] == 'config' ) {
return true;
}
else {
global $lang;
pla_error( sprintf( $lang['error_auth_type_config'],
htmlspecialchars( $server[ 'auth_type' ] ) ) );
}
}
/**
* Fetches the password of the currently logged in user (for auth_types "form" and "http" only)
* or false if the current login is anonymous.
*
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @return string
* @see have_auth_info
* @see get_logged_in_dn
*/
function get_logged_in_pass( $ldapserver ) {
debug_log(sprintf('get_logged_in_pass(): Entered with (%s)',$ldapserver->server_id),2);
if (! $ldapserver->auth_type)
return false;
switch( $ldapserver->auth_type )
{
case 'cookie':
$cookie_name = sprintf('pla_login_pass_%s',$ldapserver->server_id);
$pass = isset( $_COOKIE[ $cookie_name ] ) ? $_COOKIE[ $cookie_name ] : false;
if( $pass == '0' )
return null;
else
return pla_blowfish_decrypt( $pass );
break;
case 'session':
$session_var_name = sprintf('pla_login_pass_%s',$ldapserver->server_id);
$pass = isset( $_SESSION[ $session_var_name ] ) ? $_SESSION[ $session_var_name ] : false;
if( $pass == '0' )
return null;
else
return pla_blowfish_decrypt ( $pass );
break;
case 'config':
return $ldapserver->login_pass;
break;
default:
global $lang;
pla_error( sprintf( $lang['unknown_auth_type'], htmlspecialchars( $ldapserver->auth_type ) ) );
}
}
/**
* Returns the DN who is logged in currently to the given server, which may
* either be a DN or the string 'anonymous'. This applies only for auth_types
* "form" and "http".
*
* One place where this function is used is the tree viewer:
* After a user logs in, the text "Logged in as: " is displayed under the server
* name. This information is retrieved from this function.
*
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @return string
* @see have_auth_info
* @see get_logged_in_pass
*/
function get_logged_in_dn($ldapserver) {
debug_log(sprintf('get_logged_in_dn(): Entered with (%s)',$ldapserver->server_id),2);
# Set default return
$return = false;
if ($ldapserver->auth_type) {
switch ($ldapserver->auth_type) {
case 'cookie':
$cookie_name = sprintf('pla_login_dn_%s',$ldapserver->server_id);
if (isset($_COOKIE[$cookie_name]))
$return = pla_blowfish_decrypt($_COOKIE[$cookie_name]);
else
$return = false;
break;
case 'session':
$session_var_name = sprintf('pla_login_dn_%s',$ldapserver->server_id);
if (isset($_SESSION[$session_var_name]))
$return = pla_blowfish_decrypt($_SESSION[$session_var_name]);
else
$return = false;
break;
case 'config':
$return = $ldapserver->login_dn;
break;
default:
global $lang;
pla_error(sprintf($lang['unknown_auth_type'],htmlspecialchars($auth_type)));
}
}
debug_log(sprintf('get_logged_in_dn(): Returning (%s)',$return),1);
return $return;
}
/**
* Appends a servers base to a "sub" dn or returns the base.
*
* If $get_base is true, return at least the base, otherwise null.
* @param object $ldapserver The LDAPServer object of the server which the user hsa logged in.
* @return string|null
* @todo This function no longer return the base, since the LDAP server could have multiple bases.
*/
function expand_dn_with_base( $ldapserver,$sub_dn,$get_base=true ) {
debug_log(sprintf('expand_dn_with_base(): Entered with (%s,%s,%s)',$ldapserver->server_id,$sub_dn,$get_base),2);
$empty_str = ( is_null($sub_dn) || ( ( $len = strlen( trim( $sub_dn ) ) ) == 0 ) );
if ( $empty_str ) {
// If we have no string and want not base
if ( ! $get_base )
return null;
} elseif ( $sub_dn[$len - 1] != ',' )
// If we have a string which doesn't need a base
return $sub_dn;
if( ( $empty_str && $get_base ) || ! $empty_str ) {
if ( $ldapserver->getBaseDN() )
return ( ! $empty_str ) ? $sub_dn . $ldapserver->getBaseDN() : $ldapserver->getBaseDN();
}
return null;
}
/**
* Gets a list of child entries for an entry. Given a DN, this function fetches the list of DNs of
* child entries one level beneath the parent. For example, for the following tree:
*
*
* dc=example,dc=com
* ou=People
* cn=Dave
* cn=Fred
* cn=Joe
* ou=More People
* cn=Mark
* cn=Bob
*
*
* Calling get_container_contents( $server_id, "ou=people,dc=example,dc=com" )
* would return the following list:
*
*
* cn=Dave
* cn=Fred
* cn=Joe
* ou=More People
*
*
* @param object $ldapserver The LDAP Server Object housing the entry of interest
* @param string $dn The DN of the entry whose children to return.
* @param int $size_limit (optional) The maximum number of entries to return.
* If unspecified, no limit is applied to the number of entries in the returned.
* @param string $filter (optional) An LDAP filter to apply when fetching children, example: "(objectClass=inetOrgPerson)"
* @return array An array of DN strings listing the immediate children of the specified entry.
* @todo Move this to an LDAPServer object method.
*/
function get_container_contents( $ldapserver, $dn, $size_limit=0, $filter='(objectClass=*)', $deref=LDAP_DEREF_ALWAYS ) {
debug_log(sprintf('get_container_contents(): Entered with (%s,%s,%s,%s,%s)',
$ldapserver->server_id,$dn,$size_limit,$filter,$deref),2);
$search = @ldap_list( $ldapserver->connect(), $dn, $filter, array( 'dn' ), 1, $size_limit, 0, $deref );
if( ! $search )
return array();
$search = ldap_get_entries( $ldapserver->connect(), $search );
$return = array();
for( $i=0; $i<$search['count']; $i++ ) {
$entry = $search[$i];
$dn = $entry['dn'];
$return[] = $dn;
}
return $return;
}
/**
* Builds the initial tree that is stored in the session variable 'tree'.
* Simply returns an array with an entry for each active server in
* config.php. The structure of the returned array is simple, and looks like
* this:
*
* Array (
* 0 => Array ( )
* 1 => Array ( )
* )
*
* This function is not meant as a user callable function, but rather a convenient,
* automated method for setting up the initial structure for the tree viewer.
*/
function build_initial_tree() {
debug_log(sprintf('build_initial_tree(): Entered with ()'),2);
global $ldapservers;
$return = array();
foreach ($ldapservers->GetServerList() as $id) {
if( $ldapservers->GetValue($id,'server','host') == '' )
continue;
$return[$id] = array();
}
debug_log(sprintf('build_initial_tree(): Returning (%s)',serialize($return)),1);
return $return;
}
/**
* Builds the initial array that stores the icon-lookup for each server's DN in the tree browser. The returned
* array is then stored in the current session. The structure of the returned array is simple, and looks like
* this:
*
* Array
* (
* [0] => Array
* (
* [dc=example,dc=com] => "dcobject.png"
* )
* [1] => Array
* (
* [o=Corporation] => "o.png"
* )
* )
*
* This function is not meant as a user-callable function, but rather a convenient, automated method for
* setting up the initial data structure for the tree viewer's icon cache.
*/
function build_initial_tree_icons() {
debug_log(sprintf('build_initial_tree_icons(): Entered with ()'),2);
global $ldapservers;
$return = array();
# initialize an empty array for each server
foreach ($ldapservers->GetServerList() as $id) {
if( $ldapservers->GetValue($id,'server','host') == '' )
continue;
$ldapserver = $ldapservers->Instance($id);
$return[$id] = array();
foreach ($ldapserver->getBaseDN() as $base_dn)
$return[$id][$base_dn] = get_icon($ldapserver,$base_dn);
}
debug_log(sprintf('build_initial_tree_icons(): Returning (%s)',serialize($return)),1);
return $return;
}
/*
* Checks and fixes an initial session's tree cache if needed.
*
* This function is not meant as a user-callable function, but rather a convenient,
* automated method for checking the initial data structure of the session.
*/
function initialize_session_tree() {
debug_log(sprintf('initialize_session_tree(): Entered with ()'),2);
// From the PHP manual: If you use $_SESSION don't use
// session_register(), session_is_registered() or session_unregister()!
if( ! array_key_exists( 'tree', $_SESSION ) )
$_SESSION['tree'] = build_initial_tree();
if( ! array_key_exists( 'tree_icons', $_SESSION ) )
$_SESSION['tree_icons'] = build_initial_tree_icons();
// Make sure that the tree index is indeed well formed.
if( ! is_array( $_SESSION['tree'] ) )
$_SESSION['tree'] = build_initial_tree();
if( ! is_array( $_SESSION['tree_icons'] ) )
$_SESSION['tree_icons'] = build_initial_tree_icons();
}
/**
* Gets the operational attributes for an entry. Given a DN, this function fetches that entry's
* operational (ie, system or internal) attributes. These attributes include "createTimeStamp",
* "creatorsName", and any other attribute that the LDAP server sets automatically. The returned
* associative array is of this form:
*
* Array
* (
* [creatorsName] => Array
* (
* [0] => "cn=Admin,dc=example,dc=com"
* )
* [createTimeStamp]=> Array
* (
* [0] => "10401040130"
* )
* [hasSubordinates] => Array
* (
* [0] => "FALSE"
* )
* )
*
*
* @param object $ldapserver The LDAP Server Object of interest
* @param string $dn The DN of the entry whose interal attributes are desired.
* @param int $deref For aliases and referrals, this parameter specifies whether to
* follow references to the referenced DN or to fetch the attributes for
* the referencing DN. See http://php.net/ldap_search for the 4 valid
* options.
* @return array An associative array whose keys are attribute names and whose values
* are arrays of values for the aforementioned attribute.
* @todo Move this to an LDAPServer object method.
*/
function get_entry_system_attrs( $ldapserver, $dn, $deref=LDAP_DEREF_NEVER ) {
debug_log(sprintf('get_entry_system_attrs(): Entered with (%s,%s,%s)',$ldapserver->server_id,$dn,$deref),2);
$attrs = array( 'creatorsname', 'createtimestamp', 'modifiersname',
'structuralObjectClass', 'entryUUID', 'modifytimestamp',
'subschemaSubentry', 'hasSubordinates', '+' );
$search = @ldap_read( $ldapserver->connect(), $dn, '(objectClass=*)', $attrs, 0, 0, 0, $deref );
if( ! $search )
return false;
$entry = ldap_first_entry( $ldapserver->connect(), $search );
if( ! $entry)
return false;
$attrs = ldap_get_attributes( $ldapserver->connect(), $entry );
if( ! $attrs )
return false;
if( ! isset( $attrs['count'] ) )
return false;
$count = $attrs['count'];
unset( $attrs['count'] );
$return_attrs = array();
for( $i=0; $i<$count; $i++ ) {
$attr_name = $attrs[$i];
unset( $attrs[$attr_name]['count'] );
$return_attrs[$attr_name] = $attrs[$attr_name];
}
return $return_attrs;
}
/**
* Gets the attributes/values of an entry. Returns an associative array whose
* keys are attribute value names and whose values are arrays of values for
* said attribute. Optionally, callers may specify true for the parameter
* $lower_case_attr_names to force all keys in the associate array (attribute
* names) to be lower case.
*
* Sample return value of get_object_attrs( 0, "cn=Bob,ou=pepole,dc=example,dc=com" )
*
*
* Array
* (
* [objectClass] => Array
* (
* [0] => person
* [1] => top
* )
* [cn] => Array
* (
* [0] => Bob
* )
* [sn] => Array
* (
* [0] => Jones
* )
* [dn] => Array
* (
* [0] => cn=Bob,ou=pepole,dc=example,dc=com
* )
* )
*
*
* @param object $ldapserver The LDAP Server Object of interest
* @param string $dn The distinguished name (DN) of the entry whose attributes/values to fetch.
* @param bool $lower_case_attr_names (optional) If true, all keys of the returned associative
* array will be lower case. Otherwise, they will be cased as the LDAP server returns
* them.
* @param int $deref For aliases and referrals, this parameter specifies whether to
* follow references to the referenced DN or to fetch the attributes for
* the referencing DN. See http://php.net/ldap_search for the 4 valid
* options.
* @return array
* @see get_entry_system_attrs
* @see get_object_attr
* @todo Move this to an LDAPServer object method.
*/
function get_object_attrs( $ldapserver, $dn, $lower_case_attr_names=false, $deref=LDAP_DEREF_NEVER ) {
debug_log(sprintf('get_object_attrs(): Entered with (%s,%s,%s,%s)',
$ldapserver->server_id,$dn,$lower_case_attr_names,$deref),2);
$search = @ldap_read( $ldapserver->connect(), $dn, '(objectClass=*)', array( ), 0, 0, 0, $deref );
if( ! $search )
return false;
$entry = ldap_first_entry( $ldapserver->connect(), $search );
if( ! $entry )
return false;
$attrs = ldap_get_attributes( $ldapserver->connect(), $entry );
if( ! $attrs || $attrs['count'] == 0 )
return false;
$num_attrs = $attrs['count'];
unset( $attrs['count'] );
// strip numerical inices
for( $i=0; $i<$num_attrs; $i++ )
unset( $attrs[$i] );
$return_array = array();
foreach( $attrs as $attr => $vals ) {
if( $lower_case_attr_names )
$attr = strtolower( $attr );
if( is_attr_binary( $ldapserver, $attr ) )
$vals = ldap_get_values_len( $ldapserver->connect(), $entry, $attr );
unset( $vals['count'] );
$return_array[ $attr ] = $vals;
}
ksort( $return_array );
return $return_array;
}
/**
* Returns true if the passed string $temp contains all printable
* ASCII characters. Otherwise (like if it contains binary data),
* returns false.
*/
function is_printable_str($temp) {
debug_log(sprintf('is_printable_str(): Entered with (%s)',$temp),2);
$len = strlen($temp);
for ($i=0; $i<$len; $i++) {
$ascii_val = ord( substr( $temp,$i,1 ) );
if( $ascii_val < 32 || $ascii_val > 126 )
return false;
}
return true;
}
/**
* Much like get_object_attrs(), but only returns the values for
* one attribute of an object. Example calls:
*
*
* print_r( get_object_attr( 0, "cn=Bob,ou=people,dc=example,dc=com", "sn" ) );
* // prints:
* // Array
* // (
* // [0] => "Smith"
* // )
*
* print_r( get_object_attr( 0, "cn=Bob,ou=people,dc=example,dc=com", "objectClass" ) );
* // prints:
* // Array
* // (
* // [0] => "top"
* // [1] => "person"
* // )
*
*
* @param int $server_id The ID of the server of interest
* @param string $dn The distinguished name (DN) of the entry whose attributes/values to fetch.
* @param string $attr The attribute whose value(s) to return (ie, "objectClass", "cn", "userPassword")
* @param bool $lower_case_attr_names (optional) If true, all keys of the returned associative
* array will be lower case. Otherwise, they will be cased as the LDAP server returns
* them.
* @param int $deref For aliases and referrals, this parameter specifies whether to
* follow references to the referenced DN or to fetch the attributes for
* the referencing DN. See http://php.net/ldap_search for the 4 valid
* options.
* @see get_object_attrs
* @todo Move this to an LDAPServer object method.
*/
function get_object_attr( $ldapserver, $dn, $attr, $lower_case_attr_names=false, $deref=LDAP_DEREF_NEVER ) {
debug_log(sprintf('get_object_attr(): Entered with (%s,%s,%s,%s,%s)',
$ldapserver->server_id,$dn,$attr,$lower_case_attr_names,$deref),2);
if ($lower_case_attr_names)
$attr = strtolower( $attr );
$attrs = get_object_attrs( $ldapserver, $dn, $lower_case_attr_names, $deref );
if( isset( $attrs[$attr] ) )
return $attrs[$attr];
else
return false;
//echo "get_object_attr( $server_id, $dn, $attr )
* $samba_users = ldap_search( 0, "(&(objectClass=sambaAccount)(objectClass=posixAccount))",
* "ou=People,dc=example,dc=com", array( "uid", "homeDirectory" ) );
* print_r( $samba_users );
* // prints (for example):
* // Array
* // (
* // [uid=jsmith,ou=People,dc=example,dc=com] => Array
* // (
* // [dn] => "uid=jsmith,ou=People,dc=example,dc=com"
* // [uid] => "jsmith"
* // [homeDirectory] => "\\server\jsmith"
* // )
* // [uid=byoung,ou=People,dc=example,dc=com] => Array
* // (
* // [dn] => "uid=byoung,ou=Samba,ou=People,dc=example,dc=com"
* // [uid] => "byoung"
* // [homeDirectory] => "\\server\byoung"
* // )
* // )
*
*
* WARNING: This function will use a lot of memory on large searches since the entire result set is
* stored in a single array. For large searches, you should consider sing the less memory intensive
* PHP LDAP API directly (ldap_search(), ldap_next_entry(), ldap_next_attribute(), etc).
*
* @param int $server_id The ID of the server to search on.
* @param string $filter The LDAP filter to use when searching (example: "(objectClass=*)") (see RFC 2254)
* @param string $base_dn The DN of the base of search.
* @param array $attrs An array of attributes to include in the search result (example: array( "objectClass", "uid", "sn" )).
* @param string $scope The LDAP search scope. Must be one of "base", "one", or "sub". Standard LDAP search scope.
* @param bool $sort_results Specify false to not sort results by DN or true to have the
* returned array sorted by DN (uses ksort)
* @param int $deref When handling aliases or referrals, this specifies whether to follow referrals. Must be one of
* LDAP_DEREF_ALWAYS, LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING, or LDAP_DEREF_FINDING. See the PHP LDAP API for details.
* @todo Move this to an LDAPServer object method.
*/
function pla_ldap_search( $ldapserver, $filter, $base_dn=null, $attrs=array(), $scope='sub', $sort_results=true, $deref=LDAP_DEREF_ALWAYS ) {
debug_log(sprintf('pla_ldap_search(): Entered with (%s,%s,%s,%s,%s,%s,%s)',
$ldapserver->server_id,$filter,$base_dn,count($attrs),$scope,$sort_results,$deref),2);
if( is_null($base_dn))
$base_dn = $ldapserver->getBaseDN();
switch( $scope ) {
case 'base':
$search = @ldap_read( $ldapserver->connect(false), $base_dn, $filter, $attrs, 0, 0, 0, $deref );
break;
case 'one':
$search = @ldap_list( $ldapserver->connect(false), $base_dn, $filter, $attrs, 0, 0, 0, $defef );
break;
case 'sub':
default:
$search = @ldap_search( $ldapserver->connect(false), $base_dn, $filter, $attrs, 0, 0, 0, $deref );
break;
}
if( ! $search )
return array();
$return = array();
//get the first entry identifier
if( $entry_id = ldap_first_entry($ldapserver->connect(false),$search) )
//iterate over the entries
while($entry_id) {
//get the distinguished name of the entry
$dn = ldap_get_dn($ldapserver->connect(false),$entry_id);
//get the attributes of the entry
$attrs = ldap_get_attributes($ldapserver->connect(false),$entry_id);
$return[$dn]['dn'] = $dn;
//get the first attribute of the entry
if($attr = ldap_first_attribute($ldapserver->connect(false),$entry_id,$attrs))
//iterate over the attributes
while($attr) {
if( is_attr_binary($ldapserver,$attr))
$values = ldap_get_values_len($ldapserver->connect(false),$entry_id,$attr);
else
$values = ldap_get_values($ldapserver->connect(false),$entry_id,$attr);
//get the number of values for this attribute
$count = $values['count'];
unset($values['count']);
if($count==1)
$return[$dn][$attr] = $values[0];
else
$return[$dn][$attr] = $values;
$attr = ldap_next_attribute($ldapserver->connect(false),$entry_id,$attrs);
}// end while attr
$entry_id = ldap_next_entry($ldapserver->connect(false),$entry_id);
} // end while entry_id
if( $sort_results && is_array( $return ) )
ksort( $return );
return $return;
}
/**
* Reads the query, checks all values and sets defaults.
*
* @param int $query_id The ID of the predefined query.
* @return array The fixed query or null on error
* @todo Fix base_dn processing and use getBaseDN()
* @todo expand_dn_with_base no longer knows what the base_dn is, so you need to pass it the base, need to fix this function.
*/
function get_cleaned_up_predefined_search( $query_id ) {
debug_log(sprintf('get_cleaned_up_predefined_search(): Entered with (%s)',$query_id),2);
global $ldapservers,$queries;
if( ! isset( $queries[$query_id] ) )
return null;
$query = $queries[$query_id];
if( isset( $query['server'] ) && ( is_numeric( $query['server'] ) ) )
$server_id = $query['server'];
else $server_id = 0;
$ldapserver = $ldapservers->Instance($server_id);
$base = ( isset( $query['base'] ) ) ? $query['base'] : null;
$base = expand_dn_with_base( $ldapserver, $base );
if( isset( $query['filter'] ) && strlen( trim( $query['filter'] ) ) > 0 )
$filter = $query['filter'];
else
$filter = 'objectclass=*';
$scope = isset( $query['scope'] )
&& ( in_array( $query['scope'], array( 'base', 'sub', 'one' ) ) )
? $query['scope'] : 'sub';
if( isset( $query['attributes'] ) && strlen( trim( $query['filter'] ) ) > 0 )
$attrib = $query['attributes'];
else
$attrib = "dn, cn, sn, objectClass";
return array (
'server' => $server_id, 'base' => $base,
'filter' => $filter, 'scope' => $scope, 'attributes' => $attrib );
}
/**
* Checks the specified server id for sanity. Ensures that the server is indeed in the configured
* list and active. This is used by many many scripts to ensure that valid server ID values
* are passed in POST and GET.
* @deprecated
*/
function check_server_id( $server_id ) {
global $ldapservers;
$ldapserver = $ldapservers->Instance($server_id);
if(! isset( $ldapserver->host ) || $ldapserver->host == '' )
return false;
else
return true;
}
/**
* Used to generate a random salt for crypt-style passwords. Salt strings are used
* to make pre-built hash cracking dictionaries difficult to use as the hash algorithm uses
* not only the user's password but also a randomly generated string. The string is
* stored as the first N characters of the hash for reference of hashing algorithms later.
*
* --- added 20021125 by bayu irawan
* Array
* (
* [title] => "Invalid Credentials"
* [description] => "An invalid username and/or password was supplied to the LDAP server."
* )
*
*/
function pla_verbose_error( $err_no ) {
debug_log(sprintf('pla_verbose_error(): Entered with (%s)',$err_no),2);
static $err_codes;
if( count($err_codes) > 0 ) {
if( isset( $err_codes[ $err_no ] ) )
return $err_codes[ $err_no ];
else
return array( 'title' => null, 'desc' => null );
}
$err_codes_file = LIBDIR.'ldap_error_codes.txt';
if( ! file_exists($err_codes_file))
return false;
if( ! is_readable($err_codes_file))
return false;
if( ! ($f = fopen($err_codes_file,'r')))
return false;
$contents = fread( $f, filesize( $err_codes_file ) );
fclose( $f );
$entries = array();
preg_match_all( "/0x[A-Fa-f0-9][A-Za-z0-9]\s+[0-9A-Za-z_]+\s+\"[^\"]*\"\n/", $contents, $entries );
$err_codes = array();
foreach( $entries[0] as $e ) {
$entry = array();
preg_match( "/(0x[A-Za-z0-9][A-Za-z0-9])\s+([0-9A-Za-z_]+)\s+\"([^\"]*)\"/", $e, $entry );
$hex_code = isset( $entry[1] ) ? $entry[1] : null;
$title = isset( $entry[2] ) ? $entry[2] : null;
$desc = isset( $entry[3] ) ? $entry[3] : null;
$desc = preg_replace( "/\s+/", " ", $desc );
$err_codes[ "$hex_code" ] = array( 'title' => $title, 'desc' => $desc );
}
// Sanity check
if( isset( $err_codes[ $err_no ] ) )
return $err_codes[ $err_no ];
else
return array( 'title' => null, 'desc' => null );
}
// @todo: describe this function
function support_oid_to_text($oid_id) {
debug_log(sprintf('support_oid_to_text(): Entered with (%s)',$oid_id),2);
static $oid;
if( count($oid) > 0 ) {
if( isset( $oid[ $oid_id ] ) )
return $oid[ $oid_id ];
else
return null;
}
$oid_codes_file = LIBDIR.'ldap_supported_oids.txt';
if( ! file_exists($oid_codes_file))
return false;
if( ! is_readable($oid_codes_file))
return false;
if( ! ($f = fopen($oid_codes_file,'r')))
return false;
$contents = fread( $f, filesize( $oid_codes_file ) );
fclose( $f );
$entries = array();
preg_match_all( "/[0-9]\..+\s+\"[^\"]*\"\n/", $contents, $entries );
$err_codes = array();
foreach( $entries[0] as $e ) {
$entry = array();
preg_match( "/([0-9]\.([0-9]+\.)*[0-9]+)(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?(\s+\"([^\"]*)\")?/", $e, $entry );
$oid_id_a = isset( $entry[1] ) ? $entry[1] : null;
if ($oid_id_a) {
$oid[$oid_id_a]['title'] = isset( $entry[4] ) ? $entry[4] : null;
$oid[$oid_id_a]['ref'] = isset( $entry[6] ) ? $entry[6] : null;
$desc = isset( $entry[8] ) ? $entry[8] : null;
$oid[$oid_id_a]['desc'] = preg_replace( "/\s+/", " ", $desc );
}
}
// Sanity check
if( isset( $oid[ $oid_id ] ) )
return $oid[ $oid_id ];
else
return null;
}
/**
* Prints an HTML-formatted error string. If you specify the optional
* parameters $ldap_err_msg and $ldap_err_no, this function will
* lookup the error number and display a verbose message in addition
* to the message you pass it.
*
* @param string $msg The error message to display.
* @param string $ldap_err_msg (optional) The error message supplied by the LDAP server
* @param string $ldap_err_no (optional) The hexadecimal error number string supplied by the LDAP server
* @param bool $fatal (optional) If true, phpLDAPadmin will terminate execution with the PHP die() function.
*
* @see die
* @see ldap_errno
* @see pla_verbose_error
*/
function pla_error( $msg, $ldap_err_msg=null, $ldap_err_no=-1, $fatal=true ) {
debug_log(sprintf('pla_error(): Entered with (%s,%s,%s,%s)',$msg,$ldap_err_msg,$ldap_err_no,$fatal),2);
@include_once './header.php';
global $lang, $config;
?>
'; } if( $ldap_err_no != -1 ) { $ldap_err_no = ( '0x' . str_pad( dechex( $ldap_err_no ), 2, 0, STR_PAD_LEFT ) ); $verbose_error = pla_verbose_error( $ldap_err_no ); if( $verbose_error ) { echo sprintf( $lang['ferror_number'], $ldap_err_no, $verbose_error['title']); echo ' '; echo sprintf( $lang['ferror_discription'], $verbose_error['desc']); } else { echo sprintf($lang['ferror_number_short'], $ldap_err_no); echo ' '; echo $lang['ferror_discription_short']; } syslog_err ( sprintf($lang['ferror_number_short'], $ldap_err_no) ); } ?> |