예제 #1
0
 public void clear() throws LocalDBException, PwmUnrecoverableException {
   final Date startTime = new Date();
   LOGGER.info(PwmConstants.REPORTING_SESSION_LABEL, "clearing cached report data");
   if (userCacheService != null) {
     userCacheService.clear();
   }
   summaryData = ReportSummaryData.newSummaryData(settings.getTrackDays());
   reportStatus = new ReportStatusInfo(settings.getSettingsHash());
   saveTempData();
   LOGGER.info(
       PwmConstants.REPORTING_SESSION_LABEL,
       "finished clearing report " + TimeDuration.fromCurrent(startTime).asCompactString());
 }
예제 #2
0
  @Override
  public void clearOtpUserConfiguration(
      final PwmSession pwmSession, final UserIdentity theUser, final String userGUID)
      throws PwmUnrecoverableException {
    if (userGUID == null || userGUID.length() < 1) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_MISSING_GUID,
              "cannot save OTP secret to remote database, user "
                  + theUser
                  + " does not have a guid"));
    }

    LOGGER.trace(
        "attempting to clear OTP secret for "
            + theUser
            + " in remote database (key="
            + userGUID
            + ")");

    try {
      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      databaseAccessor.remove(DatabaseTable.OTP, userGUID);
      LOGGER.info(
          "cleared OTP secret for " + theUser + " in remote database (key=" + userGUID + ")");
    } catch (DatabaseException ex) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_WRITING_OTP_SECRET,
              "unexpected error saving otp to db: " + ex.getMessage());
      final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException(errorInfo);
      pwmOE.initCause(ex);
      throw pwmOE;
    }
  }
예제 #3
0
  private boolean checkDbVersion() throws Exception {
    LOGGER.trace("checking version number stored in LocalDB");

    final Object versionInDB = localDB.get(META_DB, KEY_VERSION);
    final String currentVersion = "version=" + settings.version;
    final boolean result = currentVersion.equals(versionInDB);

    if (!result) {
      LOGGER.info(
          "existing db version does not match current db version db=("
              + versionInDB
              + ")  current=("
              + currentVersion
              + "), clearing db");
      localDB.truncate(WORDS_DB);
      localDB.put(META_DB, KEY_VERSION, currentVersion);
      localDB.remove(META_DB, KEY_OLDEST_ENTRY);
    } else {
      LOGGER.trace(
          "existing db version matches current db version db=("
              + versionInDB
              + ")  current=("
              + currentVersion
              + ")");
    }

    return result;
  }
예제 #4
0
  public void clearResponses(final ChaiUser theUser, final String userGUID)
      throws PwmUnrecoverableException {
    if (userGUID == null || userGUID.length() < 1) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_MISSING_GUID,
              "cannot clear responses to remote database, user "
                  + theUser.getEntryDN()
                  + " does not have a guid"));
    }

    try {
      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      databaseAccessor.remove(DatabaseTable.PWM_RESPONSES, userGUID);
      LOGGER.info("cleared responses for user " + theUser.getEntryDN() + " in remote database");
    } catch (DatabaseException e) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_CLEARING_RESPONSES,
              "unexpected error clearing responses for "
                  + theUser.getEntryDN()
                  + " in remote database, error: "
                  + e.getMessage());
      final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException(errorInfo);
      pwmOE.initCause(e);
      throw pwmOE;
    }
  }
예제 #5
0
  private String fetchInstanceID(final LocalDB localDB, final PwmApplication pwmApplication) {
    String newInstanceID =
        pwmApplication.getConfig().readSettingAsString(PwmSetting.PWM_INSTANCE_NAME);

    if (newInstanceID != null && newInstanceID.trim().length() > 0) {
      return newInstanceID;
    }

    newInstanceID = readAppAttribute(AppAttribute.INSTANCE_ID);

    if (newInstanceID == null || newInstanceID.length() < 1) {
      newInstanceID = Long.toHexString(PwmRandom.getInstance().nextLong()).toUpperCase();
      LOGGER.info("generated new random instanceID " + newInstanceID);

      if (localDB != null) {
        writeAppAttribute(AppAttribute.INSTANCE_ID, newInstanceID);
      }
    } else {
      LOGGER.trace("retrieved instanceID " + newInstanceID + "" + " from localDB");
    }

    if (newInstanceID.length() < 1) {
      newInstanceID = DEFAULT_INSTANCE_ID;
    }

    return newInstanceID;
  }
예제 #6
0
  public void shutdown() {
    LOGGER.warn("shutting down");
    {
      // send system audit event
      final SystemAuditRecord auditRecord =
          SystemAuditRecord.create(AuditEvent.SHUTDOWN, null, getInstanceID());
      try {
        getAuditManager().submit(auditRecord);
      } catch (PwmException e) {
        LOGGER.warn("unable to submit alert event " + JsonUtil.serialize(auditRecord));
      }
    }

    {
      final List<Class> reverseServiceList = new ArrayList<Class>(PWM_SERVICE_CLASSES);
      Collections.reverse(reverseServiceList);
      for (final Class serviceClass : reverseServiceList) {
        if (pwmServices.containsKey(serviceClass)) {
          LOGGER.trace("closing service " + serviceClass.getName());
          final PwmService loopService = pwmServices.get(serviceClass);
          LOGGER.trace("successfully closed service " + serviceClass.getName());
          try {
            loopService.close();
          } catch (Exception e) {
            LOGGER.error(
                "error closing " + loopService.getClass().getSimpleName() + ": " + e.getMessage(),
                e);
          }
        }
      }
    }

    if (localDBLogger != null) {
      try {
        localDBLogger.close();
      } catch (Exception e) {
        LOGGER.error("error closing localDBLogger: " + e.getMessage(), e);
      }
      localDBLogger = null;
    }

    if (localDB != null) {
      try {
        localDB.close();
      } catch (Exception e) {
        LOGGER.fatal("error closing localDB: " + e, e);
      }
      localDB = null;
    }

    LOGGER.info(
        PwmConstants.PWM_APP_NAME
            + " "
            + PwmConstants.SERVLET_VERSION
            + " closed for bidness, cya!");
  }
