Passed
Push — master ( cd5bd5...26a720 )
by Tim
03:04
created

Ldap::updateEntry()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\ldap\Connector;
6
7
use SimpleSAML\Assert\Assert;
8
use SimpleSAML\Error;
9
use SimpleSAML\Logger;
10
use SimpleSAML\Module\ldap\ConnectorInterface;
11
use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
12
use Symfony\Component\Ldap\Entry;
13
use Symfony\Component\Ldap\Exception\InvalidCredentialsException;
14
use Symfony\Component\Ldap\Ldap as LdapObject;
15
16
use function array_merge;
17
use function array_pop;
18
use function explode;
19
use function implode;
20
use function ini_get;
21
use function sprintf;
22
use function var_export;
23
24
class Ldap implements ConnectorInterface
25
{
26
    use LdapHelpers;
27
28
    /**
29
     * @var \Symfony\Component\Ldap\Adapter
30
     */
31
    protected Adapter $adapter;
32
33
    /**
34
     * @var \Symfony\Component\Ldap\Ldap
35
     */
36
    protected LdapObject $connection;
37
38
39
    /**
40
     * @param string $connection_strings
41
     * @param string $encryption
42
     * @param int $version
43
     * @param string $extension
44
     * @param bool $debug
45
     * @param array $options
46
     */
47
    public function __construct(
48
        string $connection_strings,
49
        string $encryption = 'ssl',
50
        int    $version = 3,
51
        string $extension = 'ext_ldap',
0 ignored issues
show
Unused Code introduced by
The parameter $extension is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

51
        /** @scrutinizer ignore-unused */ string $extension = 'ext_ldap',

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
52
        bool   $debug = false,
53
        array  $options = ['referrals' => false, 'network_timeout' => 3]
54
    ) {
55
        foreach (explode(' ', $connection_strings) as $connection_string) {
56
            Assert::regex($connection_string, '#^ldap[s]?:\/\/#');
57
        }
58
59
        Logger::debug(
60
            sprintf(
61
                "Setting up LDAP connection: host='%s', encryption=%s, version=%d, debug=%s, timeout=%d, referrals=%s.",
62
                $connection_strings,
63
                $encryption,
64
                $version,
65
                var_export($debug, true),
66
                $options['timeout'] ?? ini_get('default_socket_timeout'),
67
                var_export($options['referrals'] ?? false, true),
68
            ));
69
70
        $this->adapter = new Adapter(
0 ignored issues
show
Documentation Bug introduced by
It seems like new Symfony\Component\Ld...'options' => $options)) of type Symfony\Component\Ldap\Adapter\ExtLdap\Adapter is incompatible with the declared type Symfony\Component\Ldap\Adapter of property $adapter.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
71
            [
72
                'connection_string' => $connection_strings,
73
                'encryption'        => $encryption,
74
                'version'           => $version,
75
                'debug'             => $debug,
76
                'options'           => $options,
77
            ]
78
        );
79
80
        $this->connection = new LdapObject($this->adapter);
81
    }
82
83
84
    /**
85
     * @return \Symfony\Component\Ldap\Adapter
86
     */
87
    public function getAdapter(): Adapter
88
    {
89
        return $this->adapter;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->adapter returns the type Symfony\Component\Ldap\Adapter\ExtLdap\Adapter which is incompatible with the documented return type Symfony\Component\Ldap\Adapter.
Loading history...
90
    }
91
92
93
    /**
94
     * @inheritDoc
95
     */
96
    public function bind(string $username, ?string $password): void
97
    {
98
        try {
99
            $this->connection->bind($username, strval($password));
100
        } catch (InvalidCredentialsException $e) {
101
            throw new Error\Error($this->resolveBindError($e));
102
        }
103
104
        Logger::debug(sprintf("LDAP bind(): Bind successful for DN '%s'.", $username));
105
    }
106
107
108
    /**
109
     * @inheritDoc
110
     */
