|
37 | 37 | use OCP\HintException;
|
38 | 38 | use OCP\IImage;
|
39 | 39 | use OCP\IL10N;
|
| 40 | +use OCP\ILogger; |
40 | 41 | use OCP\IUser;
|
41 | 42 | use OCP\IUserManager;
|
42 | 43 | use OCP\IUserSession;
|
@@ -84,7 +85,7 @@ public function __construct(IUserManager $userManager, IUserSession $userSession
|
84 | 85 | * @return int bitwise-or'ed actions
|
85 | 86 | */
|
86 | 87 | public function respondToActions() {
|
87 |
| - $setPassword = function_exists('ldap_exop_passwd') && !$this->ldapConnect->hasPasswordPolicy() |
| 88 | + $setPassword = $this->canSetPassword() && !$this->ldapConnect->hasPasswordPolicy() |
88 | 89 | ? Backend::SET_PASSWORD
|
89 | 90 | : 0;
|
90 | 91 |
|
@@ -244,27 +245,8 @@ public function createUser($username, $password) {
|
244 | 245 | throw new \Exception('Cannot create user: ' . ldap_error($connection), ldap_errno($connection));
|
245 | 246 | }
|
246 | 247 |
|
247 |
| - // Set password through ldap password exop, if supported |
248 | 248 | if ($this->respondToActions() & Backend::SET_PASSWORD) {
|
249 |
| - try { |
250 |
| - $ret = ldap_exop_passwd($connection, $newUserDN, '', $password); |
251 |
| - if ($ret === false) { |
252 |
| - $message = 'ldap_exop_passwd failed, falling back to ldap_mod_replace to to set password for new user'; |
253 |
| - $this->logger->debug($message, ['app' => Application::APP_ID]); |
254 |
| - |
255 |
| - // Fallback to `userPassword` in case the server does not support exop_passwd |
256 |
| - $ret = ldap_mod_replace($connection, $newUserDN, ['userPassword' => $password]); |
257 |
| - if ($ret === false) { |
258 |
| - $message = 'Failed to set password for new user {dn}'; |
259 |
| - $this->logger->error($message, [ |
260 |
| - 'app' => Application::APP_ID, |
261 |
| - 'dn' => $newUserDN, |
262 |
| - ]); |
263 |
| - } |
264 |
| - } |
265 |
| - } catch (\Exception $e) { |
266 |
| - $this->logger->error($e->getMessage(), ['exception' => $e, 'app' => Application::APP_ID]); |
267 |
| - } |
| 249 | + $this->setPassword($username, $password, $connection); |
268 | 250 | }
|
269 | 251 | return $ret ? $newUserDN : false;
|
270 | 252 | }
|
@@ -350,30 +332,72 @@ public function deleteUser($uid): bool {
|
350 | 332 | return $res;
|
351 | 333 | }
|
352 | 334 |
|
| 335 | + /** |
| 336 | + * checks whether the user is allowed to change their password in Nextcloud |
| 337 | + * |
| 338 | + * @return boolean either the user can or cannot |
| 339 | + */ |
| 340 | + public function canSetPassword(): bool { |
| 341 | + return $this->configuration->hasPasswordPermission(); |
| 342 | + } |
| 343 | + |
353 | 344 | /**
|
354 | 345 | * Set password
|
355 | 346 | *
|
356 | 347 | * @param string $uid The username
|
357 | 348 | * @param string $password The new password
|
| 349 | + * @param ?LDAP\Connection $connection LDAP connection or null to create one |
358 | 350 | * @return bool
|
359 | 351 | *
|
360 | 352 | * Change the password of a user
|
361 | 353 | */
|
362 |
| - public function setPassword($uid, $password) { |
363 |
| - if (!function_exists('ldap_exop_passwd')) { |
364 |
| - // since PHP 7.2 – respondToActions checked this already, this |
365 |
| - // method should not be called. Double check due to public scope. |
366 |
| - // This method can be removed when Nextcloud 16 compat is dropped. |
367 |
| - return false; |
| 354 | + public function setPassword($uid, $password, $connection = null) { |
| 355 | + if (is_null($connection)) { |
| 356 | + $connection = $this->ldapProvider->getLDAPConnection($uid); |
368 | 357 | }
|
| 358 | + |
369 | 359 | try {
|
370 |
| - $cr = $this->ldapProvider->getLDAPConnection($uid); |
371 | 360 | $userDN = $this->getUserDN($uid);
|
372 |
| - return ldap_exop_passwd($cr, $userDN, '', $password) !== false; |
| 361 | + $ret = false; |
| 362 | + |
| 363 | + // try ldap_exop_passwd first |
| 364 | + if ($this->ldapConnect->hasPasswdExopSupport($connection)) { |
| 365 | + $ret = ldap_exop_passwd($connection, $userDN, '', $password); |
| 366 | + if ($ret === false) { |
| 367 | + $message = 'Failed to set password for user {dn} using ldap_exop_passwd'; |
| 368 | + $this->logger->error($message, [ |
| 369 | + 'ldap_error' => ldap_error($connection), |
| 370 | + 'app' => Application::APP_ID, |
| 371 | + 'dn' => $userDN, |
| 372 | + ]); |
| 373 | + } |
| 374 | + } else { |
| 375 | + // Fallback to `userPassword` in case the server does not support exop_passwd |
| 376 | + $entry = []; |
| 377 | + if ($this->configuration->useUnicodePassword()) { |
| 378 | + $entry['unicodePwd'] = iconv('UTF-8', 'UTF-16LE', '"' . $password . '"'); |
| 379 | + } else { |
| 380 | + $entry['userPassword'] = $password; |
| 381 | + } |
| 382 | + $ret = ldap_mod_replace($connection, $userDN, $entry); |
| 383 | + if ($ret === false) { |
| 384 | + $message = 'Failed to set password for user {dn} using ldap_mod_replace'; |
| 385 | + $this->logger->error($message, [ |
| 386 | + 'ldap_error' => ldap_error($connection), |
| 387 | + 'app' => Application::APP_ID, |
| 388 | + 'dn' => $userDN, |
| 389 | + ]); |
| 390 | + } |
| 391 | + } |
| 392 | + return $ret; |
373 | 393 | } catch (\Exception $e) {
|
374 |
| - $this->logger->error($e->getMessage(), ['exception' => $e, 'app' => Application::APP_ID]); |
| 394 | + $this->logger->error('Exception occured while setting the password of user {dn}', [ |
| 395 | + 'app' => Application::APP_ID, |
| 396 | + 'exception' => $e, |
| 397 | + 'dn' => $uid |
| 398 | + ]); |
| 399 | + return false; |
375 | 400 | }
|
376 |
| - return false; |
377 | 401 | }
|
378 | 402 |
|
379 | 403 | /**
|
|
0 commit comments