/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2017 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.ldap;
import com.novell.ldapchai.ChaiFactory;
import com.novell.ldapchai.ChaiUser;
import com.novell.ldapchai.exception.ChaiOperationException;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import com.novell.ldapchai.provider.ChaiProvider;
import password.pwm.PwmApplication;
import password.pwm.bean.PasswordStatus;
import password.pwm.bean.ResponseInfoBean;
import password.pwm.bean.SessionLabel;
import password.pwm.bean.UserIdentity;
import password.pwm.bean.UserInfoBean;
import password.pwm.config.Configuration;
import password.pwm.config.FormConfiguration;
import password.pwm.config.FormUtility;
import password.pwm.config.PwmSetting;
import password.pwm.config.UserPermission;
import password.pwm.config.option.ADPolicyComplexity;
import password.pwm.config.option.ForceSetupPolicy;
import password.pwm.config.profile.ChallengeProfile;
import password.pwm.config.profile.LdapProfile;
import password.pwm.config.profile.ProfileType;
import password.pwm.config.profile.ProfileUtility;
import password.pwm.config.profile.PwmPasswordPolicy;
import password.pwm.config.profile.PwmPasswordRule;
import password.pwm.config.profile.UpdateAttributesProfile;
import password.pwm.error.ErrorInformation;
import password.pwm.error.PwmDataValidationException;
import password.pwm.error.PwmError;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.PwmSession;
import password.pwm.svc.PwmService;
import password.pwm.util.PasswordData;
import password.pwm.util.PwmPasswordRuleValidator;
import password.pwm.util.java.JavaHelper;
import password.pwm.util.java.JsonUtil;
import password.pwm.util.java.TimeDuration;
import password.pwm.util.logging.PwmLogger;
import password.pwm.util.operations.CrService;
import password.pwm.util.operations.OtpService;
import password.pwm.util.operations.PasswordUtility;
import password.pwm.util.operations.otp.OTPUserRecord;
import java.io.Serializable;
import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class UserStatusReader {
private static final PwmLogger LOGGER = PwmLogger.forClass(UserStatusReader.class);
private final PwmApplication pwmApplication;
private final SessionLabel sessionLabel;
private final Settings settings;
public UserStatusReader(
final PwmApplication pwmApplication,
final SessionLabel sessionLabel
) {
this.pwmApplication = pwmApplication;
this.sessionLabel = sessionLabel;
this.settings = new Settings();
}
public UserStatusReader(
final PwmApplication pwmApplication,
final SessionLabel sessionLabel,
final Settings settings
)
{
this.pwmApplication = pwmApplication;
this.sessionLabel = sessionLabel;
this.settings = settings.copy();
}
public PasswordStatus readPasswordStatus(
final ChaiUser theUser,
final PwmPasswordPolicy passwordPolicy,
final UserInfoBean userInfoBean,
final PasswordData currentPassword
)
throws ChaiUnavailableException, PwmUnrecoverableException
{
final Configuration config = pwmApplication.getConfig();
final PasswordStatus passwordStatus = new PasswordStatus();
final String userDN = theUser.getEntryDN();
final long startTime = System.currentTimeMillis();
LOGGER.trace(sessionLabel, "beginning password status check process for " + userDN);
// check if password meets existing policy.
if (userInfoBean != null && passwordPolicy.getRuleHelper().readBooleanValue(PwmPasswordRule.EnforceAtLogin)) {
if (currentPassword != null) {
try {
final PwmPasswordRuleValidator passwordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, passwordPolicy);
passwordRuleValidator.testPassword(currentPassword, null, userInfoBean, theUser);
} catch (PwmDataValidationException | PwmUnrecoverableException e) {
LOGGER.debug(sessionLabel, "user " + userDN + " password does not conform to current password policy (" + e.getMessage() + "), marking as requiring change.");
passwordStatus.setViolatesPolicy(true);
}
}
}
try {
final boolean ldapPasswordExpired = theUser.isPasswordExpired();
if (ldapPasswordExpired) {
passwordStatus.setExpired(true);
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());
}
try {
Date ldapPasswordExpirationTime = theUser.readPasswordExpirationDate();
if (ldapPasswordExpirationTime != null && ldapPasswordExpirationTime.getTime() < 0) {
// If ldapPasswordExpirationTime is less than 0, this may indicate an extremely late date, past the epoch.
LOGGER.debug(sessionLabel, "ignoring past-dated password expiration time: " + JavaHelper.toIsoDate(ldapPasswordExpirationTime));
ldapPasswordExpirationTime = null;
}
if (ldapPasswordExpirationTime != null) {
final TimeDuration expirationInterval = TimeDuration.fromCurrent(ldapPasswordExpirationTime);
LOGGER.trace(sessionLabel, "read password expiration time: "
+ JavaHelper.toIsoDate(ldapPasswordExpirationTime)
+ ", " + expirationInterval.asCompactString() + " from now"
);
final long diff = ldapPasswordExpirationTime.getTime() - System.currentTimeMillis();
// 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 > 0 && diff < preExpireMs) {
LOGGER.debug(sessionLabel, "user " + userDN + " password will expire within " + TimeDuration.asCompactString(diff) + ", marking as pre-expired");
passwordStatus.setPreExpired(true);
} else if (passwordStatus.isExpired()) {
LOGGER.debug(sessionLabel, "user " + userDN + " password is expired, marking as pre-expired.");
passwordStatus.setPreExpired(true);
}
// 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 (!passwordStatus.isExpired() && !passwordStatus.isPreExpired()) {
if (!(preWarnMs == 0 || preWarnMs < preExpireMs)) {
if (diff > 0 && diff < preWarnMs) {
LOGGER.debug(sessionLabel,
"user " + userDN + " password will expire within " + TimeDuration.asCompactString(
diff) + ", marking as within warn period");
passwordStatus.setWarnPeriod(true);
} else if (passwordStatus.isExpired()) {
LOGGER.debug(sessionLabel,
"user " + userDN + " password is expired, marking as within warn period");
passwordStatus.setWarnPeriod(true);
}
}
}
}
} catch (ChaiOperationException e) {
LOGGER.info(sessionLabel, "error reading user attrs for " + userDN + " while reading passwordExpirationDate(): " + e.getMessage());
}
LOGGER.debug(sessionLabel, "completed user password status check for " + userDN + " " + passwordStatus + " (" + TimeDuration.fromCurrent(startTime).asCompactString() + ")");
return passwordStatus;
}
public void populateActorUserInfoBean(
final PwmSession pwmSession,
final UserIdentity userIdentity
)
throws ChaiUnavailableException, PwmUnrecoverableException
{
final String userLdapProfile = userIdentity.getLdapProfileID();
final ChaiProvider provider = pwmApplication.getProxyChaiProvider(userLdapProfile);
final UserInfoBean uiBean = pwmSession.getUserInfoBean();
final PasswordData currentPassword = pwmSession.getLoginInfoBean().getUserCurrentPassword();
populateUserInfoBean(
uiBean,
pwmSession.getSessionStateBean().getLocale(),
userIdentity,
provider,
currentPassword
);
}
public UserInfoBean populateUserInfoBean(
final Locale userLocale,
final UserIdentity userIdentity
)
throws PwmUnrecoverableException
{
final ChaiProvider provider = pwmApplication.getProxyChaiProvider(userIdentity.getLdapProfileID());
final UserInfoBean userInfoBean = new UserInfoBean();
populateUserInfoBean(userInfoBean, userLocale, userIdentity, provider, null);
return userInfoBean;
}
public void populateUserInfoBean(
final UserInfoBean uiBean,
final Locale userLocale,
final UserIdentity userIdentity,
final ChaiProvider provider
)
throws PwmUnrecoverableException
{
try {
populateUserInfoBeanImpl(uiBean, userLocale, userIdentity, provider, null);
} catch (ChaiUnavailableException e) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE,e.getMessage()));
}
}
public void populateUserInfoBean(
final UserInfoBean uiBean,
final Locale userLocale,
final UserIdentity userIdentity,
final ChaiProvider provider,
final PasswordData currentPassword
)
throws PwmUnrecoverableException
{
try {
populateUserInfoBeanImpl(uiBean, userLocale, userIdentity, provider, currentPassword);
} catch (ChaiUnavailableException e) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_DIRECTORY_UNAVAILABLE,e.getMessage()));
}
}
private void populateUserInfoBeanImpl(
final UserInfoBean uiBean,
final Locale userLocale,
final UserIdentity userIdentity,
final ChaiProvider provider,
final PasswordData currentPassword
)
throws PwmUnrecoverableException, ChaiUnavailableException
{
final Configuration config = pwmApplication.getConfig();
final long methodStartTime = System.currentTimeMillis();
if (userIdentity == null || userIdentity.getUserDN() == null || userIdentity.getUserDN().length() < 1) {
throw new NullPointerException("userDN can not be null");
}
//attempt to add the object class to the user
LdapOperationsHelper.addConfiguredUserObjectClass(sessionLabel, userIdentity, pwmApplication);
final ChaiUser theUser = ChaiFactory.createChaiUser(userIdentity.getUserDN(), provider);
final LdapProfile ldapProfile = config.getLdapProfiles().get(userIdentity.getLdapProfileID());
final UserDataReader userDataReader = new LdapUserDataReader(userIdentity, theUser);
uiBean.setUserIdentity(userIdentity.canonicalized(pwmApplication));
// read authenticated profiles
for (final ProfileType profileType : ProfileType.values()) {
if (profileType.isAuthenticated()) {
final String profileID = ProfileUtility.discoverProfileIDforUser(pwmApplication, sessionLabel, userIdentity, profileType);
uiBean.getProfileIDs().put(profileType, profileID);
if (profileID != null) {
LOGGER.debug(sessionLabel, "assigned " + profileType.toString() + " profileID \"" + profileID + "\" to " + userIdentity.toDisplayString());
} else {
LOGGER.debug(sessionLabel, profileType.toString() + " has no matching profiles for user " + userIdentity.toDisplayString());
}
}
}
populateLocaleSpecificUserInfoBean(uiBean, userLocale);
//populate OTP data
if (config.readSettingAsBoolean(PwmSetting.OTP_ENABLED)){
final OtpService otpService = pwmApplication.getOtpService();
if (otpService != null && otpService.status() == PwmService.STATUS.OPEN) {
final OTPUserRecord otpUserRecord = otpService.readOTPUserConfiguration(sessionLabel, userIdentity);
uiBean.setOtpUserRecord(otpUserRecord);
uiBean.setRequiresOtpConfig(checkIfOtpUpdateNeeded(uiBean, otpUserRecord));
}
}
//populate cached password rule attributes
try {
final Set<String> interestingUserAttributes = figurePasswordRuleAttributes(uiBean);
final Map<String, String> allUserAttrs = userDataReader.readStringAttributes(interestingUserAttributes);
uiBean.setCachedPasswordRuleAttributes(allUserAttrs);
} catch (ChaiOperationException e) {
LOGGER.warn(sessionLabel, "error retrieving user cached password rule attributes " + e);
}
//populate cached attributes.
{
final List<String> cachedAttributeNames = ldapProfile.readSettingAsStringArray(PwmSetting.CACHED_USER_ATTRIBUTES);
if (cachedAttributeNames != null && !cachedAttributeNames.isEmpty()) {
try {
final Map<String,String> attributeValues = userDataReader.readStringAttributes(cachedAttributeNames);
uiBean.setCachedAttributeValues(Collections.unmodifiableMap(attributeValues));
} catch (ChaiOperationException e) {
LOGGER.warn(sessionLabel, "error retrieving user cache attributes: " + e);
}
}
}
{// set userID
final String uIDattr = ldapProfile.getUsernameAttribute();
try {
uiBean.setUsername(userDataReader.readStringAttribute(uIDattr));
} catch (ChaiOperationException e) {
LOGGER.error(sessionLabel, "error reading userID attribute: " + e.getMessage());
}
}
{ // set guid
final String userGuid = LdapOperationsHelper.readLdapGuidValue(pwmApplication, sessionLabel, userIdentity, false);
uiBean.setUserGuid(userGuid);
}
{ // set email address
final String ldapEmailAttribute = ldapProfile.readSettingAsString(PwmSetting.EMAIL_USER_MAIL_ATTRIBUTE);
try {
uiBean.setUserEmailAddress(userDataReader.readStringAttribute(ldapEmailAttribute));
} catch (ChaiOperationException e) {
LOGGER.error(sessionLabel, "error reading email address attribute: " + e.getMessage());
}
}
{ // set SMS number
final String ldapSmsAttribute = ldapProfile.readSettingAsString(PwmSetting.SMS_USER_PHONE_ATTRIBUTE);
try {
uiBean.setUserSmsNumber(userDataReader.readStringAttribute(ldapSmsAttribute));
} catch (ChaiOperationException e) {
LOGGER.error(sessionLabel, "error reading sms number attribute: " + e.getMessage());
}
}
// read password expiration time
uiBean.setPasswordExpirationTime(LdapOperationsHelper.readPasswordExpirationTime(theUser));
// read password state
uiBean.setPasswordState(readPasswordStatus(theUser, uiBean.getPasswordPolicy(), uiBean, currentPassword));
// mark if new pw required
uiBean.setRequiresNewPassword(checkIfNewPasswordRequired(userIdentity, uiBean.getPasswordState()));
// check if responses need to be updated
uiBean.setRequiresUpdateProfile(checkIfProfileUpdateNeeded(config, uiBean, userDataReader, userLocale));
// fetch last password modification time;
final Instant pwdLastModifedDate = PasswordUtility.determinePwdLastModified(pwmApplication, sessionLabel, userIdentity);
uiBean.setPasswordLastModifiedTime(pwdLastModifedDate);
// read user last login time:
try {
final Date lastLoginTime = theUser.readLastLoginTime();
uiBean.setLastLdapLoginTime(lastLoginTime == null ? null : lastLoginTime.toInstant());
} catch (ChaiOperationException e) {
LOGGER.warn(sessionLabel, "error reading user's last ldap login time: " + e.getMessage());
}
try {
final Date accountExpireDate = theUser.readAccountExpirationDate();
uiBean.setAccountExpirationTime(accountExpireDate == null ? null : accountExpireDate.toInstant());
} catch (Exception e) {
LOGGER.error(sessionLabel, "error reading account expired date for user '" + userIdentity + "', " + e.getMessage());
}
LOGGER.trace(sessionLabel, "populateUserInfoBean for " + userIdentity + " completed in " + TimeDuration.fromCurrent(methodStartTime).asCompactString());
}
public void populateLocaleSpecificUserInfoBean(
final UserInfoBean uiBean,
final Locale userLocale
)
throws PwmUnrecoverableException, ChaiUnavailableException {
final long startTime = System.currentTimeMillis();
if (uiBean == null || uiBean.getUserIdentity() == null) {
return;
}
final ChaiUser theUser = pwmApplication.getProxiedChaiUser(uiBean.getUserIdentity());
//populate password policy
uiBean.setPasswordPolicy(PasswordUtility.readPasswordPolicyForUser(pwmApplication, sessionLabel, uiBean.getUserIdentity(), theUser, userLocale));
//populate c/r challenge set.
{
final CrService crService = pwmApplication.getCrService();
final ResponseInfoBean responseInfoBean = crService.readUserResponseInfo(sessionLabel, uiBean.getUserIdentity(), theUser);
final ChallengeProfile challengeProfile = crService.readUserChallengeProfile(
sessionLabel,
uiBean.getUserIdentity(),
theUser,
uiBean.getPasswordPolicy(),
userLocale
);
uiBean.setChallengeSet(challengeProfile);
uiBean.setResponseInfoBean(responseInfoBean);
uiBean.setRequiresResponseConfig(crService.checkIfResponseConfigNeeded(pwmApplication, sessionLabel, uiBean.getUserIdentity(), challengeProfile.getChallengeSet(), responseInfoBean));
}
LOGGER.trace(sessionLabel, "finished population of locale specific UserInfoBean in " + TimeDuration.fromCurrent(startTime).asCompactString());
}
private static Set<String> figurePasswordRuleAttributes(
final UserInfoBean uiBean
) {
final Set<String> interestingUserAttributes = new HashSet<>();
interestingUserAttributes.addAll(uiBean.getPasswordPolicy().getRuleHelper().getDisallowedAttributes());
if (uiBean.getPasswordPolicy().getRuleHelper().getADComplexityLevel() == ADPolicyComplexity.AD2003
|| uiBean.getPasswordPolicy().getRuleHelper().getADComplexityLevel() == ADPolicyComplexity.AD2008) {
interestingUserAttributes.add("sAMAccountName");
interestingUserAttributes.add("displayName");
interestingUserAttributes.add("fullname");
interestingUserAttributes.add("cn");
}
return interestingUserAttributes;
}
public static class Settings implements Serializable {
private Settings copy() {
return JsonUtil.deserialize(JsonUtil.serialize(this),this.getClass());
}
}
public boolean checkIfProfileUpdateNeeded(
final Configuration configuration,
final UserInfoBean uiBean,
final UserDataReader userDataReader,
final Locale locale
)
throws ChaiUnavailableException, PwmUnrecoverableException
{
final UserIdentity userIdentity = uiBean.getUserIdentity();
if (!pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.UPDATE_PROFILE_ENABLE)) {
LOGGER.debug(sessionLabel, "checkProfiles: " + userIdentity.toString() + " profile module is not enabled");
return false;
}
UpdateAttributesProfile updateAttributesProfile = null;
if (uiBean.getProfileIDs().containsKey(ProfileType.UpdateAttributes)) {
updateAttributesProfile = configuration.getUpdateAttributesProfile().get(uiBean.getProfileIDs().get(ProfileType.UpdateAttributes));
}
if (updateAttributesProfile == null) {
return false;
}
if (!updateAttributesProfile.readSettingAsBoolean(PwmSetting.UPDATE_PROFILE_FORCE_SETUP)) {
LOGGER.debug(sessionLabel, "checkProfiles: " + userIdentity.toString() + " profile force setup is not enabled");
return false;
}
final List<FormConfiguration> updateFormFields = updateAttributesProfile.readSettingAsForm(PwmSetting.UPDATE_PROFILE_FORM);
// populate the map from ldap
try {
final Map<FormConfiguration, List<String>> valueMap = FormUtility.populateFormMapFromLdap(updateFormFields, sessionLabel, userDataReader, FormUtility.Flag.ReturnEmptyValues);
final Map<FormConfiguration, String> singleValueMap = FormUtility.multiValueMapToSingleValue(valueMap);
FormUtility.validateFormValues(configuration, singleValueMap, locale);
LOGGER.debug(sessionLabel, "checkProfile: " + userIdentity + " has value for attributes, update profile will not be required");
return false;
} catch (PwmDataValidationException e) {
LOGGER.debug(sessionLabel, "checkProfile: " + userIdentity + " does not have good attributes (" + e.getMessage() + "), update profile will be required");
return true;
}
/*
final List<UserPermission> checkProfileQueryMatch = updateAttributesProfile.readSettingAsUserPermission(PwmSetting.UPDATE_PROFILE_CHECK_QUERY_MATCH);
if (checkProfileQueryMatch != null && !checkProfileQueryMatch.isEmpty()) {
if (LdapPermissionTester.testUserPermissions(pwmApplication, sessionLabel, userIdentity, checkProfileQueryMatch)) {
LOGGER.info(sessionLabel, "checkProfiles: " + userIdentity.toString() + " matches 'checkProfiles query match', update profile will be required by user");
return true;
} else {
LOGGER.info(sessionLabel, "checkProfiles: " + userIdentity.toString() + " does not match 'checkProfiles query match', update profile not required by user");
return false;
}
} else {
LOGGER.trace("no checkProfiles query match configured, will check to see if form attributes have values");
final List<FormConfiguration> updateFormFields = updateAttributesProfile.readSettingAsForm(PwmSetting.UPDATE_PROFILE_FORM);
// populate the map with attribute values from the uiBean, which was populated through ldap.
final Map<FormConfiguration,String> formValues = new HashMap<>();
for (final FormConfiguration formItem : updateFormFields) {
try {
final String ldapValue = userDataReader.readStringAttribute(formItem.getName());
formValues.put(formItem, ldapValue);
} catch (ChaiOperationException e) {
LOGGER.error(sessionLabel,"error reading attribute while executing checkProfile, attribute=" + formItem.getName() + ", error: " + e.getMessage());
}
}
try {
FormUtility.validateFormValues(configuration, formValues, locale);
LOGGER.debug(sessionLabel, "checkProfile: " + userIdentity + " has value for attributes, update profile will not be required");
return false;
} catch (PwmDataValidationException e) {
LOGGER.debug(sessionLabel, "checkProfile: " + userIdentity + " does not have good attributes (" + e.getMessage() + "), update profile will be required");
return true;
}
}
*/
}
public boolean checkIfOtpUpdateNeeded(
final UserInfoBean uiBean,
final OTPUserRecord otpUserRecord
)
throws ChaiUnavailableException, PwmUnrecoverableException
{
LOGGER.trace(sessionLabel, "checkOtp: beginning process to check if user OTP setup is required");
final UserIdentity userIdentity = uiBean.getUserIdentity();
if (!pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.OTP_ENABLED)) {
LOGGER.trace(sessionLabel, "checkOtp: OTP is not enabled, user OTP setup is not required");
return false;
}
final boolean hasStoredOtp = otpUserRecord != null && otpUserRecord.getSecret() != null;
if (hasStoredOtp) {
LOGGER.trace(sessionLabel, "checkOtp: user has existing valid otp record, user OTP setup is not required");
return false;
}
final List<UserPermission> setupOtpPermission = pwmApplication.getConfig().readSettingAsUserPermission(PwmSetting.OTP_SETUP_USER_PERMISSION);
if (!LdapPermissionTester.testUserPermissions(pwmApplication, sessionLabel, uiBean.getUserIdentity(), setupOtpPermission)) {
LOGGER.trace(sessionLabel, "checkOtp: " + userIdentity.toString() + " is not eligible for checkOtp due to query match");
return false;
}
final ForceSetupPolicy policy = pwmApplication.getConfig().readSettingAsEnum(PwmSetting.OTP_FORCE_SETUP,ForceSetupPolicy.class);
// hasStoredOtp is always true at this point, so if forced then update needed
LOGGER.debug(sessionLabel, "checkOtp: user does not have existing valid otp record, user OTP setup is required");
return policy == ForceSetupPolicy.FORCE || policy == ForceSetupPolicy.FORCE_ALLOW_SKIP;
}
public boolean checkIfNewPasswordRequired(
final UserIdentity userIdentity,
final PasswordStatus passwordStatus
)
throws ChaiUnavailableException, PwmUnrecoverableException
{
final List<UserPermission> updateProfilePermission = pwmApplication.getConfig().readSettingAsUserPermission(
PwmSetting.QUERY_MATCH_CHANGE_PASSWORD);
if (!LdapPermissionTester.testUserPermissions(pwmApplication, sessionLabel, userIdentity, updateProfilePermission)) {
LOGGER.debug(sessionLabel,
"checkPassword: " + userIdentity.toString() + " user does not have permission to change password");
return false;
}
if (passwordStatus.isExpired()) {
LOGGER.debug(sessionLabel, "checkPassword: password is expired, marking new password as required");
return true;
}
if (passwordStatus.isPreExpired()) {
LOGGER.debug(sessionLabel, "checkPassword: password is pre-expired, marking new password as required");
return true;
}
if (passwordStatus.isWarnPeriod()) {
LOGGER.debug(sessionLabel, "checkPassword: password is within warn period, marking new password as required");
return true;
}
if (passwordStatus.isViolatesPolicy()) {
LOGGER.debug(sessionLabel, "checkPassword: current password violates password policy, marking new password as required");
return true;
}
return false;
}
}