Jason Rivard 7 vuotta sitten
vanhempi
commit
e0eb0a1c3b

+ 24 - 29
server/pom.xml

@@ -42,12 +42,6 @@
                 <checkstyle.skip>true</checkstyle.skip>
             </properties>
         </profile>
-        <profile>
-            <id>skip-jspc</id>
-            <properties>
-                <jspc.skip>true</jspc.skip>
-            </properties>
-        </profile>
         <profile>
             <id>skip-spotbugs</id>
             <properties>
@@ -107,6 +101,7 @@
                     </dependency>
                 </dependencies>
                 <configuration>
+                    <fork>false</fork>
                     <excludeFilterFile>src/build/spotbugs-exclude.xml</excludeFilterFile>
                     <includeTests>false</includeTests>
                     <skip>${skipSpotbugs}</skip>
@@ -178,10 +173,28 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.3</version>
+                <version>3.7.0</version>
                 <configuration>
                     <source>${maven.compiler.source}</source>
                     <target>${maven.compiler.target}</target>
+
+                    <!-- following allows lombok processor to execute on jdk9+ -->
+                    <showDeprecation>true</showDeprecation>
+                    <showWarnings>true</showWarnings>
+                    <fork>true</fork>
+                    <compilerargs>
+                        <arg>-Werror</arg>
+                        <arg>-Xlint:all</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
+                        <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
+                    </compilerargs>
                 </configuration>
             </plugin>
             <plugin>
@@ -247,7 +260,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
-                <version>2.17</version>
+                <version>3.0.0</version>
                 <dependencies>
                     <dependency>
                         <groupId>com.puppycrawl.tools</groupId>
@@ -314,27 +327,9 @@
                 </executions>
             </plugin>
             <plugin>
-                <groupId>org.jasig.mojo.jspc</groupId>
+                <groupId>io.leonard.maven.plugins</groupId>
                 <artifactId>jspc-maven-plugin</artifactId>
-                <version>2.0.2</version>
-                <dependencies>
-                    <dependency>
-                        <groupId>org.jasig.mojo.jspc</groupId>
-                        <artifactId>jspc-compiler-tomcat7</artifactId>
-                        <version>2.0.2</version>
-                    </dependency>
-                </dependencies>
-                <configuration>
-                    <includeInProject>false</includeInProject>
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>compile</goal>
-                        </goals>
-                        <phase>compile</phase>
-                    </execution>
-                </executions>
+                <version>2.4.2</version>
             </plugin>
             <plugin>
                 <artifactId>maven-clean-plugin</artifactId>
@@ -569,7 +564,7 @@
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.16.18</version>
+            <version>1.16.20</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

+ 5 - 88
server/src/main/java/password/pwm/http/servlet/forgottenpw/ForgottenPasswordServlet.java

@@ -51,7 +51,6 @@ import password.pwm.config.value.data.FormConfiguration;
 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;
@@ -84,9 +83,7 @@ import password.pwm.svc.stats.StatisticsManager;
 import password.pwm.svc.token.TokenPayload;
 import password.pwm.svc.token.TokenType;
 import password.pwm.util.CaptchaUtility;
-import password.pwm.util.PasswordData;
 import password.pwm.util.PostChangePasswordAction;
-import password.pwm.util.RandomPasswordGenerator;
 import password.pwm.util.form.FormUtility;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JsonUtil;
@@ -213,15 +210,15 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet {
         return ProcessStatus.Continue;
     }
 
-    private static ForgottenPasswordBean forgottenPasswordBean(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+    static ForgottenPasswordBean forgottenPasswordBean( final PwmRequest pwmRequest ) throws PwmUnrecoverableException {
         return pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ForgottenPasswordBean.class);
     }
 
