summaryrefslogtreecommitdiffstats
path: root/lib/Auth
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2015-02-27 06:52:39 -0500
committerAleksander Machniak <machniak@kolabsys.com>2015-02-27 06:52:39 -0500
commit74319e95a36347f474e49bbbff04e95a561c106e (patch)
tree503d9ad427ed03e802d5f7f2a303c34bebc74eb6 /lib/Auth
parent4d06bf5dd18f1d21213b9e7b958cbc967fb03dd1 (diff)
downloadwebadmin-74319e95a36347f474e49bbbff04e95a561c106e.tar.gz
Move domain_root_dn() and cache related methods into Net_LDAP3 (#4744)
Diffstat (limited to 'lib/Auth')
-rw-r--r--lib/Auth/LDAP.php335
1 files changed, 51 insertions, 284 deletions
diff --git a/lib/Auth/LDAP.php b/lib/Auth/LDAP.php
index a2d0ba3..1588500 100644
--- a/lib/Auth/LDAP.php
+++ b/lib/Auth/LDAP.php
@@ -40,9 +40,6 @@ class LDAP extends Net_LDAP3 {
$this->conf = Conf::get_instance();
- // Causes nesting levels to be too deep...?
- //$this->config_set('config_get_hook', array($this, "_config_get"));
-
$this->config_set("debug", Log::mode() == Log::TRACE);
$this->config_set("log_hook", array($this, "_log"));
@@ -53,6 +50,16 @@ class LDAP extends Net_LDAP3 {
$this->config_set("login_filter", $this->conf->get("kolab_wap", "login_filter"));
$this->config_set("vlv", $this->conf->get("ldap", "vlv", Conf::AUTO));
+ // configure the cache
+ $memcache_hosts = $this->conf->get('kolab_wap', 'memcache_hosts');
+ $this->config_set("memcache_pconnect", $this->conf->get('kolab_wap', 'memcache_pconnect', Conf::BOOL));
+ $this->config_set("memcache_hosts", $memcache_hosts);
+ $this->config_set("cache", !empty($memcache_hosts));
+
+ $this->config_set("domain_base_dn", $this->conf->get('ldap', 'domain_base_dn'));
+ $this->config_set("domain_filter", $this->conf->get('ldap', 'domain_filter'));
+ $this->config_set("domain_name_attribute", $this->conf->get('ldap', 'domain_name_attribute'));
+
// See if we are to connect to any domain explicitly defined.
if (empty($domain)) {
// If not, attempt to get the domain from the session.
@@ -196,8 +203,7 @@ class LDAP extends Net_LDAP3 {
}
// Query the ACI for the primary domain
- if ($domain_entry = $this->_find_domain($primary_domain)) {
- $domain_entry = array_shift($domain_entry);
+ if ($domain_entry = $this->find_domain($primary_domain)) {
if (in_array('inetdomainbasedn', $domain_entry)) {
$_base_dn = $domain_entry['inetdomainbasedn'];
}
@@ -424,7 +430,7 @@ class LDAP extends Net_LDAP3 {
$domain_dn = $this->entry_dn($domain, array(), $domain_base_dn);
if (!$domain_dn) {
- $result = $this->_find_domain($domain, $attributes);
+ $result = $this->find_domain($domain, $attributes);
}
else {
$result = $this->_read($domain_dn, $attributes);
@@ -1031,6 +1037,43 @@ class LDAP extends Net_LDAP3 {
}
/**
+ * Find domain by name
+ *
+ * @param string $domain Domain name
+ * @param array $attributes Result attributes
+ *
+ * @return array|bool Domain attributes or False on error
+ */
+ public function find_domain($domain, $attributes = array('*'))
+ {
+ if (empty($domain)) {
+ return false;
+ }
+
+ $ckey = 'domain::' . $domain . '::' . md5(implode(',', $attributes));
+
+ if (isset($this->icache[$ckey])) {
+ return $this->icache[$ckey];
+ }
+
+ // connect and bind...
+ if ($_SESSION['user'] && $_SESSION['user']->user_bind_dn) {
+ $bind_dn = $_SESSION['user']->user_bind_dn;
+ $bind_pw = $_SESSION['user']->user_bind_pw;
+ }
+ else {
+ $bind_dn = $this->conf->get('service_bind_dn');
+ $bind_pw = $this->conf->get('service_bind_pw');
+ }
+
+ if (!$this->bind($bind_dn, $bind_pw)) {
+ return false;
+ }
+
+ return parent::find_domain($domain, $attributes);
+ }
+
+ /**
* Wrapper for search_entries()
*/
protected function _list($base_dn, $filter, $scope, $attributes, $search, $params)
@@ -1164,27 +1207,6 @@ class LDAP extends Net_LDAP3 {
return $base_dn;
}
- public function _config_get($key, $default = NULL)
- {
- $key_parts = explode("_", $key);
- $this->_log(LOG_DEBUG, var_export($key_parts));
-
- while (!empty($key_parts)) {
- $value = $this->conf->get(implode("_", $key_parts));
- if (empty($value)) {
- $_discard = array_shift($key_parts);
- } else {
- break;
- }
- }
-
- if (empty($value)) {
- return $default;
- } else {
- return $value;
- }
- }
-
public function _log($level, $msg)
{
if (strstr($_SERVER["REQUEST_URI"], "/api/")) {
@@ -1271,7 +1293,6 @@ class LDAP extends Net_LDAP3 {
// List group memberships
$user_groups = $this->find_user_groups($_SESSION['user']->user_bind_dn);
- console("User's groups", $user_groups);
foreach ($user_groups as $user_group_dn) {
if ($user_is_admin)
@@ -1305,7 +1326,7 @@ class LDAP extends Net_LDAP3 {
'attributeLevelRights' => array(),
);
- $subject = $this->_search($subject_dn);
+ $subject = $this->search($subject_dn);
if (!$subject) {
return $rights;
@@ -1408,55 +1429,7 @@ class LDAP extends Net_LDAP3 {
************ Shortcut functions ****************
***********************************************************/
- /**
- * Translate a domain name into it's corresponding root dn.
- */
- private function domain_root_dn($domain)
- {
- if (empty($domain)) {
- return false;
- }
-
- $ckey = 'domain.root::' . $domain;
- if ($result = $this->icache[$ckey]) {
- return $result;
- }
-
- $this->_log(LOG_DEBUG, "Auth::LDAP::domain_root_dn(\$domain = $domain)");
-
- if ($entry_attrs = $this->_find_domain($domain)) {
- $entry_attrs = array_shift($entry_attrs);
-
- $domain_name_attribute = $this->conf->get('ldap', 'domain_name_attribute');
- if (empty($domain_name_attribute)) {
- $domain_name_attribute = 'associateddomain';
- }
-
- if (is_array($entry_attrs)) {
- if (array_key_exists('inetdomainbasedn', $entry_attrs) && !empty($entry_attrs['inetdomainbasedn'])) {
- $domain_root_dn = $entry_attrs['inetdomainbasedn'];
- }
- else {
- if (is_array($entry_attrs[$domain_name_attribute])) {
- $domain_root_dn = $this->_standard_root_dn($entry_attrs[$domain_name_attribute][0]);
- }
- else {
- $domain_root_dn = $this->_standard_root_dn($entry_attrs[$domain_name_attribute]);
- }
- }
- }
- }
-
- if (empty($domain_root_dn)) {
- $domain_root_dn = $this->_standard_root_dn($domain);
- }
-
- $this->icache[$ckey] = $domain_root_dn;
-
- return $domain_root_dn;
- }
-
- private function _read($entry_dn, $attributes = array('*'))
+ protected function _read($entry_dn, $attributes = array('*'))
{
$result = $this->search($entry_dn, '(objectclass=*)', 'base', $attributes);
@@ -1469,112 +1442,6 @@ class LDAP extends Net_LDAP3 {
}
}
- private function _search($base_dn, $filter = '(objectclass=*)', $attributes = array('*'))
- {
- $result = $this->search($base_dn, $filter, 'sub', $attributes);
- $this->_log(LOG_DEBUG, "Auth::LDAP::_search on $base_dn with $filter for attributes: " . var_export($attributes, true) . " with result: " . var_export($result, true));
- return $result;
- }
-
- /**
- * Find domain by name
- *
- * @param string $domain Domain name
- * @param array $attributes Result attributes
- *
- * @return array Domain records indexed by base DN
- */
- private function _find_domain($domain, $attributes = array('*'))
- {
- $this->_log(LOG_DEBUG, "Auth::LDAP::_find_domain($domain)");
-
- $ckey = 'domain::' . $domain;
-
- if (isset($this->icache[$ckey])) {
- return $this->icache[$ckey];
- }
-
- // use memcache
- $domain_dn = $this->get_cache_data($ckey);
-
- // connect and bind only if needed...
- if (empty($this->_current_bind_dn)) {
- $bind_dn = $_SESSION['user'] ? $_SESSION['user']->user_bind_dn : null;
-
- // ...and it is needed if we ned to call _read() or _search() below
- if (!$domain_dn || !$bind_dn) {
- if ($bind_dn) {
- $bind_pw = $_SESSION['user']->user_bind_pw;
- }
- else {
- $bind_dn = $this->conf->get('service_bind_dn');
- $bind_pw = $this->conf->get('service_bind_pw');
- }
-
- if (!$this->bind($bind_dn, $bind_pw)) {
- return false;
- }
- }
- }
-
- // Got cached domain DN, no need for searching, just read
- if ($domain_dn) {
- return $this->icache[$ckey] = $this->_read($domain_dn, $attributes);
- }
-
- $domain_base_dn = $this->conf->get('ldap', 'domain_base_dn');
- $domain_filter = $this->conf->get('ldap', 'domain_filter');
- $domain_name_attribute = $this->conf->get('ldap', 'domain_name_attribute');
-
- if (empty($domain_name_attribute)) {
- $domain_name_attribute = 'associateddomain';
- }
-
- $domain_filter = "(&" . $domain_filter . "(" . $domain_name_attribute . "=" . $domain . "))";
-
- if ($result = $this->_search($domain_base_dn, $domain_filter, $attributes)) {
- $result = $result->entries(true);
-
- // cache domain DN
- if (count($result) == 1) {
- $this->set_cache_data($ckey, key($result));
- }
- }
-
- return $this->icache[$ckey] = $result;
- }
-
- /**
- * From a domain name, such as 'kanarip.com', create a standard root
- * dn, such as 'dc=kanarip,dc=com'.
- *
- * As the parameter $associatedDomains, either pass it an array (such
- * as may have been returned by ldap_get_entries() or perhaps
- * ldap_list()), where the function will assume the first value
- * ($array[0]) to be the uber-level domain name, or pass it a string
- * such as 'kanarip.nl'.
- *
- * @return string
- */
- private function _standard_root_dn($associatedDomains)
- {
- if (is_array($associatedDomains)) {
- // Usually, the associatedDomain in position 0 is the naming attribute associatedDomain
- if ($associatedDomains['count'] > 1) {
- // Issue a debug message here
- $relevant_associatedDomain = $associatedDomains[0];
- }
- else {
- $relevant_associatedDomain = $associatedDomains[0];
- }
- }
- else {
- $relevant_associatedDomain = $associatedDomains;
- }
-
- return "dc=" . implode(',dc=', explode('.', $relevant_associatedDomain));
- }
-
/**
* Finds nsslapd-directory for specified domain
*/
@@ -1608,104 +1475,4 @@ class LDAP extends Net_LDAP3 {
return $directory;
}
-
- /**
- * Get global handle for memcache access
- *
- * @return object Memcache
- */
- public function get_cache()
- {
- if (!isset($this->memcache)) {
- // no memcache support in PHP
- if (!class_exists('Memcache')) {
- $this->memcache = false;
- return false;
- }
-
- // add all configured hosts to pool
- $pconnect = $this->conf->get('kolab_wap', 'memcache_pconnect', Conf::BOOL);
- $hosts = $this->conf->get('kolab_wap', 'memcache_hosts');
-
- if ($hosts) {
- $this->memcache = new Memcache;
- $this->mc_available = 0;
-
- $hosts = explode(',', $hosts);
- foreach ($hosts as $host) {
- $host = trim($host);
- if (substr($host, 0, 7) != 'unix://') {
- list($host, $port) = explode(':', $host);
- if (!$port) $port = 11211;
- }
- else {
- $port = 0;
- }
-
- $this->mc_available += intval($this->memcache->addServer(
- $host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
- }
-
- // test connection and failover (will result in $this->mc_available == 0 on complete failure)
- $this->memcache->increment('__CONNECTIONTEST__', 1); // NOP if key doesn't exist
- }
-
- if (!$this->mc_available) {
- $this->memcache = false;
- }
- }
-
- return $this->memcache;
- }
-
- /**
- * Callback for memcache failure
- */
- public function memcache_failure($host, $port)
- {
- static $seen = array();
-
- // only report once
- if (!$seen["$host:$port"]++) {
- $this->mc_available--;
- $this->_log(LOG_ERR, "Memcache failure on host $host:$port");
- }
- }
-
- /**
- * Get cached data
- *
- * @param string $key Cache key
- *
- * @return mixed Cached value
- */
- public function get_cache_data($key)
- {
- if ($cache = $this->get_cache()) {
- return $cache->get($key);
- }
- }
-
- /**
- * Store cached data
- *
- * @param string $key Cache key
- * @param mixed $data Data
- * @param int $ttl Cache TTL in seconds
- *
- * @return bool False on failure or when cache is disabled, True if data was saved succesfully
- */
- public function set_cache_data($key, $data, $ttl = 3600)
- {
- if ($cache = $this->get_cache()) {
- if (!$cache->replace($key, $data, MEMCACHE_COMPRESSED, $ttl)) {
- return $cache->set($key, $data, MEMCACHE_COMPRESSED, $ttl);
- }
- else {
- return true;
- }
- }
-
- return false;
- }
}