in core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java [106:226]
protected Pair<Boolean, Boolean> enforcePolicies(
final User user,
final boolean disablePwdPolicyCheck,
final String clearPassword) {
if (!disablePwdPolicyCheck) {
// ------------------------------
// Verify password policies
// ------------------------------
LOG.debug("Password Policy enforcement");
try {
int maxPPSpecHistory = 0;
for (PasswordPolicy policy : ruleProvider.getPasswordPolicies(
user.getRealm(), userDAO.findAllResources(user))) {
if (clearPassword == null && !policy.isAllowNullPassword()) {
throw new PasswordPolicyException("Password mandatory");
}
ruleProvider.getPasswordRules(policy).forEach(rule -> {
rule.enforce(user, clearPassword);
user.getLinkedAccounts().stream().
filter(account -> account.getPassword() != null).
forEach(rule::enforce);
});
boolean matching = false;
if (policy.getHistoryLength() > 0) {
List<String> pwdHistory = user.getPasswordHistory();
matching = pwdHistory.subList(policy.getHistoryLength() >= pwdHistory.size()
? 0
: pwdHistory.size() - policy.getHistoryLength(), pwdHistory.size()).stream().
map(old -> encryptorManager.getInstance().verify(
clearPassword, user.getCipherAlgorithm(), old)).
reduce(matching, (accumulator, item) -> accumulator | item);
}
if (matching) {
throw new PasswordPolicyException("Password value was used in the past: not allowed");
}
if (policy.getHistoryLength() > maxPPSpecHistory) {
maxPPSpecHistory = policy.getHistoryLength();
}
}
// update user's password history with encrypted password
if (maxPPSpecHistory > 0
&& user.getPassword() != null
&& !user.getPasswordHistory().contains(user.getPassword())) {
user.addToPasswordHistory(user.getPassword());
}
// keep only the last maxPPSpecHistory items in user's password history
if (maxPPSpecHistory < user.getPasswordHistory().size()) {
user.removeOldestEntriesFromPasswordHistory(user.getPasswordHistory().size() - maxPPSpecHistory);
}
} catch (InvalidEntityException e) {
throw e;
} catch (Exception e) {
LOG.error("Invalid password for {}", user, e);
throw new InvalidEntityException(User.class, EntityViolationType.InvalidPassword, e.getMessage());
}
}
// ------------------------------
// Verify account policies
// ------------------------------
LOG.debug("Account Policy enforcement");
boolean suspend = false;
boolean propagateSuspension = false;
try {
if (user.getUsername() == null) {
throw new AccountPolicyException("Null username");
}
if (securityProperties.getAdminUser().equals(user.getUsername())
|| securityProperties.getAnonymousUser().equals(user.getUsername())) {
throw new AccountPolicyException("Not allowed: " + user.getUsername());
}
List<AccountPolicy> accountPolicies =
ruleProvider.getAccountPolicies(user.getRealm(), userDAO.findAllResources(user));
if (accountPolicies.isEmpty()) {
if (!Entity.ID_PATTERN.matcher(user.getUsername()).matches()) {
throw new AccountPolicyException("Character(s) not allowed: " + user.getUsername());
}
user.getLinkedAccounts().stream().
filter(account -> account.getUsername() != null).
forEach(account -> {
if (!Entity.ID_PATTERN.matcher(account.getUsername()).matches()) {
throw new AccountPolicyException("Character(s) not allowed: " + account.getUsername());
}
});
} else {
for (AccountPolicy policy : accountPolicies) {
ruleProvider.getAccountRules(policy).forEach(rule -> {
rule.enforce(user);
user.getLinkedAccounts().stream().
filter(account -> account.getUsername() != null).
forEach(rule::enforce);
});
suspend |= user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0
&& user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended();
propagateSuspension |= policy.isPropagateSuspension();
}
}
} catch (InvalidEntityException e) {
throw e;
} catch (Exception e) {
LOG.error("Invalid username for {}", user, e);
throw new InvalidEntityException(User.class, EntityViolationType.InvalidUsername, e.getMessage());
}
return Pair.of(suspend, propagateSuspension);
}