-    private static void clearForgottenPasswordBean(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+    static void clearForgottenPasswordBean( final PwmRequest pwmRequest ) throws PwmUnrecoverableException {
         pwmRequest.getPwmApplication().getSessionStateService().clearBean(pwmRequest, ForgottenPasswordBean.class);
     }
 
-    private static ForgottenPasswordProfile forgottenPasswordProfile(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+    static ForgottenPasswordProfile forgottenPasswordProfile( final PwmRequest pwmRequest ) throws PwmUnrecoverableException {
         final ForgottenPasswordBean forgottenPasswordBean = forgottenPasswordBean(pwmRequest);
         return pwmRequest.getConfig().getForgottenPasswordProfiles().get(forgottenPasswordBean.getForgottenPasswordProfileID());
     }
@@ -896,7 +893,7 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet {
 
         final RecoveryAction recoveryAction = ForgottenPasswordUtil.getRecoveryAction(config, forgottenPasswordBean);
         if (recoveryAction == RecoveryAction.SENDNEWPW || recoveryAction == RecoveryAction.SENDNEWPW_AND_EXPIRE) {
-            processSendNewPassword(pwmRequest);
+            ForgottenPasswordUtil.doActionSendNewPassword(pwmRequest);
             return;
         }
 
@@ -1005,86 +1002,6 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet {
         }
     }
 
-    private static void processSendNewPassword(final PwmRequest pwmRequest)
-            throws ChaiUnavailableException, IOException, ServletException, PwmUnrecoverableException
-    {
-        final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
-        final PwmSession pwmSession = pwmRequest.getPwmSession();
-        final ForgottenPasswordBean forgottenPasswordBean = forgottenPasswordBean(pwmRequest);
-        final ForgottenPasswordProfile forgottenPasswordProfile = forgottenPasswordProfile(pwmRequest);
-        final RecoveryAction recoveryAction = ForgottenPasswordUtil.getRecoveryAction(pwmApplication.getConfig(), forgottenPasswordBean);
-
-        LOGGER.trace(pwmRequest,"beginning process to send new password to user");
-
-        if (!forgottenPasswordBean.getProgress().isAllPassed()) {
-            return;
-        }
-
-        final UserIdentity userIdentity = forgottenPasswordBean.getUserIdentity();
-        final ChaiUser theUser = pwmRequest.getPwmApplication().getProxiedChaiUser(userIdentity);
-
-        try { // try unlocking user
-            theUser.unlockPassword();
-            LOGGER.trace(pwmRequest, "unlock account succeeded");
-        } catch (ChaiOperationException e) {
-            final String errorMsg = "unable to unlock user " + theUser.getEntryDN() + " error: " + e.getMessage();
-            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNLOCK_FAILURE,errorMsg);
-            LOGGER.error(pwmRequest.getPwmSession(), errorInformation.toDebugStr());
-            pwmRequest.respondWithError(errorInformation);
-            return;
-        }
-
-        try {
-            pwmSession.getLoginInfoBean().setAuthenticated(true);
-            pwmSession.getLoginInfoBean().getAuthFlags().add(AuthenticationType.AUTH_FROM_PUBLIC_MODULE);
-            pwmSession.getLoginInfoBean().setUserIdentity(userIdentity);
-
-            LOGGER.info(pwmRequest, "user successfully supplied password recovery responses, emailing new password to: " + theUser.getEntryDN());
-
-            // add post change actions
-            addPostChangeAction(pwmRequest, userIdentity);
-
-            // create newpassword
-            final PasswordData newPassword = RandomPasswordGenerator.createRandomPassword(pwmSession, pwmApplication);
-
-            // set the password
-            LOGGER.trace(pwmRequest.getPwmSession(), "setting user password to system generated random value");
-            PasswordUtility.setActorPassword(pwmSession, pwmApplication, newPassword);
-
-            if (recoveryAction == RecoveryAction.SENDNEWPW_AND_EXPIRE) {
-                LOGGER.debug(pwmSession, "marking user password as expired");
-                theUser.expirePassword();
-            }
-
-            // mark the event log
-            pwmApplication.getAuditManager().submit(AuditEvent.RECOVER_PASSWORD, pwmSession.getUserInfo(), pwmSession);
-
-            final MessageSendMethod messageSendMethod = forgottenPasswordProfile.readSettingAsEnum(PwmSetting.RECOVERY_SENDNEWPW_METHOD,MessageSendMethod.class);
-
-            // send email or SMS
-            final String toAddress = PasswordUtility.sendNewPassword(
-                    pwmSession.getUserInfo(),
-                    pwmApplication,
-                    pwmSession.getSessionManager().getMacroMachine(pwmApplication),
-                    newPassword,
-                    pwmSession.getSessionStateBean().getLocale(),
-                    messageSendMethod
-            );
-
-            pwmRequest.getPwmResponse().forwardToSuccessPage(Message.Success_PasswordSend, toAddress);
-        } catch (PwmException e) {
-            LOGGER.warn(pwmSession,"unexpected error setting new password during recovery process for user: " + e.getMessage());
-            pwmRequest.respondWithError(e.getErrorInformation());
-        } catch (ChaiOperationException e) {
-            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"unexpected ldap error while processing recovery action " + recoveryAction + ", error: " + e.getMessage());
-            LOGGER.warn(pwmSession,errorInformation.toDebugStr());
-            pwmRequest.respondWithError(errorInformation);
-        } finally {
-            clearForgottenPasswordBean(pwmRequest);
-            pwmSession.unauthenticateUser(pwmRequest);
-            pwmSession.getSessionStateBean().setPasswordModified(false);
-        }
-    }
 
 
     private static List<FormConfiguration> figureAttributeForm(
@@ -1126,7 +1043,7 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet {
         return returnList;
     }
 
-    private static void addPostChangeAction(
+    static void addPostChangeAction(
             final PwmRequest pwmRequest,
             final UserIdentity userIdentity
     )

+ 114 - 0
server/src/main/java/password/pwm/http/servlet/forgottenpw/ForgottenPasswordUtil.java

@@ -26,6 +26,8 @@ import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.cr.Challenge;
 import com.novell.ldapchai.cr.ChallengeSet;
 import com.novell.ldapchai.cr.ResponseSet;
+import com.novell.ldapchai.exception.ChaiException;
+import com.novell.ldapchai.exception.ChaiOperationException;
 import com.novell.ldapchai.exception.ChaiUnavailableException;
 import com.novell.ldapchai.exception.ChaiValidationException;
 import password.pwm.AppProperty;
@@ -43,18 +45,25 @@ import password.pwm.config.profile.ForgottenPasswordProfile;
 import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
+import password.pwm.error.PwmException;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.bean.ForgottenPasswordBean;
 import password.pwm.http.filter.AuthenticationFilter;
+import password.pwm.i18n.Message;
 import password.pwm.ldap.UserInfo;
 import password.pwm.ldap.UserInfoFactory;
+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.svc.stats.StatisticsManager;
 import password.pwm.svc.token.TokenPayload;
 import password.pwm.svc.token.TokenService;
 import password.pwm.svc.token.TokenType;
+import password.pwm.util.PasswordData;
+import password.pwm.util.RandomPasswordGenerator;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
@@ -488,4 +497,109 @@ class ForgottenPasswordUtil {
         return displayDestAddress;
     }
 
+    static void doActionSendNewPassword( final PwmRequest pwmRequest)
+            throws ChaiUnavailableException, IOException, ServletException, PwmUnrecoverableException
+    {
+        final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
+        final ForgottenPasswordBean forgottenPasswordBean = ForgottenPasswordServlet.forgottenPasswordBean(pwmRequest);
+        final ForgottenPasswordProfile forgottenPasswordProfile = ForgottenPasswordServlet.forgottenPasswordProfile(pwmRequest);
+        final RecoveryAction recoveryAction = ForgottenPasswordUtil.getRecoveryAction(pwmApplication.getConfig(), forgottenPasswordBean);
+
+        LOGGER.trace(pwmRequest,"beginning process to send new password to user");
+
+        if (!forgottenPasswordBean.getProgress().isAllPassed()) {
+            return;
+        }
+
+        final UserIdentity userIdentity = forgottenPasswordBean.getUserIdentity();
+        final ChaiUser theUser = pwmRequest.getPwmApplication().getProxiedChaiUser(userIdentity);
+
+        try {
+            // try unlocking user
+            theUser.unlockPassword();
+            LOGGER.trace(pwmRequest, "unlock account succeeded");
+        } catch (ChaiOperationException e) {
+            final String errorMsg = "unable to unlock user " + theUser.getEntryDN() + " error: " + e.getMessage();
+            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNLOCK_FAILURE,errorMsg);
+            LOGGER.error(pwmRequest.getPwmSession(), errorInformation.toDebugStr());
+            pwmRequest.respondWithError(errorInformation);
+            return;
+        }
+
+        try {
+            final UserInfo userInfo = UserInfoFactory.newUserInfoUsingProxy(
+                    pwmApplication,
+                    pwmRequest.getSessionLabel(),
+                    userIdentity,
+                    pwmRequest.getLocale()
+            );
+
+            LOGGER.info(pwmRequest, "user successfully supplied password recovery responses, emailing new password to: " + theUser.getEntryDN());
+
+            // add post change actions
+            ForgottenPasswordServlet.addPostChangeAction(pwmRequest, userIdentity);
+
+            // create new password
+            final PasswordData newPassword = RandomPasswordGenerator.createRandomPassword(
+                    pwmRequest.getSessionLabel(),
+                    userInfo.getPasswordPolicy(),
+                    pwmApplication
+            );
+            LOGGER.trace(pwmRequest, "generated random password value based on password policy for "
+                    + userIdentity.toDisplayString());
+
+
+            // set the password
+            try {
+                theUser.setPassword(newPassword.getStringValue());
+                LOGGER.trace(pwmRequest, "set user " + userIdentity.toDisplayString()
+                        + " password to system generated random value");
+            } catch (ChaiException e) {
+                throw PwmUnrecoverableException.fromChaiException(e);
+            }
+
+            if (recoveryAction == RecoveryAction.SENDNEWPW_AND_EXPIRE) {
+                LOGGER.debug(pwmRequest, "marking user " + userIdentity.toDisplayString() + " password as expired");
+                theUser.expirePassword();
+            }
+
+            // mark the event log
+            {
+                final AuditRecord auditRecord = new AuditRecordFactory(pwmApplication).createUserAuditRecord(
+                        AuditEvent.RECOVER_PASSWORD,
+                        userIdentity,
+                        pwmRequest.getSessionLabel()
+                );
+                pwmApplication.getAuditManager().submit(auditRecord);
+            }
+
+            final MessageSendMethod messageSendMethod = forgottenPasswordProfile.readSettingAsEnum(PwmSetting.RECOVERY_SENDNEWPW_METHOD,MessageSendMethod.class);
+
+            // send email or SMS
+            final String toAddress = PasswordUtility.sendNewPassword(
+                    userInfo,
+                    pwmApplication,
+                    newPassword,
+                    pwmRequest.getLocale(),
+                    messageSendMethod
+            );
+
+            pwmRequest.getPwmResponse().forwardToSuccessPage( Message.Success_PasswordSend, toAddress);
+        } catch (PwmException e) {
+            LOGGER.warn(pwmRequest, "unexpected error setting new password during recovery process for user: " + e.getMessage());
+            pwmRequest.respondWithError(e.getErrorInformation());
+        } catch (ChaiOperationException e) {
+            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"unexpected ldap error while processing recovery action " + recoveryAction + ", error: " + e.getMessage());
+            LOGGER.warn(pwmRequest, errorInformation.toDebugStr());
+            pwmRequest.respondWithError(errorInformation);
+        } finally {
+            ForgottenPasswordServlet.clearForgottenPasswordBean(pwmRequest);
+
+            // the user should not be authenticated, this is a safety method
+            pwmRequest.getPwmSession().unauthenticateUser(pwmRequest);
+
+            // the password set flag should not have been set, this is a safety method
+            pwmRequest.getPwmSession().getSessionStateBean().setPasswordModified(false);
+        }
+    }
 }