예제 #7
0
  @Override
  public void writeOtpUserConfiguration(
      final PwmSession pwmSession,
      final UserIdentity theUser,
      final String userGUID,
      final OTPUserRecord otpConfig)
      throws PwmUnrecoverableException {
    if (userGUID == null || userGUID.length() < 1) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_MISSING_GUID,
              "cannot save OTP secret to remote database, user "
                  + theUser
                  + " does not have a guid"));
    }

    LOGGER.trace(
        "attempting to save OTP secret for "
            + theUser
            + " in remote database (key="
            + userGUID
            + ")");

    try {
      String value = composeOtpAttribute(otpConfig);
      if (getPwmApplication().getConfig().readSettingAsBoolean(PwmSetting.OTP_SECRET_ENCRYPT)) {
        LOGGER.debug("Encrypting OTP secret for storage");
        value = encryptAttributeValue(value);
      }
      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      databaseAccessor.put(DatabaseTable.OTP, userGUID, value);
      LOGGER.info("saved OTP secret for " + theUser + " in remote database (key=" + userGUID + ")");
    } catch (PwmOperationalException ex) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_WRITING_OTP_SECRET,
              "unexpected error saving otp to db: " + ex.getMessage());
      final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException(errorInfo);
      pwmOE.initCause(ex);
      throw pwmOE;
    }
  }
예제 #8
0
  private void handleCreateRequest(
      final PwmRequest pwmRequest, final GuestRegistrationBean guestRegistrationBean)
      throws PwmUnrecoverableException, ChaiUnavailableException, IOException, ServletException {
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final LocalSessionStateBean ssBean = pwmSession.getSessionStateBean();
    final Configuration config = pwmApplication.getConfig();
    final Locale locale = ssBean.getLocale();

    final List<FormConfiguration> guestUserForm = config.readSettingAsForm(PwmSetting.GUEST_FORM);

    try {
      // read the values from the request
      final Map<FormConfiguration, String> formValues =
          FormUtility.readFormValuesFromRequest(pwmRequest, guestUserForm, locale);

      // read the expiration date from the request.
      final Date expirationDate = readExpirationFromRequest(pwmRequest);

      // see if the values meet form requirements.
      FormUtility.validateFormValues(config, formValues, locale);

      // read new user DN
      final String guestUserDN = determineUserDN(formValues, config);

      // read a chai provider to make the user
      final ChaiProvider provider = pwmSession.getSessionManager().getChaiProvider();

      // set up the user creation attributes
      final Map<String, String> createAttributes = new HashMap<>();
      for (final FormConfiguration formItem : formValues.keySet()) {
        LOGGER.debug(
            pwmSession,
            "Attribute from form: " + formItem.getName() + " = " + formValues.get(formItem));
        final String n = formItem.getName();
        final String v = formValues.get(formItem);
        if (n != null && n.length() > 0 && v != null && v.length() > 0) {
          createAttributes.put(n, v);
        }
      }

      // Write creator DN
      createAttributes.put(
          config.readSettingAsString(PwmSetting.GUEST_ADMIN_ATTRIBUTE),
          pwmSession.getUserInfoBean().getUserIdentity().getUserDN());

      // read the creation object classes.
      final Set<String> createObjectClasses =
          new HashSet<>(config.readSettingAsStringArray(PwmSetting.DEFAULT_OBJECT_CLASSES));

      provider.createEntry(guestUserDN, createObjectClasses, createAttributes);
      LOGGER.info(pwmSession, "created user object: " + guestUserDN);

      final ChaiUser theUser = ChaiFactory.createChaiUser(guestUserDN, provider);
      final UserIdentity userIdentity =
          new UserIdentity(
              guestUserDN, pwmSession.getUserInfoBean().getUserIdentity().getLdapProfileID());

      // write the expiration date:
      if (expirationDate != null) {
        final String expirationAttr =
            config.readSettingAsString(PwmSetting.GUEST_EXPIRATION_ATTRIBUTE);
        theUser.writeDateAttribute(expirationAttr, expirationDate);
      }

      final PwmPasswordPolicy passwordPolicy =
          PasswordUtility.readPasswordPolicyForUser(
              pwmApplication, pwmSession.getLabel(), userIdentity, theUser, locale);
      final PasswordData newPassword =
          RandomPasswordGenerator.createRandomPassword(
              pwmSession.getLabel(), passwordPolicy, pwmApplication);
      theUser.setPassword(newPassword.getStringValue());
      /*
      final UserInfoBean guestUserInfoBean = new UserInfoBean();
      final UserStatusReader userStatusReader = new UserStatusReader(pwmApplication);
      userStatusReader.populateUserInfoBean(
              pwmSession.getLabel(),
              guestUserInfoBean,
              pwmSession.getSessionStateBean().getLocale(),
              userIdentity,
              theUser.getChaiProvider()
      );
      */

      { // execute configured actions
        LOGGER.debug(pwmSession, "executing configured actions to user " + theUser.getEntryDN());
        final List<ActionConfiguration> actions =
            pwmApplication.getConfig().readSettingAsAction(PwmSetting.GUEST_WRITE_ATTRIBUTES);
        if (actions != null && !actions.isEmpty()) {
          final MacroMachine macroMachine = MacroMachine.forUser(pwmRequest, userIdentity);

          final ActionExecutor actionExecutor =
              new ActionExecutor.ActionExecutorSettings(pwmApplication, theUser)
                  .setExpandPwmMacros(true)
                  .setMacroMachine(macroMachine)
                  .createActionExecutor();

          actionExecutor.executeActions(actions, pwmSession);
        }
      }

      // everything good so forward to success page.
      this.sendGuestUserEmailConfirmation(pwmRequest, userIdentity);

      pwmApplication.getStatisticsManager().incrementValue(Statistic.NEW_USERS);

      pwmRequest.getPwmResponse().forwardToSuccessPage(Message.Success_CreateGuest);
    } catch (ChaiOperationException e) {
      final ErrorInformation info =
          new ErrorInformation(
              PwmError.ERROR_NEW_USER_FAILURE, "error creating user: " + e.getMessage());
      pwmRequest.setResponseError(info);
      LOGGER.warn(pwmSession, info);
      this.forwardToJSP(pwmRequest, guestRegistrationBean);
    } catch (PwmOperationalException e) {
      LOGGER.error(pwmSession, e.getErrorInformation().toDebugStr());
      pwmRequest.setResponseError(e.getErrorInformation());
      this.forwardToJSP(pwmRequest, guestRegistrationBean);
    }
  }
