diff --git a/library/Icinga/Protocol/Ldap/Capability.php b/library/Icinga/Protocol/Ldap/Capability.php
new file mode 100644
index 000000000..a1da67ce2
--- /dev/null
+++ b/library/Icinga/Protocol/Ldap/Capability.php
@@ -0,0 +1,218 @@
+<?php
+/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Protocol\Ldap;
+
+/**
+ * The properties and capabilities of an LDAP server
+ *
+ * Provides information about the available encryption mechanisms (StartTLS), the supported
+ * LDAP protocol (v2/v3), vendor-specific extensions or protocols controls and extensions.
+ */
+class Capability {
+
+    const LDAP_SERVER_START_TLS_OID = '1.3.6.1.4.1.1466.20037';
+
+    const LDAP_PAGED_RESULT_OID_STRING = '1.2.840.113556.1.4.319';
+
+    const LDAP_SERVER_SHOW_DELETED_OID = '1.2.840.113556.1.4.417';
+
+    const LDAP_SERVER_SORT_OID = '1.2.840.113556.1.4.473';
+
+    const LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID = '1.2.840.113556.1.4.521';
+
+    const LDAP_SERVER_NOTIFICATION_OID = '1.2.840.113556.1.4.528';
+
+    const LDAP_SERVER_EXTENDED_DN_OID = '1.2.840.113556.1.4.529';
+
+    const LDAP_SERVER_LAZY_COMMIT_OID = '1.2.840.113556.1.4.619';
+
+    const LDAP_SERVER_SD_FLAGS_OID = '1.2.840.113556.1.4.801';
+
+    const LDAP_SERVER_TREE_DELETE_OID = '1.2.840.113556.1.4.805';
+
+    const LDAP_SERVER_DIRSYNC_OID = '1.2.840.113556.1.4.841';
+
+    const LDAP_SERVER_VERIFY_NAME_OID = '1.2.840.113556.1.4.1338';
+
+    const LDAP_SERVER_DOMAIN_SCOPE_OID = '1.2.840.113556.1.4.1339';
+
+    const LDAP_SERVER_SEARCH_OPTIONS_OID = '1.2.840.113556.1.4.1340';
+
+    const LDAP_SERVER_PERMISSIVE_MODIFY_OID = '1.2.840.113556.1.4.1413';
+
+    const LDAP_SERVER_ASQ_OID = '1.2.840.113556.1.4.1504';
+
+    const LDAP_SERVER_FAST_BIND_OID = '1.2.840.113556.1.4.1781';
+
+    const LDAP_CONTROL_VLVREQUEST = '2.16.840.1.113730.3.4.9';
+
+
+    // MS Capabilities, Source: http://msdn.microsoft.com/en-us/library/cc223359.aspx
+
+    // Running Active Directory as AD DS
+    const LDAP_CAP_ACTIVE_DIRECTORY_OID = '1.2.840.113556.1.4.800';
+
+    // Capable of signing and sealing on an NTLM authenticated connection
+    // and of performing subsequent binds on a signed or sealed connection
+    const LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID = '1.2.840.113556.1.4.1791';
+
+    // If AD DS: running at least W2K3, if AD LDS running at least W2K8
+    const LDAP_CAP_ACTIVE_DIRECTORY_V51_OID = '1.2.840.113556.1.4.1670';
+
+    // If AD LDS: accepts DIGEST-MD5 binds for AD LDSsecurity principals
+    const LDAP_CAP_ACTIVE_DIRECTORY_ADAM_DIGEST  = '1.2.840.113556.1.4.1880';
+
+    // Running Active Directory as AD LDS
+    const LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID = '1.2.840.113556.1.4.1851';
+
+    // If AD DS: it's a Read Only DC (RODC)
+    const LDAP_CAP_ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID = '1.2.840.113556.1.4.1920';
+
+    // Running at least W2K8
+    const LDAP_CAP_ACTIVE_DIRECTORY_V60_OID = '1.2.840.113556.1.4.1935';
+
+    // Running at least W2K8r2
+    const LDAP_CAP_ACTIVE_DIRECTORY_V61_R2_OID = '1.2.840.113556.1.4.2080';
+
+    // Running at least W2K12
+    const LDAP_CAP_ACTIVE_DIRECTORY_W8_OID = '1.2.840.113556.1.4.2237';
+
+    /**
+     * Attributes of the LDAP Server returned by the discovery query
+     *
+     * @var StdClass
+     */
+    private $attributes;
+
+    /**
+     * Map of supported available OIDS
+     *
+     * @var array
+     */
+    private $oids = array();
+
+    /**
+     * Construct a new capability
+     *
+     * @param $attributes   StdClass    The attributes returned, may be null for guessing default capabilities
+     */
+    public function __construct($attributes = null)
+    {
+        $this->attributes = $attributes;
+
+        if (isset($attributes->supportedControl)) {
+            foreach ($attributes->supportedControl as $oid) {
+                $this->oids[$oid] = true;
+            }
+        }
+        if (isset($attributes->supportedExtension)) {
+            foreach ($attributes->supportedExtension as $oid) {
+                $this->oids[$oid] = true;
+            }
+        }
+        if (isset($attributes->supportedFeatures)) {
+            foreach ($attributes->supportedFeatures as $oid) {
+                $this->oids[$oid] = true;
+            }
+        }
+        if (isset($attributes->supportedCapabilities)) {
+            foreach ($attributes->supportedCapabilities as $oid) {
+                $this->oids[$oid] = true;
+            }
+        }
+    }
+
+    /**
+     * Return if the capability object contains support for StartTLS
+     *
+     * @return      bool    Whether StartTLS is supported
+     */
+    public function hasStartTLS()
+    {
+        return isset($this->oids[self::LDAP_SERVER_START_TLS_OID]);
+    }
+
+    /**
+     * Return if the capability object contains support for StartTLS
+     *
+     * @return      bool Whether StartTLS is supported
+     */
+    public function hasPagedResult()
+    {
+        return isset($this->oids[self::LDAP_PAGED_RESULT_OID_STRING]);
+    }
+
+    /**
+     * Whether the ldap server is an ActiveDirectory server
+     *
+     * @return      boolean
+     */
+    public function hasAdOid()
+    {
+        return isset($this->oids[self::LDAP_CAP_ACTIVE_DIRECTORY_OID]);
+    }
+
+    /**
+     * Return if the capability objects contains support for LdapV3, defaults to true if discovery failed
+     *
+     * @return bool
+     */
+    public function hasLdapV3()
+    {
+        if (!isset($this->attributes)) {
+            // Default to true, if unknown
+            return true;
+        }
+
+        return (is_string($this->attributes->supportedLDAPVersion)
+            && (int) $this->attributes->supportedLDAPVersion === 3)
+        || (is_array($this->attributes->supportedLDAPVersion)
+            && in_array(3, $this->attributes->supportedLDAPVersion));
+    }
+
+    /**
+     * Whether the capability with the given OID is supported
+     *
+     * @param $oid  string  The OID of the capability
+     *
+     * @return      bool
+     */
+    public function hasOid($oid)
+    {
+        return isset($this->oids[$oid]);
+    }
+
+    /**
+     * Get the default naming context
+     *
+     * @return string|null the default naming context, or null when no contexts are available
+     */
+    public function getDefaultNamingContext()
+    {
+        // defaultNamingContext entry has higher priority
+        if (isset($this->attributes->defaultNamingContext)) {
+            return $this->attributes->defaultNamingContext;
+        }
+
+        // if its missing use namingContext
+        $namingContexts = $this->namingContexts();
+        return empty($namingContexts) ? null : $namingContexts[0];
+    }
+
+    /**
+     * Fetch the namingContexts
+     *
+     * @return array    the available naming contexts
+     */
+    public function namingContexts()
+    {
+        if (!isset($this->attributes->namingContexts)) {
+            return array();
+        }
+        if (!is_array($this->attributes->namingContexts)) {
+            return array($this->attributes->namingContexts);
+        }
+        return$this->attributes->namingContexts;
+    }
+}
diff --git a/library/Icinga/Protocol/Ldap/Connection.php b/library/Icinga/Protocol/Ldap/Connection.php
index 65eafffe0..39e447486 100644
--- a/library/Icinga/Protocol/Ldap/Connection.php
+++ b/library/Icinga/Protocol/Ldap/Connection.php
@@ -44,47 +44,6 @@ class Connection
     protected $root_dn;
     protected $count;
 
