This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
lnldap/classes/Kohana/Database/LDAP.php

268 lines
7.1 KiB
PHP
Raw Normal View History

<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class takes care of communicating with LDAP
*
* @package Kohana/LDAP
* @category Database/LDAP
* @author Deon George
* @copyright (c) phpLDAPadmin Development Team
* @license http://dev.phpldapadmin.org/license.html
*/
abstract class Kohana_Database_LDAP extends Database {
// Our required abstract functions
public function set_charset($charset) {}
public function query($type, $sql, $as_object = FALSE, array $params = NULL) {}
public function begin($mode = NULL) {}
public function commit() {}
public function rollback() {}
public function list_tables($like = NULL) {}
public function list_columns($table, $like = NULL, $add_prefix = TRUE) {}
public function escape($value) { return $value;}
/** OVERRIDES **/
/**
* We override this parent function, since LDAP doesnt quote columns
* @note Override
*/
public function quote_column($column) {
return $column;
}
/** Database_LDAP **/
/**
* @var boolean Whether we are full connected connection & bind
*/
protected $_connected = FALSE;
/**
* @var string Our default usage when connection
*/
public static $usage = 'default';
private function _bind($u,$p) {
/*
// @todo To implement
// If SASL has been configured for binding, then start it now.
if ($this->isSASLEnabled())
$br = $this->startSASL($this->_r,$method);
// Normal bind...
else
*/
if (Kohana::$profiling)
$benchmark = Profiler::start("Database Bind ({$this->_instance})", $this->_instance);
try {
$br = ldap_bind($this->_connection,$u,$p);
} catch (Exception $e) {
// This benchmark is worthless
if (isset($benchmark))
Profiler::delete($benchmark);
return FALSE;
}
if (! $br)
return FALSE;
$this->_connected = TRUE;
/*
// @todo To implement
# If this is a proxy session, we need to switch to the proxy user
if ($this->isProxyEnabled() && $bind['id'] && $method != 'anon')
if (! $this->startProxy($this->_r,$method)) {
$CACHE[$this->index][$method] = null;
}
*/
/*
// @todo To implement
if (function_exists('run_hook'))
run_hook('post_connect',array('server_id'=>$this->index,'method'=>$method,'id'=>$bind['id']));
*/
if (isset($benchmark))
Profiler::stop($benchmark);
return $br;
}
/**
* Bind to the LDAP server
*
* @param string User DN to connect with, or blank for anonymous
* @param string Password for DN, or blank for anonymous
*/
public function bind($user,$pass) {
// If we are already connected, no need to re-bind.
if ($this->_connected)
return $this;
// Make sure we are connected.
$this->_connection OR $this->connect();
// Do we need to do an search to find the DN
if (! empty($this->_config['login_attr']) AND strtoupper($this->_config['login_attr']) != 'DN') {
// Do we need to authenticate for this search?
// Extract the connection parameters, adding required variabels
extract($this->_config['connection'] + array(
'username' => '',
'password' => '',
'hostname' => '',
'port' => '',
));
// Prevent this information from showing up in traces
unset($this->_config['connection']['username'], $this->_config['connection']['password']);
// Sanity check
if ($this->_instance == 'auth')
throw new Kohana_Exception('We shouldnt be authing an auth');
$config = array(
'login_attr'=>'DN',
'type'=>$this->_config['type'],
'connection'=>array(
'hostname'=>$hostname,
'port'=>$port,
),
);
try {
$x = Database_LDAP::factory('auth',NULL,$config);
// Our Auth Bind credentials are wrong
if (! $x->bind($username,$password))
return FALSE;
$u = $x->search(NULL)
->scope('sub')
->where($this->_config['login_attr'],'=',$user)
->run();
if (! $u)
return FALSE;
} catch (Exception $e) {
// If we are a command line, we can just print the error
echo _('Unable to bind to LDAP server with CONFIG settings, please check them.');
echo _('The error message is').': '.$e->getMessage();
die();
}
foreach ($u as $base => $entries)
foreach ($entries as $dn => $details)
if ($this->_bind($details['dn'],$pass)) {
// \xFF is a better delimiter, but the PHP driver uses underscore
$this->_connection_id = sha1($this->_instance.'_'.$details['dn']);
return $this;
}
// We didnt find an AUTH DN to bind with
return FALSE;
}
// Bind
if ($this->_bind($user,$pass))
return $this;
else
return FALSE;
}
/**
* Create a connection to an LDAP server
*/
public function connect() {
if ($this->_connection)
return;
// Extract the connection parameters, adding required variabels
extract($this->_config['connection'] + array(
'hostname' => '',
'port' => '',
));
/*
// @todo To implement
if (function_exists('run_hook'))
run_hook('pre_connect',array('server_id'=>$this->index,'method'=>$method));
*/
// Benchmark this connection for the current instance
if (Kohana::$profiling)
$benchmark = Profiler::start("Database Connect ({$this->_instance})", $this->_instance);
$r = (! empty($this->_config['port'])) ? ldap_connect($hostname,$port) : ldap_connect($hostname);
if (! is_resource($r)) {
// This benchmark is worthless
if (isset($benchmark))
Profiler::delete($benchmark);
throw HTTP_Exception::factory(501,'UNHANDLED, $r is not a resource');
}
// Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
ldap_set_option($r,LDAP_OPT_PROTOCOL_VERSION,3);
/* 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($r,LDAP_OPT_REFERRALS,0);
/*
// @todo To implement
# Try to fire up TLS is specified in the config
if ($this->isTLSEnabled())
$this->startTLS($this->_connection);
*/
if (isset($benchmark))
Profiler::stop($benchmark);
$this->_connection = $r;
}
public function connected() {
return ($this->_connection AND $this->_connected);
}
/**
* A wrapper for parent::instance(), so that we can create multiple connections
* to the same LDAP server with different credentials/purposes.
*
* @param string A free form usage name, for this connection
* @param string A database configuration name, as per parent::instance()
* @param array An alternative database configuration to use for $name.
* @see Database::instance();
*/
public static function factory($usage=NULL,$name=NULL,array $config=NULL) {
// Use the default instance name
if ($usage === NULL)
$usage = Database_LDAP::$usage;
if (! isset(Database::$instances[$usage])) {
// Use the default instance name
if ($name === NULL)
$name = Database::$default;
// Load the configuration for this database
if ($config === NULL)
$config = Kohana::$config->load('database')->$name;
}
return parent::instance($usage,$config);
}
public function search($base=array()) {
return new Database_LDAP_Search($this->_connection,$base);
}
}
?>