* 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) {
if (DEBUG_ENABLED)
debug_log('pla_compare_dns(): Entered with (%s,%s)',1,$dn1,$dn2);
# If pla_compare_dns is passed via a tree, then we'll just get the DN part.
if (is_array($dn1))
$dn1 = $dn1['dn'];
if (is_array($dn2))
$dn2 = $dn2['dn'];
# If they are obviously the same, return immediately
if (! 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 < count($dn1_parts) && $i < count($dn2_parts); $i++) {
/* dnX_part is of the form: "cn=joe" or "cn = joe" or "dc=example"
ie, one part of a multi-part DN. */
$dn1_part = $dn1_parts[$i];
$dn2_part = $dn2_parts[$i];
/* Each "part" consists of two sub-parts:
1. the attribute (ie, "cn" or "o")
2. the value (ie, "joe" or "example") */
$dn1_sub_parts = explode('=',$dn1_part,2);
$dn2_sub_parts = explode('=',$dn2_part,2);
$dn1_sub_part_attr = trim($dn1_sub_parts[0]);
$dn2_sub_part_attr = trim($dn2_sub_parts[0]);
if (0 != ($cmp = strcasecmp($dn1_sub_part_attr,$dn2_sub_part_attr)))
return $cmp;
$dn1_sub_part_val = trim($dn1_sub_parts[1]);
$dn2_sub_part_val = trim($dn2_sub_parts[1]);
if (0 != ($cmp = strcasecmp($dn1_sub_part_val,$dn2_sub_part_val)))
return $cmp;
}
/* If we iterated through all entries in the smaller of the two DNs
(ie, the one with fewer parts), and the entries are different sized,
then, the smaller of the two must be "less than" than the larger. */
if (count($dn1_parts) > count($dn2_parts)) {
return 1;
} elseif (count($dn2_parts) > count($dn1_parts)) {
return -1;
} else {
return 0;
}
}
/**
* Prunes off anything after the ";" in an attr name. This is useful for
* attributes that may have ";binary" appended to their names. With
* real_attr_name(), you can more easily fetch these attributes' schema
* with their "real" attribute name.
*
* @param string $attr_name The name of the attribute to examine.
* @return string
*/
function real_attr_name($attr_name) {
if (DEBUG_ENABLED)
debug_log('real_attr_name(): Entered with (%s)',1,$attr_name);
$attr_name = preg_replace('/;.*$/U','',$attr_name);
return $attr_name;
}
/**
* 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 Must turn off auto_uid|gid in template if config is disabled.
*/
function get_next_number(&$ldapserver,$startbase='',$type='uid') {
if (DEBUG_ENABLED)
debug_log('get_next_number(): Entered with (%s,%s,%s)',1,$ldapserver->server_id,$startbase,$type);
global $config,$ldapservers;
if (! $ldapservers->GetValue($ldapserver->server_id,'auto_number','enable'))
return false;
# Based on the configured mechanism, go get the next available uidNumber!
$mechanism = $ldapservers->GetValue($ldapserver->server_id,'auto_number','mechanism');
switch ($mechanism) {
case 'search' :
if (! $startbase) {
$base_dn = $ldapservers->GetValue($ldapserver->server_id,'auto_number','search_base');
if (is_null($base_dn))
pla_error(sprintf(_('You specified the "auto_uid_number_mechanism" as "search" in your
configuration for server %s, but you did not specify the
"auto_uid_number_search_base". Please specify it before proceeding.'),$ldapserver->name));
} else {
$base_dn = $startbase;
}
if (! $ldapserver->dnExists($base_dn))
pla_error(sprintf(_('Your phpLDAPadmin configuration specifies an invalid auto_uid_search_base for server %s'),$ldapserver->name));
$filter = '(|(uidNumber=*)(gidNumber=*))';
$results = array();
# Check see and use our alternate uid_dn and password if we have it.
$con = $ldapserver->connect(false,'auto_search',false,
$ldapservers->GetValue($ldapserver->server_id,'auto_number','dn'),
$ldapservers->GetValue($ldapserver->server_id,'auto_number','pass'));
if (! $con)
pla_error(sprintf(_('Unable to bind to %s with your with auto_uid credentials. Please check your configuration file.'),$ldapserver->name));
$search = $ldapserver->search($con,$base_dn,$filter,array('uidNumber','gidNumber'),'sub',false,$config->GetValue('deref','search'));
if (! is_array($search))
pla_error('Untrapped error.');
foreach ($search as $dn => $attrs) {
$attrs = array_change_key_case($attrs);
$entry = array();
switch ($type) {
case 'uid' :
if (isset($attrs['uidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['uidnumber'];
$results[] = $entry;
}
break;
case 'gid' :
if (isset($attrs['gidnumber'])) {
$entry['dn'] = $attrs['dn'];
$entry['uniqnumber'] = $attrs['gidnumber'];
$results[] = $entry;
}
break;
default :
pla_error(sprintf('Unknown type [%s] in search',$type));
}
}
# construct a list of used numbers
$autonum = array();
foreach ($results as $result)
if (isset($result['uniqnumber']))
$autonum[] = $result['uniqnumber'];
$autonum = array_unique($autonum);
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( _('You specified an invalid value for auto_uid_number_mechanism ("%s")
in your configration. Only "uidpool" and "search" are valid.
Please correct this problem.') , $mechanism) );
}
}
/**
* 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 ) {
if (DEBUG_ENABLED)
debug_log('get_icon(): Entered with (%s,%s)',1,$ldapserver->server_id,$dn);
// fetch and lowercase all the objectClasses in an array
$object_classes = $ldapserver->getDNAttr($dn,'objectClass',true);
if (! is_array($object_classes))
$object_classes = array($object_classes);
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';
}
/**
* Appends a servers base to a "sub" dn or returns the base.
*
* @param string $base The baseDN to be added if the DN is relative
* @param string $sub_dn The DN to be made absolute
* @return string|null Returns null if both base is null and sub_dn is null or empty
*/
function expand_dn_with_base( $base,$sub_dn ) {
if (DEBUG_ENABLED)
debug_log('expand_dn_with_base(): Entered with (%s,%s)',1,$base,$sub_dn);
$empty_str = ( is_null($sub_dn) || ( ( $len = strlen( trim( $sub_dn ) ) ) == 0 ) );
if ( $empty_str ) {
return $base;
} elseif ( $sub_dn[$len - 1] != ',' ) {
// If we have a string which doesn't need a base
return $sub_dn;
} else {
return $sub_dn . $base;
}
}
/**
* 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() {
global $ldapservers;
$return = array();
foreach ($ldapservers->GetServerList() as $id) {
if (! trim($ldapservers->GetValue($id,'server','host')))
continue;
$return[$id] = array();
}
if (DEBUG_ENABLED)
debug_log('build_initial_tree(): Entered with (), Returning (%s)',1,$return);
return $return;
}
/**
* 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) {
if (DEBUG_ENABLED)
debug_log('is_printable_str(): Entered with (%s)',1,$temp);
$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;
}
/**
* 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
*/
function get_cleaned_up_predefined_search($query_id) {
if (DEBUG_ENABLED)
debug_log('get_cleaned_up_predefined_search(): Entered with (%s)',1,$query_id);
global $queries;
if (! isset($queries[$query_id]))
return null;
$query = $queries[$query_id];
$base = (isset($query['base'])) ? $query['base'] : null;
if (isset($query['filter']) && trim($query['filter']))
$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']) && trim($query['filter']))
$attrib = $query['attributes'];
else
$attrib = 'dn, cn, sn, objectClass';
return array('base'=>$base,'filter'=>$filter,'scope'=>$scope,'attributes'=>$attrib);
}
/**
* 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 '; } 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( _('Error number: %s (%s)'), $ldap_err_no, $verbose_error['title']); echo ' '; echo sprintf( _('Description: %s '), $verbose_error['desc']); } else { echo sprintf(_('Error number: %s '), $ldap_err_no); echo ' '; echo _('Description: (no description available) '); } if (function_exists('syslog_err')) syslog_err(sprintf(_('Error number: %s '),$ldap_err_no)); } ?> |