-    protected $ldap_extension = array(
-        '1.3.6.1.4.1.1466.20037' => 'STARTTLS',
-        // '1.3.6.1.4.1.4203.1.11.1' => '11.1', // PASSWORD_MODIFY
-        // '1.3.6.1.4.1.4203.1.11.3' => '11.3', // Whoami
-        // '1.3.6.1.1.8' => '8', // Cancel Extended Request
-    );
-
-    protected $ms_capability = array(
-        // Prefix LDAP_CAP_
-        // Source: http://msdn.microsoft.com/en-us/library/cc223359.aspx
-
-        // Running Active Directory as AD DS:
-        '1.2.840.113556.1.4.800'  => 'ACTIVE_DIRECTORY_OID',
-
-        // Capable of signing and sealing on an NTLM authenticated connection
-        // and of performing subsequent binds on a signed or sealed connection.
-        '1.2.840.113556.1.4.1791' => 'ACTIVE_DIRECTORY_LDAP_INTEG_OID',
-
-        // If AD DS: running at least W2K3, if AD LDS running at least W2K8
-        '1.2.840.113556.1.4.1670' => 'ACTIVE_DIRECTORY_V51_OID',
-
-        // If AD LDS: accepts DIGEST-MD5 binds for AD LDSsecurity principals
-        '1.2.840.113556.1.4.1880' => 'ACTIVE_DIRECTORY_ADAM_DIGEST',
-
-        // Running Active Directory as AD LDS
-        '1.2.840.113556.1.4.1851' => 'ACTIVE_DIRECTORY_ADAM_OID',
-
-        // If AD DS: it's a Read Only DC (RODC)
-        '1.2.840.113556.1.4.1920' => 'ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID',
-
-        // Running at least W2K8
-        '1.2.840.113556.1.4.1935' => 'ACTIVE_DIRECTORY_V60_OID',
-
-        // Running at least W2K8r2
-        '1.2.840.113556.1.4.2080' => 'ACTIVE_DIRECTORY_V61_R2_OID',
-
-        // Running at least W2K12
-        '1.2.840.113556.1.4.2237' => 'ACTIVE_DIRECTORY_W8_OID',
-
-    );
-
     /**
      * Whether the bind on this connection was already performed
      *
@@ -94,11 +53,14 @@ class Connection
 
     protected $root;
 
-    protected $supports_v3  = false;
-    protected $supports_tls = false;
-
+    /**
+     * @var Capability
+     */
     protected $capabilities;
