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); } } ?>