@Override public User save(final User user) { // 1. save clear password value before save String clearPwd = user.getClearPassword(); // 2. save and flush to trigger entity validation User merged = super.save(user); entityManager().flush(); // 3. set back the sole clear password value JPAUser.class.cast(merged).setClearPassword(clearPwd); // 4. enforce password and account policies try { enforcePolicies(merged); } catch (InvalidEntityException e) { entityManager().remove(merged); throw e; } roleDAO.refreshDynMemberships(merged); groupDAO.refreshDynMemberships(merged); return merged; }
@PreAuthorize("isAnonymous() or hasRole('" + Entitlement.ANONYMOUS + "')") public SecurityQuestionTO read(final String username) { if (username == null) { throw new NotFoundException("Null username"); } User user = userDAO.find(username); if (user == null) { throw new NotFoundException("User " + username); } if (user.getSecurityQuestion() == null) { LOG.error("Could not find security question for user '" + username + "'"); throw new NotFoundException("Security question for user " + username); } return binder.getSecurityQuestionTO(user.getSecurityQuestion()); }
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public Collection<ExternalResource> findAllResources(final User user) { Set<ExternalResource> result = new HashSet<>(); result.addAll(user.getResources()); for (Group group : findAllGroups(user)) { result.addAll(group.getResources()); } return result; }
@Override protected void securityChecks(final User user) { // Allows anonymous (during self-registration) and self (during self-update) to read own user, // otherwise goes through security checks to see if required entitlements are owned if (!AuthContextUtils.getUsername().equals(anonymousUser) && !AuthContextUtils.getUsername().equals(user.getUsername())) { Set<String> authRealms = AuthContextUtils.getAuthorizations().get(StandardEntitlement.USER_READ); boolean authorized = IterableUtils.matchesAny( authRealms, new Predicate<String>() { @Override public boolean evaluate(final String realm) { return user.getRealm().getFullPath().startsWith(realm); } }); if (authRealms == null || authRealms.isEmpty() || !authorized) { throw new DelegatedAdministrationException(AnyTypeKind.USER, user.getKey()); } } }
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public Collection<Group> findAllGroups(final User user) { return CollectionUtils.union( CollectionUtils.collect( user.getMemberships(), new Transformer<UMembership, Group>() { @Override public Group transform(final UMembership input) { return input.getRightEnd(); } }, new ArrayList<Group>()), findDynGroupMemberships(user)); }
private List<AccountPolicy> getAccountPolicies(final User user) { List<AccountPolicy> policies = new ArrayList<>(); // add resource policies for (ExternalResource resource : findAllResources(user)) { AccountPolicy policy = resource.getAccountPolicy(); if (policy != null) { policies.add(policy); } } // add realm policies for (Realm realm : realmDAO.findAncestors(user.getRealm())) { AccountPolicy policy = realm.getAccountPolicy(); if (policy != null) { policies.add(policy); } } return policies; }
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public Collection<Role> findAllRoles(final User user) { return CollectionUtils.union(user.getRoles(), findDynRoleMemberships(user)); }
@Transactional(readOnly = true) @Override public Pair<Boolean, Boolean> enforcePolicies(final User user) { // ------------------------------ // Verify password policies // ------------------------------ LOG.debug("Password Policy enforcement"); try { int maxPPSpecHistory = 0; for (PasswordPolicy policy : getPasswordPolicies(user)) { if (user.getPassword() == null && !policy.isAllowNullPassword()) { throw new PasswordPolicyException("Password mandatory"); } for (PasswordRuleConf ruleConf : policy.getRuleConfs()) { Class<? extends PasswordRule> ruleClass = implementationLookup.getPasswordRuleClass(ruleConf.getClass()); if (ruleClass == null) { LOG.warn("Could not find matching password rule for {}", ruleConf.getClass()); } else { // fetch (or create) rule PasswordRule rule; if (ApplicationContextProvider.getBeanFactory() .containsSingleton(ruleClass.getName())) { rule = (PasswordRule) ApplicationContextProvider.getBeanFactory().getSingleton(ruleClass.getName()); } else { rule = (PasswordRule) ApplicationContextProvider.getBeanFactory() .createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); ApplicationContextProvider.getBeanFactory() .registerSingleton(ruleClass.getName(), rule); } // enforce rule rule.enforce(ruleConf, user); } } if (user.verifyPasswordHistory(user.getClearPassword(), policy.getHistoryLength())) { 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().add(user.getPassword()); } // keep only the last maxPPSpecHistory items in user's password history if (maxPPSpecHistory < user.getPasswordHistory().size()) { for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) { user.getPasswordHistory().remove(i); } } } catch (Exception e) { LOG.error("Invalid password for {}", user, e); throw new InvalidEntityException( User.class, EntityViolationType.InvalidPassword, e.getMessage()); } finally { // password has been validated, let's remove its clear version user.removeClearPassword(); } // ------------------------------ // Verify account policies // ------------------------------ LOG.debug("Account Policy enforcement"); boolean suspend = false; boolean propagateSuspension = false; try { if (adminUser.equals(user.getUsername()) || anonymousUser.equals(user.getUsername())) { throw new AccountPolicyException("Not allowed: " + user.getUsername()); } for (AccountPolicy policy : getAccountPolicies(user)) { for (AccountRuleConf ruleConf : policy.getRuleConfs()) { Class<? extends AccountRule> ruleClass = implementationLookup.getAccountRuleClass(ruleConf.getClass()); if (ruleClass == null) { LOG.warn("Could not find matching password rule for {}", ruleConf.getClass()); } else { // fetch (or create) rule AccountRule rule; if (ApplicationContextProvider.getBeanFactory() .containsSingleton(ruleClass.getName())) { rule = (AccountRule) ApplicationContextProvider.getBeanFactory().getSingleton(ruleClass.getName()); } else { rule = (AccountRule) ApplicationContextProvider.getBeanFactory() .createBean(ruleClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); ApplicationContextProvider.getBeanFactory() .registerSingleton(ruleClass.getName(), rule); } // enforce rule rule.enforce(ruleConf, user); } } suspend |= user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0 && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended(); propagateSuspension |= policy.isPropagateSuspension(); } } catch (Exception e) { LOG.error("Invalid username for {}", user, e); throw new InvalidEntityException( User.class, EntityViolationType.InvalidUsername, e.getMessage()); } return ImmutablePair.of(suspend, propagateSuspension); }
@SuppressWarnings("unchecked") public <T extends PolicySpec> T evaluate(final Policy policy, final Any<?, ?, ?> any) { if (policy == null) { return null; } T result = null; switch (policy.getType()) { case PASSWORD: PasswordPolicySpec ppSpec = policy.getSpecification(PasswordPolicySpec.class); PasswordPolicySpec evaluatedPPSpec = new PasswordPolicySpec(); BeanUtils.copyProperties(ppSpec, evaluatedPPSpec, new String[] {"schemasNotPermitted"}); for (String schema : ppSpec.getSchemasNotPermitted()) { PlainAttr attr = any.getPlainAttr(schema); if (attr != null) { List<String> values = attr.getValuesAsStrings(); if (values != null && !values.isEmpty()) { evaluatedPPSpec.getWordsNotPermitted().add(values.get(0)); } } } // Password history verification and update if (!(any instanceof User)) { LOG.error( "Cannot check previous passwords. instance is not user object: {}", any.getClass().getName()); result = (T) evaluatedPPSpec; break; } User user = (User) any; if (user.verifyPasswordHistory(user.getClearPassword(), ppSpec.getHistoryLength())) { evaluatedPPSpec.getWordsNotPermitted().add(user.getClearPassword()); } result = (T) evaluatedPPSpec; break; case ACCOUNT: final AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class); final AccountPolicySpec accountPolicy = new AccountPolicySpec(); BeanUtils.copyProperties(spec, accountPolicy, new String[] {"schemasNotPermitted"}); for (String schema : spec.getSchemasNotPermitted()) { PlainAttr attr = any.getPlainAttr(schema); if (attr != null) { List<String> values = attr.getValuesAsStrings(); if (values != null && !values.isEmpty()) { accountPolicy.getWordsNotPermitted().add(values.get(0)); } } } result = (T) accountPolicy; break; case SYNC: default: result = null; } return result; }