-    protected $namingContexts;
+
+    /**
+     * @var bool
+     */
     protected $discoverySuccess = false;
 
     /**
@@ -374,8 +336,8 @@ class Connection
         $cookie = '';
         $entries = array();
         do {
-            // do not set controlPageResult as a critical extension, since we still want the
-            // server to return an answer in case the pagination extension is missing.
+            // do not set controlPageResult as a critical extension, since there is still the possibillity that the
+            // server returns an answer in case the pagination extension is missing.
             ldap_control_paged_result($this->ds, $pageSize, false, $cookie);
 
             $results = @ldap_search($this->ds, $base, $queryString, $fields, 0, $limit ? $offset + $limit : 0);
@@ -516,24 +478,18 @@ class Connection
 
         $ds = ldap_connect($this->hostname, $this->port);
         try {
-            $capabilities = $this->discoverCapabilities($ds);
-            list($cap, $namingContexts) = $capabilities;
+            $this->capabilities = $this->discoverCapabilities($ds);
             $this->discoverySuccess = true;
+
         } catch (LdapException $e) {
 
-            // discovery failed, guess defaults
-            $cap = (object) array(
-                'supports_ldapv3'   => true,
-                'supports_starttls' => false,
-                'msCapabilities'    => array()
-            );
-            $namingContexts = null;
+            // create empty default capabilities
+            Logger::warning('LADP discovery failed, assuming default LDAP settings.');
+            $this->capabilities = new Capability();
         }
-        $this->capabilities = $cap;
-        $this->namingContexts = $namingContexts;
 
         if ($use_tls) {
-            if ($cap->supports_starttls) {
+            if ($this->capabilities->hasStartTLS()) {
                 if (@ldap_start_tls($ds)) {
                     Logger::debug('LDAP STARTTLS succeeded');
                 } else {
@@ -549,11 +505,11 @@ class Connection
                     $this->hostname
                 );
             } else {
-                // TODO: Log noticy -> TLS enabled but not announced
+                Logger::warning('LDAP TLS enabled but not announced');
             }
         }
         // ldap_rename requires LDAPv3:
-        if ($cap->supports_ldapv3) {
+        if ($this->capabilities->hasLdapV3()) {
             if (! ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
                 throw new LdapException('LDAPv3 is required');
             }
@@ -591,141 +547,15 @@ class Connection
     }
 
     /**
-     * Return if the capability object contains support for StartTLS
+     * Get the capabilities of the connected server
      *
-     * @param $cap  The object containing the capabilities
-     *
-     * @return bool Whether StartTLS is supported
-     */
-    protected function hasCapabilityStartTLS($cap)
-    {
-        $cap = $this->getExtensionCapabilities($cap);
-        return isset($cap['1.3.6.1.4.1.1466.20037']);
-    }
-
-    /**
-     * Return if the capability objects contains support for LdapV3
-     *
-     * @param $cap
-     *
-     * @return bool
-     */
-    protected function hasCapabilityLdapV3($cap)
-    {
-        if ((is_string($cap->supportedLDAPVersion)
-                && (int) $cap->supportedLDAPVersion === 3)
-            || (is_array($cap->supportedLDAPVersion)
-                && in_array(3, $cap->supportedLDAPVersion)
-            )) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Extract an array of all extension capabilities from the given ldap response
-     *
-     * @param $cap      object  The response returned by a ldap_search discovery query
-     *
-     * @return object           The extracted capabilities.
-     */
-    protected function getExtensionCapabilities($cap)
-    {
-        $extensions = array();
-        if (isset($cap->supportedExtension)) {
-            foreach ($cap->supportedExtension as $oid) {
-                if (array_key_exists($oid, $this->ldap_extension)) {
-                    if ($this->ldap_extension[$oid] === 'STARTTLS') {
-                        $extensions['1.3.6.1.4.1.1466.20037'] = $this->ldap_extension['1.3.6.1.4.1.1466.20037'];
-                    }
-                }
-            }
-        }
-        return $extensions;
-    }
-
-    /**
-     * Extract an array of all MSAD capabilities from the given ldap response
-     *
-     * @param $cap      object  The response returned by a ldap_search discovery query
-     *
-     * @return object           The extracted capabilities.
-     */
-    protected function getMsCapabilities($cap)
-    {
-        $ms = array();
-        foreach ($this->ms_capability as $name) {
-            $ms[$this->convName($name)] = false;
-        }
-
-        if (isset($cap->supportedCapabilities)) {
-            foreach ($cap->supportedCapabilities as $oid) {
-                if (array_key_exists($oid, $this->ms_capability)) {
-                    $ms[$this->convName($this->ms_capability[$oid])] = true;
-                }
-            }
-        }
-        return (object)$ms;
-    }
-
-    /**
-     * Convert a single capability name entry into camel-case
-     *
-     * @param   $name   string  The name to convert
-     *
-     * @return          string  The name in camel-case
-     */
-    private function convName($name)
-    {
-        $parts = explode('_', $name);
-        foreach ($parts as $i => $part) {
-            $parts[$i] = ucfirst(strtolower($part));
-        }
-        return implode('', $parts);
-    }
-
-    /**
-     * Get the capabilities of this ldap server
-     *
-     * @return stdClass     An object, providing the flags 'ldapv3' and 'starttls' to indicate LdapV3 and StartTLS
-     * support and an additional property 'msCapabilities', containing all supported active directory capabilities.
+     * @return Capability   The capability object
      */
     public function getCapabilities()
     {
         return $this->capabilities;
     }
 
-    /**
-     * Get the default naming context of this ldap connection
-     *
-     * @return string|null the default naming context, or null when no contexts are available
-     */
-    public function getDefaultNamingContext()
-    {
-        $cap = $this->capabilities;
-        if (isset($cap->defaultNamingContext)) {
-            return $cap->defaultNamingContext;
-        }
-        $namingContexts = $this->namingContexts($cap);
-        return empty($namingContexts) ? null : $namingContexts[0];
-    }
-
-    /**
-     * Fetch the namingContexts for this Ldap-Connection
-     *
-     * @return array    the available naming contexts
-     */
-    public function namingContexts()
-    {
-        if (!isset($this->namingContexts)) {
-            return array();
-        }
-        if (!is_array($this->namingContexts)) {
-            return array($this->namingContexts);
-        }
-        return $this->namingContexts;
-    }
-
     /**
      * Whether service discovery was successful
      *
@@ -742,7 +572,7 @@ class Connection
      *
      * @param  resource     $ds     The link identifier of the current ldap connection
      *
-     * @return array                The capabilities and naming-contexts
+     * @return Capability           The capabilities
      * @throws LdapException        When the capability query fails
      */
     protected function discoverCapabilities($ds)
@@ -759,6 +589,7 @@ class Connection
                 'schemaNamingContext',
                 'supportedLDAPVersion', // => array(3, 2)
                 'supportedCapabilities',
+                'supportedControl',
                 'supportedExtension',
                 '+'
             )
