LDAP Wizard: autodetect base DN

This commit is contained in:
Arthur Schiwon 2013-09-29 23:53:14 +02:00
parent 7c60384f20
commit 8290929aa6
6 changed files with 162 additions and 22 deletions

View File

@ -45,6 +45,7 @@ $wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper);
switch($action) {
case 'guessPortAndTLS':
case 'guessBaseDN':
try {
$result = $wizard->$action();
if($result !== false) {

View File

@ -126,7 +126,7 @@ var LdapConfiguration = {
var LdapWizard = {
checkPortInfoShown: false,
changeIndicators: {},
saveBlacklist: {},
ajax: function(param, fnOnSuccess, fnOnError) {
$.post(
@ -144,10 +144,36 @@ var LdapWizard = {
applyChanges: function (result) {
for (id in result.changes) {
LdapWizard.saveBlacklist[id] = true;
$('#'+id).val(result.changes[id]);
}
},
checkBaseDN: function() {
host = $('#ldap_host').val();
user = $('#ldap_dn').val();
pass = $('#ldap_agent_password').val();
if(host && user && pass) {
param = 'action=guessBaseDN'+
'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
LdapWizard.ajax(param,
function(result) {
LdapWizard.applyChanges(result);
if($('#ldap_base').val()) {
$('#ldap_base').removeClass('hidden');
LdapWizard.hideInfoBox();
}
},
function (result) {
$('#ldap_base').removeClass('hidden');
LdapWizard.showInfoBox('Please specify a port');
}
);
}
},
checkPort: function() {
host = $('#ldap_host').val();
user = $('#ldap_dn').val();
@ -162,30 +188,45 @@ var LdapWizard = {
LdapWizard.applyChanges(result);
if($('#ldap_port').val()) {
$('#ldap_port').removeClass('hidden');
if(LdapWizard.checkPortInfoShown) {
$('#ldapWizard1 .ldapWizardInfo').addClass('hidden');
LdapWizard.checkPortInfoShown = false;
}
LdapWizard.hideInfoBox();
}
},
function (result) {
$('#ldap_port').removeClass('hidden');
$('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap',
'Please specify a port'));
$('#ldapWizard1 .ldapWizardInfo').removeClass('hidden');
LdapWizard.checkPortInfoShown = true;
LdapWizard.showInfoBox('Please specify the BaseDN');
}
);
}
},
hideInfoBox: function() {
if(LdapWizard.checkInfoShown) {
$('#ldapWizard1 .ldapWizardInfo').addClass('hidden');
LdapWizard.checkInfoShown = false;
}
},
init: function() {
if($('#ldap_port').val()) {
$('#ldap_port').removeClass('hidden');
}
},
processChanges: function(triggerObj) {
if(triggerObj.id == 'ldap_host'
|| triggerObj.id == 'ldap_port'
|| triggerObj.id == 'ldap_dn'
|| triggerObj.id == 'ldap_agent_password') {
LdapWizard.checkPort();
LdapWizard.checkBaseDN();
}
},
save: function(inputObj) {
if(LdapWizard.saveBlacklist.hasOwnProperty(inputObj.id)) {
delete LdapWizard.saveBlacklist[inputObj.id];
return;
}
param = 'cfgkey='+inputObj.id+
'&cfgval='+$(inputObj).val()+
'&action=save'+
@ -196,16 +237,18 @@ var LdapWizard = {
param,
function(result) {
if(result.status == 'success') {
if(inputObj.id == 'ldap_host'
|| inputObj.id == 'ldap_dn'
|| inputObj.id == 'ldap_agent_password') {
LdapWizard.checkPort();
}
LdapWizard.processChanges(inputObj);
} else {
// alert('Oooooooooooh :(');
}
}
);
},
showInfoBox: function(text) {
$('#ldapWizard1 .ldapWizardInfo').text(t('user_ldap', text));
$('#ldapWizard1 .ldapWizardInfo').removeClass('hidden');
LdapWizard.checkInfoShown = true;
}
};

View File

@ -161,4 +161,25 @@ class Helper {
return true;
}
/**
* @brief extractsthe domain from a given URL
* @param $url the URL
* @return mixed, domain as string on success, false otherwise
*/
static public function getDomainFromURL($url) {
$uinfo = parse_url($url);
if(!is_array($uinfo)) {
return false;
}
$domain = false;
if(isset($uinfo['host'])) {
$domain = $uinfo['host'];
} else if(isset($uinfo['path'])) {
$domain = $uinfo['path'];
}
return $domain;
}
}

View File

@ -67,6 +67,14 @@ interface ILDAPWrapper {
*/
public function controlPagedResultResponse($link, $result, &$cookie);
/**
* @brief Count the number of entries in a search
* @param $link LDAP link resource
* @param $result LDAP result resource
* @return mixed, number of results on success, false otherwise
*/
public function countEntries($link, $result);
/**
* @brief Return the LDAP error number of the last LDAP command
* @param $link LDAP link resource

View File

@ -49,6 +49,10 @@ class LDAP implements ILDAPWrapper {
$isCritical, $cookie);
}
public function countEntries($link, $result) {
return $this->invokeLDAPMethod('count_entries', $link, $result);
}
public function errno($link) {
return $this->invokeLDAPMethod('errno', $link);
}

View File

@ -89,6 +89,10 @@ class Wizard extends LDAPUtility {
return false;
}
/**
* @brief tries to determine a base dn from User DN or LDAP Host
* @returns mixed WizardResult on success, false otherwise
*/
public function guessBaseDN() {
if(!$this->checkRequirements(array('ldapHost',
'ldapAgentName',
@ -97,10 +101,52 @@ class Wizard extends LDAPUtility {
))) {
return false;
}
$cr = $this->getConnection();
if(!$cr) {
//check whether a DN is given in the agent name (99.9% of all cases)
$base = null;
$i = stripos($this->configuration->ldapAgentName, 'dc=');
if($i !== false) {
$base = substr($this->configuration->ldapAgentName, $i);
if($this->testBaseDN($base)) {
$this->applyFind('ldap_base', $base);
$this->applyFind('ldap_base_users', $base);
$this->applyFind('ldap_base_groups', $base);
return $this->result;
}
}
//this did not help :(
//Let's see whether we can parse the Host URL and convert the domain to
//a base DN
$domain = Helper::getDomainFromURL($this->configuration->ldapHost);
if(!$domain) {
return false;
}
$dparts = explode('.', $domain);
$base2 = implode('dc=', $dparts);
if($base !== $base2 && $this->testBaseDN($base2)) {
$this->applyFind('ldap_base', $base2);
$this->applyFind('ldap_base_users', $base2);
$this->applyFind('ldap_base_groups', $base2);
return $this->result;
}
return false;
}
/**
* @brief sets the found value for the configuration key in the WizardResult
* as well as in the Configuration instance
* @param $key the configuration key
* @param $value the (detected) value
* @return null
*
*/
private function applyFind($key, $value) {
$this->result->addChange($key, $value);
$this->configuration->setConfiguration(array($key => $value));
}
/**
@ -116,15 +162,32 @@ class Wizard extends LDAPUtility {
if(is_array($hostInfo) && isset($hostInfo['port'])) {
$port = $hostInfo['port'];
$host = str_replace(':'.$port, '', $host);
$config = array('ldapHost' => $host,
'ldapPort' => $port,
);
$this->result->addChange('ldap_host', $host);
$this->result->addChange('ldap_port', $port);
$this->configuration->setConfiguration($config);
$this->applyFind('ldap_host', $host);
$this->applyFind('ldap_port', $port);
}
}
/**
* @brief Checks whether for a given BaseDN results will be returned
* @param $base the BaseDN to test
* @return bool true on success, false otherwise
*/
private function testBaseDN($base) {
$cr = $this->getConnection();
if(!$cr) {
throw new \Excpetion('Could not connect to LDAP');
}
//base is there, let's validate it. If we search for anything, we should
//get a result set > 0 on a proper base
$rr = $this->ldap->search($cr, $base, 'objectClass=*', array('dn'), 0, 1);
if(!$this->ldap->isResource($rr)) {
return false;
}
$entries = $this->ldap->countEntries($cr, $rr);
return ($entries !== false) && ($entries > 0);
}
/**
* Connects and Binds to an LDAP Server
* @param $port the port to connect with