This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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\AdapterInterface; |
||
12 | use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter; |
||
13 | use Symfony\Component\Ldap\Entry; |
||
14 | use Symfony\Component\Ldap\Exception\InvalidCredentialsException; |
||
15 | use Symfony\Component\Ldap\Exception\LdapException; |
||
16 | use Symfony\Component\Ldap\Ldap as LdapObject; |
||
17 | |||
18 | use function array_merge; |
||
19 | use function array_pop; |
||
20 | use function explode; |
||
21 | use function implode; |
||
22 | use function ini_get; |
||
23 | use function sprintf; |
||
24 | use function var_export; |
||
25 | |||
26 | class Ldap implements ConnectorInterface |
||
27 | { |
||
28 | use LdapHelpers; |
||
29 | |||
30 | /** |
||
31 | * @var \Symfony\Component\Ldap\Adapter\AdapterInterface |
||
32 | */ |
||
33 | protected AdapterInterface $adapter; |
||
34 | |||
35 | /** |
||
36 | * @var \Symfony\Component\Ldap\Ldap |
||
37 | */ |
||
38 | protected LdapObject $connection; |
||
39 | |||
40 | |||
41 | /** |
||
42 | * @param string $connection_strings |
||
43 | * @param string $encryption |
||
44 | * @param int $version |
||
45 | * @param string $extension |
||
46 | * @param bool $debug |
||
47 | * @param array<mixed> $options |
||
48 | */ |
||
49 | public function __construct( |
||
50 | string $connection_strings, |
||
51 | string $encryption = 'ssl', |
||
52 | int $version = 3, |
||
53 | string $extension = 'ext_ldap', |
||
0 ignored issues
–
show
|
|||
54 | bool $debug = false, |
||
55 | array $options = ['referrals' => false, 'network_timeout' => 3], |
||
56 | ) { |
||
57 | foreach (explode(' ', $connection_strings) as $connection_string) { |
||
58 | Assert::regex($connection_string, '#^ldap[s]?:\/\/#'); |
||
59 | } |
||
60 | |||
61 | Logger::debug(sprintf( |
||
62 | "Setting up LDAP connection: host='%s', encryption=%s, version=%d, debug=%s, timeout=%d, referrals=%s.", |
||
63 | $connection_strings, |
||
64 | $encryption, |
||
65 | $version, |
||
66 | var_export($debug, true), |
||
67 | $options['timeout'] ?? ini_get('default_socket_timeout'), |
||
68 | var_export($options['referrals'] ?? false, true), |
||
69 | )); |
||
70 | |||
71 | $this->adapter = new Adapter( |
||
72 | [ |
||
73 | 'connection_string' => $connection_strings, |
||
74 | 'encryption' => $encryption, |
||
75 | 'version' => $version, |
||
76 | 'debug' => $debug, |
||
77 | 'options' => $options, |
||
78 | ], |
||
79 | ); |
||
80 | |||
81 | $this->connection = new LdapObject($this->adapter); |
||
82 | } |
||
83 | |||
84 | |||
85 | /** |
||
86 | * @return \Symfony\Component\Ldap\Adapter\AdapterInterface |
||
87 | */ |
||
88 | public function getAdapter(): AdapterInterface |
||
89 | { |
||
90 | return $this->adapter; |
||
91 | } |
||
92 | |||
93 | |||
94 | /** |
||
95 | * @inheritDoc |
||
96 | */ |
||
97 | public function bind(?string $username, #[\SensitiveParameter]?string $password): void |
||
98 | { |
||
99 | try { |
||
100 | $this->connection->bind($username, strval($password)); |
||
101 | } catch (InvalidCredentialsException $e) { |
||
102 | throw new Error\Error($this->resolveBindException()); |
||
103 | } |
||
104 | |||
105 | if ($username === null) { |
||
106 | Logger::debug("LDAP bind(): Anonymous bind succesful."); |
||
107 | } else { |
||
108 | Logger::debug(sprintf("LDAP bind(): Bind successful for DN '%s'.", $username)); |
||
109 | } |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * @inheritDoc |
||
114 | */ |
||
115 | public function saslBind( |
||
116 | ?string $username, |
||
117 | #[\SensitiveParameter]?string $password, |
||
118 | ?string $mech, |
||
119 | ?string $realm, |
||
120 | ?string $authcId, |
||
121 | ?string $authzId, |
||
122 | ?string $props, |
||
123 | ): void { |
||
124 | if (!method_exists($this->connection, 'saslBind')) { |
||
125 | throw new Error\Error("SASL not implemented"); |
||
126 | } |
||
127 | |||
128 | try { |
||
129 | $this->connection->saslBind($username, strval($password), $mech, $realm, $authcId, $authzId, $props); |
||
130 | } catch (InvalidCredentialsException $e) { |
||
131 | throw new Error\Error($this->resolveBindException()); |
||
132 | } |
||
133 | |||
134 | if ($username === null) { |
||
135 | Logger::debug("LDAP bind(): Anonymous bind succesful."); |
||
136 | } else { |
||
137 | Logger::debug(sprintf("LDAP bind(): Bind successful for DN '%s'.", $username)); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @inheritDoc |
||
143 | */ |
||
144 | public function whoami(): string |
||
145 | { |
||
146 | if (!method_exists($this->connection, 'whoami')) { |
||
147 | throw new Error\Error("SASL not implemented"); |
||
148 | } |
||
149 | |||
150 | return $this->connection->whoami(); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @inheritDoc |
||
155 | */ |
||
156 | public function search( |
||
157 | array $searchBase, |
||
158 | string $filter, |
||
159 | array $options, |
||
160 | bool $allowMissing, |
||
161 | ): ?Entry { |
||
162 | $entry = null; |
||
163 | |||
164 | foreach ($searchBase as $base) { |
||
165 | $query = $this->connection->query($base, $filter, $options); |
||
166 | $result = $query->execute()->toArray(); |
||
167 | |||
168 | if (count($result) > 1) { |
||
169 | throw new Error\Exception(sprintf( |
||
170 | "LDAP search(): Found %d entries searching base '%s' for '%s'", |
||
171 | count($result), |
||
172 | $base, |
||
173 | $filter, |
||
174 | )); |
||
175 | } elseif (count($result) === 1) { |
||
176 | $entry = array_pop($result); |
||
177 | break; |
||
178 | } else { |
||
179 | Logger::debug(sprintf( |
||
180 | "LDAP search(): Found no entries searching base '%s' for '%s'", |
||
181 | $base, |
||
182 | $filter, |
||
183 | )); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | if ($entry === null && $allowMissing === false) { |
||
188 | throw new Error\Exception(sprintf( |
||
189 | "Object not found using search base [%s] and filter '%s'", |
||
190 | implode(', ', $searchBase), |
||
191 | $filter, |
||
192 | )); |
||
193 | } |
||
194 | |||
195 | return $entry; |
||
196 | } |
||
197 | |||
198 | |||
199 | /** |
||
200 | * @inheritDoc |
||
201 | */ |
||
202 | public function searchForMultiple( |
||
203 | array $searchBase, |
||
204 | string $filter, |
||
205 | array $options, |
||
206 | bool $allowMissing, |
||
207 | ): array { |
||
208 | $results = []; |
||
209 | |||
210 | foreach ($searchBase as $base) { |
||
211 | $query = $this->connection->query($base, $filter, $options); |
||
212 | $result = $query->execute()->toArray(); |
||
213 | $results = array_merge($results, $result); |
||
214 | |||
215 | Logger::debug(sprintf( |
||
216 | "Library - LDAP search(): Found %d entries searching base '%s' for '%s'", |
||
217 | count($result), |
||
218 | $base, |
||
219 | $filter, |
||
220 | )); |
||
221 | } |
||
222 | |||
223 | if (empty($results) && ($allowMissing === false)) { |
||
224 | throw new Error\Exception(sprintf( |
||
225 | "No Objects found using search base [%s] and filter '%s'", |
||
226 | implode(', ', $searchBase), |
||
227 | $filter, |
||
228 | )); |
||
229 | } |
||
230 | |||
231 | return $results; |
||
232 | } |
||
233 | |||
234 | |||
235 | /** |
||
236 | * Resolve the message to a UI exception |
||
237 | * |
||
238 | * @return string |
||
239 | */ |
||
240 | protected function resolveBindException(): string |
||
241 | { |
||
242 | return self::ERR_WRONG_PASS; |
||
243 | } |
||
244 | |||
245 | |||
246 | /** |
||
247 | * @param \Symfony\Component\Ldap\Entry $entry |
||
248 | * @return bool |
||
249 | */ |
||
250 | public function updateEntry(Entry $entry): bool |
||
251 | { |
||
252 | try { |
||
253 | $this->adapter->getEntryManager()->update($entry); |
||
254 | return true; |
||
255 | } catch (LdapException $e) { |
||
256 | Logger::warning($e->getMessage()); |
||
257 | return false; |
||
258 | } |
||
259 | } |
||
260 | } |
||
261 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.