@@ -789,19 +620,9 @@ class Connection
             );
         }
 
-        $cap = (object) array(
-            'supports_ldapv3'   => false,
-            'supports_starttls' => false,
-            'msCapabilities' => array()
-        );
-
         $ldapAttributes = ldap_get_attributes($ds, $entry);
         $result = $this->cleanupAttributes($ldapAttributes);
-        $cap->supports_ldapv3 = $this->hasCapabilityLdapV3($result);
-        $cap->supports_starttls = $this->hasCapabilityStartTLS($result);
-        $cap->msCapabilities = $this->getMsCapabilities($result);
-
-        return array($cap,  $result->namingContexts);
+        return new Capability($result);
     }
 
     /**
diff --git a/library/Icinga/Protocol/Ldap/Discovery.php b/library/Icinga/Protocol/Ldap/Discovery.php
index 18ef40307..1d7acbab9 100644
--- a/library/Icinga/Protocol/Ldap/Discovery.php
+++ b/library/Icinga/Protocol/Ldap/Discovery.php
@@ -54,7 +54,7 @@ class Discovery {
         return array(
             'hostname' => $this->connection->getHostname(),
             'port' => $this->connection->getPort(),
-            'root_dn' => $this->connection->getDefaultNamingContext()
+            'root_dn' => $this->connection->getCapabilities()->getDefaultNamingContext()
         );
     }
 
@@ -69,14 +69,14 @@ class Discovery {
         $this->execDiscovery();
         if ($this->isAd()) {
             return array(
-                'base_dn' => $this->connection->getDefaultNamingContext(),
+                'base_dn' => $this->connection->getCapabilities()->getDefaultNamingContext(),
                 'user_class' => 'user',
                 'user_name_attribute' => 'sAMAccountName'
             );
         } else {
             return array(
-                'base_dn' => $this->connection->getDefaultNamingContext(),
-                'user_class' => 'getDefaultNamingContext',
+                'base_dn' => $this->connection->getCapabilities()->getDefaultNamingContext(),
+                'user_class' => 'inetOrgPerson',
                 'user_name_attribute' => 'uid'
             );
         }
@@ -90,8 +90,7 @@ class Discovery {
     public function isAd()
     {
         $this->execDiscovery();
-        $caps = $this->connection->getCapabilities();
-        return isset($caps->msCapabilities->ActiveDirectoryOid) && $caps->msCapabilities->ActiveDirectoryOid;
+        return $this->connection->getCapabilities()->hasAdOid();
     }
 
     /**