summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Protocol/Ldap/Discovery.php
blob: 9c7990a0ff1a0cf78d3f0400d77d8630f3cb3935 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */

namespace Icinga\Protocol\Ldap;

use Icinga\Data\ConfigObject;
use Icinga\Protocol\Dns;

class Discovery
{
    /**
     * @var LdapConnection
     */
    private $connection;

    /**
     * @param   LdapConnection  $conn   The ldap connection to use for the discovery
     */
    public function __construct(LdapConnection $conn)
    {
        $this->connection = $conn;
    }

    /**
     * Suggests a resource configuration of hostname, port and root_dn
     * based on the discovery
     *
     * @return array    The suggested configuration as an array
     */
    public function suggestResourceSettings()
    {
        return array(
            'hostname' => $this->connection->getHostname(),
            'port' => $this->connection->getPort(),
            'root_dn' => $this->connection->getCapabilities()->getDefaultNamingContext()
        );
    }

    /**
     * Suggests a backend configuration of base_dn, user_class and user_name_attribute
     * based on the discovery
     *
     * @return array    The suggested configuration as an array
     */
    public function suggestBackendSettings()
    {
        if ($this->isAd()) {
            return array(
                'backend' => 'msldap',
                'base_dn' => $this->connection->getCapabilities()->getDefaultNamingContext(),
                'user_class' => 'user',
                'user_name_attribute' => 'sAMAccountName'
            );
        } else {
            return array(
                'backend' => 'ldap',
                'base_dn' => $this->connection->getCapabilities()->getDefaultNamingContext(),
                'user_class' => 'inetOrgPerson',
                'user_name_attribute' => 'uid'
            );
        }
    }

    /**
     * Whether the suggested ldap server is an ActiveDirectory
     *
     * @return boolean
     */
    public function isAd()
    {
        return $this->connection->getCapabilities()->isActiveDirectory();
    }

    /**
     * Whether the discovery was successful
     *
     * @return bool     False when the suggestions are guessed
     */
    public function isSuccess()
    {
        return $this->connection->discoverySuccessful();
    }

    /**
     * Why the discovery failed
     *
     * @return \Exception|null
     */
    public function getError()
    {
        return $this->connection->getDiscoveryError();
    }

    /**
     * Discover LDAP servers on the given domain
     *
     * @param  ?string   $domain The object containing the form elements
     *
     * @return Discovery        True when the discovery was successful, false when the configuration was guessed
     */
    public static function discoverDomain($domain)
    {
        if (! isset($domain)) {
            return false;
        }

        // Attempt 1: Connect to the domain directly
        $disc = Discovery::discover($domain, 389);
        if ($disc->isSuccess()) {
            return $disc;
        }

        // Attempt 2: Discover all available ldap dns records and connect to the first one
        $records = array_merge(Dns::getSrvRecords($domain, 'ldap'), Dns::getSrvRecords($domain, 'ldaps'));
        if (isset($records[0])) {
            $record = $records[0];
            return Discovery::discover(
                isset($record['target']) ? $record['target'] : $domain,
                isset($record['port'])   ? $record['port'] : $domain
            );
        }

        // Return the first failed discovery, which will suggest properties based on guesses
        return $disc;
    }

    /**
     * Convenience method to instantiate a new Discovery
     *
     * @param $host         The host on which to execute the discovery
     * @param $port         The port on which to execute the discovery
     *
     * @return Discovery     The resulting Discovery
     */
    public static function discover($host, $port)
    {
        $conn = new LdapConnection(new ConfigObject(array(
            'hostname' => $host,
            'port'     => $port
        )));
        return new Discovery($conn);
    }
}