111
    public function search(
112
        array  $searchBase,
113
        string $filter,
114
        array  $options,
115
        bool   $allowMissing
116
    ): ?Entry
117
    {
118
        $entry = null;
119
120
        foreach ($searchBase as $base) {
121
            $query  = $this->connection->query($base, $filter, $options);
122
            $result = $query->execute()->toArray();
123
124
            if (count($result) > 1) {
125
                throw new Error\Exception(
126
                    sprintf(
127
                        "LDAP search(): Found %d entries searching base '%s' for '%s'",
128
                        count($result),
129
                        $base,
130
                        $filter,
131
                    )
132
                );
133
            } elseif (count($result) === 1) {
134
                $entry = array_pop($result);
0 ignored issues
show
Bug introduced by
$result of type Symfony\Component\Ldap\Adapter\list is incompatible with the type array expected by parameter $array of array_pop(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

134
                $entry = array_pop(/** @scrutinizer ignore-type */ $result);
Loading history...
135
                break;
136
            } else {
137
                Logger::debug(
138
                    sprintf(
139
                        "LDAP search(): Found no entries searching base '%s' for '%s'",
140
                        $base,
141
                        $filter,
142
                    )
143
                );
144
            }
145
        }
146
147
        if ($entry === null && $allowMissing === false) {
148
            throw new Error\Exception(
149
                sprintf(
150
                    "Object not found using search base [%s] and filter '%s'",
151
                    implode(', ', $searchBase),
152
                    $filter
153
                )
154
            );
155
        }
156
157
        return $entry;
158
    }
159
160
161
    /**
162
     * @inheritDoc
163
     */
164
    public function searchForMultiple(
165
        array  $searchBase,
166
        string $filter,
167
        array  $options,
168
        bool   $allowMissing
169
    ): array
170
    {
171
        $results = [];
172
173
        foreach ($searchBase as $base) {
174
            $query   = $this->connection->query($base, $filter, $options);
175
            $result  = $query->execute()->toArray();
176
            $results = array_merge($results, $result);
0 ignored issues
show
Bug introduced by
$result of type Symfony\Component\Ldap\Adapter\list is incompatible with the type array expected by parameter $arrays of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

176
            $results = array_merge($results, /** @scrutinizer ignore-type */ $result);
Loading history...
177
178
            Logger::debug(sprintf(
179
                "Library - LDAP search(): Found %d entries searching base '%s' for '%s'",
180
                count($result),
181
                $base,
182
                $filter,
183
            ));
184
        }
185
186
        if (empty($results) && ($allowMissing === false)) {
187
            throw new Error\Exception(
188
                sprintf(
189
                    "No Objects found using search base [%s] and filter '%s'",
190
                    implode(', ', $searchBase),
191
                    $filter
192
                )
193
            );
194
        }
195
196
        return $results;
197
    }
198
199
200
    /**
201
     * Resolve the message to a UI exception
202
     *
203
     * @param InvalidCredentialsException $e
204
     * @return string
205
     */
206
    protected function resolveBindError(InvalidCredentialsException $e): string
0 ignored issues
show
Unused Code introduced by
The parameter $e is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

206
    protected function resolveBindError(/** @scrutinizer ignore-unused */ InvalidCredentialsException $e): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
207
    {
208
        return self::ERR_WRONG_PASS;
209
    }
210
211
212
    /**
213
     * @param \Symfony\Component\Ldap\Entry $entry
214
     * @return bool
215
     */
216
    public function updateEntry(Entry $entry): bool
217
    {
218
        try {
219
            $this->adapter->getEntryManager()->update($entry);
220
            return true;
221
        } catch (LdapException $e) {
0 ignored issues
show
Bug introduced by
The type SimpleSAML\Module\ldap\Connector\LdapException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
222
            Logger::warning($e->getMessage());
223
            return false;
224
        }
225
    }
226
}
227