+ 50 - 20
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java

@@ -34,15 +34,16 @@ import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.bean.EmailItemBean;
 import password.pwm.bean.UserIdentity;
-import password.pwm.config.value.data.ActionConfiguration;
 import password.pwm.config.Configuration;
-import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.option.HelpdeskClearResponseMode;
 import password.pwm.config.option.HelpdeskUIMode;
 import password.pwm.config.option.IdentityVerificationMethod;
 import password.pwm.config.option.MessageSendMethod;
 import password.pwm.config.profile.HelpdeskProfile;
+import password.pwm.config.profile.PwmPasswordPolicy;
+import password.pwm.config.value.data.ActionConfiguration;
+import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
@@ -739,17 +740,17 @@ public class HelpdeskServlet extends ControlledPwmServlet {
         try {
             TokenService.TokenSender.sendToken(
                     TokenService.TokenSendInfo.builder()
-                    .pwmApplication( pwmRequest.getPwmApplication() )
-                    .userInfo( userInfo )
-                    .macroMachine( macroMachine )
-                    .configuredEmailSetting( emailItemBean )
-                    .tokenSendMethod( tokenSendMethod )
-                    .emailAddress( destEmailAddress )
-                    .smsNumber( userInfo.getUserSmsNumber() )
-                    .smsMessage( smsMessage )
-                    .tokenKey( tokenKey )
-                    .sessionLabel( pwmRequest.getSessionLabel() )
-                    .build()
+                            .pwmApplication( pwmRequest.getPwmApplication() )
+                            .userInfo( userInfo )
+                            .macroMachine( macroMachine )
+                            .configuredEmailSetting( emailItemBean )
+                            .tokenSendMethod( tokenSendMethod )
+                            .emailAddress( destEmailAddress )
+                            .smsNumber( userInfo.getUserSmsNumber() )
+                            .smsMessage( smsMessage )
+                            .tokenKey( tokenKey )
+                            .sessionLabel( pwmRequest.getSessionLabel() )
+                            .build()
             );
         } catch (PwmException e) {
             LOGGER.error(pwmRequest, e.getErrorInformation());
@@ -1153,13 +1154,13 @@ public class HelpdeskServlet extends ControlledPwmServlet {
     @ActionHandler(action = "setPassword")
     private ProcessStatus processSetPasswordAction(final PwmRequest pwmRequest) throws IOException, PwmUnrecoverableException, ChaiUnavailableException
     {
+        final HelpdeskProfile helpdeskProfile = pwmRequest.getPwmSession().getSessionManager().getHelpdeskProfile(pwmRequest.getPwmApplication());
+
         final RestSetPasswordServer.JsonInputData jsonInput = JsonUtil.deserialize(
                 pwmRequest.readRequestBodyAsString(),
                 RestSetPasswordServer.JsonInputData.class
         );
 
-        final PasswordData newPassword = new PasswordData(jsonInput.getPassword());
-        final HelpdeskProfile helpdeskProfile = pwmRequest.getPwmSession().getSessionManager().getHelpdeskProfile(pwmRequest.getPwmApplication());
         final UserIdentity userIdentity = UserIdentity.fromKey(jsonInput.getUsername(),pwmRequest.getPwmApplication());
         final ChaiUser chaiUser = getChaiUser(pwmRequest, helpdeskProfile, userIdentity);
         final UserInfo userInfo = UserInfoFactory.newUserInfo(
@@ -1171,16 +1172,45 @@ public class HelpdeskServlet extends ControlledPwmServlet {
         );
 
         HelpdeskServletUtil.checkIfUserIdentityViewable(pwmRequest, helpdeskProfile, userIdentity);
+        final HelpdeskUIMode mode = helpdeskProfile.readSettingAsEnum(PwmSetting.HELPDESK_SET_PASSWORD_MODE, HelpdeskUIMode.class);
 
-        {
-            final HelpdeskUIMode mode = helpdeskProfile.readSettingAsEnum(PwmSetting.HELPDESK_CLEAR_RESPONSES, HelpdeskUIMode.class);
-            if (mode == HelpdeskUIMode.none) {
+        if (mode == HelpdeskUIMode.none) {
+            throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,"setting "
+                    + PwmSetting.HELPDESK_SET_PASSWORD_MODE.toMenuLocationDebug(helpdeskProfile.getIdentifier(), pwmRequest.getLocale())
+                    + " must not be set to none"));
+        }
+
+
+        final PasswordData newPassword;
+        if (jsonInput.getPassword() == null) {
+            if (mode != HelpdeskUIMode.random) {
                 throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,"setting "
-                        + PwmSetting.HELPDESK_CLEAR_RESPONSES.toMenuLocationDebug(helpdeskProfile.getIdentifier(), pwmRequest.getLocale())
-                        + " must not be set to none"));
+                        + PwmSetting.HELPDESK_SET_PASSWORD_MODE.toMenuLocationDebug(helpdeskProfile.getIdentifier(), pwmRequest.getLocale())
+                        + " is set to " + mode + " and no password is included in request"));
+            }
+            final PwmPasswordPolicy passwordPolicy = PasswordUtility.readPasswordPolicyForUser(
+                    pwmRequest.getPwmApplication(),
+                    pwmRequest.getSessionLabel(),
+                    userIdentity,
+                    chaiUser,
+                    pwmRequest.getLocale()
+            );
+            newPassword = RandomPasswordGenerator.createRandomPassword(
+                    pwmRequest.getSessionLabel(),
+                    passwordPolicy,
+                    pwmRequest.getPwmApplication()
+            );
+        } else {
+            if (mode == HelpdeskUIMode.random) {
+                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,"setting "
+                        + PwmSetting.HELPDESK_SET_PASSWORD_MODE.toMenuLocationDebug(helpdeskProfile.getIdentifier(), pwmRequest.getLocale())
+                        + " is set to autogen yet a password is included in request"));
             }
