summaryrefslogtreecommitdiffstats
path: root/apps/user_ldap/lib/connection.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/user_ldap/lib/connection.php')
-rw-r--r--apps/user_ldap/lib/connection.php299
1 files changed, 255 insertions, 44 deletions
diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php
index 7046cbbfc78..acc33e047c6 100644
--- a/apps/user_ldap/lib/connection.php
+++ b/apps/user_ldap/lib/connection.php
@@ -4,7 +4,7 @@
* ownCloud – LDAP Access
*
* @author Arthur Schiwon
- * @copyright 2012 Arthur Schiwon blizzz@owncloud.com
+ * @copyright 2012, 2013 Arthur Schiwon blizzz@owncloud.com
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -25,6 +25,7 @@ namespace OCA\user_ldap\lib;
class Connection {
private $ldapConnectionRes = null;
+ private $configPrefix;
private $configID;
private $configured = false;
@@ -35,6 +36,8 @@ class Connection {
protected $config = array(
'ldapHost' => null,
'ldapPort' => null,
+ 'ldapBackupHost' => null,
+ 'ldapBackupPort' => null,
'ldapBase' => null,
'ldapBaseUsers' => null,
'ldapBaseGroups' => null,
@@ -48,6 +51,7 @@ class Connection {
'ldapUserFilter' => null,
'ldapGroupFilter' => null,
'ldapGroupDisplayName' => null,
+ 'ldapGroupMemberAssocAttr' => null,
'ldapLoginFilter' => null,
'ldapQuotaAttribute' => null,
'ldapQuotaDefault' => null,
@@ -55,15 +59,24 @@ class Connection {
'ldapCacheTTL' => null,
'ldapUuidAttribute' => null,
'ldapOverrideUuidAttribute' => null,
+ 'ldapOverrideMainServer' => false,
+ 'ldapConfigurationActive' => false,
+ 'ldapAttributesForUserSearch' => null,
+ 'ldapAttributesForGroupSearch' => null,
'homeFolderNamingRule' => null,
'hasPagedResultSupport' => false,
);
- public function __construct($configID = 'user_ldap') {
+ /**
+ * @brief Constructor
+ * @param $configPrefix a string with the prefix for the configkey column (appconfig table)
+ * @param $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections
+ */
+ public function __construct($configPrefix = '', $configID = 'user_ldap') {
+ $this->configPrefix = $configPrefix;
$this->configID = $configID;
$this->cache = \OC_Cache::getGlobalCache();
$this->config['hasPagedResultSupport'] = (function_exists('ldap_control_paged_result') && function_exists('ldap_control_paged_result_response'));
- \OCP\Util::writeLog('user_ldap', 'PHP supports paged results? '.print_r($this->config['hasPagedResultSupport'], true), \OCP\Util::INFO);
}
public function __destruct() {
@@ -84,12 +97,12 @@ class Connection {
public function __set($name, $value) {
$changed = false;
- //omly few options are writable
+ //only few options are writable
if($name == 'ldapUuidAttribute') {
\OCP\Util::writeLog('user_ldap', 'Set config ldapUuidAttribute to '.$value, \OCP\Util::DEBUG);
$this->config[$name] = $value;
if(!empty($this->configID)) {
- \OCP\Config::setAppValue($this->configID, 'ldap_uuid_attribute', $value);
+ \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', $value);
}
$changed = true;
}
@@ -126,7 +139,7 @@ class Connection {
}
private function getCacheKey($key) {
- $prefix = 'LDAP-'.$this->configID.'-';
+ $prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-';
if(is_null($key)) {
return $prefix;
}
@@ -164,7 +177,8 @@ class Connection {
if(!$this->configured) {
$this->readConfiguration();
}
- if(!$this->config['ldapCacheTTL']) {
+ if(!$this->config['ldapCacheTTL']
+ || !$this->config['ldapConfigurationActive']) {
return null;
}
$key = $this->getCacheKey($key);
@@ -176,43 +190,97 @@ class Connection {
$this->cache->clear($this->getCacheKey(null));
}
+ private function getValue($varname) {
+ static $defaults;
+ if(is_null($defaults)){
+ $defaults = $this->getDefaults();
+ }
+ return \OCP\Config::getAppValue($this->configID,
+ $this->configPrefix.$varname,
+ $defaults[$varname]);
+ }
+
+ private function setValue($varname, $value) {
+ \OCP\Config::setAppValue($this->configID,
+ $this->configPrefix.$varname,
+ $value);
+ }
+
/**
* Caches the general LDAP configuration.
*/
private function readConfiguration($force = false) {
- \OCP\Util::writeLog('user_ldap', 'Checking conf state: isConfigured? '.print_r($this->configured, true).' isForce? '.print_r($force, true).' configID? '.print_r($this->configID, true), \OCP\Util::DEBUG);
if((!$this->configured || $force) && !is_null($this->configID)) {
- \OCP\Util::writeLog('user_ldap', 'Reading the configuration', \OCP\Util::DEBUG);
- $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, 'ldap_host', '');
- $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, 'ldap_port', 389);
- $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, 'ldap_dn', '');
- $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, 'ldap_agent_password', ''));
- $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base', ''));
- $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base_users', $this->config['ldapBase']));
- $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base_groups', $this->config['ldapBase']));
- $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, 'ldap_tls', 0);
- $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, 'ldap_nocase', 0);
- $this->config['turnOffCertCheck'] = \OCP\Config::getAppValue($this->configID, 'ldap_turn_off_cert_check', 0);
- $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_display_name', 'uid'), 'UTF-8');
- $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_userlist_filter', 'objectClass=person');
- $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_filter', '(objectClass=posixGroup)');
- $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_login_filter', '(uid=%uid)');
- $this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_group_display_name', 'uid'), 'UTF-8');
- $this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_attr', '');
- $this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_def', '');
- $this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_email_attr', '');
- $this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_member_assoc_attribute', 'uniqueMember');
- $this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false);
- $this->config['ldapCacheTTL'] = \OCP\Config::getAppValue($this->configID, 'ldap_cache_ttl', 10*60);
- $this->config['ldapUuidAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_uuid_attribute', 'auto');
- $this->config['ldapOverrideUuidAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_override_uuid_attribute', 0);
- $this->config['homeFolderNamingRule'] = \OCP\Config::getAppValue($this->configID, 'home_folder_naming_rule', 'opt:username');
+ $defaults = $this->getDefaults();
+ $v = 'getValue';
+ $this->config['ldapHost'] = $this->$v('ldap_host');
+ $this->config['ldapBackupHost'] = $this->$v('ldap_backup_host');
+ $this->config['ldapPort'] = $this->$v('ldap_port');
+ $this->config['ldapBackupPort'] = $this->$v('ldap_backup_port');
+ $this->config['ldapOverrideMainServer']
+ = $this->$v('ldap_override_main_server');
+ $this->config['ldapAgentName'] = $this->$v('ldap_dn');
+ $this->config['ldapAgentPassword']
+ = base64_decode($this->$v('ldap_agent_password'));
+ $rawLdapBase = $this->$v('ldap_base');
+ $this->config['ldapBase']
+ = preg_split('/\r\n|\r|\n/', $rawLdapBase);
+ $this->config['ldapBaseUsers']
+ = preg_split('/\r\n|\r|\n/', ($this->$v('ldap_base_users')));
+ $this->config['ldapBaseGroups']
+ = preg_split('/\r\n|\r|\n/', $this->$v('ldap_base_groups'));
+ unset($rawLdapBase);
+ $this->config['ldapTLS'] = $this->$v('ldap_tls');
+ $this->config['ldapNoCase'] = $this->$v('ldap_nocase');
+ $this->config['turnOffCertCheck']
+ = $this->$v('ldap_turn_off_cert_check');
+ $this->config['ldapUserDisplayName']
+ = mb_strtolower($this->$v('ldap_display_name'),'UTF-8');
+ $this->config['ldapUserFilter']
+ = $this->$v('ldap_userlist_filter');
+ $this->config['ldapGroupFilter'] = $this->$v('ldap_group_filter');
+ $this->config['ldapLoginFilter'] = $this->$v('ldap_login_filter');
+ $this->config['ldapGroupDisplayName']
+ = mb_strtolower($this->$v('ldap_group_display_name'), 'UTF-8');
+ $this->config['ldapQuotaAttribute']
+ = $this->$v('ldap_quota_attr');
+ $this->config['ldapQuotaDefault']
+ = $this->$v('ldap_quota_def');
+ $this->config['ldapEmailAttribute']
+ = $this->$v('ldap_email_attr');
+ $this->config['ldapGroupMemberAssocAttr']
+ = $this->$v('ldap_group_member_assoc_attribute');
+ $this->config['ldapIgnoreNamingRules']
+ = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false);
+ $this->config['ldapCacheTTL'] = $this->$v('ldap_cache_ttl');
+ $this->config['ldapUuidAttribute']
+ = $this->$v('ldap_uuid_attribute');
+ $this->config['ldapOverrideUuidAttribute']
+ = $this->$v('ldap_override_uuid_attribute');
+ $this->config['homeFolderNamingRule']
+ = $this->$v('home_folder_naming_rule');
+ $this->config['ldapConfigurationActive']
+ = $this->$v('ldap_configuration_active');
+ $this->config['ldapAttributesForUserSearch']
+ = preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_user_search'));
+ $this->config['ldapAttributesForGroupSearch']
+ = preg_split('/\r\n|\r|\n/', $this->$v('ldap_attributes_for_group_search'));
$this->configured = $this->validateConfiguration();
}
}
/**
+ * @return returns an array that maps internal variable names to database fields
+ */
+ private function getConfigTranslationArray() {
+ static $array = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldap_override_main_server' => 'ldapOverrideMainServer', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName',
+
+ 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule', 'ldap_turn_off_cert_check' => 'turnOffCertCheck', 'ldap_configuration_active' => 'ldapConfigurationActive', 'ldap_attributes_for_user_search' => 'ldapAttributesForUserSearch', 'ldap_attributes_for_group_search' => 'ldapAttributesForGroupSearch');
+ return $array;
+ }
+
+ /**
* @brief set LDAP configuration with values delivered by an array, not read from configuration
* @param $config array that holds the config parameters in an associated array
* @param &$setParameters optional; array where the set fields will be given to
@@ -223,9 +291,7 @@ class Connection {
return false;
}
- $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName',
-
- 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule');
+ $params = $this->getConfigTranslationArray();
foreach($config as $parameter => $value) {
if(isset($this->config[$parameter])) {
@@ -247,6 +313,71 @@ class Connection {
}
/**
+ * @brief saves the current Configuration in the database
+ */
+ public function saveConfiguration() {
+ $trans = array_flip($this->getConfigTranslationArray());
+ foreach($this->config as $key => $value) {
+ \OCP\Util::writeLog('user_ldap', 'LDAP: storing key '.$key.' value '.$value, \OCP\Util::DEBUG);
+ switch ($key) {
+ case 'ldapAgentPassword':
+ $value = base64_encode($value);
+ break;
+ case 'homeFolderNamingRule':
+ $value = empty($value) ? 'opt:username' : 'attr:'.$value;
+ break;
+ case 'ldapBase':
+ case 'ldapBaseUsers':
+ case 'ldapBaseGroups':
+ case 'ldapAttributesForUserSearch':
+ case 'ldapAttributesForGroupSearch':
+ if(is_array($value)){
+ $value = implode("\n", $value);
+ }
+ break;
+ case 'ldapIgnoreNamingRules':
+ case 'ldapOverrideUuidAttribute':
+ case 'ldapUuidAttribute':
+ case 'hasPagedResultSupport':
+ continue 2;
+ }
+ if(is_null($value)) {
+ $value = '';
+ }
+
+ $this->setValue($trans[$key], $value);
+ }
+ $this->clearCache();
+ }
+
+ /**
+ * @brief get the current LDAP configuration
+ * @return array
+ */
+ public function getConfiguration() {
+ $this->readConfiguration();
+ $trans = $this->getConfigTranslationArray();
+ $config = array();
+ foreach($trans as $dbKey => $classKey) {
+ if($classKey == 'homeFolderNamingRule') {
+ if(strpos($this->config[$classKey], 'opt') === 0) {
+ $config[$dbKey] = '';
+ } else {
+ $config[$dbKey] = substr($this->config[$classKey], 5);
+ }
+ continue;
+ } else if((strpos($classKey, 'ldapBase') !== false)
+ || (strpos($classKey, 'ldapAttributes') !== false)) {
+ $config[$dbKey] = implode("\n", $this->config[$classKey]);
+ continue;
+ }
+ $config[$dbKey] = $this->config[$classKey];
+ }
+
+ return $config;
+ }
+
+ /**
* @brief Validates the user specified configuration
* @returns true if configuration seems OK, false otherwise
*/
@@ -264,9 +395,21 @@ class Connection {
\OCP\Util::writeLog('user_ldap', 'No group filter is specified, LDAP group feature will not be used.', \OCP\Util::INFO);
}
if(!in_array($this->config['ldapUuidAttribute'], array('auto', 'entryuuid', 'nsuniqueid', 'objectguid')) && (!is_null($this->configID))) {
- \OCP\Config::setAppValue($this->configID, 'ldap_uuid_attribute', 'auto');
+ \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto');
\OCP\Util::writeLog('user_ldap', 'Illegal value for the UUID Attribute, reset to autodetect.', \OCP\Util::INFO);
}
+ if(empty($this->config['ldapBackupPort'])) {
+ //force default
+ $this->config['ldapBackupPort'] = $this->config['ldapPort'];
+ }
+ foreach(array('ldapAttributesForUserSearch', 'ldapAttributesForGroupSearch') as $key) {
+ if(is_array($this->config[$key])
+ && count($this->config[$key]) == 1
+ && empty($this->config[$key][0])) {
+ $this->config[$key] = array();
+ }
+ }
+
//second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning.
@@ -311,9 +454,50 @@ class Connection {
}
/**
+ * @returns an associative array with the default values. Keys are correspond
+ * to config-value entries in the database table
+ */
+ public function getDefaults() {
+ return array(
+ 'ldap_host' => '',
+ 'ldap_port' => '389',
+ 'ldap_backup_host' => '',
+ 'ldap_backup_port' => '',
+ 'ldap_override_main_server' => '',
+ 'ldap_dn' => '',
+ 'ldap_agent_password' => '',
+ 'ldap_base' => '',
+ 'ldap_base_users' => '',
+ 'ldap_base_groups' => '',
+ 'ldap_userlist_filter' => 'objectClass=person',
+ 'ldap_login_filter' => 'uid=%uid',
+ 'ldap_group_filter' => 'objectClass=posixGroup',
+ 'ldap_display_name' => 'cn',
+ 'ldap_group_display_name' => 'cn',
+ 'ldap_tls' => 1,
+ 'ldap_nocase' => 0,
+ 'ldap_quota_def' => '',
+ 'ldap_quota_attr' => '',
+ 'ldap_email_attr' => '',
+ 'ldap_group_member_assoc_attribute' => 'uniqueMember',
+ 'ldap_cache_ttl' => 600,
+ 'ldap_uuid_attribute' => 'auto',
+ 'ldap_override_uuid_attribute' => 0,
+ 'home_folder_naming_rule' => 'opt:username',
+ 'ldap_turn_off_cert_check' => 0,
+ 'ldap_configuration_active' => 1,
+ 'ldap_attributes_for_user_search' => '',
+ 'ldap_attributes_for_group_search' => '',
+ );
+ }
+
+ /**
* Connects and Binds to LDAP
*/
private function establishConnection() {
+ if(!$this->config['ldapConfigurationActive']) {
+ return null;
+ }
static $phpLDAPinstalled = true;
if(!$phpLDAPinstalled) {
return false;
@@ -336,16 +520,40 @@ class Connection {
\OCP\Util::writeLog('user_ldap', 'Could not turn off SSL certificate validation.', \OCP\Util::WARN);
}
}
- $this->ldapConnectionRes = ldap_connect($this->config['ldapHost'], $this->config['ldapPort']);
- if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
- if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
- if($this->config['ldapTLS']) {
- ldap_start_tls($this->ldapConnectionRes);
+ if(!$this->config['ldapOverrideMainServer'] && !$this->getFromCache('overrideMainServer')) {
+ $this->doConnect($this->config['ldapHost'], $this->config['ldapPort']);
+ $bindStatus = $this->bind();
+ $error = ldap_errno($this->ldapConnectionRes);
+ } else {
+ $bindStatus = false;
+ $error = null;
+ }
+
+ $error = null;
+ //if LDAP server is not reachable, try the Backup (Replica!) Server
+ if((!$bindStatus && ($error == -1))
+ || $this->config['ldapOverrideMainServer']
+ || $this->getFromCache('overrideMainServer')) {
+ $this->doConnect($this->config['ldapBackupHost'], $this->config['ldapBackupPort']);
+ $bindStatus = $this->bind();
+ if($bindStatus && $error == -1) {
+ //when bind to backup server succeeded and failed to main server,
+ //skip contacting him until next cache refresh
+ $this->writeToCache('overrideMainServer', true);
}
- }
}
+ return $bindStatus;
+ }
+ }
- return $this->bind();
+ private function doConnect($host, $port) {
+ $this->ldapConnectionRes = ldap_connect($host, $port);
+ if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+ if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
+ if($this->config['ldapTLS']) {
+ ldap_start_tls($this->ldapConnectionRes);
+ }
+ }
}
}
@@ -353,6 +561,9 @@ class Connection {
* Binds to LDAP
*/
public function bind() {
+ if(!$this->config['ldapConfigurationActive']) {
+ return false;
+ }
$ldapLogin = @ldap_bind($this->getConnectionResource(), $this->config['ldapAgentName'], $this->config['ldapAgentPassword']);
if(!$ldapLogin) {
\OCP\Util::writeLog('user_ldap', 'Bind failed: ' . ldap_errno($this->ldapConnectionRes) . ': ' . ldap_error($this->ldapConnectionRes), \OCP\Util::ERROR);