diff --git a/CHANGELOG.md b/CHANGELOG.md
index e264aeb..2684f26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Added
- Whirlpool hash algorithm
+- 'Prepend salt' toggle
### Fixed
- Error when 'Display name' not set
- Encoding of iteration for 'Extended DES (Crypt)'
diff --git a/README.md b/README.md
index 8d26e16..a482017 100644
--- a/README.md
+++ b/README.md
@@ -49,6 +49,7 @@ Name | Description | Details
--- | --- | ---
**Allow display name change** | With this option enabled user can change its display name. The display name change is propagated to the database. | Optional.
Default: false.
Requires: user *Display name* column.
**Allow password change** | Can user change its password. The password change is propagated to the database. See [Hash algorithms](#hash-algorithms). | Optional.
Default: false.
+**Prepend salt** | Prepend a salt to the password instead of appending it. See [User table](#user-table) -> **Salt**. | Optional.
Default: false.
**Use cache** | Use database query results cache. The cache can be cleared any time with the *Clear cache* button click. | Optional.
Default: false.
**Hash algorithm** | How users passwords are stored in the database. See [Hash algorithms](#hash-algorithms). | Mandatory.
**Email sync** | Sync e-mail address with the Nextcloud.
- *None* - Disables this feature. This is the default option.
- *Synchronise only once* - Copy the e-mail address to the Nextcloud preferences if its not set.
- *Nextcloud always wins* - Always copy the e-mail address to the database. This updates the user table.
- *SQL always wins* - Always copy the e-mail address to the Nextcloud preferences. | Optional.
Default: *None*.
Requires: user *Email* column.
diff --git a/lib/Backend/UserBackend.php b/lib/Backend/UserBackend.php
index a39b8fd..a8166d2 100644
--- a/lib/Backend/UserBackend.php
+++ b/lib/Backend/UserBackend.php
@@ -297,9 +297,7 @@ final class UserBackend extends ABackend implements
return false;
}
- if ($user->salt !== null) {
- $password .= $user->salt;
- }
+ $password = $this->addSalt($user, $password);
$isCorrect = $passwordAlgorithm->checkPassword(
$password, $user->password
@@ -350,6 +348,27 @@ final class UserBackend extends ABackend implements
return $passwordAlgorithm;
}
+ /**
+ * Append or prepend salt from external column if available.
+ *
+ * @param User $user The user instance.
+ * @param string $password The password.
+ *
+ * @return string Salted password.
+ */
+ private function addSalt(User $user, string $password): string
+ {
+ if ($user->salt !== null) {
+ if (empty($this->properties[Opt::PREPEND_SALT])) {
+ return $password . $user->salt;
+ } else {
+ return $user->salt . $password;
+ }
+ }
+
+ return $password;
+ }
+
/**
* @inheritdoc
*/
@@ -457,9 +476,7 @@ final class UserBackend extends ABackend implements
return false;
}
- if ($user->salt !== null) {
- $password .= $user->salt;
- }
+ $password = $this->addSalt($user, $password);
$passwordHash = $passwordAlgorithm->getPasswordHash($password);
if ($passwordHash === false) {
diff --git a/lib/Constant/Opt.php b/lib/Constant/Opt.php
index a1f6617..fe6449a 100644
--- a/lib/Constant/Opt.php
+++ b/lib/Constant/Opt.php
@@ -34,6 +34,7 @@ final class Opt
const HOME_MODE = "opt.home_mode";
const NAME_CHANGE = "opt.name_change";
const PASSWORD_CHANGE = "opt.password_change";
+ const PREPEND_SALT = "opt.prepend_salt";
const QUOTA_SYNC = "opt.quota_sync";
const USE_CACHE = "opt.use_cache";
}
diff --git a/templates/admin.php b/templates/admin.php
index 8f05648..2542b56 100644
--- a/templates/admin.php
+++ b/templates/admin.php
@@ -109,7 +109,8 @@ function print_select_options(
t("Here are all currently supported options.")); ?>