2009-06-30 09:29:51 +00:00
< ? php
2009-06-30 10:26:08 +00:00
/* $Header: /cvsroot/phpldapadmin/phpldapadmin/lib/server_functions.php,v 1.34.2.24 2006/01/15 13:05:52 wurley Exp $ */
2009-06-30 09:29:51 +00:00
/**
* Classes and functions for LDAP server configuration and capability
*
* @ author The phpLDAPadmin development team
* @ package phpLDAPadmin
*/
/**
* @ package phpLDAPadmin
*/
2009-06-30 09:40:37 +00:00
class LDAPserver {
2009-06-30 09:29:51 +00:00
/** Server ID as defined in config.php */
var $server_id ;
/** Server Name as defined in config.php */
var $name ;
/** Server Hostname as defined in config.php */
var $host ;
/** Server Port as defined in config.php */
var $port ;
/** Server Authentication method as defined in config.php */
var $auth_type ;
/** Server Authentication Login DN as defined in config.php */
var $login_dn ;
/** Server Authentication Password as defined in config.php */
var $login_pass ;
/** Array of our connections to this LDAP server */
var $connections = array ();
/** Server Base Dn */
var $_baseDN ;
2009-06-30 09:40:37 +00:00
/** Schema DN */
var $_schemaDN = null ;
/** Raw Schema entries */
var $_schema_entries = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:29:51 +00:00
/** Default constructor .
* @ param int $server_id the server_id of the LDAP server as defined in config . php
*/
2009-06-30 09:40:37 +00:00
function LDAPserver ( $server_id ) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::__construct(): Entered with (%s)' , 17 , get_class ( $this ), $server_id );
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
$this -> _baseDN = null ;
2009-06-30 09:29:51 +00:00
$this -> server_id = $server_id ;
}
/**
* 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 .
*
* @ param int $server_id the server_id of the LDAP server as defined in config . php
* @ return bool
*/
function isValidServer () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isValidServer(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( trim ( $this -> host ))
2009-06-30 09:29:51 +00:00
return true ;
2009-06-30 09:40:37 +00:00
else
return false ;
2009-06-30 09:29:51 +00:00
}
/**
* Check if there is sufficent information to Authenticate to the LDAP server .
*
* Given a server , 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
2009-06-30 10:26:08 +00:00
* the specified server . If the auth_type is session or cookie , then getLoggedInDN () is
2009-06-30 09:29:51 +00:00
* called to verify that the user has logged in . If the auth_type is config , then the
* $ldapservers configuration 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 .
*
* @ return bool
2009-06-30 10:26:08 +00:00
* @ see getLoggedInDN
2009-06-30 09:29:51 +00:00
*/
function haveAuthInfo () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED ) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::haveAuthInfo(): Entered with ()' , 17 , get_class ( $this ));
debug_log ( '%s::haveAuthInfo(): We are a (%s) auth_type' , 80 , get_class ( $this ), $this -> auth_type );
2009-06-30 09:40:37 +00:00
}
2009-06-30 09:29:51 +00:00
# Set default return
$return = false ;
# For session or cookie auth_types, we check the session or cookie to see if a user has logged in.
if ( in_array ( $this -> auth_type , array ( 'session' , 'cookie' ))) {
2009-06-30 10:26:08 +00:00
/* we don ' t look at getLoggedInPass () cause it may be null for anonymous binds
getLoggedInDN () will never return null if someone is really logged in . */
if ( $this -> getLoggedInDN ())
2009-06-30 09:29:51 +00:00
$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 ) */
2009-06-30 09:40:37 +00:00
} elseif ( $this -> auth_type == 'config' ) {
2009-06-30 09:29:51 +00:00
$return = true ;
} else {
2009-06-30 10:26:08 +00:00
pla_error ( sprintf ( _ ( 'Error: You have an error in your config file. The only three allowed values for auth_type in the $servers section are \'session\', \'cookie\', and \'config\'. You entered \'%s\', which is not allowed.' ), htmlspecialchars ( $this -> auth_type )));
2009-06-30 09:29:51 +00:00
}
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::haveAuthInfo(): Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
function _connect ( $connect_name ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::_connect(): Entered with (%s)' , 17 , get_class ( $this ), $connect_name );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
if ( isset ( $this -> connections [ $connect_name ][ 'resource' ])) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::_connect(): Returning CACHED connection resource [%s](%s)' , 16 ,
get_class ( $this ), $this -> connections [ $connect_name ][ 'resource' ], $connect_name );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
return $this -> connections [ $connect_name ][ 'resource' ];
2009-06-30 09:40:37 +00:00
}
return false ;
}
2009-06-30 09:29:51 +00:00
/**
* Connect to the LDAP server .
2009-06-30 10:26:08 +00:00
*
* @ param bool $process_error Whether to call an error page , if the connection fails
* @ param bool $connect_id The ID for this connection
2009-06-30 09:29:51 +00:00
* @ param bool $reconnect Use a cached connetion , or create a new one .
* @ returns resource | false Connection resource to LDAP server , or false if no connection made .
*/
2009-06-30 10:26:08 +00:00
function connect ( $process_error = true , $connect_id = 'user' , $reconnect = false , $dn = null , $pass = null ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Entered with (%s,%s,%s)' , 17 ,
get_class ( $this ), $process_error , $connect_id , $reconnect );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
# Quick return if we have already connected.
$resource = $this -> _connect ( $connect_id );
if ( $resource && ! $reconnect )
2009-06-30 09:40:37 +00:00
return $resource ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Creating new connection [%s] for Server ID [%s]' , 16 ,
get_class ( $this ), $connect_id , $this -> server_id );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
# grab the auth info based on the auth_type for this server
if ( $connect_id == 'anonymous' ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): This IS an anonymous login' , 80 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
$this -> connections [ $connect_id ][ 'login_dn' ] = null ;
$this -> connections [ $connect_id ][ 'login_pass' ] = null ;
2009-06-30 09:40:37 +00:00
} elseif ( $this -> auth_type == 'config' ) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): This IS a "config" login' , 80 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
if ( ! $this -> login_dn ) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): No login_dn, so well do anonymous' , 80 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
$connect_id = 'anonymous' ;
2009-06-30 09:40:37 +00:00
} else {
2009-06-30 10:26:08 +00:00
$this -> connections [ $connect_id ][ 'login_dn' ] = $this -> login_dn ;
$this -> connections [ $connect_id ][ 'login_pass' ] = $this -> login_pass ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Config settings, DN [%s], PASS [%s]' , 80 ,
get_class ( $this ), $this -> connections [ $connect_id ][ 'login_dn' ],
$this -> connections [ $connect_id ][ 'login_pass' ] ? md5 ( $this -> connections [ $connect_id ][ 'login_pass' ]) : '' );
2009-06-30 09:40:37 +00:00
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:29:51 +00:00
} else {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): This IS some other login' , 80 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
# Did we pass the dn/pass to this function?
if ( $dn ) {
$this -> connections [ $connect_id ][ 'login_dn' ] = $dn ;
$this -> connections [ $connect_id ][ 'login_pass' ] = $pass ;
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
# Was this an anonyous bind (the cookie stores 0 if so)?
} elseif ( $this -> getLoggedInDN () == 'anonymous' ) {
$connect_id = 'anonymous' ;
$this -> connections [ $connect_id ][ 'login_dn' ] = null ;
$this -> connections [ $connect_id ][ 'login_pass' ] = null ;
} else {
$this -> connections [ $connect_id ][ 'login_dn' ] = $this -> getLoggedInDN ();
$this -> connections [ $connect_id ][ 'login_pass' ] = $this -> getLoggedInPass ();
}
2009-06-30 09:40:37 +00:00
}
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( DEBUG_ENABLED )
debug_log ( '%s::connect(): Config settings, DN [%s], PASS [%s]' , 80 ,
get_class ( $this ), $this -> connections [ $connect_id ][ 'login_dn' ],
$this -> connections [ $connect_id ][ 'login_pass' ] ? md5 ( $this -> connections [ $connect_id ][ 'login_pass' ]) : '' );
if ( $connect_id != 'anonymous' && ! $this -> connections [ $connect_id ][ 'login_dn' ] && ! $this -> connections [ $connect_id ][ 'login_pass' ]) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): We dont have enough auth info for server [%s]' , 80 , get_class ( $this ), $this -> server_id );
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
return false ;
}
2009-06-30 10:26:08 +00:00
# Now that we have worked out the connect_id, lets just check and see if we have already connected.
$resource = $this -> _connect ( $connect_id );
if ( $resource && ! $reconnect )
return $resource ;
run_hook ( 'pre_connect' , array ( 'server_id' => $this -> server_id , 'connect_id' => $connect_id ));
2009-06-30 09:40:37 +00:00
if ( $this -> port )
2009-06-30 10:26:08 +00:00
$resource = @ ldap_connect ( $this -> host , $this -> port );
2009-06-30 09:40:37 +00:00
else
2009-06-30 10:26:08 +00:00
$resource = @ ldap_connect ( $this -> host );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): LDAP Resource [%s], Host [%s], Port [%s]' , 16 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), $resource , $this -> host , $this -> port );
2009-06-30 10:26:08 +00:00
# Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
@ ldap_set_option ( $resource , LDAP_OPT_PROTOCOL_VERSION , 3 );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
/* Disabling this makes it possible to browse the tree for Active Directory , and seems
to not affect other LDAP servers ( tested with OpenLDAP ) as phpLDAPadmin explicitly
specifies deref behavior for each ldap_search operation . */
@ ldap_set_option ( $resource , LDAP_OPT_REFERRALS , 0 );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
# Try to fire up TLS is specified in the config
if ( $this -> isTLSEnabled ()) {
function_exists ( 'ldap_start_tls' ) or pla_error ( _ ( 'Your PHP install does not support TLS.' ));
@ ldap_start_tls ( $resource ) or pla_error ( _ ( 'Could not start TLS. Please check your LDAP server configuration.' ), ldap_error ( $resource ));
2009-06-30 09:40:37 +00:00
}
2009-06-30 10:26:08 +00:00
$bind_result = @ ldap_bind ( $resource , $this -> connections [ $connect_id ][ 'login_dn' ],
$this -> connections [ $connect_id ][ 'login_pass' ]);
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Resource [%s], Bind Result [%s]' , 16 , get_class ( $this ), $resource , $bind_result );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
if ( ! $bind_result ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Leaving with FALSE, bind FAILed' , 16 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
if ( $process_error ) {
2009-06-30 10:26:08 +00:00
switch ( ldap_errno ( $resource )) {
case 0x31 :
pla_error ( _ ( 'Bad username or password. Please try again.' ));
break ;
case 0x32 :
pla_error ( _ ( 'Insufficient access rights.' ));
break ;
case - 1 :
pla_error ( sprintf ( _ ( 'Could not connect to "%s" on port "%s"' ), $this -> host , $this -> port ));
break ;
default :
pla_error ( _ ( 'Could not bind to the LDAP server.' ), ldap_err2str ( $resource ), $resource );
2009-06-30 09:40:37 +00:00
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
} else {
2009-06-30 10:26:08 +00:00
return false ;
2009-06-30 09:40:37 +00:00
}
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( is_resource ( $resource ) && ( $bind_result )) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Bind successful' , 16 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
$this -> connections [ $connect_id ][ 'resource' ] = $resource ;
2009-06-30 09:29:51 +00:00
}
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::connect(): Leaving with Connect [%s], Resource [%s]' , 16 ,
get_class ( $this ), $connect_id , $this -> connections [ $connect_id ][ 'resource' ]);
return $this -> connections [ $connect_id ][ 'resource' ];
2009-06-30 09:40:37 +00:00
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:29:51 +00:00
/**
* Gets the root DN of the specified LDAPServer , or null if it
* can 't find it (ie, the server won' t give it to us , or it isnt
* specified in the configuration file ) .
*
* Tested with OpenLDAP 2.0 , Netscape iPlanet , and Novell eDirectory 8.7 ( nldap . com )
* Please report any and all bugs !!
*
* Please note : On FC systems , it seems that php_ldap uses / etc / openldap / ldap . conf in
* the search base if it is blank - so edit that file and comment out the BASE line .
*
* @ return array dn | null The root DN of the server on success ( string ) or null on error .
* @ todo Sort the entries , so that they are in the correct DN order .
*/
function getBaseDN () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
global $ldapservers ;
# Return the cached entry if we've been here before.
if ( ! is_null ( $this -> _baseDN )) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): Return CACHED BaseDN [%s]' , 17 , get_class ( $this ), implode ( '|' , $this -> _baseDN ));
2009-06-30 09:29:51 +00:00
return $this -> _baseDN ;
}
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): Checking config for BaseDN' , 80 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
# If the base is set in the configuration file, then just return that.
if ( count ( $ldapservers -> GetValue ( $this -> server_id , 'server' , 'base' )) > 0 ) {
$this -> _baseDN = $ldapservers -> GetValue ( $this -> server_id , 'server' , 'base' );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): Return BaseDN from Config [%s]' , 17 , get_class ( $this ), implode ( '|' , $this -> _baseDN ));
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $this -> _baseDN ;
# We need to figure it out.
} else {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): Connect to LDAP to find BaseDN' , 80 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
if ( $this -> connect ()) {
2009-06-30 10:26:08 +00:00
$r = array_pop ( $this -> search ( null , '' , 'objectClass=*' , array ( 'namingContexts' ), 'base' ));
$r = array_change_key_case ( $r );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
if ( isset ( $r [ 'namingcontexts' ])) {
if ( ! is_array ( $r [ 'namingcontexts' ]))
$r [ 'namingcontexts' ] = array ( $r [ 'namingcontexts' ]);
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getBaseDN(): LDAP Entries:%s' , 80 , get_class ( $this ), implode ( '|' , $r [ 'namingcontexts' ]));
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
$this -> _baseDN = $r [ 'namingcontexts' ];
2009-06-30 09:29:51 +00:00
return $this -> _baseDN ;
} else {
return array ( '' );
}
} else {
return array ( '' );
}
}
}
/**
* 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
2009-06-30 10:26:08 +00:00
* < code >
* $config -> custom -> appearance [ 'anonymous_bind_implies_read_only' ] = true ;
* </ code >
* then this also returns true . Servers can be configured read - only in
2009-06-30 09:29:51 +00:00
* config . php thus :
* < code >
2009-06-30 10:26:08 +00:00
* $ldapservers -> SetValue ( $i , 'server' , 'read_only' , false );
2009-06-30 09:29:51 +00:00
* </ code >
*
* @ return bool
*/
function isReadOnly () {
global $config ;
# Set default return
$return = false ;
if ( $this -> read_only == true )
$return = true ;
2009-06-30 10:26:08 +00:00
elseif ( $this -> getLoggedInDN () === 'anonymous' &&
2009-06-30 09:29:51 +00:00
( $config -> GetValue ( 'appearance' , 'anonymous_bind_implies_read_only' ) === true ))
$return = true ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isReadOnly(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
/**
* Returns true if the user has configured the specified server to enable mass deletion .
*
* Mass deletion is enabled in config . php this :
* < code >
2009-06-30 10:26:08 +00:00
* $config -> custom -> appearance [ 'mass_delete' ] = true ;
2009-06-30 09:29:51 +00:00
* </ code >
* Notice that mass deletes are not enabled on a per - server basis , but this
* function checks that the server is not in a read - only state as well .
*
* @ return bool
*/
function isMassDeleteEnabled () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isMassDeleteEnabled(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
global $config ;
2009-06-30 10:26:08 +00:00
if ( $this -> connect ( false ) && $this -> haveAuthInfo () && ! $this -> isReadOnly () &&
! $config -> GetValue ( 'appearance' , 'tree_plm' )) {
$config -> GetValue ( 'appearance' , 'mass_delete' ) === true ;
2009-06-30 09:29:51 +00:00
return true ;
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
} else
2009-06-30 09:29:51 +00:00
return false ;
}
/**
* Gets whether the admin has configured phpLDAPadmin to show the " Create New " link in the tree viewer .
* < code >
2009-06-30 10:26:08 +00:00
* $ldapservers -> SetValue ( $i , 'appearance' , 'show_create' , 'true|false' );
2009-06-30 09:29:51 +00:00
* </ code >
* If NOT set , then default to show the Create New item .
* If IS set , then return the value ( it should be true or false ) .
*
* @ default true
* @ return bool True if the feature is enabled and false otherwise .
*/
function isShowCreateEnabled () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isShowCreateEnabled(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
return $this -> show_create ;
}
/**
* Fetch whether the user has configured a certain server as " low bandwidth " .
*
* Users may choose to configure a server as " low bandwidth " in config . php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'server' , 'low_bandwidth' , 'true|false' );
* </ code >
*
* @ default false
* @ return bool
*/
function isLowBandwidth () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isLowBandwidth(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
return $this -> low_bandwidth ;
}
/**
* Should this LDAP server be shown in the tree ?
*
* < code >
* $ldapservers -> SetValue ( $i , 'server' , 'visible' , 'true|false' );
* </ code >
*
* @ default true
* @ return bool True if the feature is enabled and false otherwise .
*/
function isVisible () {
2009-06-30 09:40:37 +00:00
if ( $this -> isValidServer () && $this -> visible )
2009-06-30 09:29:51 +00:00
$return = true ;
else
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isVisible(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
/**
* This function will query the ldap server and request the subSchemaSubEntry which should be the Schema DN .
*
* If we cant connect to the LDAP server , we ' ll return false .
* If we can connect but cant get the entry , then we ' ll return null .
*
* @ return array | false Schema if available , null if its not or false if we cant connect .
*/
function getSchemaDN ( $dn = '' ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Entered with (%s)' , 25 , get_class ( $this ), $dn );
2009-06-30 09:29:51 +00:00
# If we already got the SchemaDN, then return it.
if ( $this -> _schemaDN )
return $this -> _schemaDN ;
if ( ! $this -> connect ())
return false ;
$search = @ ldap_read ( $this -> connect (), $dn , 'objectClass=*' , array ( 'subschemaSubentry' ));
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Search returned (%s)' , 24 , get_class ( $this ), is_resource ( $search ));
2009-06-30 09:29:51 +00:00
# Fix for broken ldap.conf configuration.
if ( ! $search && ! $dn ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Trying to find the DN for "broken" ldap.conf' , 80 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
if ( isset ( $this -> _baseDN )) {
foreach ( $this -> _baseDN as $base ) {
$search = @ ldap_read ( $this -> connect (), $base , 'objectClass=*' , array ( 'subschemaSubentry' ));
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Search returned (%s) for base (%s)' , 24 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), is_resource ( $search ), $base );
if ( $search )
break ;
2009-06-30 09:29:51 +00:00
}
}
}
if ( ! $search )
return null ;
if ( ! @ ldap_count_entries ( $this -> connect (), $search )) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Search returned 0 entries. Returning NULL' , 25 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return null ;
}
$entries = @ ldap_get_entries ( $this -> connect (), $search );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Search returned [%s]' , 24 , get_class ( $this ), $entries );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
if ( ! $entries || ! is_array ( $entries ))
return null ;
$entry = isset ( $entries [ 0 ]) ? $entries [ 0 ] : false ;
if ( ! $entry ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Entry is false, Returning NULL' , 80 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return null ;
}
$sub_schema_sub_entry = isset ( $entry [ 0 ]) ? $entry [ 0 ] : false ;
if ( ! $sub_schema_sub_entry ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Sub Entry is false, Returning NULL' , 80 , get_class ( $this ));
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return null ;
}
$this -> _schemaDN = isset ( $entry [ $sub_schema_sub_entry ][ 0 ]) ? $entry [ $sub_schema_sub_entry ][ 0 ] : false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaDN(): Returning (%s)' , 25 , get_class ( $this ), $this -> _schemaDN );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $this -> _schemaDN ;
}
/**
* Fetches the raw schema array for the subschemaSubentry of the server . Note ,
* this function has grown many hairs to accomodate more LDAP servers . It is
* needfully complicated as it now supports many popular LDAP servers that
* don ' t necessarily expose their schema " the right way " .
*
* Please note : On FC systems , it seems that php_ldap uses / etc / openldap / ldap . conf in
* the search base if it is blank - so edit that file and comment out the BASE line .
*
* @ param string $schema_to_fetch - A string indicating which type of schema to
* fetch . Five valid values : 'objectclasses' , 'attributetypes' ,
* 'ldapsyntaxes' , 'matchingruleuse' , or 'matchingrules' .
* Case insensitive .
* @ param dn $dn ( optional ) This paremeter is the DN of the entry whose schema you
* would like to fetch . Entries have the option of specifying
* their own subschemaSubentry that points to the DN of the system
* schema entry which applies to this attribute . If unspecified ,
* this will try to retrieve the schema from the RootDSE subschemaSubentry .
* Failing that , we use some commonly known schema DNs . Default
* value is the Root DSE DN ( zero - length string )
* @ return array an array of strings of this form :
2009-06-30 10:26:08 +00:00
* Array (
* [ 0 ] => " (1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...
* [ 1 ] => " (1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...
* etc .
2009-06-30 09:29:51 +00:00
*/
function getRawSchema ( $schema_to_fetch , $dn = '' ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Entered with (%s,%s)' , 25 , get_class ( $this ), $schema_to_fetch , $dn );
2009-06-30 09:29:51 +00:00
$valid_schema_to_fetch = array ( 'objectclasses' , 'attributetypes' , 'ldapsyntaxes' , 'matchingrules' , 'matchingruleuse' );
if ( ! $this -> connect ())
return false ;
# error checking
$schema_to_fetch = strtolower ( $schema_to_fetch );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( ! is_null ( $this -> _schema_entries ) && isset ( $this -> _schema_entries [ $schema_to_fetch ])) {
2009-06-30 10:26:08 +00:00
$schema = $this -> _schema_entries [ $schema_to_fetch ];
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning CACHED (%s)' , 25 , get_class ( $this ), $schema );
2009-06-30 09:40:37 +00:00
return $schema ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:29:51 +00:00
# This error message is not localized as only developers should ever see it
if ( ! in_array ( $schema_to_fetch , $valid_schema_to_fetch ))
pla_error ( sprintf ( 'Bad parameter provided to function to %s::getRawSchema(). "%s" is not valid for the schema_to_fetch parameter.' ,
2009-06-30 10:26:08 +00:00
get_class ( $this ), htmlspecialchars ( $schema_to_fetch )));
2009-06-30 09:29:51 +00:00
# Try to get the schema DN from the specified entry.
$schema_dn = $this -> getSchemaDN ( $dn );
# Do we need to try again with the Root DSE?
if ( ! $schema_dn )
$schema_dn = $this -> getSchemaDN ( '' );
# Store the eventual schema retrieval in $schema_search
$schema_search = null ;
if ( $schema_dn ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Using Schema DN (%s)' , 24 , get_class ( $this ), $schema_dn );
2009-06-30 09:29:51 +00:00
foreach ( array ( '(objectClass=*)' , '(objectClass=subschema)' ) as $schema_filter ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Looking for schema with Filter (%s)' , 24 , get_class ( $this ), $schema_filter );
2009-06-30 09:29:51 +00:00
$schema_search = @ ldap_read ( $this -> connect (), $schema_dn , $schema_filter , array ( $schema_to_fetch ), 0 , 0 , 0 , LDAP_DEREF_ALWAYS );
2009-06-30 09:40:37 +00:00
if ( is_null ( $schema_search ))
2009-06-30 10:26:08 +00:00
continue ;
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
$schema_entries = @ ldap_get_entries ( $this -> connect (), $schema_search );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Search returned [%s]' , 24 , get_class ( $this ), $schema_entries );
2009-06-30 09:40:37 +00:00
2009-06-30 10:26:08 +00:00
if ( is_array ( $schema_entries ) && isset ( $schema_entries [ 'count' ])) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Found schema with filter of (%s)' , 24 , get_class ( $this ), $schema_filter );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
break ;
}
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Didnt find schema with filter (%s)' , 24 , get_class ( $this ), $schema_filter );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
unset ( $schema_entries );
$schema_search = null ;
}
}
/* Second chance : If the DN or Root DSE didn ' t give us the subschemaSubentry , ie $schema_search
is still null , use some common subSchemaSubentry DNs as a work - around . */
2009-06-30 09:40:37 +00:00
if ( is_null ( $schema_search )) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Attempting work-arounds for "broken" LDAP servers...' , 24 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
foreach ( $this -> getBaseDN () as $base ) {
$ldap [ 'W2K3 AD' ][ expand_dn_with_base ( $base , 'cn=Aggregate,cn=Schema,cn=configuration,' )] = '(objectClass=*)' ;
$ldap [ 'W2K AD' ][ expand_dn_with_base ( $base , 'cn=Schema,cn=configuration,' )] = '(objectClass=*)' ;
$ldap [ 'W2K AD' ][ expand_dn_with_base ( $base , 'cn=Schema,ou=Admin,' )] = '(objectClass=*)' ;
}
2009-06-30 10:26:08 +00:00
# OpenLDAP and Novell
2009-06-30 09:29:51 +00:00
$ldap [ 'OpenLDAP' ][ 'cn=subschema' ] = '(objectClass=*)' ;
foreach ( $ldap as $ldap_server_name => $ldap_options ) {
foreach ( $ldap_options as $ldap_dn => $ldap_filter ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Attempting [%s] (%s) (%s)<BR>' , 24 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), $ldap_server_name , $ldap_dn , $ldap_filter );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
$schema_search = @ ldap_read ( $this -> connect (), $ldap_dn , $ldap_filter ,
array ( $schema_to_fetch ), 0 , 0 , 0 , LDAP_DEREF_ALWAYS );
2009-06-30 09:40:37 +00:00
if ( is_null ( $schema_search ))
2009-06-30 10:26:08 +00:00
continue ;
2009-06-30 09:40:37 +00:00
$schema_entries = @ ldap_get_entries ( $this -> connect (), $schema_search );
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Search returned [%s]' , 24 , get_class ( $this ), $schema_entries );
2009-06-30 09:40:37 +00:00
if ( $schema_entries && isset ( $schema_entries [ 0 ][ $schema_to_fetch ])) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Found schema with filter of (%s)' , 24 , get_class ( $this ), $ldap_filter );
2009-06-30 09:40:37 +00:00
break ;
}
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Didnt find schema with filter (%s)' , 24 , get_class ( $this ), $ldap_filter );
2009-06-30 09:40:37 +00:00
unset ( $schema_entries );
$schema_search = null ;
}
2009-06-30 09:29:51 +00:00
if ( $schema_search )
break ;
}
2009-06-30 09:40:37 +00:00
}
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( is_null ( $schema_search )) {
2009-06-30 10:26:08 +00:00
/* Still cant find the schema , try with the RootDSE
Attempt to pull schema from Root DSE with scope " base " , or
Attempt to pull schema from Root DSE with scope " one " ( work - around for Isode M - Vault X . 500 / LDAP ) */
2009-06-30 09:29:51 +00:00
foreach ( array ( 'base' , 'one' ) as $ldap_scope ) {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Attempting to find schema with scope (%s), filter (objectClass=*) and a blank base.' , 24 ,
get_class ( $this ), $ldap_scope );
2009-06-30 09:29:51 +00:00
switch ( $ldap_scope ) {
case 'base' :
2009-06-30 09:40:37 +00:00
$schema_search = @ ldap_read ( $this -> connect (), '' , '(objectClass=*)' , array ( $schema_to_fetch ), 0 , 0 , 0 , LDAP_DEREF_ALWAYS );
2009-06-30 09:29:51 +00:00
break ;
case 'one' :
2009-06-30 09:40:37 +00:00
$schema_search = @ ldap_list ( $this -> connect (), '' , '(objectClass=*)' , array ( $schema_to_fetch ), 0 , 0 , 0 , LDAP_DEREF_ALWAYS );
2009-06-30 09:29:51 +00:00
break ;
}
2009-06-30 09:40:37 +00:00
if ( is_null ( $schema_search ))
2009-06-30 10:26:08 +00:00
continue ;
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
$schema_entries = @ ldap_get_entries ( $this -> connect (), $schema_search );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Search returned [%s]' , 24 , get_class ( $this ), $schema_entries );
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( $schema_entries && isset ( $schema_entries [ 0 ][ $schema_to_fetch ])) {
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Found schema with filter of (%s)' , 24 , get_class ( $this ), '(objectClass=*)' );
2009-06-30 09:29:51 +00:00
break ;
2009-06-30 09:40:37 +00:00
}
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Didnt find schema with filter (%s)' , 24 , get_class ( $this ), '(objectClass=*)' );
2009-06-30 09:40:37 +00:00
unset ( $schema_entries );
$schema_search = null ;
2009-06-30 09:29:51 +00:00
}
}
2009-06-30 09:40:37 +00:00
$schema_error_message = 'Please contact the phpLDAPadmin developers and let them know:<ul><li>Which LDAP server you are running, including which version<li>What OS it is running on<li>Which version of PHP<li>As well as a link to some documentation that describes how to obtain the SCHEMA information</ul><br />We\'ll then add support for your LDAP server in an upcoming release.' ;
2009-06-30 09:29:51 +00:00
$schema_error_message_array = array ( 'objectclasses' , 'attributetypes' );
# Shall we just give up?
if ( is_null ( $schema_search )) {
# We need to have objectclasses and attribues, so display an error, asking the user to get us this information.
if ( in_array ( $schema_to_fetch , $schema_error_message_array )) {
pla_error ( sprintf ( 'Our attempts to find your SCHEMA for "%s" have FAILED.<br /><br />%s' , $schema_to_fetch , $schema_error_message ));
} else {
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning because schema_search is NULL (%s)' , 25 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
}
# Did we get something unrecognizable?
if ( gettype ( $schema_search ) != 'resource' ) {
if ( in_array ( $schema_to_fetch , $schema_error_message_array )) {
2009-06-30 10:26:08 +00:00
pla_error ( sprintf ( 'Our attempts to find your SCHEMA for "%s" has return UNEXPECTED results.<br /><br /><small>(We expected a "resource" for $schema_search, instead, we got (%s))</small><br /><br />%s<br /><br />Dump of $schema_search:<hr /><pre><small>%s</small></pre>' ,
2009-06-30 09:29:51 +00:00
$schema_to_fetch , gettype ( $schema_search ), $schema_error_message , serialize ( $schema_search )));
} else {
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning because schema_search type is not a resource (%s)' , 25 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), $return );
2009-06-30 09:29:51 +00:00
return $return ;
}
}
2009-06-30 09:40:37 +00:00
if ( ! $schema_entries ) {
2009-06-30 09:29:51 +00:00
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning false since ldap_get_entries() returned false.' , 25 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), $return );
2009-06-30 09:29:51 +00:00
return $return ;
}
2009-06-30 09:40:37 +00:00
if ( ! isset ( $schema_entries [ 0 ][ $schema_to_fetch ])) {
2009-06-30 09:29:51 +00:00
if ( in_array ( $schema_to_fetch , $schema_error_message_array )) {
2009-06-30 10:26:08 +00:00
pla_error ( sprintf ( 'Our attempts to find your SCHEMA for "%s" has return UNEXPECTED results.<br /><br /><small>(We expected a "%s" in the $schema array but it wasnt there.)</small><br /><br />%s<br /><br />Dump of $schema_search:<hr /><pre><small>%s</small></pre>' ,
2009-06-30 09:40:37 +00:00
$schema_to_fetch , gettype ( $schema_search ), $schema_error_message , serialize ( $schema_entries )));
2009-06-30 09:29:51 +00:00
} else {
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning because (%s) isnt in the schema array. (%s)' , 25 ,
2009-06-30 09:40:37 +00:00
get_class ( $this ), $schema_to_fetch , $return );
2009-06-30 09:29:51 +00:00
return $return ;
}
}
/* Make a nice array of this form :
2009-06-30 10:26:08 +00:00
Array (
[ 0 ] => " (1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' DESC 'Pool ...) "
[ 1 ] => " (1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Sa ...) "
etc . ) */
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
$schema = $schema_entries [ 0 ][ $schema_to_fetch ];
2009-06-30 09:29:51 +00:00
unset ( $schema [ 'count' ]);
2009-06-30 10:26:08 +00:00
$this -> _schema_entries [ $schema_to_fetch ] = $schema ;
2009-06-30 09:29:51 +00:00
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getRawSchema(): Returning (%s)' , 25 , get_class ( $this ), $schema );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $schema ;
}
/**
* Fetches whether the login_attr feature is enabled for a specified server .
*
* This is configured in config . php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'login' , 'attr' , '<ldap attr>' );
* </ code >
*
* By virtue of the fact that the login_attr is not blank and not 'dn' , the
* feature is configured to be enabled .
*
* @ default uid
* @ return bool
*/
function isLoginAttrEnabled () {
if (( strcasecmp ( $this -> login_attr , 'dn' ) != 0 ) && trim ( $this -> login_attr ))
$return = true ;
else
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isLoginAttrEnabled(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
/**
* Fetches whether the login_attr feature is enabled for a specified server .
*
* This is configured in config . php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'login' , 'attr' , 'string' );
* </ code >
*
* @ return bool
*/
function isLoginStringEnabled () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isLoginStringEnabled(): login_attr is [%s]' , 80 , get_class ( $this ), $this -> login_attr );
2009-06-30 09:29:51 +00:00
if ( ! strcasecmp ( $this -> login_attr , 'string' ))
$return = true ;
else
$return = false ;
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isLoginStringEnabled(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
/**
* Fetches the login_attr string if enabled for a specified server .
*
* This is configured in config . php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'login' , 'login_string' , 'uid=<username>,ou=People,dc=example,dc=com' );
* </ code >
*
* @ return string | false
*/
function getLoginString () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getLoginString(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
return $this -> login_string ;
}
/**
* Fetch whether the user has configured a certain server login to be non anonymous
*
* < code >
* $ldapservers -> SetValue ( $i , 'login' , 'anon_bind' , 'true|false' );
* </ code >
*
* @ default true
* @ return bool
*/
function isAnonBindAllowed () {
global $ldapservers ;
// If only_login_allowed_dns is set, then we cant have anonymous.
if ( count ( $ldapservers -> GetValue ( $this -> server_id , 'login' , 'allowed_dns' )) > 0 )
$return = false ;
else
$return = $ldapservers -> GetValue ( $this -> server_id , 'login' , 'anon_bind' );
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isAnonBindAllowed(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
/**
* Fetches whether TLS has been configured for use with a certain server .
*
* Users may configure phpLDAPadmin to use TLS in config , php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'login' , 'tls' , 'true|false' );
* </ code >
*
* @ default false
* @ return bool
*/
function isTLSEnabled () {
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isTLSEnabled(): Entered with ()' , 17 , get_class ( $this ));
2009-06-30 09:29:51 +00:00
return $this -> tls ;
}
/**
* Returns true if the user has configured the specified server to enable branch ( non - leaf ) renames .
*
* This is configured in config . php thus :
* < code >
* $ldapservers -> SetValue ( $i , 'server' , 'branch_rename' , 'true|false' );
* </ code >
*
* @ default false
* @ param int $server_id The ID of the server of interest from config . php .
* @ return bool
*/
function isBranchRenameEnabled () {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::isBranchRenameEnabled(): Entered with (), Returning (%s).' , 17 ,
get_class ( $this ), $this -> branch_rename );
2009-06-30 09:40:37 +00:00
return $this -> branch_rename ;
}
/**
* Gets an associative array of ObjectClass objects for the specified
* server . Each array entry ' s key is the name of the objectClass
* in lower - case and the value is an ObjectClass object .
*
* @ param string $dn ( optional ) It is easier to fetch schema if a DN is provided
* which defines the subschemaSubEntry attribute ( all entries should ) .
*
* @ return array An array of ObjectClass objects .
*
* @ see ObjectClass
* @ see getSchemaObjectClass
*/
function SchemaObjectClasses ( $dn = '' ) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaObjectClasses(): Entered with (%s)' , 25 , get_class ( $this ), $dn );
2009-06-30 09:40:37 +00:00
# Set default return
$return = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( $return = get_cached_item ( $this -> server_id , 'schema' , 'objectclasses' )) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaObjectClasses(): Returning CACHED [%s] (%s)' , 25 ,
get_class ( $this ), $this -> server_id , 'objectclasses' );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$raw_oclasses = $this -> getRawSchema ( 'objectclasses' , $dn );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( $raw_oclasses ) {
# build the array of objectClasses
$return = array ();
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
foreach ( $raw_oclasses as $class_string ) {
if ( is_null ( $class_string ) || ! strlen ( $class_string ))
continue ;
2009-06-30 10:26:08 +00:00
$object_class = new ObjectClass ( $class_string , $this );
2009-06-30 09:40:37 +00:00
$return [ strtolower ( $object_class -> getName ())] = $object_class ;
}
2009-06-30 10:26:08 +00:00
# Now go through and reference the parent/child relationships
foreach ( $return as $oclass ) {
foreach ( $oclass -> getSupClasses () as $parent_name ) {
if ( isset ( $return [ strtolower ( $parent_name )]))
$return [ strtolower ( $parent_name )] -> addChildObjectClass ( $oclass -> getName ());
}
}
2009-06-30 09:40:37 +00:00
ksort ( $return );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item ( $this -> server_id , 'schema' , 'objectclasses' , $return );
}
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaObjectClasses(): Returning (%s)' , 25 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
/**
* Gets a single ObjectClass object specified by name .
*
* @ param string $oclass_name The name of the objectClass to fetch .
* @ param string $dn ( optional ) It is easier to fetch schema if a DN is provided
* which defines the subschemaSubEntry attribute ( all entries should ) .
*
* @ return ObjectClass The specified ObjectClass object or false on error .
*
* @ see ObjectClass
* @ see SchemaObjectClasses
*/
function getSchemaObjectClass ( $oclass_name , $dn = '' ) {
$oclass_name = strtolower ( $oclass_name );
$oclasses = $this -> SchemaObjectClasses ( $dn );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# Default return value
$return = false ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( isset ( $oclasses [ $oclass_name ]))
$return = $oclasses [ $oclass_name ];
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaObjectClass(): Entered with (%s,%s), Returning (%s).' , 25 ,
get_class ( $this ), $oclass_name , $dn , $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
/**
* Gets a single AttributeType object specified by name .
*
* @ param string $oclass_name The name of the AttributeType to fetch .
* @ param string $dn ( optional ) It is easier to fetch schema if a DN is provided
* which defines the subschemaSubEntry attribute ( all entries should ) .
*
* @ return AttributeType The specified AttributeType object or false on error .
*
* @ see AttributeType
* @ see SchemaAttributes
*/
function getSchemaAttribute ( $attr_name , $dn = null ) {
$attr_name = real_attr_name ( strtolower ( $attr_name ));
$schema_attrs = $this -> SchemaAttributes ( $dn );
# Default return value
$return = false ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( isset ( $schema_attrs [ $attr_name ]))
$return = $schema_attrs [ $attr_name ];
2009-06-30 10:26:08 +00:00
debug_log ( '%s::getSchemaAttribute(): Entered with (%s,%s), Returning (%s).' , 25 ,
get_class ( $this ), $attr_name , $dn , $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
/**
* Gets an associative array of AttributeType objects for the specified
* server . Each array entry ' s key is the name of the attributeType
* in lower - case and the value is an AttributeType object .
*
* @ param int $server_id The ID of the server whose AttributeTypes to fetch
* @ param string $dn ( optional ) It is easier to fetch schema if a DN is provided
* which defines the subschemaSubEntry attribute ( all entries should ) .
*
* @ return array An array of AttributeType objects .
*/
function SchemaAttributes ( $dn = null ) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaAttributes(): Entered with (%s)' , 25 , get_class ( $this ), $dn );
2009-06-30 09:40:37 +00:00
# Set default return
$return = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( $return = get_cached_item ( $this -> server_id , 'schema' , 'attributes' )) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaAttributes(): Returning CACHED [%s] (%s)' , 25 ,
get_class ( $this ), $this -> server_id , 'attributes' );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
$raw_attrs = $this -> getRawSchema ( 'attributeTypes' , $dn );
2009-06-30 09:40:37 +00:00
if ( $raw_attrs ) {
# build the array of attribueTypes
$syntaxes = $this -> SchemaSyntaxes ( $dn );
$attrs = array ();
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/**
* bug 856832 : create two arrays - one indexed by name ( the standard
* $attrs array above ) and one indexed by oid ( the new $attrs_oid array
* below ) . This will help for directory servers , like IBM ' s , that use OIDs
* in their attribute definitions of SUP , etc
*/
$attrs_oid = array ();
foreach ( $raw_attrs as $attr_string ) {
if ( is_null ( $attr_string ) || ! strlen ( $attr_string ))
continue ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$attr = new AttributeType ( $attr_string );
if ( isset ( $syntaxes [ $attr -> getSyntaxOID ()])) {
$syntax = $syntaxes [ $attr -> getSyntaxOID ()];
$attr -> setType ( $syntax -> getDescription ());
}
$attrs [ strtolower ( $attr -> getName ())] = $attr ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/**
* bug 856832 : create an entry in the $attrs_oid array too . This
* will be a ref to the $attrs entry for maintenance and performance
* reasons
*/
$attrs_oid [ $attr -> getOID ()] = & $attrs [ strtolower ( $attr -> getName ())];
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# go back and add data from aliased attributeTypes
foreach ( $attrs as $name => $attr ) {
$aliases = $attr -> getAliases ();
if ( is_array ( $aliases ) && count ( $aliases ) > 0 ) {
/* foreach of the attribute ' s aliases , create a new entry in the attrs array
with its name set to the alias name , and all other data copied .*/
foreach ( $aliases as $alias_attr_name ) {
# clone is a PHP5 function and must be used.
if ( function_exists ( 'clone' ))
$new_attr = clone ( $attr );
else
$new_attr = $attr ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$new_attr -> setName ( $alias_attr_name );
$new_attr -> addAlias ( $attr -> getName ());
$new_attr -> removeAlias ( $alias_attr_name );
$new_attr_key = strtolower ( $alias_attr_name );
$attrs [ $new_attr_key ] = $new_attr ;
}
}
}
# go back and add any inherited descriptions from parent attributes (ie, cn inherits name)
foreach ( $attrs as $key => $attr ) {
$sup_attr_name = $attr -> getSupAttribute ();
$sup_attr = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( trim ( $sup_attr_name )) {
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* This loop really should traverse infinite levels of inheritance ( SUP ) for attributeTypes ,
but just in case we get carried away , stop at 100. This shouldn ' t happen , but for
some weird reason , we have had someone report that it has happened . Oh well .*/
$i = 0 ;
2009-06-30 10:26:08 +00:00
while ( $i ++< 100 /** 100 == INFINITY ;) */ ) {
2009-06-30 09:40:37 +00:00
if ( isset ( $attrs_oid [ $sup_attr_name ])) {
$attr -> setSupAttribute ( $attrs_oid [ $sup_attr_name ] -> getName ());
$sup_attr_name = $attr -> getSupAttribute ();
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( ! isset ( $attrs [ strtolower ( $sup_attr_name )])){
pla_error ( sprintf ( 'Schema error: attributeType "%s" inherits from "%s", but attributeType "%s" does not exist.' ,
$attr -> getName (), $sup_attr_name , $sup_attr_name ));
return ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$sup_attr = $attrs [ strtolower ( $sup_attr_name )];
$sup_attr_name = $sup_attr -> getSupAttribute ();
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# Does this superior attributeType not have a superior attributeType?
if ( is_null ( $sup_attr_name ) || strlen ( trim ( $sup_attr_name )) == 0 ) {
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* Since this attribute ' s superior attribute does not have another superior
attribute , clone its properties for this attribute . Then , replace
those cloned values with those that can be explicitly set by the child
attribute attr ) . Save those few properties which the child can set here :*/
$tmp_name = $attr -> getName ();
$tmp_oid = $attr -> getOID ();
$tmp_sup = $attr -> getSupAttribute ();
$tmp_aliases = $attr -> getAliases ();
$tmp_single_val = $attr -> getIsSingleValue ();
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* clone the SUP attributeType and populate those values
that were set by the child attributeType */
# clone is a PHP5 function and must be used.
if ( function_exists ( 'clone' ))
$attr = clone ( $sup_attr );
else
$attr = $sup_attr ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$attr -> setOID ( $tmp_oid );
$attr -> setName ( $tmp_name );
$attr -> setSupAttribute ( $tmp_sup );
$attr -> setAliases ( $tmp_aliases );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* only overwrite the SINGLE - VALUE property if the child explicitly sets it
( note : All LDAP attributes default to multi - value if not explicitly set SINGLE - VALUE ) */
2009-06-30 10:26:08 +00:00
if ( $tmp_single_val )
2009-06-30 09:40:37 +00:00
$attr -> setIsSingleValue ( true );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* replace this attribute in the attrs array now that we have populated
new values therein */
$attrs [ $key ] = $attr ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# very important: break out after we are done with this attribute
$sup_attr_name = null ;
$sup_attr = null ;
break ;
}
}
}
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
ksort ( $attrs );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# Add the used in and required_by values.
$schema_object_classes = $this -> SchemaObjectClasses ();
if ( ! is_array ( $schema_object_classes ))
return array ();
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
foreach ( $schema_object_classes as $object_class ) {
$must_attrs = $object_class -> getMustAttrNames ( $schema_object_classes );
$may_attrs = $object_class -> getMayAttrNames ( $schema_object_classes );
$oclass_attrs = array_unique ( array_merge ( $must_attrs , $may_attrs ));
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# Add Used In.
foreach ( $oclass_attrs as $attr_name ) {
if ( isset ( $attrs [ strtolower ( $attr_name )]))
$attrs [ strtolower ( $attr_name )] -> addUsedInObjectClass ( $object_class -> getName ());
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
else {
#echo "Warning, attr not set: $attr_name<br />";
}
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# Add Required By.
foreach ( $must_attrs as $attr_name ) {
if ( isset ( $attrs [ strtolower ( $attr_name )]))
$attrs [ strtolower ( $attr_name )] -> addRequiredByObjectClass ( $object_class -> getName ());
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
else {
#echo "Warning, attr not set: $attr_name<br />";
}
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$return = $attrs ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item ( $this -> server_id , 'schema' , 'attributes' , $return );
}
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaAttributes(): Returning (%s)' , 25 , get_class ( $this ), $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
/**
* Returns an array of MatchingRule objects for the specified server .
* The key of each entry is the OID of the matching rule .
*/
function MatchingRules ( $dn = null ) {
# Set default return
$return = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( $return = get_cached_item ( $this -> server_id , 'schema' , 'matchingrules' )) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::MatchingRules(): Returning CACHED [%s] (%s).' , 25 ,
get_class ( $this ), $this -> server_id , 'matchingrules' );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# build the array of MatchingRule objects
2009-06-30 10:26:08 +00:00
$raw_matching_rules = $this -> getRawSchema ( 'matchingRules' , $dn );
2009-06-30 09:40:37 +00:00
if ( $raw_matching_rules ) {
$rules = array ();
foreach ( $raw_matching_rules as $rule_string ) {
if ( is_null ( $rule_string ) || 0 == strlen ( $rule_string ))
continue ;
$rule = new MatchingRule ( $rule_string );
$key = strtolower ( $rule -> getName ());
$rules [ $key ] = $rule ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
ksort ( $rules );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/* For each MatchingRuleUse entry , add the attributes who use it to the
MatchingRule in the $rules array .*/
$raw_matching_rule_use = $this -> getRawSchema ( 'matchingRuleUse' );
if ( $raw_matching_rule_use != false ) {
foreach ( $raw_matching_rule_use as $rule_use_string ) {
if ( $rule_use_string == null || 0 == strlen ( $rule_use_string ))
continue ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$rule_use = new MatchingRuleUse ( $rule_use_string );
$key = strtolower ( $rule_use -> getName ());
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( isset ( $rules [ $key ]))
$rules [ $key ] -> setUsedByAttrs ( $rule_use -> getUsedByAttrs ());
}
} else {
/* No MatchingRuleUse entry in the subschema , so brute - forcing
the reverse - map for the " $rule->getUsedByAttrs () " data .*/
$attrs = $this -> SchemaAttributes ( $dn );
if ( is_array ( $attrs ))
foreach ( $attrs as $attr ) {
$rule_key = strtolower ( $attr -> getEquality ());
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( isset ( $rules [ $rule_key ]))
$rules [ $rule_key ] -> addUsedByAttr ( $attr -> getName ());
}
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
$return = $rules ;
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item ( $this -> server_id , 'schema' , 'matchingrules' , $return );
}
2009-06-30 10:26:08 +00:00
debug_log ( '%s::MatchingRules(): Entered with (%s), Returning (%s).' , 25 , get_class ( $this ), $dn , $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
/**
* Returns an array of Syntax objects that this LDAP server uses mapped to
* their descriptions . The key of each entry is the OID of the Syntax .
*/
function SchemaSyntaxes ( $dn = null ) {
# Set default return
$return = null ;
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
if ( $return = get_cached_item ( $this -> server_id , 'schema' , 'syntaxes' )) {
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaSyntaxes(): Returning CACHED [%s] (%s).' , 25 ,
get_class ( $this ), $this -> server_id , 'syntaxes' );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
$raw_syntaxes = $this -> getRawSchema ( 'ldapSyntaxes' , $dn );
2009-06-30 09:40:37 +00:00
if ( $raw_syntaxes ) {
# build the array of attributes
$return = array ();
foreach ( $raw_syntaxes as $syntax_string ) {
$syntax = new Syntax ( $syntax_string );
$key = strtolower ( trim ( $syntax -> getOID ()));
2009-06-30 10:26:08 +00:00
if ( ! $key )
continue ;
2009-06-30 09:40:37 +00:00
$return [ $key ] = $syntax ;
}
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
ksort ( $return );
2009-06-30 10:26:08 +00:00
2009-06-30 09:40:37 +00:00
# cache the schema to prevent multiple schema fetches from LDAP server
set_cached_item ( $this -> server_id , 'schema' , 'syntaxes' , $return );
}
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SchemaSyntaxes(): Entered with (%s), Returning (%s).' , 25 ,
get_class ( $this ), $dn , $return );
2009-06-30 09:40:37 +00:00
return $return ;
}
2009-06-30 10:26:08 +00:00
/**
* Add objects
*
*/
function add ( $dn , $entry_array ) {
$result = @ ldap_add ( $this -> connect (), dn_escape ( $dn ), $entry_array );
if ( $result ) {
$tree = get_cached_item ( $this -> server_id , 'tree' );
$tree [ 'browser' ][ $dn ][ 'icon' ] = get_icon ( $this , $dn );
# If this DN is in our miss list, we can remove it now.
if ( isset ( $tree [ 'misses' ][ $dn ]))
unset ( $tree [ 'misses' ][ $dn ]);
# Update this DN's parent's children list as well.
$parent = get_container ( $dn );
$tree [ 'browser' ][ $parent ][ 'children' ][] = $dn ;
usort ( $tree [ 'browser' ][ $parent ][ 'children' ], 'pla_compare_dns' );
set_cached_item ( $this -> server_id , 'tree' , 'null' , $tree );
}
return $result ;
}
2009-06-30 09:40:37 +00:00
/**
* Modify objects
2009-06-30 10:26:08 +00:00
*/
function modify ( $dn , $update_array ) {
return @ ldap_modify ( $this -> connect (), dn_escape ( $dn ), $update_array );
}
/**
* Modify attributes
*/
function attrModify ( $dn , $update_array ) {
return @ ldap_mod_add ( $this -> connect (), dn_escape ( $dn ), $update_array );
}
function attrDelete ( $dn , $update_array ) {
return @ ldap_mod_del ( $this -> connect (), dn_escape ( $dn ), $update_array );
}
function attrReplace ( $dn , $update_array ) {
return @ ldap_mod_replace ( $this -> connect (), dn_escape ( $dn ), $update_array );
}
/**
* Delete objects
*/
function delete ( $dn ) {
$result = @ ldap_delete ( $this -> connect (), dn_escape ( $dn ));
if ( $result ) {
$tree = get_cached_item ( $this -> server_id , 'tree' );
unset ( $tree [ 'browser' ][ $dn ]);
# Delete entry from parent's children as well.
$parent = get_container ( $dn );
$index = array_search ( $dn , $tree [ 'browser' ][ $parent ][ 'children' ]);
unset ( $tree [ 'browser' ][ $parent ][ 'children' ][ $index ]);
# Might be worthwhile adding it to our miss list, while we are here.
$tree [ 'misses' ][ $dn ] = true ;
set_cached_item ( $this -> server_id , 'tree' , 'null' , $tree );
}
return $result ;
}
/**
* Rename objects
2009-06-30 09:40:37 +00:00
*
*/
2009-06-30 10:26:08 +00:00
function rename ( $dn , $new_rdn , $container , $deleteoldrdn ) {
if ( ! @ ldap_rename ( $this -> connect (), $dn , $new_rdn , $container , $deleteoldrdn )) {
pla_error ( _ ( 'Could not rename the entry' ), $this -> error (), $this -> errno (), false );
} else {
# Update the tree
$tree = get_cached_item ( $this -> server_id , 'tree' );
$newdn = sprintf ( '%s,%s' , $new_rdn , $container );
$tree [ 'browser' ][ $newdn ] = $tree [ 'browser' ][ $dn ];
unset ( $tree [ 'browser' ][ $dn ]);
# Might be worthwhile adding it to our miss list, while we are here.
$tree [ 'misses' ][ $dn ] = true ;
if ( isset ( $tree [ 'misses' ][ $newdn ]))
unset ( $tree [ 'misses' ][ $newdn ]);
# Update the parent's children
$parent = get_container ( $dn );
$index = array_search ( $dn , $tree [ 'browser' ][ $parent ][ 'children' ]);
$tree [ 'browser' ][ $parent ][ 'children' ][ $index ] = $newdn ;
usort ( $tree [ 'browser' ][ $parent ][ 'children' ], 'pla_compare_dns' );
set_cached_item ( $this -> server_id , 'tree' , 'null' , $tree );
return true ;
}
2009-06-30 09:40:37 +00:00
}
/**
* Return error from last operation
*
*/
function error () {
return ldap_error ( $this -> connect ());
}
/**
* Return errno from last operation
*
*/
function errno () {
return ldap_errno ( $this -> connect ());
2009-06-30 09:29:51 +00:00
}
2009-06-30 10:26:08 +00:00
/**
* Gets whether an entry exists based on its DN . If the entry exists ,
* returns true . Otherwise returns false .
*
* If we are not aware of the dn , and a read results in a hit , then
* we ' ll update the info for the tree .
*
* @ param string $dn The DN of the entry of interest .
* @ return bool
*/
function dnExists ( $dn ) {
# Set default return
$return = false ;
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
$tree = get_cached_item ( $this -> server_id , 'tree' );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( isset ( $tree [ 'browser' ][ $dn ])) {
debug_log ( '%s::dnExists(): Returning CACHED HIT (%s)' , 17 ,
get_class ( $this ), $this -> server_id , $dn );
return true ;
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
} elseif ( isset ( $tree [ 'misses' ][ $dn ])) {
debug_log ( '%s::dnExists(): Returning CACHED MISS (%s)' , 17 ,
get_class ( $this ), $this -> server_id , $dn );
return false ;
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
# We havent looked for this dn.
} else {
if ( DEBUG_ENABLED )
debug_log ( '%s::dnExists(): Search for (%s) [%s]' , 16 , get_class ( $this ), $this -> server_id , $dn );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
$search_result = @ ldap_read ( $this -> connect ( false ), dn_escape ( $dn ), 'objectClass=*' , array ( 'dn' ));
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( $search_result ) {
$num_entries = ldap_count_entries ( $this -> connect ( false ), $search_result );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( $num_entries > 0 ) {
$return = true ;
$tree [ 'browser' ][ $dn ][ 'icon' ] = get_icon ( $this , $dn );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
} else {
$return = false ;
$tree [ 'misses' ][ $dn ] = true ;
}
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
} else {
$return = false ;
$tree [ 'misses' ][ $dn ] = true ;
}
set_cached_item ( $this -> server_id , 'tree' , 'null' , $tree );
}
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( DEBUG_ENABLED )
debug_log ( '%s::dnExists(): Entered with (%s,%s), Returning (%s)' , 17 ,
get_class ( $this ), $this -> server_id , $dn , $return );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
return $return ;
}
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
/**
* 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 :
*
* < code >
* dc = example , dc = com
* ou = People
* cn = Dave
* cn = Fred
* cn = Joe
* ou = More People
* cn = Mark
* cn = Bob
* </ code >
*
* Calling < code > getContainerContents ( " ou=people,dc=example,dc=com " ) </ code >
* would return the following list :
*
* < code >
* cn = Dave
* cn = Fred
* cn = Joe
* ou = More People
* </ code >
*
* @ 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 .
*/
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
function getContainerContents ( $dn , $size_limit = 0 , $filter = '(objectClass=*)' , $deref = LDAP_DEREF_ALWAYS ) {
$tree = get_cached_item ( $this -> server_id , 'tree' );
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( isset ( $tree [ 'browser' ][ $dn ][ 'children' ]) && $filter == '(objectClass=*)' )
if ( ! isset ( $tree [ 'browser' ][ $dn ][ 'size_limited' ]) || ! $tree [ 'browser' ][ $dn ][ 'size_limited' ])
return $tree [ 'browser' ][ $dn ][ 'children' ];
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
$return = array ();
$search = $this -> search ( null , dn_escape ( $dn ), $filter , array ( 'dn' ), 'one' , true , $deref ,( $size_limit > 0 ? $size_limit + 1 : $size_limit ));
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
if ( ! $search ) {
$tree [ 'browser' ][ $dn ][ 'children' ] = array ();
2009-06-30 09:29:51 +00:00
2009-06-30 10:26:08 +00:00
} else {
foreach ( $search as $searchdn => $entry ) {
$child_dn = dn_unescape ( $entry [ 'dn' ]);
$tree [ 'browser' ][ $child_dn ][ 'icon' ] = get_icon ( $this , $child_dn );
$return [] = $child_dn ;
}
usort ( $return , 'pla_compare_dns' );
$tree [ 'browser' ][ $dn ][ 'children' ] = $return ;
if ( $size_limit > 0 && count ( $tree [ 'browser' ][ $dn ][ 'children' ]) > $size_limit )
$tree [ 'browser' ][ $dn ][ 'size_limited' ] = true ;
else
if ( isset ( $tree [ 'browser' ][ $dn ][ 'size_limited' ]))
unset ( $tree [ 'browser' ][ $dn ][ 'size_limited' ]);
}
set_cached_item ( $this -> server_id , 'tree' , 'null' , $tree );
if ( DEBUG_ENABLED )
debug_log ( '%s::getContainerContents(): Entered with (%s,%s,%s,%s), Returning (%s)' , 17 ,
get_class ( $this ), $dn , $size_limit , $filter , $deref , $return );
return $tree [ 'browser' ][ $dn ][ 'children' ];
}
/**
* A handy ldap searching function very similar to PHP ' s ldap_search () with the
* following exceptions : Callers may specify a search scope and the return value
* is an array containing the search results rather than an LDAP result resource .
*
* Example usage :
* < code >
* $samba_users = $ldapserver -> search ( null , " ou=People,dc=example,dc=com " ,
* " (&(objectClass=sambaAccount)(objectClass=posixAccount)) " ,
* 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"
* // )
* // )
* </ code >
*
* 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 resource $resource If an existing LDAP results should be used .
* @ 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 .
* @ param int $size_limit Size limit for search
* @ todo : Add entries to tree cache .
*/
function search ( $resource = null , $base_dn = null , $filter , $attrs = array (), $scope = 'sub' , $sort_results = true , $deref = LDAP_DEREF_NEVER , $size_limit = 0 ) {
if ( DEBUG_ENABLED )
debug_log ( '%s::search(): Entered with (%s,%s,%s,%s,%s,%s,%s)' , 17 ,
get_class ( $this ), is_resource ( $this ), $base_dn , $filter , $attrs , $scope , $sort_results , $deref );
# If we dont have a resource, we'll connect with default settings
if ( ! is_resource ( $resource ))
$resource = $this -> connect ( false );
# If the baseDN is null, we'll just search the first DN.
if ( is_null ( $base_dn ))
foreach ( $this -> getBaseDN () as $baseDN ) {
$base_dn = $baseDN ;
break ;
}
if ( DEBUG_ENABLED )
debug_log ( '%s::search(): %s search PREPARE.' , 16 , get_class ( $this ), $scope );
switch ( $scope ) {
case 'base' :
$search = @ ldap_read ( $resource , $base_dn , $filter , $attrs , 0 , $size_limit , 0 , $deref );
break ;
case 'one' :
$search = @ ldap_list ( $resource , $base_dn , $filter , $attrs , 0 , $size_limit , 0 , $deref );
break ;
case 'sub' :
default :
$search = @ ldap_search ( $resource , $base_dn , $filter , $attrs , 0 , $size_limit , 0 , $deref );
break ;
}
if ( DEBUG_ENABLED )
debug_log ( '%s::search(): %s search from base [%s] with [%s] for [%s] COMPLETE ().' , 16 ,
get_class ( $this ), $scope , $base_dn , $filter , $attrs , is_null ( $search ));
if ( ! $search )
return array ();
$return = array ();
# Get the first entry identifier
if ( $entry_id = ldap_first_entry ( $resource , $search ))
# Iterate over the entries
while ( $entry_id ) {
# Get the distinguished name of the entry
$dn = ldap_get_dn ( $resource , $entry_id );
$return [ $dn ][ 'dn' ] = $dn ;
# Get the attributes of the entry
$attrs = ldap_get_attributes ( $resource , $entry_id );
# Get the first attribute of the entry
if ( $attr = ldap_first_attribute ( $resource , $entry_id , $attrs ))
# Iterate over the attributes
while ( $attr ) {
if ( $this -> isAttrBinary ( $attr ))
$values = ldap_get_values_len ( $resource , $entry_id , $attr );
else
$values = ldap_get_values ( $resource , $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 ( $resource , $entry_id , $attrs );
} # end while attr
$entry_id = ldap_next_entry ( $resource , $entry_id );
} # End while entry_id
if ( $sort_results && is_array ( $return ))
ksort ( $return );
if ( DEBUG_ENABLED )
debug_log ( '%s::search(): Returning (%s)' , 17 , get_class ( $this ), $return );
return $return ;
}
/**
* Determines if an attribute ' s value can contain multiple lines . Attributes that fall
* in this multi - line category may be configured in config . php . Hence , this function
* accesses the global variable $config -> custom -> appearance [ 'multi_line_attributes' ];
*
* Usage example :
* < code >
* if ( $ldapserver -> isMultiLineAttr ( 'postalAddress' ))
* echo " <textarea name= \" postalAddress \" ></textarea> " ;
* else
* echo " <input name= \" postalAddress \" type= \" text \" > " ;
* </ code >
*
* @ 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 )
* @ return bool
*/
function isMultiLineAttr ( $attr_name , $val = null ) {
global $config ;
# Set default return
$return = false ;
# First, check the optional val param for a \n or a \r
if ( ! is_null ( $val ) && ( strpos ( $val , " \n " ) || strpos ( $val , " \r " )))
$return = true ;
# Next, compare strictly by name first
else
foreach ( $config -> GetValue ( 'appearance' , '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 ) {
$schema_attr = $this -> getSchemaAttribute ( $attr_name );
if ( $schema_attr ) {
$syntax_oid = $schema_attr -> getSyntaxOID ();
if ( $syntax_oid )
foreach ( $config -> GetValue ( 'appearance' , 'multi_line_syntax_oids' ) as $multi_line_syntax_oid )
if ( $multi_line_syntax_oid == $syntax_oid ) {
$return = true ;
break ;
}
}
}
if ( DEBUG_ENABLED )
debug_log ( '%s:isMultiLineAttr(): Entered with (%s,%s), Returning (%s)' , 17 ,
get_class ( $this ), $attr_name , $val , $return );
return $return ;
}
/**
* Returns true if the attribute specified is required to take as input a DN .
* Some examples include 'distinguishedName' , 'member' and 'uniqueMember' .
* @ param string $attr_name The name of the attribute of interest ( case insensitive )
* @ return bool
*/
function isDNAttr ( $attr_name ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isDNAttr(): Entered with (%s)' , 17 , get_class ( $this ), $attr_name );
# Simple test first
$dn_attrs = array ( 'aliasedObjectName' );
foreach ( $dn_attrs as $dn_attr )
if ( strcasecmp ( $attr_name , $dn_attr ) == 0 )
return true ;
# Now look at the schema OID
$attr_schema = $this -> getSchemaAttribute ( $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 = $this -> SchemaSyntaxes ();
if ( ! isset ( $syntaxes [ $syntax_oid ]))
return false ;
$syntax_desc = $syntaxes [ $syntax_oid ] -> getDescription ();
if ( strpos ( strtolower ( $syntax_desc ), 'distinguished name' ))
return true ;
return false ;
}
/**
* 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 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 unsetLoginDN
*/
function setLoginDN ( $dn , $password , $anon_bind ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:setLoginDN(): Entered with (%s,%s,%s)' , 17 , get_class ( $this ), $dn , $password , $anon_bind );
if ( ! $this -> auth_type )
return false ;
switch ( $this -> auth_type ) {
case 'cookie' :
$cookie_dn_name = sprintf ( 'pla_login_dn_%s' , $this -> server_id );
$cookie_pass_name = sprintf ( 'pla_login_pass_%s' , $this -> 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' , $this -> server_id );
$sess_var_pass_name = sprintf ( 'pla_login_pass_%s' , $this -> 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 :
pla_error ( sprintf ( _ ( 'Unknown auth_type: %s' ), htmlspecialchars ( $this -> auth_type )));
break ;
}
}
/**
* Log a user out of the LDAP server .
*
* Removes the cookies / session - vars set by setLoginDN ()
* after a user logs out using " auth_type " of " session " or " cookie " .
* Returns true on success , false on failure .
*
* @ return bool True on success , false on failure .
* @ see setLoginDN
*/
function unsetLoginDN () {
if ( DEBUG_ENABLED )
debug_log ( '%s:unsetLoginDN(): Entered with ()' , 17 , get_class ( $this ));
if ( ! $this -> auth_type )
return false ;
switch ( $this -> auth_type ) {
case 'cookie' :
$logged_in_dn = $this -> getLoggedInDN ();
if ( ! $logged_in_dn )
return false ;
$logged_in_pass = $this -> getLoggedInPass ();
$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' , $this -> server_id );
$cookie_pass_name = sprintf ( 'pla_login_pass_%s' , $this -> 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' , $this -> server_id );
$session_var_pass_name = sprintf ( 'pla_login_pass_%s' , $this -> 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 ]);
return true ;
break ;
default :
pla_error ( sprintf ( _ ( 'Unknown auth_type: %s' ), htmlspecialchars ( $auth_type )));
break ;
}
}
/**
* 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 string $attr_name The name of the attribute to test .
* @ return bool
* @ see draw_jpeg_photos
*/
function isJpegPhoto ( $attr_name ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isJpegPhoto(): Entered with (%s)' , 17 , get_class ( $this ), $attr_name );
# easy quick check
if ( ! strcasecmp ( $attr_name , 'jpegPhoto' ) || ! strcasecmp ( $attr_name , 'photo' ))
return true ;
# go to the schema and get the Syntax OID
$schema_attr = $this -> getSchemaAttribute ( $attr_name );
if ( ! $schema_attr )
return false ;
$oid = $schema_attr -> getSyntaxOID ();
$type = $schema_attr -> getType ();
if ( ! strcasecmp ( $type , 'JPEG' ) || ( $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 string $attr_name The name of the attribute to test .
* @ return bool
*/
function isAttrBoolean ( $attr_name ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isAttrBoolean(): Entered with (%s)' , 17 , get_class ( $this ), $attr_name );
$type = ( $schema_attr = $this -> getSchemaAttribute ( $attr_name )) ? $schema_attr -> getType () : null ;
if ( ! strcasecmp ( 'boolean' , $type ) ||
! strcasecmp ( 'isCriticalSystemObject' , $attr_name ) ||
! 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 string $attr_name The name of the attribute to test .
* @ return bool
*
* @ see isJpegPhoto
*/
function isAttrBinary ( $attr_name ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isAttrBinary(): Entered with (%s)' , 17 , get_class ( $this ), $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 ;
$attr_name = strtolower ( $attr_name );
if ( isset ( $attr_cache [ $this -> server_id ][ $attr_name ]))
return $attr_cache [ $this -> server_id ][ $attr_name ];
if ( $attr_name == 'userpassword' ) {
$attr_cache [ $this -> server_id ][ $attr_name ] = false ;
return false ;
}
# Quick check: If the attr name ends in ";binary", then it's binary.
if ( strcasecmp ( substr ( $attr_name , strlen ( $attr_name ) - 7 ), ';binary' ) == 0 ) {
$attr_cache [ $this -> server_id ][ $attr_name ] = true ;
return true ;
}
# See what the server schema says about this attribute
$schema_attr = $this -> getSchemaAttribute ( $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 ( 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' ) == 0 ||
$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 [ $this -> server_id ][ $attr_name ] = true ;
return true ;
} else {
$attr_cache [ $this -> 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 :
* < code >
* $read_only_attrs = array ( " objectClass " , " givenName " );
* </ code >
*
* @ param string $attr The name of the attribute to test .
* @ return bool
*/
function isAttrReadOnly ( $attr ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isAttrReadOnly(): Entered with (%s)' , 17 , get_class ( $this ), $attr );
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 ) && $this -> userIsMember ( $this -> getLoggedInDN (), $read_only_except_dn ))
return false ;
foreach ( $read_only_attrs as $attr_name )
if ( strcasecmp ( $attr , trim ( $attr_name )) == 0 )
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 :
* < code >
* $hidden_attrs = array ( " objectClass " , " givenName " );
* </ code >
* or
* < code >
* $hidden_attrs_ro = array ( " objectClass " , " givenName " , " shadowWarning " ,
* " shadowLastChange " , " shadowMax " , " shadowFlag " ,
* " shadowInactive " , " shadowMin " , " shadowExpire " );
* </ code >
*
* @ param string $attr The name of the attribute to test .
* @ return bool
*/
function isAttrHidden ( $attr ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isAttrHidden(): Entered with (%s)' , 17 , get_class ( $this ), $attr );
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 ) && $this -> userIsMember ( $this -> getLoggedInDN (), $hidden_except_dn ))
return false ;
if ( $this -> isReadOnly ()) {
foreach ( $hidden_attrs_ro as $attr_name )
if ( strcasecmp ( $attr , trim ( $attr_name )) == 0 )
return true ;
} else {
foreach ( $hidden_attrs as $attr_name )
if ( strcasecmp ( $attr , trim ( $attr_name )) == 0 )
return true ;
}
return false ;
}
/**
* Fetches the password of the currently logged in user ( for auth_types " cookie " and " session " only )
* or false if the current login is anonymous .
*
* @ return string
* @ see have_auth_info
* @ see getLoggedInDN
*/
function getLoggedInPass () {
if ( DEBUG_ENABLED )
debug_log ( '%s:getLoggedInPass(): Entered with ()' , 17 , get_class ( $this ));
if ( ! $this -> auth_type )
return false ;
switch ( $this -> auth_type ) {
case 'cookie' :
$cookie_name = sprintf ( 'pla_login_pass_%s' , $this -> 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' , $this -> 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 $this -> login_pass ;
break ;
default :
pla_error ( sprintf ( _ ( 'Unknown auth_type: %s' ), htmlspecialchars ( $this -> 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
* " cookie " and " session " .
*
* 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 .
*
* @ return string
* @ see have_auth_info
* @ see getLoggedInPass
*/
function getLoggedInDN () {
# Set default return
$return = false ;
if ( $this -> auth_type ) {
switch ( $this -> auth_type ) {
case 'cookie' :
$cookie_name = sprintf ( 'pla_login_dn_%s' , $this -> 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' , $this -> server_id );
if ( isset ( $_SESSION [ $session_var_name ]))
$return = pla_blowfish_decrypt ( $_SESSION [ $session_var_name ]);
else
$return = false ;
break ;
case 'config' :
$return = $this -> login_dn ;
break ;
default :
pla_error ( sprintf ( _ ( 'Unknown auth_type: %s' ), htmlspecialchars ( $auth_type )));
}
}
if ( DEBUG_ENABLED )
debug_log ( '%s:getLoggedInDN(): Entered with (), Returning (%s)' , 17 , get_class ( $this ), $return );
return $return ;
}
/**
* 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 :
* < code >
* Array
* (
* [ creatorsName ] => Array
* (
* [ 0 ] => " cn=Admin,dc=example,dc=com "
* )
* [ createTimeStamp ] => Array
* (
* [ 0 ] => " 10401040130 "
* )
* [ hasSubordinates ] => Array
* (
* [ 0 ] => " FALSE "
* )
* )
* </ code >
*
* @ 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 .
*/
function getDNSysAttrs ( $dn , $deref = LDAP_DEREF_NEVER ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:getDNSysAttrs(): Entered with (%s,%s)' , 17 , get_class ( $this ), $dn , $deref );
$attrs = array ( 'creatorsname' , 'createtimestamp' , 'modifiersname' ,
'structuralObjectClass' , 'entryUUID' , 'modifytimestamp' ,
'subschemaSubentry' , 'hasSubordinates' , '+' );
$search = $this -> search ( null , $dn , '(objectClass=*)' , $attrs , 'base' , false , $deref );
foreach ( $search as $dn => $attrs )
foreach ( $attrs as $attr => $value ) {
$return_attrs [ $attr ][] = $value ;
}
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 < code > getDNAttrs ( 0 , " cn=Bob,ou=pepole,dc=example,dc=com " ) </ code >
*
* < code >
* 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
* )
* )
* </ code >
*
* @ 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 getDNSysAttrs
* @ see getDNAttr
*/
function getDNAttrs ( $dn , $lower_case_attr_names = false , $deref = LDAP_DEREF_NEVER ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:getDNAttrs(): Entered with (%s,%s,%s)' , 17 ,
get_class ( $this ), $dn , $lower_case_attr_names , $deref );
$attrs = array_pop ( $this -> search ( null , dn_escape ( $dn ), '(objectClass=*)' , array (), 'base' , false , $deref ));
if ( $lower_case_attr_names )
$attrs = array_change_key_case ( $attrs );
if ( is_array ( $attrs ))
ksort ( $attrs );
return $attrs ;
}
/**
* Much like getDNAttrs (), but only returns the values for
* one attribute of an object . Example calls :
*
* < code >
* print_r ( getDNAttr ( 0 , " cn=Bob,ou=people,dc=example,dc=com " , " sn " ) );
* // prints:
* // Array
* // (
* // [0] => "Smith"
* // )
*
* print_r ( getDNAttr ( 0 , " cn=Bob,ou=people,dc=example,dc=com " , " objectClass " ) );
* // prints:
* // Array
* // (
* // [0] => "top"
* // [1] => "person"
* // )
* </ code >
*
* @ 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 getDNAttrs
*/
function getDNAttr ( $dn , $attr , $lower_case_attr_names = false , $deref = LDAP_DEREF_NEVER ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:getDNAttr(): Entered with (%s,%s,%s,%s)' , 17 ,
get_class ( $this ), $dn , $attr , $lower_case_attr_names , $deref );
if ( $lower_case_attr_names )
$attr = strtolower ( $attr );
$attrs = $this -> getDNAttrs ( $dn , $lower_case_attr_names , $deref );
if ( isset ( $attrs [ $attr ]))
return $attrs [ $attr ];
else
return false ;
}
/**
* Given a DN string , this returns the top container portion of the string .
* @ param string $dn The DN whose container string to return .
* @ return string The container
* @ see get_rdn
* @ see get_container
*/
function getContainerTop ( $dn ) {
foreach ( $this -> getBaseDN () as $base_dn ) {
if ( preg_match ( " / ${ base_dn } $ / " , $dn )) {
$return = $base_dn ;
break ;
}
}
debug_log ( '%s:getContainerTop(): Entered with (%s), Returning (%s)' , 17 , get_class ( $this ), $dn , $return );
return $return ;
}
/**
* Given a DN string and a path like syntax , this returns the parent container portion of the string .
* @ param string $dn The DN whose container string to return .
* @ param string $path Either '/' , '.' or a series of '../'
* @ return string The container
* @ see get_rdn
* @ see get_container
*/
function getContainerParent ( $container , $path ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:getContainerParent(): Entered with (%s,%s)' , 17 , get_class ( $this ), $container , $path );
$top = $this -> getContainerTop ( $container );
if ( $path == '/' ) {
return $top ;
} elseif ( $path == '.' ) {
return $container ;
} else {
$parenttree = explode ( '/' , $path );
foreach ( $parenttree as $index => $value ) {
if ( $value == '..' ) {
if ( get_container ( $container ))
$container = get_container ( $container );
if ( $container == $top )
break ;
} else {
break ;
}
}
return $container ;
}
}
/**
* Show friendly attribute .
*/
function showFriendlyAttr ( $attr ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:showFriendlyAttr(): Entered with (%s)' , 17 , get_class ( $this ), $attr );
$friendly_attrs = process_friendly_attr_table ();
if ( isset ( $friendly_attrs [ strtolower ( $attr )]))
$return = $friendly_attrs [ strtolower ( $attr )];
else
$return = $attr ;
if ( DEBUG_ENABLED )
debug_log ( '%s:showFriendlyAttr(): Returning (%s)' , 17 , get_class ( $this ), $return );
return $return ;
}
/**
* Determins if the specified attribute is contained in the $unique_attrs list
* configured in config . php .
* @ return bool True if the specified attribute is in the $unique_attrs list and false
* otherwise .
*/
function isUniqueAttr ( $attr_name ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:isUniqueAttr(): Entered with (%s)' , 17 , get_class ( $this ), $attr_name );
global $unique_attrs ;
if ( isset ( $unique_attrs ) && is_array ( $unique_attrs ))
foreach ( $unique_attrs as $attr )
if ( strcasecmp ( $attr_name , $attr ) == 0 )
return true ;
return false ;
}
/**
* This function will check whether the value for an attribute being changed
* is already assigned to another DN .
*
* Inputs :
* @ param dn $dn DN that is being changed
* @ param string $attr_name Attribute being changed
* @ param string | array $new values New values for the attribute
*
* Returns the bad value , or null if all values are OK
*/
function checkUniqueAttr ( $dn , $attr_name , $new_value ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:checkUniqueAttr(): Entered with (%s,%s,%s)' , 17 ,
get_class ( $this ), $dn , $attr_name , count ( $new_value ));
global $ldapservers ;
# Is this attribute in the unique_attrs list?
if ( $this -> isUniqueAttr ( $attr_name )) {
$con = $this -> connect ( false , 'unique_attr' , false ,
$ldapservers -> GetValue ( $this -> server_id , 'unique_attrs' , 'dn' ),
$ldapservers -> GetValue ( $this -> server_id , 'unique_attrs' , 'pass' ));
if ( ! $con )
pla_error ( sprintf ( _ ( 'Unable to bind to <b>%s</b> with your with unique_attrs credentials. Please check your configuration file.' ), $this -> name ));
# Build our search filter to double check each attribute.
$searchfilter = '(|' ;
if ( is_array ( $new_value ))
foreach ( $new_value as $val )
$searchfilter .= sprintf ( '(%s=%s)' , $attr_name , clean_search_vals ( $val ));
elseif ( $new_value )
$searchfilter .= sprintf ( '(%s=%s)' , $attr_name , clean_search_vals ( $new_value ));
$searchfilter .= ')' ;
# Do we need a sanity check to just in case $new_value was null and hence the search string is bad?
foreach ( $this -> getBaseDN () as $base_dn ) {
# Do the search
$search = $this -> search ( $con , $base_dn , $searchfilter , array ( 'dn' , $attr_name ), 'sub' , false , LDAP_DEREF_ALWAYS );
foreach ( $search as $searchdn => $result )
# If one of the attributes is owned to somebody else, then we may as well die here.
if ( $result [ 'dn' ] != $dn )
if ( is_array ( $result [ $attr_name ])) {
foreach ( $result [ $attr_name ] as $attr )
foreach ( $new_value as $new_value_attr )
if ( $new_value_attr == $attr )
return $attr ;
} else {
foreach ( $new_value as $new_value_attr )
if ( $new_value_attr == $result [ $attr_name ])
return $result [ $attr_name ];
}
}
# If we get here, then it must be OK?
return ;
} else {
return ;
}
}
/**
* This function will test if a user is a member of a group .
*
* Inputs :
* @ param string $user membership value that is being checked
* @ param dn $group DN to see if user is a member
* @ return bool true | false
*/
function userIsMember ( $user , $group ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:userIsMember(): Entered with (%s,%s)' , 17 , get_class ( $this ), $user , $group );
$user = strtolower ( $user );
$group = $this -> getDNAttrs ( $group , false , $deref = LDAP_DEREF_NEVER );
if ( is_array ( $group )) {
$group = array_change_key_case ( $group );
# If you are using groupOfNames objectClass
if ( array_key_exists ( 'member' , $group ) && ! is_array ( $group [ 'member' ]))
$group [ 'member' ] = array ( $group [ 'member' ]);
if ( array_key_exists ( 'member' , $group ) &&
in_array ( $user , arrayLower ( $group [ 'member' ])))
return true ;
# If you are using groupOfUniqueNames objectClass
if ( array_key_exists ( 'uniquemember' , $group ) && ! is_array ( $group [ 'uniquemember' ]))
$group [ 'uniquemember' ] = array ( $group [ 'uniquemember' ]);
if ( array_key_exists ( 'uniquemember' , $group ) &&
in_array ( $user , arrayLower ( $group [ 'uniquemember' ])))
return true ;
return false ;
}
}
/**
*/
function userIsAllowedLogin ( $user ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:userIsAllowedLogin(): Entered with (%s)' , 17 , get_class ( $this ), $user );
global $ldapservers ;
$user = trim ( strtolower ( $user ));
if ( ! $ldapservers -> GetValue ( $this -> server_id , 'login' , 'allowed_dns' ))
return true ;
foreach ( $ldapservers -> GetValue ( $this -> server_id , 'login' , 'allowed_dns' ) as $login_allowed_dn ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:userIsAllowedLogin: Working through (%s)' , 80 , get_class ( $this ), $login_allowed_dn );
/* Check if $login_allowed_dn is an ldap search filter
Is first occurence of 'filter=' ( case ensitive ) at position 0 ? */
if ( preg_match ( '/^\([&|]\(/' , $login_allowed_dn )) {
$filter = $login_allowed_dn ;
foreach ( $this -> getBaseDN () as $base_dn ) {
$dn_array = array ();
$results = $this -> search ( null , $base_dn , $filter , array ( 'dn' ));
if ( DEBUG_ENABLED )
debug_log ( '%s:userIsAllowedLogin: Search, Filter [%s], BaseDN [%s] Results [%s]' , 16 ,
get_class ( $this ), $filter , $base_dn , $results );
if ( $results ) {
foreach ( $results as $result )
$dn_array [] = $result [ 'dn' ];
$dn_array = array_unique ( $dn_array );
if ( count ( $dn_array ) !== 0 )
foreach ( $dn_array as $result_dn ) {
if ( DEBUG_ENABLED )
debug_log ( '%s:userIsAllowedLogin: Comparing with [%s]' , 80 ,
get_class ( $this ), $result_dn );
# Check if $result_dn is a user DN
if ( strcasecmp ( $user , trim ( strtolower ( $result_dn ))) == 0 )
return true ;
# Check if $result_dn is a group DN
if ( $this -> userIsMember ( $user , $result_dn ))
return true ;
}
}
}
}
# Check if $login_allowed_dn is a user DN
if ( strcasecmp ( $user , trim ( strtolower ( $login_allowed_dn ))) == 0 )
return true ;
# Check if $login_allowed_dn is a group DN
if ( $this -> userIsMember ( $user , $login_allowed_dn ) )
return true ;
}
return false ;
}
/**
* Get the LDAP base DN for a named DN .
*
* @ param string $dn DN in question
* @ return string $base_dn
*/
function getDNBase ( $dn ) {
foreach ( $this -> getBaseDN () as $base_dn ) {
if ( preg_match ( '/' . $base_dn . '$/' , $dn ))
return $base_dn ;
}
return null ;
}
}
class LDAPservers {
/* All LDAP servers */
var $_ldapservers ;
/* Default settings for a new LDAP server configuration. */
var $default ;
function LDAPservers () {
$this -> default = new StdClass ;
$this -> default -> server [ 'name' ] = array (
'desc' => 'Server name' ,
'var' => 'name' ,
'default' => 'LDAP Server' );
$this -> default -> server [ 'host' ] = array (
'desc' => 'Host Name' ,
'var' => 'host' ,
'default' => '127.0.0.1' );
$this -> default -> server [ 'port' ] = array (
'desc' => 'Port Number' ,
'var' => 'port' ,
'default' => '389' );
$this -> default -> server [ 'base' ] = array (
'desc' => 'Base DN' ,
'default' => array ());
$this -> default -> server [ 'tls' ] = array (
'desc' => 'Connect using TLS' ,
'var' => 'tls' ,
'default' => false );
$this -> default -> server [ 'auth_type' ] = array (
'desc' => 'Authentication Type' ,
'var' => 'auth_type' ,
'default' => 'cookie' );
$this -> default -> server [ 'low_bandwidth' ] = array (
'desc' => 'Enable LOW Bandwidth optimisations' ,
'var' => 'low_bandwidth' ,
'default' => false );
$this -> default -> server [ 'read_only' ] = array (
'desc' => 'Server is in READ ONLY mode' ,
'var' => 'read_only' ,
'default' => false );
$this -> default -> server [ 'branch_rename' ] = array (
'desc' => 'Permit renaming branches' ,
'var' => 'branch_rename' ,
'default' => false );
/* This was created for IDS - since it doesnt present STRUCTURAL against objectClasses
definitions when reading the schema .*/
$this -> default -> server [ 'schema_oclass_default' ] = array (
'desc' => 'When reading the schema, and it doesnt specify objectClass type, default it to this' ,
'var' => 'schema_oclass_default' ,
'default' => null );
$this -> default -> login [ 'dn' ] = array (
'desc' => 'User Login DN' ,
'var' => 'login_dn' ,
'default' => '' );
$this -> default -> login [ 'pass' ] = array (
'desc' => 'User Login Password' ,
'var' => 'login_pass' ,
'default' => '' );
$this -> default -> login [ 'attr' ] = array (
'desc' => 'Attribute to use to find the users DN' ,
'var' => 'login_attr' ,
'default' => 'dn' );
$this -> default -> login [ 'class' ] = array (
'desc' => 'Strict login to users containing a specific objectClass' ,
'default' => null );
$this -> default -> login [ 'string' ] = array (
'desc' => 'Login string if using auth_type=string' ,
'var' => 'login_string' ,
'default' => null );
$this -> default -> login [ 'anon_bind' ] = array (
'desc' => 'Whether to allow anonymous binds' ,
2009-06-30 09:29:51 +00:00
'default' => true );
$this -> default -> login [ 'allowed_dns' ] = array (
'desc' => 'Limit logins to users who match any of the following LDAP filters' ,
'default' => array ());
$this -> default -> login [ 'timeout' ] = array (
'desc' => 'Session timout in seconds' ,
'var' => 'session_timeout' ,
'default' => session_cache_expire () - 1 );
$this -> default -> appearance [ 'password_hash' ] = array (
'desc' => 'Default HASH to use for passwords' ,
'var' => 'default_hash' ,
'default' => 'md5' );
$this -> default -> appearance [ 'show_create' ] = array (
'desc' => 'Show CREATE options in the tree' ,
'var' => 'show_create' ,
'default' => true );
$this -> default -> appearance [ 'visible' ] = array (
'desc' => 'Whether this LDAP server is visible in the tree' ,
'var' => 'visible' ,
'default' => true );
$this -> default -> auto_number [ 'enable' ] = array (
'desc' => 'Enable the AUTO UID feature' ,
'default' => true );
$this -> default -> auto_number [ 'mechanism' ] = array (
'desc' => 'Mechanism to use to search for automatic numbers' ,
'default' => 'search' );
$this -> default -> auto_number [ 'search_base' ] = array (
'desc' => 'Base DN to use for search mechanisms' ,
'default' => null );
$this -> default -> auto_number [ 'min' ] = array (
'desc' => 'Minimum UID number to start with' ,
'default' => 1000 );
$this -> default -> auto_number [ 'dn' ] = array (
'desc' => 'DN to use when evaluating numbers' ,
'default' => null );
$this -> default -> auto_number [ 'pass' ] = array (
'desc' => 'Password for DN to use when evaluating numbers' ,
'default' => null );
$this -> default -> unique_attrs [ 'dn' ] = array (
'desc' => 'DN to use when evaluating uniqueness' ,
'default' => null );
$this -> default -> unique_attrs [ 'pass' ] = array (
'desc' => 'Password for DN to use when evaluating uniqueness' ,
'default' => null );
$this -> default -> custom [ 'pages_prefix' ] = array (
'desc' => 'Path to custom pages' ,
'default' => null );
2009-06-30 10:26:08 +00:00
2009-06-30 09:29:51 +00:00
}
function SetValue ( $server_id , $key , $index , $value ) {
2009-06-30 09:40:37 +00:00
if ( defined ( 'DEBUG_ENABLED' ) && ( DEBUG_ENABLED ))
2009-06-30 10:26:08 +00:00
debug_log ( '%s::SetValue(): Entered with (%s,%s,%s,%s)' , 3 ,
get_class ( $this ), $server_id , $key , $index , $value );
2009-06-30 09:29:51 +00:00
if ( ! isset ( $this -> default -> $key ))
pla_error ( " ERROR: Setting a key [ $key ] that isnt predefined. " );
else
$default = $this -> default -> $key ;
if ( ! isset ( $default [ $index ]))
pla_error ( " ERROR: Setting a index [ $index ] that isnt predefined. " );
else
$default = $default [ $index ];
# Test if its should be an array or not.
if ( is_array ( $default [ 'default' ]) && ! is_array ( $value ))
pla_error ( " Error in configuration file, { $key } [' $index '] SHOULD be an array of values. " );
if ( ! is_array ( $default [ 'default' ]) && is_array ( $value ))
pla_error ( " Error in configuration file, { $key } [' $index '] should NOT be an array of values. " );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
# Some special processing.
if ( $key == 'server' ) {
switch ( $index ) {
case 'host' :
2009-06-30 09:40:37 +00:00
if ( strstr ( $value , " ldapi:// " ))
2009-06-30 09:29:51 +00:00
$this -> _ldapservers [ $server_id ][ $key ][ 'port' ] = false ;
break ;
}
}
$this -> _ldapservers [ $server_id ][ $key ][ $index ] = $value ;
}
function GetValue ( $server_id , $key , $index ) {
if ( isset ( $this -> _ldapservers [ $server_id ][ $key ][ $index ]))
$return = $this -> _ldapservers [ $server_id ][ $key ][ $index ];
else
$return = $this -> default -> { $key }[ $index ][ 'default' ];
2009-06-30 09:40:37 +00:00
if ( DEBUG_ENABLED )
2009-06-30 10:26:08 +00:00
debug_log ( '%s::GetValue(): Entered with (%s,%s,%s), Returning (%s)' , 3 ,
get_class ( $this ), $server_id , $key , $index , $return );
2009-06-30 09:40:37 +00:00
2009-06-30 09:29:51 +00:00
return $return ;
}
function GetServerList () {
return count ( $this -> _ldapservers ) ? array_keys ( $this -> _ldapservers ) : null ;
}
function Instance ( $server_id ) {
$instance = new LDAPserver ( $server_id );
foreach ( $this -> default as $key => $details ) {
foreach ( $details as $index => $value ) {
if ( isset ( $value [ 'var' ]))
$instance -> { $value [ 'var' ]} = $this -> GetValue ( $server_id , $key , $index );
}
}
return $instance ;
}
}
?>