+
+            newPassword = new PasswordData(jsonInput.getPassword());
         }
 
+
         try {
             PasswordUtility.helpdeskSetUserPassword(
                     pwmRequest.getPwmSession(),

+ 9 - 5
server/src/main/java/password/pwm/util/operations/PasswordUtility.java

@@ -109,7 +109,6 @@ public class PasswordUtility {
     public static String sendNewPassword(
             final UserInfo userInfo,
             final PwmApplication pwmApplication,
-            final MacroMachine macroMachine,
             final PasswordData newPassword,
             final Locale userLocale,
             final MessageSendMethod messageSendMethod
@@ -120,6 +119,15 @@ public class PasswordUtility {
         final String smsNumber = userInfo.getUserSmsNumber();
         String returnToAddress = emailAddress;
 
+        final MacroMachine macroMachine;
+        {
+            final LoginInfoBean loginInfoBean = new LoginInfoBean();
+            loginInfoBean.setUserCurrentPassword(newPassword);
+            loginInfoBean.setUserIdentity(userInfo.getUserIdentity());
+            macroMachine = MacroMachine.forUser(pwmApplication, null, userInfo, loginInfoBean);
+        }
+
+
         final ErrorInformation error;
         switch (messageSendMethod) {
             case SMSONLY:
@@ -532,13 +540,9 @@ public class PasswordUtility {
                 messageSendMethod = forgottenPasswordProfile.readSettingAsEnum(PwmSetting.RECOVERY_SENDNEWPW_METHOD, MessageSendMethod.class);
 
             }
-            final LoginInfoBean loginInfoBean = new LoginInfoBean();
-            loginInfoBean.setUserCurrentPassword(newPassword);
-            final MacroMachine macroMachine = new MacroMachine(pwmApplication, pwmSession.getLabel(), userInfo, loginInfoBean);
             PasswordUtility.sendNewPassword(
                     userInfo,
                     pwmApplication,
-                    macroMachine,
                     newPassword,
                     pwmSession.getSessionStateBean().getLocale(),
                     messageSendMethod

+ 2 - 0
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -2528,6 +2528,8 @@
             <value>{"name":"mail","minimumLength":1,"maximumLength":64,"type":"email","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Email Address"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
             <value>{"name":"sn","minimumLength":1,"maximumLength":64,"type":"text","required":true,"confirmationRequired":false,"readonly":false,"labels":{"":"Last Name"},"regexErrors":{"":""},"description":{"":""},"selectOptions":{}}</value>
         </default>
+        <option value="text">text</option>
+        <option value="password">password</option>
     </setting>
     <setting hidden="false" key="forgottenUsername.searchFilter" level="2">
         <default/>