2006-12-02 04:36:16 +00:00
< ? php
/*
2011-12-31 17:42:56 +00:00
* e107 website system
*
* Copyright ( C ) 2008 - 2012 e107 Inc ( e107 . org )
* Released under the terms and conditions of the
* GNU General Public License ( http :// www . gnu . org / licenses / gpl . txt )
*
* LDAP authorisation for alt_auth plugin
*
* $URL $
* $Id $
*/
/**
* e107 Alternate authorisation plugin
*
* @ package e107_plugins
* @ subpackage alt_auth
* @ version $Id $ ;
*/
2006-12-02 04:36:16 +00:00
class auth_login
{
2011-12-31 17:42:56 +00:00
private $server ; // The LDAP server (array of possible servers)
private $dn ; // LDAP domain
private $ou ; // LDAP OU
private $usr ; // User name to log on to server
private $pwd ; // Password to log on to server
private $serverType ; // Server type = LDAP/AD/eDirectory
public $ldapErrorCode ; // LDAP error code on exit
public $ldapErrorText ; // LDAP error string on exit
public $ErrorText ; // e107 error string on exit
private $connection ; // LDAP resource for connection
private $ldapVersion ; // Version of LDAP to use
public $Available = FALSE ; // Flag indicates whether DB connection available
private $filter ; // Filter for eDirectory search
private $copyAttribs ; // Any attributes which are to be copied on successful login
private $copyMethods ; // Methods which are to be used to copy attributes
2006-12-02 04:36:16 +00:00
2011-12-31 17:42:56 +00:00
/**
* Read configuration , initialise connection to LDAP database
*
* @ return AUTH_xxxx result code
*/
public function auth_login ()
2006-12-02 04:36:16 +00:00
{
2008-07-25 19:33:04 +00:00
$this -> copyAttribs = array ();
2008-12-23 20:31:30 +00:00
$this -> copyMethods = array ();
2011-12-31 17:42:56 +00:00
$sql = e107 :: getDB ( 'altAuth' );
$sql -> db_Select ( 'alt_auth' , '*' , " auth_type = 'ldap' " );
2008-12-01 21:47:17 +00:00
while ( $row = $sql -> db_Fetch ())
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
$ldap [ $row [ 'auth_parmname' ]] = base64_decode ( base64_decode ( $row [ 'auth_parmval' ]));
if (( strpos ( $row [ 'auth_parmname' ], 'ldap_xf_' ) === 0 ) && $ldap [ $row [ 'auth_parmname' ]]) // Attribute to copy on successful login
{
$this -> copyAttribs [ substr ( $row [ 'auth_parmname' ], strlen ( 'ldap_xf_' ))] = $ldap [ $row [ 'auth_parmname' ]]; // Key = LDAP attribute. Value = e107 field name
}
2008-12-23 20:31:30 +00:00
elseif (( strpos ( $row [ 'auth_parmname' ], 'ldap_pm_' ) === 0 ) && $ldap [ $row [ 'auth_parmname' ]] && ( $ldap [ $row [ 'auth_parmname' ]] != 'none' )) // Method to use to copy parameter
{ // Any fields with non-null 'copy' methods
$this -> copyMethods [ substr ( $row [ 'auth_parmname' ], strlen ( 'ldap_pm_' ))] = $ldap [ $row [ 'auth_parmname' ]]; // Key = e107 field name. Value = copy method
}
unset ( $row [ 'auth_parmname' ]);
2006-12-02 04:36:16 +00:00
}
2011-12-31 17:42:56 +00:00
$this -> server = explode ( ',' , $ldap [ 'ldap_server' ]);
2006-12-02 04:36:16 +00:00
$this -> serverType = $ldap [ 'ldap_servertype' ];
$this -> dn = $ldap [ 'ldap_basedn' ];
2008-12-23 20:31:30 +00:00
$this -> ou = $ldap [ 'ldap_ou' ];
2006-12-02 04:36:16 +00:00
$this -> usr = $ldap [ 'ldap_user' ];
$this -> pwd = $ldap [ 'ldap_passwd' ];
$this -> ldapVersion = $ldap [ 'ldap_version' ];
$this -> filter = ( isset ( $ldap [ 'ldap_edirfilter' ]) ? $ldap [ 'ldap_edirfilter' ] : " " );
2008-12-01 21:47:17 +00:00
if ( ! function_exists ( 'ldap_connect' ))
2006-12-02 04:36:16 +00:00
{
2011-12-31 17:42:56 +00:00
return AUTH_NORESOURCE ;
2006-12-02 04:36:16 +00:00
}
2008-12-01 21:47:17 +00:00
if ( ! $this -> connect ())
2006-12-02 04:36:16 +00:00
{
return AUTH_NOCONNECT ;
}
2011-12-31 17:42:56 +00:00
$this -> Available = TRUE ;
return AUTH_SUCCESS ;
2006-12-02 04:36:16 +00:00
}
2011-12-31 17:42:56 +00:00
/**
* Retrieve and construct error strings
*/
private function makeErrorText ( $extra = '' )
2008-09-02 19:39:13 +00:00
{
2008-12-01 21:47:17 +00:00
$this -> ldapErrorCode = ldap_errno ( $this -> connection );
$this -> ldapErrorText = ldap_error ( $this -> connection );
$this -> ErrorText = $extra . ' ' . $this -> ldapErrorCode . ': ' . $this -> ldapErrorText ;
2008-09-02 19:39:13 +00:00
}
2011-12-31 17:42:56 +00:00
/**
* Connect to the LDAP server
*
* @ return boolean TRUE for success , FALSE for failure
*/
public function connect ()
2006-12-02 04:36:16 +00:00
{
foreach ( $this -> server as $key => $host )
{
$this -> connection = ldap_connect ( $host );
2008-12-01 21:47:17 +00:00
if ( $this -> connection )
{
if ( $this -> ldapVersion == 3 || $this -> serverType == " ActiveDirectory " )
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
@ ldap_set_option ( $this -> connection , LDAP_OPT_PROTOCOL_VERSION , 3 );
2006-12-02 04:36:16 +00:00
}
return true ;
}
}
2008-12-01 21:47:17 +00:00
2006-12-02 04:36:16 +00:00
$this -> ldapErrorCode = - 1 ;
$this -> ldapErrorText = " Unable to connect to any server " ;
2008-12-01 21:47:17 +00:00
$this -> ErrorText = $this -> ldapErrorCode . ': ' . $this -> ldapErrorText ;
2006-12-02 04:36:16 +00:00
return false ;
}
2011-12-31 17:42:56 +00:00
/**
* Close the connection to the LDAP server
*/
public function close ()
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
if ( !@ ldap_close ( $this -> connection ))
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
$this -> makeErrorText (); // Read the error code and explanatory string
2006-12-02 04:36:16 +00:00
return false ;
}
else
{
return true ;
}
}
2011-12-31 17:42:56 +00:00
/**
* Validate login credentials
*
* @ param string $uname - The user name requesting access
* @ param string $pass - Password to use ( usually plain text )
* @ param pointer & $newvals - pointer to array to accept other data read from database
* @ param boolean $connect_only - TRUE to simply connect to the server
*
* @ return integer result ( AUTH_xxxx )
*
* On a successful login , & $newvals array is filled with the requested data from the server
*/
2008-12-01 21:47:17 +00:00
function login ( $uname , $pass , & $newvals , $connect_only = false )
2006-12-02 04:36:16 +00:00
{
/* Construct the full DN , eg :-
** " uid=username, ou=People, dc=orgname,dc=com "
*/
2008-12-01 21:47:17 +00:00
// echo "Login to server type: {$this->serverType}<br />";
2008-07-25 19:33:04 +00:00
$current_filter = " " ;
2006-12-02 04:36:16 +00:00
if ( $this -> serverType == " ActiveDirectory " )
{
2008-12-01 21:47:17 +00:00
$checkDn = $uname . '@' . $this -> dn ;
// added by Father Barry Keal
// $current_filter = "(sAMAccountName={$uname})"; for pre windows 2000
$current_filter = " (userprincipalname= { $uname } @ { $this -> dn } ) " ; // for 2000 +
// end add by Father Barry Keal
2006-12-02 04:36:16 +00:00
}
else
{
2008-12-01 21:47:17 +00:00
if ( $this -> usr != '' && $this -> pwd != '' )
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
$this -> result = ldap_bind ( $this -> connection , $this -> usr , $this -> pwd );
2006-12-02 04:36:16 +00:00
}
else
{
2008-12-01 21:47:17 +00:00
$this -> result = ldap_bind ( $this -> connection );
2006-12-02 04:36:16 +00:00
}
2008-12-01 21:47:17 +00:00
if ( $this -> result === false )
{
// echo "LDAP bind failed<br />";
$this -> makeErrorText (); // Read the error code and explanatory string
return AUTH_NOCONNECT ;
}
// In ldap_auth.php, should look like this instead for eDirectory
// $query = ldap_search($this -> connection, $this -> dn, "cn=".$uname);
if ( $this -> serverType == " eDirectory " )
{
$current_filter = " (&(cn= { $uname } ) " . $this -> filter . " ) " ;
}
else
{
$current_filter = " uid= " . $uname ;
}
// echo "LDAP search: {$this->dn}, {$current_filter}<br />";
$query = ldap_search ( $this -> connection , $this -> dn , $current_filter );
2006-12-02 04:36:16 +00:00
2008-12-01 21:47:17 +00:00
if ( $query === false )
{
// Could not perform query to LDAP directory
echo " LDAP - search for user failed<br /> " ;
$this -> makeErrorText (); // Read the error code and explanatory string
return AUTH_NOCONNECT ;
}
else
{
$query_result = ldap_get_entries ( $this -> connection , $query );
2006-12-02 04:36:16 +00:00
2008-12-01 21:47:17 +00:00
if ( $query_result [ " count " ] != 1 )
{
if ( $connect_only ) return AUTH_SUCCESS ;
else return AUTH_NOUSER ;
2006-12-02 04:36:16 +00:00
}
else
{
2008-12-01 21:47:17 +00:00
$checkDn = $query_result [ 0 ][ " dn " ];
$this -> close ();
$this -> connect ();
2006-12-02 04:36:16 +00:00
}
}
2008-12-01 21:47:17 +00:00
}
// Try and connect...
$this -> result = ldap_bind ( $this -> connection , $checkDn , $pass );
if ( $this -> result )
{
// Connected OK - login credentials are fine!
// But bind can return success even if no password! Does reject an invalid password, however
if ( $connect_only ) return AUTH_SUCCESS ;
if ( trim ( $pass ) == '' ) return AUTH_BADPASSWORD ; // Pick up a blank password
if ( count ( $this -> copyAttribs ) == 0 ) return AUTH_SUCCESS ; // No attributes required - we're done
$ldap_attributes = array_values ( array_unique ( $this -> copyAttribs ));
if ( $this -> serverType == " ActiveDirectory " )
{ // If we are using AD then build up the full string from the fqdn
$altauth_tmp = explode ( '.' , $this -> dn );
$checkDn = '' ;
foreach ( $altauth_tmp as $$altauth_dc )
{
$checkDn .= " ,DC= { $altauth_dc } " ;
}
// prefix with the OU
$checkDn = $this -> ou . $checkDn ;
}
$this -> result = ldap_search ( $this -> connection , $checkDn , $current_filter , $ldap_attributes );
if ( $this -> result )
2008-07-25 19:33:04 +00:00
{
2008-12-01 21:47:17 +00:00
$entries = ldap_get_entries ( $this -> connection , $this -> result );
if ( count ( $entries ) == 2 ) // All OK
{
for ( $j = 0 ; $j < $entries [ 0 ][ 'count' ]; $j ++ )
{
$k = $entries [ 0 ][ $j ]; // LDAP attribute name
$tlv = $entries [ 0 ][ $k ]; // Array of LDAP data
if ( is_array ( $tlv ) && count ( $tempKeys = array_keys ( $this -> copyAttribs , $k ))) // This bit executed if we've successfully got some data. Key is the attribute name, then array of data
{
foreach ( $tempKeys as $tk ) // Single LDAP attribute may be mapped to several fields
{
2008-12-23 20:31:30 +00:00
// $newvals[$tk] = $this->translate($tlv[0]); // Just grab the first value
$newvals [ $tk ] = $tlv [ 0 ]; // Just grab the first value
2008-12-01 21:47:17 +00:00
}
}
else
{
// echo " Unexpected non-array value - Key: {$k} Value: {$tlv}<br />";
$this -> makeErrorText (); // Read the error code and explanatory string
return AUTH_NOCONNECT ; // Not really a suitable return code for this - its an error
}
}
}
else
{
// echo "Got wrong number of entries<br />";
$this -> makeErrorText (); // Read the error code and explanatory string
return AUTH_NOUSER ; // Bit debateable what to return if this happens
}
2008-07-25 19:33:04 +00:00
}
2008-12-01 21:47:17 +00:00
else // Probably a bit strange if we don't get any info back - but possible
{
// echo "No results!<br />";
}
2008-07-25 19:33:04 +00:00
2008-12-01 21:47:17 +00:00
return AUTH_SUCCESS ;
2006-12-02 04:36:16 +00:00
}
else
{
2011-12-31 17:42:56 +00:00
/* Login failed . Return error code .
** The common error codes and reasons are listed below :
2006-12-02 04:36:16 +00:00
** ( for iPlanet , other servers may differ )
** 19 - Account locked out ( too many invalid login attempts )
** 32 - User does not exist
** 49 - Wrong password
** 53 - Account inactive ( manually locked out by administrator )
*/
2008-12-01 21:47:17 +00:00
$this -> makeErrorText (); // Read the error code and explanatory string
2006-12-02 04:36:16 +00:00
2008-12-01 21:47:17 +00:00
switch ( $this -> ldapErrorCode )
2006-12-02 04:36:16 +00:00
{
2008-12-01 21:47:17 +00:00
case 32 :
return AUTH_NOUSER ;
case 49 :
return AUTH_BADPASSWORD ;
2006-12-02 04:36:16 +00:00
}
// return error code as if it never connected, maybe change that in the future
2008-12-01 21:47:17 +00:00
return AUTH_NOCONNECT ;
2006-12-02 04:36:16 +00:00
}
}
}
2008-12-01 21:47:17 +00:00
2006-12-02 04:36:16 +00:00
?>