예제 #9
0
  public static void doProfileUpdate(
      final PwmRequest pwmRequest,
      final Map<FormConfiguration, String> formValues,
      final ChaiUser theUser)
      throws PwmUnrecoverableException, ChaiUnavailableException, PwmOperationalException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final UserInfoBean uiBean = pwmRequest.getPwmSession().getUserInfoBean();

    // verify form meets the form requirements (may be redundant, but shouldn't hurt)
    verifyFormAttributes(pwmRequest, formValues, false);

    // write values.
    LOGGER.info(
        "updating profile for " + pwmRequest.getPwmSession().getUserInfoBean().getUserIdentity());

    pwmRequest.getPwmSession().getSessionManager().getChaiProvider();

    Helper.writeFormValuesToLdap(
        pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), theUser, formValues, false);

    final UserIdentity userIdentity = uiBean.getUserIdentity();

    // re-populate the uiBean because we have changed some values.
    final UserStatusReader userStatusReader =
        new UserStatusReader(pwmRequest.getPwmApplication(), pwmRequest.getSessionLabel());
    userStatusReader.populateActorUserInfoBean(pwmRequest.getPwmSession(), userIdentity);

    // clear cached read attributes.
    pwmRequest.getPwmSession().getSessionManager().clearUserDataReader();

    { // execute configured actions
      final List<ActionConfiguration> actions =
          pwmApplication
              .getConfig()
              .readSettingAsAction(PwmSetting.UPDATE_PROFILE_WRITE_ATTRIBUTES);
      if (actions != null && !actions.isEmpty()) {
        LOGGER.debug(pwmRequest, "executing configured actions to user " + userIdentity);

        final ActionExecutor actionExecutor =
            new ActionExecutor.ActionExecutorSettings(pwmApplication, userIdentity)
                .setExpandPwmMacros(true)
                .createActionExecutor();

        actionExecutor.executeActions(actions, pwmSession);
      }
    }

    sendProfileUpdateEmailNotice(pwmSession, pwmApplication);

    // mark the event log
    pwmApplication
        .getAuditManager()
        .submit(AuditEvent.UPDATE_PROFILE, pwmSession.getUserInfoBean(), pwmSession);

    // mark the uiBean so we user isn't recycled to the update profile page by the CommandServlet
    uiBean.setRequiresUpdateProfile(false);

    // clear out the updateProfileBean
    pwmSession.clearUpdateProfileBean();

    // success, so forward to success page
    pwmApplication.getStatisticsManager().incrementValue(Statistic.UPDATE_ATTRIBUTES);
  }
