/* * 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.http.servlet.changepw; import com.novell.ldapchai.ChaiUser; import com.novell.ldapchai.exception.ChaiException; import com.novell.ldapchai.exception.ChaiOperationException; import com.novell.ldapchai.exception.ChaiUnavailableException; import password.pwm.AppProperty; import password.pwm.Permission; import password.pwm.PwmApplication; import password.pwm.bean.EmailItemBean; import password.pwm.bean.LocalSessionStateBean; import password.pwm.bean.LoginInfoBean; import password.pwm.bean.PasswordStatus; 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.option.RequireCurrentPasswordMode; import password.pwm.config.profile.PwmPasswordRule; import password.pwm.error.ErrorInformation; import password.pwm.error.PwmDataValidationException; import password.pwm.error.PwmError; import password.pwm.error.PwmException; import password.pwm.error.PwmOperationalException; import password.pwm.error.PwmUnrecoverableException; import password.pwm.http.HttpMethod; import password.pwm.http.JspUrl; import password.pwm.http.ProcessStatus; import password.pwm.http.PwmRequest; import password.pwm.http.PwmRequestAttribute; import password.pwm.http.PwmSession; import password.pwm.http.bean.ChangePasswordBean; import password.pwm.http.servlet.ControlledPwmServlet; import password.pwm.i18n.Message; import password.pwm.ldap.PasswordChangeProgressChecker; import password.pwm.ldap.auth.AuthenticationType; import password.pwm.svc.event.AuditEvent; import password.pwm.svc.event.AuditRecord; import password.pwm.svc.event.AuditRecordFactory; import password.pwm.svc.stats.Statistic; 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.macro.MacroMachine; import password.pwm.util.operations.PasswordUtility; import password.pwm.ws.server.RestResultBean; import password.pwm.ws.server.rest.RestCheckPasswordServer; import javax.servlet.ServletException; import java.io.IOException; import java.time.Instant; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; /** * User interaction servlet for changing (self) passwords. * * @author Jason D. Rivard. */ public abstract class ChangePasswordServlet extends ControlledPwmServlet { private static final PwmLogger LOGGER = PwmLogger.forClass(ChangePasswordServlet.class); private enum ChangePasswordAction implements ControlledPwmServlet.ProcessAction { checkProgress(HttpMethod.POST), complete(HttpMethod.GET), change(HttpMethod.POST), form(HttpMethod.POST), agree(HttpMethod.POST), warnResponse(HttpMethod.POST), reset(HttpMethod.POST), checkPassword(HttpMethod.POST), ; private final HttpMethod method; ChangePasswordAction(final HttpMethod method) { this.method = method; } public Collection<HttpMethod> permittedMethods() { return Collections.singletonList(method); } } enum WarnResponseValue { skip, change, } @Override public Class<? extends ProcessAction> getProcessActionsClass() { return ChangePasswordServlet.ChangePasswordAction.class; } @ActionHandler(action = "reset") ProcessStatus processResetAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { if (pwmRequest.getPwmSession().getLoginInfoBean().getAuthFlags().contains(AuthenticationType.AUTH_FROM_PUBLIC_MODULE)) { // Must have gotten here from the "Forgotten Password" link. Better clear out the temporary authentication pwmRequest.getPwmSession().unauthenticateUser(pwmRequest); } pwmRequest.getPwmApplication().getSessionStateService().clearBean(pwmRequest, ChangePasswordBean.class); pwmRequest.sendRedirectToContinue(); return ProcessStatus.Halt; } @ActionHandler(action = "warnResponse") public ProcessStatus processWarnResponse(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); if (pwmRequest.getPwmSession().getUserInfoBean().getPasswordState().isWarnPeriod()) { final String warnResponseStr = pwmRequest.readParameterAsString("warnResponse"); final WarnResponseValue warnResponse = JavaHelper.readEnumFromString(WarnResponseValue.class, null, warnResponseStr); if (warnResponse != null) { switch (warnResponse) { case skip: pwmRequest.getPwmSession().getLoginInfoBean().setFlag(LoginInfoBean.LoginFlag.skipNewPw); pwmRequest.sendRedirectToContinue(); return ProcessStatus.Halt; case change: changePasswordBean.setWarnPassed(true); break; default: JavaHelper.unhandledSwitchStatement(warnResponse); } } } return ProcessStatus.Continue; } @ActionHandler(action = "change") ProcessStatus processChangeAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException, ChaiUnavailableException { final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final UserInfoBean uiBean = pwmRequest.getPwmSession().getUserInfoBean(); 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(), uiBean.getPasswordPolicy()); pwmPasswordRuleValidator.testPassword(password1,null,uiBean,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 = uiBean.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 { executeChangePassword(pwmRequest, password1); } catch (PwmOperationalException e) { LOGGER.debug(e.getErrorInformation().toDebugStr()); setLastError(pwmRequest, e.getErrorInformation()); } return ProcessStatus.Continue; } @ActionHandler(action = "agree") ProcessStatus processAgreeAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException, ChaiUnavailableException { final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); LOGGER.debug(pwmRequest, "user accepted password change agreement"); if (!changePasswordBean.isAgreementPassed()) { changePasswordBean.setAgreementPassed(true); final AuditRecord auditRecord = new AuditRecordFactory(pwmRequest).createUserAuditRecord( AuditEvent.AGREEMENT_PASSED, pwmRequest.getUserInfoIfLoggedIn(), pwmRequest.getSessionLabel(), "ChangePassword" ); pwmRequest.getPwmApplication().getAuditManager().submit(auditRecord); } return ProcessStatus.Continue; } @ActionHandler(action = "form") ProcessStatus processFormAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException, ChaiUnavailableException { final ChangePasswordBean cpb = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final LocalSessionStateBean ssBean = pwmRequest.getPwmSession().getSessionStateBean(); final UserInfoBean uiBean = pwmRequest.getPwmSession().getUserInfoBean(); final LoginInfoBean loginBean = pwmRequest.getPwmSession().getLoginInfoBean(); final PasswordData currentPassword = pwmRequest.readParameterAsPassword("currentPassword"); // check the current password if (cpb.isCurrentPasswordRequired() && loginBean.getUserCurrentPassword() != null) { if (currentPassword == null) { LOGGER.debug(pwmRequest, "failed password validation check: currentPassword value is missing"); setLastError(pwmRequest, new ErrorInformation(PwmError.ERROR_MISSING_PARAMETER)); return ProcessStatus.Continue; } final boolean passed; { final boolean caseSensitive = Boolean.parseBoolean( uiBean.getPasswordPolicy().getValue(PwmPasswordRule.CaseSensitive)); final PasswordData storedPassword = loginBean.getUserCurrentPassword(); passed = caseSensitive ? storedPassword.equals(currentPassword) : storedPassword.equalsIgnoreCase(currentPassword); } if (!passed) { pwmRequest.getPwmApplication().getIntruderManager().convenience().markUserIdentity( uiBean.getUserIdentity(), pwmRequest.getSessionLabel()); LOGGER.debug(pwmRequest, "failed password validation check: currentPassword value is incorrect"); setLastError(pwmRequest, new ErrorInformation(PwmError.ERROR_BAD_CURRENT_PASSWORD)); return ProcessStatus.Continue; } cpb.setCurrentPasswordPassed(true); } final List<FormConfiguration> formItem = pwmRequest.getConfig().readSettingAsForm(PwmSetting.PASSWORD_REQUIRE_FORM); try { //read the values from the request final Map<FormConfiguration,String> formValues = FormUtility.readFormValuesFromRequest( pwmRequest, formItem, ssBean.getLocale()); validateParamsAgainstLDAP(formValues, pwmRequest.getPwmSession(), pwmRequest.getPwmSession().getSessionManager().getActor(pwmRequest.getPwmApplication())); cpb.setFormPassed(true); } catch (PwmOperationalException e) { pwmRequest.getPwmApplication().getIntruderManager().convenience().markAddressAndSession(pwmRequest.getPwmSession()); pwmRequest.getPwmApplication().getIntruderManager().convenience().markUserIdentity(uiBean.getUserIdentity(), pwmRequest.getSessionLabel()); LOGGER.debug(pwmRequest, e.getErrorInformation()); setLastError(pwmRequest, e.getErrorInformation()); return ProcessStatus.Continue; } return ProcessStatus.Continue; } @ActionHandler(action = "checkProgress") ProcessStatus processCheckProgressAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final PasswordChangeProgressChecker.ProgressTracker progressTracker = changePasswordBean.getChangeProgressTracker(); final PasswordChangeProgressChecker.PasswordChangeProgress passwordChangeProgress; if (progressTracker == null) { passwordChangeProgress = PasswordChangeProgressChecker.PasswordChangeProgress.COMPLETE; } else { final PasswordChangeProgressChecker checker = new PasswordChangeProgressChecker( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(), pwmRequest.getSessionLabel(), pwmRequest.getLocale() ); passwordChangeProgress = checker.figureProgress(progressTracker); } final RestResultBean restResultBean = new RestResultBean(); restResultBean.setData(passwordChangeProgress); LOGGER.trace(pwmRequest, "returning result for restCheckProgress: " + JsonUtil.serialize(restResultBean)); pwmRequest.outputJsonResult(restResultBean); return ProcessStatus.Halt; } @ActionHandler(action = "complete") public ProcessStatus processCompleteAction(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { final ChangePasswordBean cpb = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final PasswordChangeProgressChecker.ProgressTracker progressTracker = cpb.getChangeProgressTracker(); boolean isComplete = true; if (progressTracker != null) { final PasswordChangeProgressChecker checker = new PasswordChangeProgressChecker( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity(), pwmRequest.getSessionLabel(), pwmRequest.getLocale() ); final PasswordChangeProgressChecker.PasswordChangeProgress passwordChangeProgress = checker.figureProgress(progressTracker); isComplete = passwordChangeProgress.isComplete(); } if (isComplete) { if (progressTracker != null) { final TimeDuration totalTime = TimeDuration.fromCurrent(progressTracker.getBeginTime()); try { pwmRequest.getPwmApplication().getStatisticsManager().updateAverageValue(Statistic.AVG_PASSWORD_SYNC_TIME,totalTime.getTotalMilliseconds()); LOGGER.trace(pwmRequest,"password sync process marked completed (" + totalTime.asCompactString() + ")"); } catch (Exception e) { LOGGER.error(pwmRequest,"unable to update average password sync time statistic: " + e.getMessage()); } } cpb.setChangeProgressTracker(null); final Locale locale = pwmRequest.getLocale(); final String completeMessage = pwmRequest.getConfig().readSettingAsLocalizedString(PwmSetting.PASSWORD_COMPLETE_MESSAGE,locale); pwmRequest.getPwmApplication().getSessionStateService().clearBean(pwmRequest, ChangePasswordBean.class); if (completeMessage != null && !completeMessage.isEmpty()) { final MacroMachine macroMachine = pwmRequest.getPwmSession().getSessionManager().getMacroMachine(pwmRequest.getPwmApplication()); final String expandedText = macroMachine.expandMacros(completeMessage); pwmRequest.setAttribute(PwmRequestAttribute.CompleteText, expandedText); pwmRequest.forwardToJsp(JspUrl.PASSWORD_COMPLETE); } else { pwmRequest.getPwmResponse().forwardToSuccessPage(Message.Success_PasswordChange); } } else { forwardToWaitPage(pwmRequest); } return ProcessStatus.Halt; } @ActionHandler(action = "checkPassword") private ProcessStatus processCheckPasswordAction(final PwmRequest pwmRequest) throws IOException, PwmUnrecoverableException, ChaiUnavailableException { final RestCheckPasswordServer.JsonInput jsonInput = JsonUtil.deserialize( pwmRequest.readRequestBodyAsString(), RestCheckPasswordServer.JsonInput.class ); final UserInfoBean userInfoBean = pwmRequest.getPwmSession().getUserInfoBean(); final RestCheckPasswordServer.PasswordCheckRequest passwordCheckRequest = new RestCheckPasswordServer.PasswordCheckRequest( userInfoBean.getUserIdentity(), PasswordData.forStringValue(jsonInput.getPassword1()), PasswordData.forStringValue(jsonInput.getPassword2()), userInfoBean ); final RestCheckPasswordServer.JsonData checkResult = RestCheckPasswordServer.doPasswordRuleCheck( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), passwordCheckRequest); final RestResultBean restResultBean = new RestResultBean(checkResult); pwmRequest.outputJsonResult(restResultBean); return ProcessStatus.Halt; } private void executeChangePassword( final PwmRequest pwmRequest, final PasswordData newPassword ) throws ChaiUnavailableException, PwmUnrecoverableException, PwmOperationalException { final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final PwmSession pwmSession = pwmRequest.getPwmSession(); // password accepted, setup change password final ChangePasswordBean cpb = pwmApplication.getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); // change password PasswordUtility.setActorPassword(pwmSession, pwmApplication, newPassword); //init values for progress screen { final PasswordChangeProgressChecker.ProgressTracker tracker = new PasswordChangeProgressChecker.ProgressTracker(); final PasswordChangeProgressChecker checker = new PasswordChangeProgressChecker( pwmApplication, pwmSession.getUserInfoBean().getUserIdentity(), pwmSession.getLabel(), pwmSession.getSessionStateBean().getLocale() ); cpb.setChangeProgressTracker(tracker); cpb.setChangePasswordMaxCompletion(checker.maxCompletionTime(tracker)); } // send user an email confirmation sendChangePasswordEmailNotice(pwmSession, pwmApplication); // send audit event pwmApplication.getAuditManager().submit(AuditEvent.CHANGE_PASSWORD, pwmSession.getUserInfoBean(), pwmSession); } public void nextStep( final PwmRequest pwmRequest ) throws IOException, PwmUnrecoverableException, ChaiUnavailableException, ServletException { final ChangePasswordBean changePasswordBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final PwmSession pwmSession = pwmRequest.getPwmSession(); final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final Configuration config = pwmApplication.getConfig(); if (changePasswordBean.getChangeProgressTracker() != null) { forwardToWaitPage(pwmRequest); return; } if (warnPageShouldBeShown(pwmRequest, changePasswordBean)) { LOGGER.trace(pwmRequest, "password expiration is within password warn period, forwarding user to warning page"); pwmRequest.forwardToJsp(JspUrl.PASSWORD_WARN); return; } final String agreementMsg = pwmApplication.getConfig().readSettingAsLocalizedString(PwmSetting.PASSWORD_CHANGE_AGREEMENT_MESSAGE, pwmRequest.getLocale()); if (agreementMsg != null && agreementMsg.length() > 0 && !changePasswordBean.isAgreementPassed()) { final MacroMachine macroMachine = pwmSession.getSessionManager().getMacroMachine(pwmApplication); final String expandedText = macroMachine.expandMacros(agreementMsg); pwmRequest.setAttribute(PwmRequestAttribute.AgreementText,expandedText); pwmRequest.forwardToJsp(JspUrl.PASSWORD_AGREEMENT); return; } if (determineIfCurrentPasswordRequired(pwmApplication, pwmSession) && !changePasswordBean.isCurrentPasswordPassed()) { forwardToFormPage(pwmRequest); return; } if (!config.readSettingAsForm(PwmSetting.PASSWORD_REQUIRE_FORM).isEmpty() && !changePasswordBean.isFormPassed()) { forwardToFormPage(pwmRequest); return; } changePasswordBean.setAllChecksPassed(true); forwardToChangePage(pwmRequest); } private static boolean determineIfCurrentPasswordRequired( final PwmApplication pwmApplication, final PwmSession pwmSession ) throws PwmUnrecoverableException { final RequireCurrentPasswordMode currentSetting = pwmApplication.getConfig().readSettingAsEnum(PwmSetting.PASSWORD_REQUIRE_CURRENT, RequireCurrentPasswordMode.class); if (currentSetting == RequireCurrentPasswordMode.FALSE) { return false; } if (pwmSession.getLoginInfoBean().getType() == AuthenticationType.AUTH_FROM_PUBLIC_MODULE) { LOGGER.debug(pwmSession, "skipping user current password requirement, authentication type is " + AuthenticationType.AUTH_FROM_PUBLIC_MODULE); return false; } { final PasswordData currentPassword = pwmSession.getLoginInfoBean().getUserCurrentPassword(); if (currentPassword == null) { LOGGER.debug(pwmSession, "skipping user current password requirement, current password is not known to application"); return false; } } if (currentSetting == RequireCurrentPasswordMode.TRUE) { return true; } final PasswordStatus passwordStatus = pwmSession.getUserInfoBean().getPasswordState(); return currentSetting == RequireCurrentPasswordMode.NOTEXPIRED && !passwordStatus.isExpired() && !passwordStatus.isPreExpired() && !passwordStatus.isViolatesPolicy() && !pwmSession.getUserInfoBean().isRequiresNewPassword(); } private static void validateParamsAgainstLDAP( final Map<FormConfiguration, String> formValues, final PwmSession pwmSession, final ChaiUser theUser ) throws ChaiUnavailableException, PwmDataValidationException { for (final FormConfiguration formItem : formValues.keySet()) { final String attrName = formItem.getName(); final String value = formValues.get(formItem); try { if (!theUser.compareStringAttribute(attrName, value)) { final String errorMsg = "incorrect value for '" + attrName + "'"; final ErrorInformation errorInfo = new ErrorInformation(PwmError.ERROR_INCORRECT_RESPONSE, errorMsg, new String[]{attrName}); LOGGER.debug(pwmSession, errorInfo.toDebugStr()); throw new PwmDataValidationException(errorInfo); } LOGGER.trace(pwmSession, "successful validation of ldap value for '" + attrName + "'"); } catch (ChaiOperationException e) { LOGGER.error(pwmSession, "error during param validation of '" + attrName + "', error: " + e.getMessage()); throw new PwmDataValidationException(new ErrorInformation(PwmError.ERROR_INCORRECT_RESPONSE, "ldap error testing value for '" + attrName + "'", new String[]{attrName})); } } } private static void sendChangePasswordEmailNotice( final PwmSession pwmSession, final PwmApplication pwmApplication ) throws PwmUnrecoverableException { final Configuration config = pwmApplication.getConfig(); final Locale locale = pwmSession.getSessionStateBean().getLocale(); final EmailItemBean configuredEmailSetting = config.readSettingAsEmail(PwmSetting.EMAIL_CHANGEPASSWORD, locale); if (configuredEmailSetting == null) { LOGGER.debug(pwmSession, "skipping change password email for '" + pwmSession.getUserInfoBean().getUserIdentity() + "' no email configured"); return; } pwmApplication.getEmailQueue().submitEmail( configuredEmailSetting, pwmSession.getUserInfoBean(), pwmSession.getSessionManager().getMacroMachine(pwmApplication)); } private static void checkMinimumLifetime( final PwmApplication pwmApplication, final PwmSession pwmSession, final ChangePasswordBean changePasswordBean, final UserInfoBean userInfoBean ) throws PwmUnrecoverableException, ChaiUnavailableException, PwmOperationalException { if (changePasswordBean.isNextAllowedTimePassed()) { return; } try { PasswordUtility.checkIfPasswordWithinMinimumLifetime( pwmSession.getSessionManager().getActor(pwmApplication), pwmSession.getLabel(), userInfoBean.getPasswordPolicy(), userInfoBean.getPasswordLastModifiedTime(), userInfoBean.getPasswordState() ); } catch (PwmException e) { final boolean enforceFromForgotten = pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.CHALLENGE_ENFORCE_MINIMUM_PASSWORD_LIFETIME); if (!enforceFromForgotten && userInfoBean.isRequiresNewPassword()) { LOGGER.debug(pwmSession, "current password is too young, but skipping enforcement of minimum lifetime check due to setting " + PwmSetting.CHALLENGE_ENFORCE_MINIMUM_PASSWORD_LIFETIME.toMenuLocationDebug(null, pwmSession.getSessionStateBean().getLocale())); } else { throw new PwmUnrecoverableException(e.getErrorInformation()); } } changePasswordBean.setNextAllowedTimePassed(true); } private boolean warnPageShouldBeShown(final PwmRequest pwmRequest, final ChangePasswordBean changePasswordBean) { final PwmSession pwmSession = pwmRequest.getPwmSession(); if (!pwmSession.getUserInfoBean().getPasswordState().isWarnPeriod()) { return false; } if (pwmRequest.getPwmSession().getLoginInfoBean().isLoginFlag(LoginInfoBean.LoginFlag.skipNewPw)) { return false; } if (changePasswordBean.isWarnPassed()) { return false; } if (pwmRequest.getPwmSession().getLoginInfoBean().getAuthFlags().contains(AuthenticationType.AUTH_FROM_PUBLIC_MODULE)) { return false; } if (pwmRequest.getPwmSession().getLoginInfoBean().getType() == AuthenticationType.AUTH_FROM_PUBLIC_MODULE) { return false; } return true; } private void forwardToFormPage(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { pwmRequest.addFormInfoToRequestAttr(PwmSetting.PASSWORD_REQUIRE_FORM,false,false); pwmRequest.forwardToJsp(JspUrl.PASSWORD_FORM); } private void forwardToWaitPage(final PwmRequest pwmRequest) throws PwmUnrecoverableException, ServletException, IOException { final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final ChangePasswordBean changePasswordBean = pwmApplication.getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); final Instant maxCompleteTime = changePasswordBean.getChangePasswordMaxCompletion(); pwmRequest.setAttribute( PwmRequestAttribute.ChangePassword_MaxWaitSeconds, maxCompleteTime == null ? 30 : TimeDuration.fromCurrent(maxCompleteTime).getTotalSeconds() ); pwmRequest.setAttribute( PwmRequestAttribute.ChangePassword_CheckIntervalSeconds, Long.parseLong(pwmRequest.getConfig().readAppProperty(AppProperty.CLIENT_AJAX_PW_WAIT_CHECK_SECONDS)) ); pwmRequest.forwardToJsp(JspUrl.PASSWORD_CHANGE_WAIT); } @Override public ProcessStatus preProcessCheck(final PwmRequest pwmRequest) throws PwmUnrecoverableException, IOException, ServletException { final PwmSession pwmSession = pwmRequest.getPwmSession(); final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final ChangePasswordBean changePasswordBean = pwmApplication.getSessionStateService().getBean(pwmRequest, ChangePasswordBean.class); if (pwmSession.getLoginInfoBean().getType() == AuthenticationType.AUTH_WITHOUT_PASSWORD) { throw new PwmUnrecoverableException(PwmError.ERROR_PASSWORD_REQUIRED); } if (!pwmRequest.isAuthenticated()) { pwmRequest.respondWithError(PwmError.ERROR_AUTHENTICATION_REQUIRED.toInfo()); return ProcessStatus.Halt; } if (determineIfCurrentPasswordRequired(pwmApplication, pwmSession)) { changePasswordBean.setCurrentPasswordRequired(true); } if (!pwmSession.getSessionManager().checkPermission(pwmApplication, Permission.CHANGE_PASSWORD)) { pwmRequest.respondWithError(PwmError.ERROR_UNAUTHORIZED.toInfo()); return ProcessStatus.Halt; } try { checkMinimumLifetime(pwmApplication, pwmSession, changePasswordBean, pwmSession.getUserInfoBean()); } catch (PwmOperationalException e) { throw new PwmUnrecoverableException(e.getErrorInformation()); } catch (ChaiException e) { throw PwmUnrecoverableException.fromChaiException(e); } return ProcessStatus.Continue; } private void forwardToChangePage(final PwmRequest pwmRequest) throws ServletException, PwmUnrecoverableException, IOException { final String passwordPolicyChangeMessage = pwmRequest.getPwmSession().getUserInfoBean().getPasswordPolicy().getRuleHelper().getChangeMessage(); if (passwordPolicyChangeMessage.length() > 1) { final MacroMachine macroMachine = pwmRequest.getPwmSession().getSessionManager().getMacroMachine(pwmRequest.getPwmApplication()); macroMachine.expandMacros(passwordPolicyChangeMessage); pwmRequest.setAttribute(PwmRequestAttribute.ChangePassword_PasswordPolicyChangeMessage, passwordPolicyChangeMessage); } pwmRequest.forwardToJsp(JspUrl.PASSWORD_CHANGE); } }