]> source.dussan.org Git - nextcloud-server.git/commitdiff
LDAP Wizard: autodetect base DN
authorArthur Schiwon <blizzz@owncloud.com>
Sun, 29 Sep 2013 21:53:14 +0000 (23:53 +0200)
committerArthur Schiwon <blizzz@owncloud.com>
Thu, 17 Oct 2013 17:13:14 +0000 (19:13 +0200)
apps/user_ldap/ajax/wizard.php
apps/user_ldap/js/settings.js
apps/user_ldap/lib/helper.php
apps/user_ldap/lib/ildapwrapper.php
apps/user_ldap/lib/ldap.php
apps/user_ldap/lib/wizard.php

index 53c66c34f8e35bb3213a6b1b918e340b6779cb69..7df922f17afef815788e42ad751672f0c4aad2e1 100644 (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) {
index 97470b4da417da52e5b531641f574923e314c120..45b1a9239f5821859d05b9ee7fe78973e8e22545 100644 (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;
        }
 };
 
index 4c9dd07a12cb8420769d139f7e064f97f054c70f..09f646921e34d975fc47523a67ecfea78e3c52a0 100644 (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;
+       }
 }
index 9e6bd56ef2a0920087e259030b02ce756bafdc4f..5e12c7c63b9d8b6e59d3a0b8800e686899cd3f7a 100644 (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
index b63e969912a129515f7f5977e3c1b613229f5c2e..13314462b8cd3a7fe5ca448d91ae93dfcba7b040 100644 (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);
        }
index 04802205cd4fdc054af8c04e63061b46644c5277..ad71fd10f63a2ecc61ce97261deaa238f3b56d49 100644 (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,13 +162,30 @@ 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);
        }
 
        /**