예제 #10
0
  /**
   * 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>ldap password set is attempted<br>
   *       <br>
   *       if successful:
   *       <ul>
   *         <li>uiBean is updated with old and new passwords
   *         <li>uiBean's password expire flag is set to false
   *         <li>any configured external methods are invoked
   *         <li>user email notification is sent
   *         <li>return true
   *       </ul>
   *       <br>
   *       if unsuccessful
   *       <ul>
   *         <li>ssBean is updated with appropriate error
   *         <li>return false
   *       </ul>
   * </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 UserInfoBean uiBean = pwmSession.getUserInfoBean();

    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);
    }

    // double check to make sure password meets PWM rule requirements.  This should
    // have been done before setActorPassword() is invoked, so it should be redundant
    // but we do it just in case.
    try {
      final PwmPasswordRuleValidator pwmPasswordRuleValidator =
          new PwmPasswordRuleValidator(pwmApplication, uiBean.getPasswordPolicy());
      pwmPasswordRuleValidator.testPassword(
          newPassword, null, uiBean, 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()
          == ChaiProvider.DIRECTORY_VENDOR.MICROSOFT_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);
      }
    }

    try {
      final ChaiProvider provider = pwmSession.getSessionManager().getChaiProvider();
      final ChaiUser theUser =
          ChaiFactory.createChaiUser(
              pwmSession.getUserInfoBean().getUserIdentity().getUserDN(), provider);
      final boolean boundAsSelf =
          theUser
              .getEntryDN()
              .equals(provider.getChaiConfiguration().getSetting(ChaiSetting.BIND_DN));
      LOGGER.trace(
          pwmSession,
          "preparing to setActorPassword for '"
              + theUser.getEntryDN()
              + "', bindAsSelf="
              + boundAsSelf
              + ", authType="
              + pwmSession.getLoginInfoBean().getType());
      if (setPasswordWithoutOld) {
        theUser.setPassword(newPassword.getStringValue(), true);
      } else {
        theUser.changePassword(oldPassword.getStringValue(), newPassword.getStringValue());
      }
    } catch (ChaiPasswordPolicyException e) {
      final String errorMsg =
          "error setting password for user '" + uiBean.getUserIdentity() + "'' " + 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 '" + uiBean.getUserIdentity() + "'' " + 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);
    }

    // at this point the password has been changed, so log it.
    LOGGER.info(
        pwmSession, "user '" + uiBean.getUserIdentity() + "' successfully changed password");

    // 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, uiBean.getUserIdentity(), newPassword);

    // clear the "requires new password flag"
    uiBean.setRequiresNewPassword(false);

    // 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".
    final UserStatusReader userStatusReader =
        new UserStatusReader(pwmApplication, pwmSession.getLabel());
    uiBean.setPasswordState(
        userStatusReader.readPasswordStatus(
            pwmSession.getSessionManager().getActor(pwmApplication),
            uiBean.getPasswordPolicy(),
            uiBean,
            newPassword));

    // 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);
      pwmApplication.getStatisticsManager().updateEps(Statistic.EpsType.PASSWORD_CHANGES, 1);
      final int passwordStrength =
          PasswordUtility.judgePasswordStrength(newPassword.getStringValue());
      pwmApplication
          .getStatisticsManager()
          .updateAverageValue(Statistic.AVG_PASSWORD_STRENGTH, passwordStrength);
    }

    // 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(pwmSession, oldPassword.getStringValue());
    }

    // 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 =
            new MacroMachine(
                pwmApplication,
                pwmSession.getLabel(),
                pwmSession.getUserInfoBean(),
                clonedLoginInfoBean,
                pwmSession.getSessionManager().getUserDataReader(pwmApplication));

        final ActionExecutor actionExecutor =
            new ActionExecutor.ActionExecutorSettings(pwmApplication, uiBean.getUserIdentity())
                .setMacroMachine(macroMachine)
                .setExpandPwmMacros(true)
                .createActionExecutor();
        actionExecutor.executeActions(configValues, pwmSession);
      }
    }

    // update the current last password update field in ldap
    LdapOperationsHelper.updateLastPasswordUpdateAttribute(
        pwmApplication, pwmSession.getLabel(), uiBean.getUserIdentity());
  }
예제 #11
0
  private void initialize(final boolean initLogging) throws PwmUnrecoverableException {
    final Date startTime = new Date();

    // initialize log4j
    if (initLogging) {
      final String log4jFileName =
          configuration.readSettingAsString(PwmSetting.EVENTS_JAVA_LOG4JCONFIG_FILE);
      final File log4jFile = Helper.figureFilepath(log4jFileName, applicationPath);
      final String consoleLevel, fileLevel;
      switch (getApplicationMode()) {
        case ERROR:
        case NEW:
          consoleLevel = PwmLogLevel.TRACE.toString();
          fileLevel = PwmLogLevel.TRACE.toString();
          break;

        default:
          consoleLevel = configuration.readSettingAsString(PwmSetting.EVENTS_JAVA_STDOUT_LEVEL);
          fileLevel = configuration.readSettingAsString(PwmSetting.EVENTS_FILE_LEVEL);
          break;
      }

      PwmLogManager.initializeLogger(
          this, configuration, log4jFile, consoleLevel, applicationPath, fileLevel);

      switch (getApplicationMode()) {
        case RUNNING:
          break;

        case ERROR:
          LOGGER.fatal(
              "starting up in ERROR mode! Check log or health check information for cause");
          break;

        default:
          LOGGER.trace(
              "setting log level to TRACE because application mode is " + getApplicationMode());
          break;
      }
    }

    LOGGER.info(
        "initializing, application mode="
            + getApplicationMode()
            + ", applicationPath="
            + (applicationPath == null ? "null" : applicationPath.getAbsolutePath())
            + ", configurationFile="
            + (configurationFile == null ? "null" : configurationFile.getAbsolutePath()));

    this.localDB = Initializer.initializeLocalDB(this);
    this.localDBLogger = PwmLogManager.initializeLocalDBLogger(this);

    // log the loaded configuration
    LOGGER.info("configuration load completed");

    // read the pwm servlet instance id
    instanceID = fetchInstanceID(localDB, this);
    LOGGER.info("using '" + getInstanceID() + "' for instance's ID (instanceID)");

    // read the pwm installation date
    installTime = fetchInstallDate(startupTime);
    LOGGER.debug(
        "this application instance first installed on "
            + PwmConstants.DEFAULT_DATETIME_FORMAT.format(installTime));

    initServices();

    final TimeDuration totalTime = TimeDuration.fromCurrent(startTime);
    LOGGER.info(
        PwmConstants.PWM_APP_NAME
            + " "
            + PwmConstants.SERVLET_VERSION
            + " open for bidness! ("
            + totalTime.asCompactString()
            + ")");
    StatisticsManager.incrementStat(this, Statistic.PWM_STARTUPS);
    LOGGER.debug(
        "buildTime="
            + PwmConstants.BUILD_TIME
            + ", javaLocale="
            + Locale.getDefault()
            + ", DefaultLocale="
            + PwmConstants.DEFAULT_LOCALE);

    final Thread postInitThread =
        new Thread() {
          @Override
          public void run() {
            postInitTasks();
          }
        };
    postInitThread.setDaemon(true);
    postInitThread.setName(Helper.makeThreadName(this, PwmApplication.class));
    postInitThread.start();
  }
예제 #12
0
  private void publishStatisticsToCloud()
      throws URISyntaxException, IOException, PwmUnrecoverableException {
    final StatsPublishBean statsPublishData;
    {
      final StatisticsBundle bundle = getStatBundleForKey(KEY_CUMULATIVE);
      final Map<String, String> statData = new HashMap<>();
      for (final Statistic loopStat : Statistic.values()) {
        statData.put(loopStat.getKey(), bundle.getStatistic(loopStat));
      }
      final Configuration config = pwmApplication.getConfig();
      final List<String> configuredSettings = new ArrayList<>();
      for (final PwmSetting pwmSetting : config.nonDefaultSettings()) {
        if (!pwmSetting.getCategory().hasProfiles() && !config.isDefaultValue(pwmSetting)) {
          configuredSettings.add(pwmSetting.getKey());
        }
      }
      final Map<String, String> otherData = new HashMap<>();
      otherData.put(
          StatsPublishBean.KEYS.SITE_URL.toString(),
          config.readSettingAsString(PwmSetting.PWM_SITE_URL));
      otherData.put(
          StatsPublishBean.KEYS.SITE_DESCRIPTION.toString(),
          config.readSettingAsString(PwmSetting.PUBLISH_STATS_SITE_DESCRIPTION));
      otherData.put(
          StatsPublishBean.KEYS.INSTALL_DATE.toString(),
          PwmConstants.DEFAULT_DATETIME_FORMAT.format(pwmApplication.getInstallTime()));

      try {
        otherData.put(
            StatsPublishBean.KEYS.LDAP_VENDOR.toString(),
            pwmApplication
                .getProxyChaiProvider(config.getDefaultLdapProfile().getIdentifier())
                .getDirectoryVendor()
                .toString());
      } catch (Exception e) {
        LOGGER.trace("unable to read ldap vendor type for stats publication: " + e.getMessage());
      }

      statsPublishData =
          new StatsPublishBean(
              pwmApplication.getInstanceID(),
              new Date(),
              statData,
              configuredSettings,
              PwmConstants.BUILD_NUMBER,
              PwmConstants.BUILD_VERSION,
              otherData);
    }
    final URI requestURI = new URI(PwmConstants.PWM_URL_CLOUD + "/rest/pwm/statistics");
    final HttpPost httpPost = new HttpPost(requestURI.toString());
    final String jsonDataString = JsonUtil.serialize(statsPublishData);
    httpPost.setEntity(new StringEntity(jsonDataString));
    httpPost.setHeader("Accept", PwmConstants.AcceptValue.json.getHeaderValue());
    httpPost.setHeader("Content-Type", PwmConstants.ContentTypeValue.json.getHeaderValue());
    LOGGER.debug(
        "preparing to send anonymous statistics to "
            + requestURI.toString()
            + ", data to send: "
            + jsonDataString);
    final HttpResponse httpResponse =
        PwmHttpClient.getHttpClient(pwmApplication.getConfig()).execute(httpPost);
    if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      throw new IOException(
          "http response error code: " + httpResponse.getStatusLine().getStatusCode());
    }
    LOGGER.info("published anonymous statistics to " + requestURI.toString());
    try {
      localDB.put(
          LocalDB.DB.PWM_STATS,
          KEY_CLOUD_PUBLISH_TIMESTAMP,
          String.valueOf(System.currentTimeMillis()));
    } catch (LocalDBException e) {
      LOGGER.error(
          "unexpected error trying to save last statistics published time to LocalDB: "
              + e.getMessage());
    }
  }
예제 #13
0
  public void init(final PwmApplication pwmApplication) throws PwmException {
    settings.maxAgeMs =
        1000
            * pwmApplication
                .getConfig()
                .readSettingAsLong(PwmSetting.PASSWORD_SHAREDHISTORY_MAX_AGE); // convert to MS;
    settings.caseInsensitive =
        Boolean.parseBoolean(
            pwmApplication
                .getConfig()
                .readAppProperty(AppProperty.SECURITY_SHAREDHISTORY_CASE_INSENSITIVE));
    settings.hashName =
        pwmApplication.getConfig().readAppProperty(AppProperty.SECURITY_SHAREDHISTORY_HASH_NAME);
    settings.hashIterations =
        Integer.parseInt(
            pwmApplication
                .getConfig()
                .readAppProperty(AppProperty.SECURITY_SHAREDHISTORY_HASH_ITERATIONS));
    settings.version =
        "2"
            + "_"
            + settings.hashName
            + "_"
            + settings.hashIterations
            + "_"
            + settings.caseInsensitive;

    final int SALT_LENGTH =
        Integer.parseInt(
            pwmApplication
                .getConfig()
                .readAppProperty(AppProperty.SECURITY_SHAREDHISTORY_SALT_LENGTH));
    this.localDB = pwmApplication.getLocalDB();

    boolean needsClearing = false;
    if (localDB == null) {
      LOGGER.info("LocalDB is not available, will remain closed");
      status = STATUS.CLOSED;
      return;
    }

    if (settings.maxAgeMs < 1) {
      LOGGER.debug("max age=" + settings.maxAgeMs + ", will remain closed");
      needsClearing = true;
    }

    {
      this.salt = localDB.get(META_DB, KEY_SALT);
      if (salt == null || salt.length() < SALT_LENGTH) {
        LOGGER.warn("stored global salt value is not present, creating new salt");
        this.salt = PwmRandom.getInstance().alphaNumericString(SALT_LENGTH);
        localDB.put(META_DB, KEY_SALT, this.salt);
        needsClearing = true;
      }
    }

    if (needsClearing) {
      LOGGER.trace("clearing wordlist");
      try {
        localDB.truncate(WORDS_DB);
      } catch (Exception e) {
        LOGGER.error("error during wordlist truncate", e);
      }
    }

    new Thread(
            new Runnable() {
              public void run() {
                LOGGER.debug("starting up in background thread");
                init(pwmApplication, settings.maxAgeMs);
              }
            },
            Helper.makeThreadName(pwmApplication, this.getClass()) + " initializer")
        .start();
  }
예제 #14
0
  private void init(final PwmApplication pwmApplication, final long maxAgeMs) {
    status = STATUS.OPENING;
    final long startTime = System.currentTimeMillis();

    try {
      checkDbVersion();
    } catch (Exception e) {
      LOGGER.error("error checking db version", e);
      status = STATUS.CLOSED;
      return;
    }

    try {
      final String oldestEntryStr = localDB.get(META_DB, KEY_OLDEST_ENTRY);
      if (oldestEntryStr == null || oldestEntryStr.length() < 1) {
        oldestEntry = 0;
        LOGGER.trace("no oldestEntry timestamp stored, will rescan");
      } else {
        oldestEntry = Long.parseLong(oldestEntryStr);
        LOGGER.trace(
            "oldest timestamp loaded from localDB, age is "
                + TimeDuration.fromCurrent(oldestEntry).asCompactString());
      }
    } catch (LocalDBException e) {
      LOGGER.error(
          "unexpected error loading oldest-entry meta record, will remain closed: "
              + e.getMessage(),
          e);
      status = STATUS.CLOSED;
      return;
    }

    try {
      final int size = localDB.size(WORDS_DB);
      final StringBuilder sb = new StringBuilder();
      sb.append("open with ").append(size).append(" words (");
      sb.append(new TimeDuration(System.currentTimeMillis(), startTime).asCompactString())
          .append(")");
      sb.append(", maxAgeMs=").append(new TimeDuration(maxAgeMs).asCompactString());
      sb.append(", oldestEntry=")
          .append(new TimeDuration(System.currentTimeMillis(), oldestEntry).asCompactString());
      LOGGER.info(sb.toString());
    } catch (LocalDBException e) {
      LOGGER.error(
          "unexpected error examining size of DB, will remain closed: " + e.getMessage(), e);
      status = STATUS.CLOSED;
      return;
    }

    status = STATUS.OPEN;
    // populateFromWordlist();  //only used for debugging!!!

    if (pwmApplication.getApplicationMode() == PwmApplication.MODE.RUNNING
        || pwmApplication.getApplicationMode() == PwmApplication.MODE.CONFIGURATION) {
      long frequencyMs = maxAgeMs > MAX_CLEANER_FREQUENCY ? MAX_CLEANER_FREQUENCY : maxAgeMs;
      frequencyMs = frequencyMs < MIN_CLEANER_FREQUENCY ? MIN_CLEANER_FREQUENCY : frequencyMs;

      LOGGER.debug(
          "scheduling cleaner task to run once every "
              + new TimeDuration(frequencyMs).asCompactString());
      final String threadName = Helper.makeThreadName(pwmApplication, this.getClass()) + " timer";
      cleanerTimer = new Timer(threadName, true);
      cleanerTimer.schedule(new CleanerTask(), 1000, frequencyMs);
    }
  }
예제 #15
0
  public static void helpdeskSetUserPassword(
      final PwmSession pwmSession,
      final ChaiUser chaiUser,
      final UserIdentity userIdentity,
      final PwmApplication pwmApplication,
      final PasswordData newPassword)
      throws ChaiUnavailableException, PwmUnrecoverableException, PwmOperationalException {
    final SessionLabel sessionLabel = pwmSession.getLabel();

    if (!pwmSession.isAuthenticated()) {
      final String errorMsg = "attempt to helpdeskSetUserPassword, but user is not authenticated";
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_UNAUTHORIZED, errorMsg);
      throw new PwmOperationalException(errorInformation);
    }

    final HelpdeskProfile helpdeskProfile =
        pwmSession.getSessionManager().getHelpdeskProfile(pwmApplication);
    if (helpdeskProfile == null) {
      final String errorMsg =
          "attempt to helpdeskSetUserPassword, but user does not have helpdesk permission";
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_UNAUTHORIZED, errorMsg);
      throw new PwmOperationalException(errorInformation);
    }

    try {
      chaiUser.setPassword(newPassword.getStringValue());
    } catch (ChaiPasswordPolicyException e) {
      final String errorMsg =
          "error setting password for user '" + chaiUser.getEntryDN() + "'' " + 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 '" + chaiUser.getEntryDN() + "'' " + 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);
    }

    // at this point the password has been changed, so log it.
    LOGGER.info(
        sessionLabel,
        "user '"
            + pwmSession.getUserInfoBean().getUserIdentity()
            + "' successfully changed password for "
            + chaiUser.getEntryDN());

    // create a proxy user object for pwm to update/read the user.
    final ChaiUser proxiedUser = pwmApplication.getProxiedChaiUser(userIdentity);

    // mark the event log
    {
      final HelpdeskAuditRecord auditRecord =
          pwmApplication
              .getAuditManager()
              .createHelpdeskAuditRecord(
                  AuditEvent.HELPDESK_SET_PASSWORD,
                  pwmSession.getUserInfoBean().getUserIdentity(),
                  null,
                  userIdentity,
                  pwmSession.getSessionStateBean().getSrcAddress(),
                  pwmSession.getSessionStateBean().getSrcHostname());
      pwmApplication.getAuditManager().submit(auditRecord);
    }

    // update statistics
    pwmApplication.getStatisticsManager().updateEps(Statistic.EpsType.PASSWORD_CHANGES, 1);
    pwmApplication.getStatisticsManager().incrementValue(Statistic.HELPDESK_PASSWORD_SET);

    // create a uib for end user
    final UserInfoBean userInfoBean = new UserInfoBean();
    final UserStatusReader userStatusReader =
        new UserStatusReader(pwmApplication, pwmSession.getLabel());
    userStatusReader.populateUserInfoBean(
        userInfoBean,
        pwmSession.getSessionStateBean().getLocale(),
        userIdentity,
        proxiedUser.getChaiProvider());

    { // execute configured actions
      LOGGER.debug(
          sessionLabel,
          "executing changepassword and helpdesk post password change writeAttributes to user "
              + userIdentity);
      final List<ActionConfiguration> actions = new ArrayList<>();
      actions.addAll(
          pwmApplication
              .getConfig()
              .readSettingAsAction(PwmSetting.CHANGE_PASSWORD_WRITE_ATTRIBUTES));
      actions.addAll(
          helpdeskProfile.readSettingAsAction(
              PwmSetting.HELPDESK_POST_SET_PASSWORD_WRITE_ATTRIBUTES));
      if (!actions.isEmpty()) {

        final ActionExecutor actionExecutor =
            new ActionExecutor.ActionExecutorSettings(pwmApplication, userIdentity)
                .setMacroMachine(
                    MacroMachine.forUser(
                        pwmApplication,
                        pwmSession.getSessionStateBean().getLocale(),
                        sessionLabel,
                        userIdentity))
                .setExpandPwmMacros(true)
                .createActionExecutor();

        actionExecutor.executeActions(actions, pwmSession);
      }
    }

    final HelpdeskClearResponseMode settingClearResponses =
        HelpdeskClearResponseMode.valueOf(
            helpdeskProfile.readSettingAsString(PwmSetting.HELPDESK_CLEAR_RESPONSES));
    if (settingClearResponses == HelpdeskClearResponseMode.yes) {
      final String userGUID =
          LdapOperationsHelper.readLdapGuidValue(pwmApplication, sessionLabel, userIdentity, false);
      pwmApplication.getCrService().clearResponses(pwmSession, proxiedUser, userGUID);

      // mark the event log
      final HelpdeskAuditRecord auditRecord =
          pwmApplication
              .getAuditManager()
              .createHelpdeskAuditRecord(
                  AuditEvent.HELPDESK_CLEAR_RESPONSES,
                  pwmSession.getUserInfoBean().getUserIdentity(),
                  null,
                  userIdentity,
                  pwmSession.getSessionStateBean().getSrcAddress(),
                  pwmSession.getSessionStateBean().getSrcHostname());
      pwmApplication.getAuditManager().submit(auditRecord);
    }

    // send email notification
    sendChangePasswordHelpdeskEmailNotice(pwmSession, pwmApplication, userInfoBean);

    // expire if so configured
    if (helpdeskProfile.readSettingAsBoolean(PwmSetting.HELPDESK_FORCE_PW_EXPIRATION)) {
      LOGGER.trace(
          pwmSession, "preparing to expire password for user " + userIdentity.toDisplayString());
      try {
        proxiedUser.expirePassword();
      } catch (ChaiOperationException e) {
        LOGGER.warn(
            pwmSession,
            "error while forcing password expiration for user "
                + userIdentity.toDisplayString()
                + ", error: "
                + e.getMessage());
        e.printStackTrace();
      }
    }

    // send password
    final boolean sendPassword =
        helpdeskProfile.readSettingAsBoolean(PwmSetting.HELPDESK_SEND_PASSWORD);
    if (sendPassword) {
      final MessageSendMethod messageSendMethod;
      {
        final String profileID =
            ProfileUtility.discoverProfileIDforUser(
                pwmApplication, sessionLabel, userIdentity, ProfileType.ForgottenPassword);
        final ForgottenPasswordProfile forgottenPasswordProfile =
            pwmApplication.getConfig().getForgottenPasswordProfiles().get(profileID);
        messageSendMethod =
            forgottenPasswordProfile.readSettingAsEnum(
                PwmSetting.RECOVERY_SENDNEWPW_METHOD, MessageSendMethod.class);
      }
      final UserDataReader userDataReader = new LdapUserDataReader(userIdentity, chaiUser);
      final LoginInfoBean loginInfoBean = new LoginInfoBean();
      loginInfoBean.setUserCurrentPassword(newPassword);
      final MacroMachine macroMachine =
          new MacroMachine(
              pwmApplication, pwmSession.getLabel(), userInfoBean, loginInfoBean, userDataReader);
      PasswordUtility.sendNewPassword(
          userInfoBean,
          pwmApplication,
          macroMachine,
          newPassword,
          pwmSession.getSessionStateBean().getLocale(),
          messageSendMethod);
    }
  }
예제 #16
0
  @Override
  public void writeResponses(ChaiUser theUser, String userGUID, ResponseInfoBean responseInfoBean)
      throws PwmUnrecoverableException {
    if (userGUID == null || userGUID.length() < 1) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_MISSING_GUID,
              "cannot save responses to remote database, user "
                  + theUser.getEntryDN()
                  + " does not have a guid"));
    }

    LOGGER.trace(
        "attempting to save responses for "
            + theUser.getEntryDN()
            + " in remote database (key="
            + userGUID
            + ")");

    try {
      final ChaiResponseSet responseSet =
          ChaiCrFactory.newChaiResponseSet(
              responseInfoBean.getCrMap(),
              responseInfoBean.getHelpdeskCrMap(),
              responseInfoBean.getLocale(),
              responseInfoBean.getMinRandoms(),
              theUser.getChaiProvider().getChaiConfiguration(),
              responseInfoBean.getCsIdentifier());

      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      databaseAccessor.put(DatabaseTable.PWM_RESPONSES, userGUID, responseSet.stringValue());
      LOGGER.info(
          "saved responses for "
              + theUser.getEntryDN()
              + " in remote database (key="
              + userGUID
              + ")");
    } catch (ChaiException e) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_WRITING_RESPONSES,
              "unexpected error saving responses for "
                  + theUser.getEntryDN()
                  + " in remote database: "
                  + e.getMessage());
      final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException(errorInfo);
      LOGGER.error(errorInfo.toDebugStr());
      pwmOE.initCause(e);
      throw pwmOE;
    } catch (DatabaseException e) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_WRITING_RESPONSES,
              "unexpected error saving responses for "
                  + theUser.getEntryDN()
                  + " in remote database: "
                  + e.getMessage());
      final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException(errorInfo);
      LOGGER.error(errorInfo.toDebugStr());
      pwmOE.initCause(e);
      throw pwmOE;
    }
  }
예제 #17
0
  private void restLockConfiguration(final PwmRequest pwmRequest)
      throws IOException, ServletException, PwmUnrecoverableException, ChaiUnavailableException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final PwmSession pwmSession = pwmRequest.getPwmSession();

    if (PwmConstants.TRIAL_MODE) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_TRIAL_VIOLATION, "configuration lock not available in trial");
      final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
      LOGGER.debug(pwmSession, errorInfo);
      pwmRequest.outputJsonResult(restResultBean);
      return;
    }

    if (!pwmSession.isAuthenticated()) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_AUTHENTICATION_REQUIRED,
              "You must be authenticated before restricting the configuration");
      final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
      LOGGER.debug(pwmSession, errorInfo);
      pwmRequest.outputJsonResult(restResultBean);
      return;
    }

    if (!pwmSession.getSessionManager().checkPermission(pwmApplication, Permission.PWMADMIN)) {
      final ErrorInformation errorInfo =
          new ErrorInformation(
              PwmError.ERROR_UNAUTHORIZED,
              "You must be authenticated with admin privileges before restricting the configuration");
      final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
      LOGGER.debug(pwmSession, errorInfo);
      pwmRequest.outputJsonResult(restResultBean);
      return;
    }

    try {
      final StoredConfigurationImpl storedConfiguration = readCurrentConfiguration(pwmRequest);
      if (!storedConfiguration.hasPassword()) {
        final ErrorInformation errorInfo =
            new ErrorInformation(
                PwmError.CONFIG_FORMAT_ERROR,
                null,
                new String[] {
                  "Please set a configuration password before restricting the configuration"
                });
        final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
        LOGGER.debug(pwmSession, errorInfo);
        pwmRequest.outputJsonResult(restResultBean);
        return;
      }

      storedConfiguration.writeConfigProperty(ConfigurationProperty.CONFIG_IS_EDITABLE, "false");
      saveConfiguration(pwmRequest, storedConfiguration);
      final ConfigManagerBean configManagerBean =
          pwmRequest
              .getPwmApplication()
              .getSessionStateService()
              .getBean(pwmRequest, ConfigManagerBean.class);
      configManagerBean.setConfiguration(null);
    } catch (PwmException e) {
      final ErrorInformation errorInfo = e.getErrorInformation();
      final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
      LOGGER.debug(pwmSession, errorInfo.toDebugStr());
      pwmRequest.outputJsonResult(restResultBean);
      return;
    } catch (Exception e) {
      final ErrorInformation errorInfo =
          new ErrorInformation(PwmError.ERROR_UNKNOWN, e.getMessage());
      final RestResultBean restResultBean = RestResultBean.fromError(errorInfo, pwmRequest);
      LOGGER.debug(pwmSession, errorInfo.toDebugStr());
      pwmRequest.outputJsonResult(restResultBean);
      return;
    }
    final HashMap<String, String> resultData = new HashMap<>();
    LOGGER.info(pwmSession, "Configuration Locked");
    pwmRequest.outputJsonResult(new RestResultBean(resultData));
  }