use of password.pwm.util.PwmPasswordRuleValidator in project pwm by pwm-project.
the class UserInfoReader method getPasswordStatus.
@Override
public PasswordStatus getPasswordStatus() throws PwmUnrecoverableException {
final Configuration config = pwmApplication.getConfig();
final PasswordStatus.PasswordStatusBuilder passwordStatusBuilder = PasswordStatus.builder();
final String userDN = chaiUser.getEntryDN();
final PwmPasswordPolicy passwordPolicy = selfCachedReference.getPasswordPolicy();
final long startTime = System.currentTimeMillis();
LOGGER.trace(sessionLabel, "beginning password status check process for " + userDN);
// check if password meets existing policy.
if (passwordPolicy.getRuleHelper().readBooleanValue(PwmPasswordRule.EnforceAtLogin)) {
if (currentPassword != null) {
try {
final PwmPasswordRuleValidator passwordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, passwordPolicy);
passwordRuleValidator.testPassword(currentPassword, null, selfCachedReference, chaiUser);
} catch (PwmDataValidationException | PwmUnrecoverableException e) {
LOGGER.debug(sessionLabel, "user " + userDN + " password does not conform to current password policy (" + e.getMessage() + "), marking as requiring change.");
passwordStatusBuilder.violatesPolicy(true);
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
}
}
}
boolean ldapPasswordExpired = false;
try {
ldapPasswordExpired = chaiUser.isPasswordExpired();
if (ldapPasswordExpired) {
LOGGER.trace(sessionLabel, "password for " + userDN + " appears to be expired");
} else {
LOGGER.trace(sessionLabel, "password for " + userDN + " does not appear to be expired");
}
} catch (ChaiOperationException e) {
LOGGER.info(sessionLabel, "error reading LDAP attributes for " + userDN + " while reading isPasswordExpired(): " + e.getMessage());
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
}
final Instant ldapPasswordExpirationTime = selfCachedReference.getPasswordExpirationTime();
boolean preExpired = false;
if (ldapPasswordExpirationTime != null) {
final TimeDuration expirationInterval = TimeDuration.fromCurrent(ldapPasswordExpirationTime);
LOGGER.trace(sessionLabel, "read password expiration time: " + JavaHelper.toIsoDate(ldapPasswordExpirationTime) + ", " + expirationInterval.asCompactString() + " from now");
final TimeDuration diff = TimeDuration.fromCurrent(ldapPasswordExpirationTime);
// now check to see if the user's expire time is within the 'preExpireTime' setting.
final long preExpireMs = config.readSettingAsLong(PwmSetting.PASSWORD_EXPIRE_PRE_TIME) * 1000;
if (diff.getTotalMilliseconds() > 0 && diff.getTotalMilliseconds() < preExpireMs) {
LOGGER.debug(sessionLabel, "user " + userDN + " password will expire within " + diff.asCompactString() + ", marking as pre-expired");
preExpired = true;
} else if (ldapPasswordExpired) {
preExpired = true;
LOGGER.debug(sessionLabel, "user " + userDN + " password is expired, marking as pre-expired.");
}
// now check to see if the user's expire time is within the 'preWarnTime' setting.
final long preWarnMs = config.readSettingAsLong(PwmSetting.PASSWORD_EXPIRE_WARN_TIME) * 1000;
// don't check if the 'preWarnTime' setting is zero or less than the expirePreTime
if (!ldapPasswordExpired && !preExpired) {
if (!(preWarnMs == 0 || preWarnMs < preExpireMs)) {
if (diff.getTotalMilliseconds() > 0 && diff.getTotalMilliseconds() < preWarnMs) {
LOGGER.debug(sessionLabel, "user " + userDN + " password will expire within " + diff.asCompactString() + ", marking as within warn period");
passwordStatusBuilder.warnPeriod(true);
}
}
}
passwordStatusBuilder.preExpired(preExpired);
}
LOGGER.debug(sessionLabel, "completed user password status check for " + userDN + " " + passwordStatusBuilder + " (" + TimeDuration.fromCurrent(startTime).asCompactString() + ")");
passwordStatusBuilder.expired(ldapPasswordExpired);
return passwordStatusBuilder.build();
}
use of password.pwm.util.PwmPasswordRuleValidator in project pwm by pwm-project.
the class PasswordUtility method setPassword.
public static void setPassword(final PwmApplication pwmApplication, final SessionLabel sessionLabel, final ChaiProvider chaiProvider, final UserInfo userInfo, final PasswordData oldPassword, final PasswordData newPassword) throws PwmUnrecoverableException, PwmOperationalException {
final UserIdentity userIdentity = userInfo.getUserIdentity();
final Instant startTime = Instant.now();
final boolean bindIsSelf;
final String bindDN;
try {
final ChaiUser theUser = chaiProvider.getEntryFactory().newChaiUser(userIdentity.getUserDN());
final Locale locale = PwmConstants.DEFAULT_LOCALE;
final PwmPasswordPolicy passwordPolicy = PasswordUtility.readPasswordPolicyForUser(pwmApplication, sessionLabel, userIdentity, theUser, locale);
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, passwordPolicy);
pwmPasswordRuleValidator.testPassword(newPassword, null, userInfo, theUser);
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
} catch (PwmException e) {
throw new PwmUnrecoverableException(e.getErrorInformation());
}
try {
final ChaiUser theUser = chaiProvider.getEntryFactory().newChaiUser(userIdentity.getUserDN());
bindDN = chaiProvider.getChaiConfiguration().getSetting(ChaiSetting.BIND_DN);
bindIsSelf = userIdentity.canonicalEquals(new UserIdentity(bindDN, userIdentity.getLdapProfileID()), pwmApplication);
LOGGER.trace(sessionLabel, "preparing to setActorPassword for '" + theUser.getEntryDN() + "', using bind DN: " + bindDN);
final boolean settingEnableChange = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.LDAP_PASSWORD_CHANGE_SELF_ENABLE));
if (settingEnableChange) {
if (oldPassword == null) {
theUser.setPassword(newPassword.getStringValue(), true);
} else {
theUser.changePassword(oldPassword.getStringValue(), newPassword.getStringValue());
}
} else {
LOGGER.debug(sessionLabel, "skipping actual ldap password change operation due to app property " + AppProperty.LDAP_PASSWORD_CHANGE_SELF_ENABLE.getKey() + "=false");
}
} catch (ChaiPasswordPolicyException e) {
final String errorMsg = "error setting password for user '" + userIdentity.toDisplayString() + "'' " + e.toString();
final PwmError pwmError = PwmError.forChaiError(e.getErrorCode());
final ErrorInformation error = new ErrorInformation(pwmError == null ? PwmError.PASSWORD_UNKNOWN_VALIDATION : pwmError, errorMsg);
throw new PwmOperationalException(error);
} catch (ChaiOperationException e) {
final String errorMsg = "error setting password for user '" + userIdentity.toDisplayString() + "'' " + e.getMessage();
final PwmError pwmError = PwmError.forChaiError(e.getErrorCode()) == null ? PwmError.ERROR_UNKNOWN : PwmError.forChaiError(e.getErrorCode());
final ErrorInformation error = new ErrorInformation(pwmError, errorMsg);
throw new PwmOperationalException(error);
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
}
// add the old password to the global history list (if the old password is known)
if (oldPassword != null && pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.PASSWORD_SHAREDHISTORY_ENABLE)) {
pwmApplication.getSharedHistoryManager().addWord(sessionLabel, oldPassword.getStringValue());
}
// update stats
pwmApplication.getStatisticsManager().updateEps(EpsStatistic.PASSWORD_CHANGES, 1);
final int passwordStrength = PasswordUtility.judgePasswordStrength(pwmApplication.getConfig(), newPassword.getStringValue());
pwmApplication.getStatisticsManager().updateAverageValue(Statistic.AVG_PASSWORD_STRENGTH, passwordStrength);
// at this point the password has been changed, so log it.
final String msg = (bindIsSelf ? "user " + userIdentity.toDisplayString() + " has changed own password" : "password for user '" + userIdentity.toDisplayString() + "' has been changed by " + bindDN) + " (" + TimeDuration.fromCurrent(startTime).asCompactString() + ")";
LOGGER.info(sessionLabel, msg);
}
use of password.pwm.util.PwmPasswordRuleValidator in project pwm by pwm-project.
the class PasswordUtility method setActorPassword.
/**
* This is the entry point under which all password changes are managed.
* The following is the general procedure when this method is invoked.
* <ul>
* <li> password is checked against PWM password requirement </li>
* <li> ldap password set is attempted<br/>
* <br/>if successful:
* <ul>
* <li> uiBean is updated with old and new passwords </li>
* <li> uiBean's password expire flag is set to false </li>
* <li> any configured external methods are invoked </li>
* <li> user email notification is sent </li>
* <li> return true </li>
* </ul>
* <br/>if unsuccessful
* <ul>
* <li> ssBean is updated with appropriate error </li>
* <li> return false </li>
* </ul>
* </li>
* </ul>
*
* @param newPassword the new password that is being set.
* @param pwmSession beanmanager for config and user info lookup
* @throws com.novell.ldapchai.exception.ChaiUnavailableException if the ldap directory is not unavailable
* @throws password.pwm.error.PwmUnrecoverableException if user is not authenticated
*/
public static void setActorPassword(final PwmSession pwmSession, final PwmApplication pwmApplication, final PasswordData newPassword) throws ChaiUnavailableException, PwmUnrecoverableException, PwmOperationalException {
final UserInfo userInfo = pwmSession.getUserInfo();
if (!pwmSession.getSessionManager().checkPermission(pwmApplication, Permission.CHANGE_PASSWORD)) {
final String errorMsg = "attempt to setActorPassword, but user does not have password change permission";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNAUTHORIZED, errorMsg);
throw new PwmOperationalException(errorInformation);
}
// but we do it just in case.
try {
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, userInfo.getPasswordPolicy());
pwmPasswordRuleValidator.testPassword(newPassword, null, userInfo, pwmSession.getSessionManager().getActor(pwmApplication));
} catch (PwmDataValidationException e) {
final String errorMsg = "attempt to setActorPassword, but password does not pass local policy validator";
final ErrorInformation errorInformation = new ErrorInformation(e.getErrorInformation().getError(), errorMsg);
throw new PwmOperationalException(errorInformation);
}
// retrieve the user's old password from the userInfoBean in the session
final PasswordData oldPassword = pwmSession.getLoginInfoBean().getUserCurrentPassword();
boolean setPasswordWithoutOld = false;
if (oldPassword == null) {
if (pwmSession.getSessionManager().getActor(pwmApplication).getChaiProvider().getDirectoryVendor() == DirectoryVendor.ACTIVE_DIRECTORY) {
setPasswordWithoutOld = true;
}
}
if (!setPasswordWithoutOld) {
// Check to make sure we actually have an old password
if (oldPassword == null) {
final String errorMsg = "cannot set password for user, old password is not available";
final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_WRONGPASSWORD, errorMsg);
throw new PwmOperationalException(errorInformation);
}
}
final ChaiProvider provider = pwmSession.getSessionManager().getChaiProvider();
setPassword(pwmApplication, pwmSession.getLabel(), provider, userInfo, setPasswordWithoutOld ? null : oldPassword, newPassword);
// update the session state bean's password modified flag
pwmSession.getSessionStateBean().setPasswordModified(true);
// update the login info bean with the user's new password
pwmSession.getLoginInfoBean().setUserCurrentPassword(newPassword);
// close any outstanding ldap connections (since they cache the old password)
pwmSession.getSessionManager().updateUserPassword(pwmApplication, userInfo.getUserIdentity(), newPassword);
// clear the "requires new password flag"
pwmSession.getLoginInfoBean().getLoginFlags().remove(LoginInfoBean.LoginFlag.forcePwChange);
// mark the auth type as authenticatePd now that we have the user's natural password.
pwmSession.getLoginInfoBean().setType(AuthenticationType.AUTHENTICATED);
// update the uibean's "password expired flag".
pwmSession.reloadUserInfoBean(pwmApplication);
// create a proxy user object for pwm to update/read the user.
final ChaiUser proxiedUser = pwmSession.getSessionManager().getActor(pwmApplication);
// update statistics
{
pwmApplication.getStatisticsManager().incrementValue(Statistic.PASSWORD_CHANGES);
}
// invoke post password change actions
invokePostChangePasswordActions(pwmSession, newPassword.getStringValue());
{
// execute configured actions
LOGGER.debug(pwmSession, "executing configured actions to user " + proxiedUser.getEntryDN());
final List<ActionConfiguration> configValues = pwmApplication.getConfig().readSettingAsAction(PwmSetting.CHANGE_PASSWORD_WRITE_ATTRIBUTES);
if (configValues != null && !configValues.isEmpty()) {
final LoginInfoBean clonedLoginInfoBean = JsonUtil.cloneUsingJson(pwmSession.getLoginInfoBean(), LoginInfoBean.class);
clonedLoginInfoBean.setUserCurrentPassword(newPassword);
final MacroMachine macroMachine = MacroMachine.forUser(pwmApplication, pwmSession.getLabel(), pwmSession.getUserInfo(), clonedLoginInfoBean);
final ActionExecutor actionExecutor = new ActionExecutor.ActionExecutorSettings(pwmApplication, userInfo.getUserIdentity()).setMacroMachine(macroMachine).setExpandPwmMacros(true).createActionExecutor();
actionExecutor.executeActions(configValues, pwmSession.getLabel());
}
}
// update the current last password update field in ldap
LdapOperationsHelper.updateLastPasswordUpdateAttribute(pwmApplication, pwmSession.getLabel(), userInfo.getUserIdentity());
}
use of password.pwm.util.PwmPasswordRuleValidator in project pwm by pwm-project.
the class PasswordUtility method checkEnteredPassword.
public static PasswordCheckInfo checkEnteredPassword(final PwmApplication pwmApplication, final Locale locale, final ChaiUser user, final UserInfo userInfo, final LoginInfoBean loginInfoBean, final PasswordData password, final PasswordData confirmPassword) throws PwmUnrecoverableException, ChaiUnavailableException {
if (userInfo == null) {
throw new NullPointerException("userInfoBean cannot be null");
}
boolean pass = false;
String userMessage = "";
int errorCode = 0;
final boolean passwordIsCaseSensitive = userInfo.getPasswordPolicy() == null || userInfo.getPasswordPolicy().getRuleHelper().readBooleanValue(PwmPasswordRule.CaseSensitive);
final CachePolicy cachePolicy;
{
final long cacheLifetimeMS = Long.parseLong(pwmApplication.getConfig().readAppProperty(AppProperty.CACHE_PWRULECHECK_LIFETIME_MS));
cachePolicy = CachePolicy.makePolicyWithExpirationMS(cacheLifetimeMS);
}
if (password == null) {
userMessage = new ErrorInformation(PwmError.PASSWORD_MISSING).toUserStr(locale, pwmApplication.getConfig());
} else {
final CacheService cacheService = pwmApplication.getCacheService();
final CacheKey cacheKey = user != null && userInfo.getUserIdentity() != null ? CacheKey.makeCacheKey(PasswordUtility.class, userInfo.getUserIdentity(), user.getEntryDN() + ":" + password.hash()) : null;
if (pwmApplication.getConfig().isDevDebugMode()) {
LOGGER.trace("generated cacheKey for password check request: " + cacheKey);
}
try {
if (cacheService != null && cacheKey != null) {
final String cachedValue = cacheService.get(cacheKey);
if (cachedValue != null) {
if (NEGATIVE_CACHE_HIT.equals(cachedValue)) {
pass = true;
} else {
LOGGER.trace("cache hit!");
final ErrorInformation errorInformation = JsonUtil.deserialize(cachedValue, ErrorInformation.class);
throw new PwmDataValidationException(errorInformation);
}
}
}
if (!pass) {
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, userInfo.getPasswordPolicy(), locale);
final PasswordData oldPassword = loginInfoBean == null ? null : loginInfoBean.getUserCurrentPassword();
pwmPasswordRuleValidator.testPassword(password, oldPassword, userInfo, user);
pass = true;
if (cacheService != null && cacheKey != null) {
cacheService.put(cacheKey, cachePolicy, NEGATIVE_CACHE_HIT);
}
}
} catch (PwmDataValidationException e) {
errorCode = e.getError().getErrorCode();
userMessage = e.getErrorInformation().toUserStr(locale, pwmApplication.getConfig());
pass = false;
if (cacheService != null && cacheKey != null) {
final String jsonPayload = JsonUtil.serialize(e.getErrorInformation());
cacheService.put(cacheKey, cachePolicy, jsonPayload);
}
}
}
final PasswordCheckInfo.MatchStatus matchStatus = figureMatchStatus(passwordIsCaseSensitive, password, confirmPassword);
if (pass) {
switch(matchStatus) {
case EMPTY:
userMessage = new ErrorInformation(PwmError.PASSWORD_MISSING_CONFIRM).toUserStr(locale, pwmApplication.getConfig());
break;
case MATCH:
userMessage = new ErrorInformation(PwmError.PASSWORD_MEETS_RULES).toUserStr(locale, pwmApplication.getConfig());
break;
case NO_MATCH:
userMessage = new ErrorInformation(PwmError.PASSWORD_DOESNOTMATCH).toUserStr(locale, pwmApplication.getConfig());
break;
default:
userMessage = "";
}
}
final int strength = judgePasswordStrength(pwmApplication.getConfig(), password == null ? null : password.getStringValue());
return new PasswordCheckInfo(userMessage, pass, strength, matchStatus, errorCode);
}
use of password.pwm.util.PwmPasswordRuleValidator in project pwm by pwm-project.
the class ChangePasswordServlet method processChangeAction.
@ActionHandler(action = "change")
ProcessStatus processChangeAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException, ChaiUnavailableException {
final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class);
final UserInfo userInfo = pwmRequest.getPwmSession().getUserInfo();
if (!changePasswordBean.isAllChecksPassed()) {
return ProcessStatus.Continue;
}
final PasswordData password1 = pwmRequest.readParameterAsPassword("password1");
final PasswordData password2 = pwmRequest.readParameterAsPassword("password2");
// check the password meets the requirements
try {
final ChaiUser theUser = pwmRequest.getPwmSession().getSessionManager().getActor(pwmRequest.getPwmApplication());
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmRequest.getPwmApplication(), userInfo.getPasswordPolicy());
final PasswordData oldPassword = pwmRequest.getPwmSession().getLoginInfoBean().getUserCurrentPassword();
pwmPasswordRuleValidator.testPassword(password1, oldPassword, userInfo, theUser);
} catch (PwmDataValidationException e) {
setLastError(pwmRequest, e.getErrorInformation());
LOGGER.debug(pwmRequest, "failed password validation check: " + e.getErrorInformation().toDebugStr());
return ProcessStatus.Continue;
}
// make sure the two passwords match
final boolean caseSensitive = userInfo.getPasswordPolicy().getRuleHelper().readBooleanValue(PwmPasswordRule.CaseSensitive);
if (PasswordUtility.PasswordCheckInfo.MatchStatus.MATCH != PasswordUtility.figureMatchStatus(caseSensitive, password1, password2)) {
setLastError(pwmRequest, PwmError.PASSWORD_DOESNOTMATCH.toInfo());
forwardToChangePage(pwmRequest);
return ProcessStatus.Continue;
}
try {
ChangePasswordServletUtil.executeChangePassword(pwmRequest, password1);
} catch (PwmOperationalException e) {
LOGGER.debug(e.getErrorInformation().toDebugStr());
setLastError(pwmRequest, e.getErrorInformation());
}
return ProcessStatus.Continue;
}
Aggregations