Пример #1
0
  public static PwmPasswordPolicy readPasswordPolicyForUser(
      final PwmApplication pwmApplication,
      final SessionLabel pwmSession,
      final UserIdentity userIdentity,
      final ChaiUser theUser,
      final Locale locale)
      throws PwmUnrecoverableException {
    final long startTime = System.currentTimeMillis();
    final PasswordPolicySource ppSource =
        PasswordPolicySource.valueOf(
            pwmApplication.getConfig().readSettingAsString(PwmSetting.PASSWORD_POLICY_SOURCE));

    final PwmPasswordPolicy returnPolicy;
    switch (ppSource) {
      case MERGE:
        final PwmPasswordPolicy pwmPolicy =
            determineConfiguredPolicyProfileForUser(
                pwmApplication, pwmSession, userIdentity, locale);
        final PwmPasswordPolicy userPolicy = readLdapPasswordPolicy(pwmApplication, theUser);
        LOGGER.trace(
            pwmSession,
            "read user policy for '"
                + theUser.getEntryDN()
                + "', policy: "
                + userPolicy.toString());
        returnPolicy = pwmPolicy.merge(userPolicy);
        LOGGER.debug(
            pwmSession,
            "merged user password policy of '"
                + theUser.getEntryDN()
                + "' with PWM configured policy: "
                + returnPolicy.toString());
        break;

      case LDAP:
        returnPolicy = readLdapPasswordPolicy(pwmApplication, theUser);
        LOGGER.debug(
            pwmSession,
            "discovered assigned password policy for "
                + theUser.getEntryDN()
                + " "
                + returnPolicy.toString());
        break;

      case PWM:
        returnPolicy =
            determineConfiguredPolicyProfileForUser(
                pwmApplication, pwmSession, userIdentity, locale);
        break;

      default:
        throw new IllegalStateException("unknown policy source defined: " + ppSource.name());
    }

    LOGGER.trace(
        pwmSession,
        "readPasswordPolicyForUser completed in "
            + TimeDuration.fromCurrent(startTime).asCompactString());
    return returnPolicy;
  }
Пример #2
0
  private void doHealthChecks() {
    if (status != STATUS.OPEN) {
      return;
    }

    LOGGER.trace("beginning health check process");
    final List<HealthRecord> newResults = new ArrayList<>();
    for (final HealthChecker loopChecker : healthCheckers) {
      try {
        final List<HealthRecord> loopResults = loopChecker.doHealthCheck(pwmApplication);
        if (loopResults != null) {
          newResults.addAll(loopResults);
        }
      } catch (Exception e) {
        LOGGER.warn("unexpected error during healthCheck: " + e.getMessage(), e);
      }
    }
    for (final PwmService service : pwmApplication.getPwmServices()) {
      try {
        final List<HealthRecord> loopResults = service.healthCheck();
        if (loopResults != null) {
          newResults.addAll(loopResults);
        }
      } catch (Exception e) {
        LOGGER.warn("unexpected error during healthCheck: " + e.getMessage(), e);
      }
    }
    final Set<HealthRecord> sortedRecordList = new TreeSet<>();
    sortedRecordList.addAll(newResults);
    healthRecords = Collections.unmodifiableSet(sortedRecordList);
    lastHealthCheckDate = new Date();
    LOGGER.trace("health check process completed");
  }
Пример #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
  @Override
  void closeConnection(final Connection connection) throws SQLException {

    if (aggressiveCompact) {
      CallableStatement statement = null;
      try {
        LOCK.writeLock().lock();
        final java.util.Date start = new java.util.Date();
        LOGGER.trace("beginning shutdown compact");
        statement = dbConnection.prepareCall("SHUTDOWN COMPACT");
        statement.execute();
        LOGGER.trace(
            "completed shutdown compact in " + TimeDuration.fromCurrent(start).asCompactString());
      } catch (SQLException ex) {
        LOGGER.error("error during shutdown compact: " + ex.getMessage());
      } finally {
        close(statement);
        LOCK.writeLock().unlock();
      }
    }

    try {
      connection.close();
      if (driver != null) {
        DriverManager.deregisterDriver(driver);
        driver = null;
      }
    } catch (Exception e) {
      LOGGER.error("error during H2 shutdown: " + e.getMessage());
    }
  }
Пример #5
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!");
  }
Пример #6
0
  public static void verifyApplicationPath(final File applicationPath)
      throws PwmUnrecoverableException {

    if (applicationPath == null) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_STARTUP_ERROR, "unable to determine valid applicationPath"));
    }

    LOGGER.trace("examining applicationPath of " + applicationPath.getAbsolutePath() + "");

    if (!applicationPath.exists()) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_STARTUP_ERROR,
              "applicationPath " + applicationPath.getAbsolutePath() + " does not exist"));
    }

    if (!applicationPath.canRead()) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_STARTUP_ERROR,
              "unable to read from applicationPath " + applicationPath.getAbsolutePath() + ""));
    }

    if (!applicationPath.canWrite()) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_STARTUP_ERROR,
              "unable to write to applicationPath " + applicationPath.getAbsolutePath() + ""));
    }

    final File infoFile =
        new File(
            applicationPath.getAbsolutePath()
                + File.separator
                + PwmConstants.APPLICATION_PATH_INFO_FILE);
    LOGGER.trace(
        "checking "
            + infoFile.getAbsolutePath()
            + " status, (applicationPathType="
            + PwmEnvironment.ApplicationPathType.derived
            + ")");
    if (infoFile.exists()) {
      final String errorMsg =
          "The file "
              + infoFile.getAbsolutePath()
              + " exists, and an applicationPath was not explicitly specified."
              + "  This happens when an applicationPath was previously configured, but is not now being specified."
              + "  An explicit applicationPath parameter must be specified, or the file can be removed if the applicationPath should be changed to the default /WEB-INF directory.";
      throw new PwmUnrecoverableException(
          new ErrorInformation(PwmError.ERROR_STARTUP_ERROR, errorMsg));
    } else {
      LOGGER.trace("marker file " + infoFile.getAbsolutePath() + " does not exist");
    }
  }
Пример #7
0
  private static Date determinePwdLastModified(
      final PwmApplication pwmApplication,
      final SessionLabel sessionLabel,
      final ChaiUser theUser,
      final UserIdentity userIdentity)
      throws ChaiUnavailableException, PwmUnrecoverableException {
    // fetch last password modification time from pwm last update attribute operation
    try {
      final Date chaiReadDate = theUser.readPasswordModificationDate();
      if (chaiReadDate != null) {
        LOGGER.trace(
            sessionLabel,
            "read last user password change timestamp (via chai) as: "
                + PwmConstants.DEFAULT_DATETIME_FORMAT.format(chaiReadDate));
        return chaiReadDate;
      }
    } catch (ChaiOperationException e) {
      LOGGER.error(
          sessionLabel,
          "unexpected error reading password last modified timestamp: " + e.getMessage());
    }

    final LdapProfile ldapProfile =
        pwmApplication.getConfig().getLdapProfiles().get(userIdentity.getLdapProfileID());
    final String pwmLastSetAttr =
        ldapProfile.readSettingAsString(PwmSetting.PASSWORD_LAST_UPDATE_ATTRIBUTE);
    if (pwmLastSetAttr != null && pwmLastSetAttr.length() > 0) {
      try {
        final Date pwmPwdLastModified = theUser.readDateAttribute(pwmLastSetAttr);
        LOGGER.trace(
            sessionLabel,
            "read pwmPasswordChangeTime as: "
                + (pwmPwdLastModified == null
                    ? "n/a"
                    : PwmConstants.DEFAULT_DATETIME_FORMAT.format(pwmPwdLastModified)));
        return pwmPwdLastModified;
      } catch (ChaiOperationException e) {
        LOGGER.error(
            sessionLabel,
            "error parsing password last modified PWM password value for user "
                + theUser.getEntryDN()
                + "; error: "
                + e.getMessage());
      }
    }

    LOGGER.debug(sessionLabel, "unable to determine time of user's last password modification");
    return null;
  }
Пример #8
0
  public static void incrementStat(final PwmApplication pwmApplication, final Statistic statistic) {
    if (pwmApplication == null) {
      LOGGER.error(
          "skipping requested statistic increment of " + statistic + " due to null pwmApplication");
      return;
    }

    final StatisticsManager statisticsManager = pwmApplication.getStatisticsManager();
    if (statisticsManager == null) {
      LOGGER.error(
          "skipping requested statistic increment of "
              + statistic
              + " due to null statisticsManager");
      return;
    }

    if (statisticsManager.status() != STATUS.OPEN) {
      LOGGER.trace(
          "skipping requested statistic increment of "
              + statistic
              + " due to StatisticsManager being closed");
      return;
    }

    statisticsManager.incrementValue(statistic);
  }
Пример #9
0
  public UserCacheRecord updateUserCache(final UserInfoBean userInfoBean)
      throws PwmUnrecoverableException {
    final StorageKey storageKey = StorageKey.fromUserInfoBean(userInfoBean);

    boolean preExisting = false;
    try {
      UserCacheRecord userCacheRecord = readStorageKey(storageKey);
      if (userCacheRecord == null) {
        userCacheRecord = new UserCacheRecord();
      } else {
        preExisting = true;
      }
      userCacheRecord.addUiBeanData(userInfoBean);
      store(userCacheRecord);
      return userCacheRecord;
    } catch (LocalDBException e) {
      LOGGER.error("unable to store user status cache to localdb: " + e.getMessage());
    }
    LOGGER.trace(
        "updateCache: "
            + (preExisting ? "updated existing" : "created new")
            + " user cache for "
            + userInfoBean.getUserIdentity()
            + " user key "
            + storageKey.getKey());
    return null;
  }
Пример #10
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;
    }
  }
Пример #11
0
  public String getStatistic(final Statistic statistic) {
    switch (statistic.getType()) {
      case INCREMENTOR:
        return valueMap.containsKey(statistic) ? valueMap.get(statistic) : "0";

      case AVERAGE:
        final String avgStrValue = valueMap.get(statistic);

        AverageBean avgBean = new AverageBean();
        if (avgStrValue != null && avgStrValue.length() > 0) {
          try {
            avgBean = JsonUtil.deserialize(avgStrValue, AverageBean.class);
          } catch (Exception e) {
            LOGGER.trace(
                "unable to parse statistics value for stat "
                    + statistic.toString()
                    + ", value="
                    + avgStrValue);
          }
        }
        return avgBean.getAverage().toString();

      default:
        return "";
    }
  }
Пример #12
0
  private static void invokePostChangePasswordActions(
      final PwmSession pwmSession, final String newPassword) throws PwmUnrecoverableException {
    final List<PostChangePasswordAction> postChangePasswordActions =
        pwmSession.getUserSessionDataCacheBean().removePostChangePasswordActions();
    if (postChangePasswordActions == null || postChangePasswordActions.isEmpty()) {
      LOGGER.trace(pwmSession, "no post change password actions pending from previous operations");
      return;
    }

    for (final PostChangePasswordAction postChangePasswordAction : postChangePasswordActions) {
      try {
        postChangePasswordAction.doAction(pwmSession, newPassword);
      } catch (PwmUnrecoverableException e) {
        LOGGER.error(
            pwmSession,
            "error during post change password action '"
                + postChangePasswordAction.getLabel()
                + "' "
                + e.getMessage());
        throw e;
      } catch (Exception e) {
        LOGGER.error(
            pwmSession,
            "unexpected error during post change password action '"
                + postChangePasswordAction.getLabel()
                + "' "
                + e.getMessage(),
            e);
        final ErrorInformation errorInfo =
            new ErrorInformation(PwmError.ERROR_UNKNOWN, e.getMessage());
        throw new PwmUnrecoverableException(errorInfo);
      }
    }
  }
Пример #13
0
  public synchronized void addWord(final PwmSession pwmSession, final String word) {
    if (status != STATUS.OPEN) {
      return;
    }

    final String addWord = normalizeWord(word);

    if (addWord == null) {
      return;
    }

    final long startTime = System.currentTimeMillis();

    try {
      final String hashedWord = hashWord(addWord);

      final boolean preExisting = localDB.contains(WORDS_DB, hashedWord);
      localDB.put(WORDS_DB, hashedWord, Long.toString(System.currentTimeMillis()));

      {
        final StringBuilder logOutput = new StringBuilder();
        logOutput.append(preExisting ? "updated" : "added").append(" word");
        logOutput
            .append(" (")
            .append(new TimeDuration(System.currentTimeMillis(), startTime).asCompactString())
            .append(")");
        logOutput.append(" (").append(this.size()).append(" total words)");
        LOGGER.trace(logOutput.toString());
      }
    } catch (Exception e) {
      LOGGER.warn(pwmSession, "error adding word to global history list: " + e.getMessage());
    }
  }
Пример #14
0
  private void restBrowseLdap(final PwmRequest pwmRequest, final ConfigGuideBean configGuideBean)
      throws IOException, ServletException, PwmUnrecoverableException {
    final StoredConfigurationImpl storedConfiguration =
        StoredConfigurationImpl.copy(configGuideBean.getStoredConfiguration());
    if (configGuideBean.getStep() == STEP.LDAP_ADMIN) {
      storedConfiguration.resetSetting(PwmSetting.LDAP_PROXY_USER_DN, LDAP_PROFILE_KEY, null);
      storedConfiguration.resetSetting(PwmSetting.LDAP_PROXY_USER_PASSWORD, LDAP_PROFILE_KEY, null);
    }

    final Date startTime = new Date();
    final Map<String, String> inputMap =
        pwmRequest.readBodyAsJsonStringMap(PwmHttpRequestWrapper.Flag.BypassValidation);
    final String profile = inputMap.get("profile");
    final String dn = inputMap.containsKey("dn") ? inputMap.get("dn") : "";

    final LdapBrowser ldapBrowser = new LdapBrowser(storedConfiguration);
    final LdapBrowser.LdapBrowseResult result = ldapBrowser.doBrowse(profile, dn);
    ldapBrowser.close();

    LOGGER.trace(
        pwmRequest,
        "performed ldapBrowse operation in "
            + TimeDuration.fromCurrent(startTime).asCompactString()
            + ", result="
            + JsonUtil.serialize(result));

    pwmRequest.outputJsonResult(new RestResultBean(result));
  }
Пример #15
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;
  }
Пример #16
0
 public void scheduleImmediateUpdate() {
   if (!reportStatus.isInProgress()) {
     executorService.submit(new DredgeTask());
     LOGGER.trace(
         PwmConstants.REPORTING_SESSION_LABEL,
         "submitted new ldap dredge task to executorService");
   }
 }
Пример #17
0
  private void updateRestingCacheData() {
    final long startTime = System.currentTimeMillis();
    int examinedRecords = 0;
    ClosableIterator<UserCacheRecord> iterator = null;
    try {
      LOGGER.trace(PwmConstants.REPORTING_SESSION_LABEL, "checking size of stored cache records");
      final int totalRecords = userCacheService.size();
      LOGGER.debug(
          PwmConstants.REPORTING_SESSION_LABEL,
          "beginning cache review process of " + totalRecords + " records");
      iterator = iterator();
      Date lastLogOutputTime = new Date();
      while (iterator.hasNext() && status == STATUS.OPEN) {
        final UserCacheRecord record = iterator.next(); // (purge routine is embedded in next();

        if (summaryData != null && record != null) {
          summaryData.update(record);
        }

        examinedRecords++;

        if (TimeDuration.fromCurrent(lastLogOutputTime).isLongerThan(30, TimeUnit.SECONDS)) {
          final TimeDuration progressDuration = TimeDuration.fromCurrent(startTime);
          LOGGER.trace(
              PwmConstants.REPORTING_SESSION_LABEL,
              "cache review process in progress, examined "
                  + examinedRecords
                  + " records in "
                  + progressDuration.asCompactString());
          lastLogOutputTime = new Date();
        }
      }
      final TimeDuration totalTime = TimeDuration.fromCurrent(startTime);
      LOGGER.debug(
          PwmConstants.REPORTING_SESSION_LABEL,
          "completed cache review process of "
              + examinedRecords
              + " cached report records in "
              + totalTime.asCompactString());
    } finally {
      if (iterator != null) {
        iterator.close();
      }
    }
  }
Пример #18
0
  public int outputStatsToCsv(
      final OutputStream outputStream, final Locale locale, final boolean includeHeader)
      throws IOException {
    LOGGER.trace("beginning output stats to csv process");
    final Date startTime = new Date();

    final StatisticsManager statsManger = pwmApplication.getStatisticsManager();
    final CSVPrinter csvPrinter = Helper.makeCsvPrinter(outputStream);

    if (includeHeader) {
      final List<String> headers = new ArrayList<>();
      headers.add("KEY");
      headers.add("YEAR");
      headers.add("DAY");
      for (Statistic stat : Statistic.values()) {
        headers.add(stat.getLabel(locale));
      }
      csvPrinter.printRecord(headers);
    }

    int counter = 0;
    final Map<StatisticsManager.DailyKey, String> keys =
        statsManger.getAvailableKeys(PwmConstants.DEFAULT_LOCALE);
    for (final StatisticsManager.DailyKey loopKey : keys.keySet()) {
      counter++;
      final StatisticsBundle bundle = statsManger.getStatBundleForKey(loopKey.toString());
      final List<String> lineOutput = new ArrayList<>();
      lineOutput.add(loopKey.toString());
      lineOutput.add(String.valueOf(loopKey.year));
      lineOutput.add(String.valueOf(loopKey.day));
      for (final Statistic stat : Statistic.values()) {
        lineOutput.add(bundle.getStatistic(stat));
      }
      csvPrinter.printRecord(lineOutput);
    }

    csvPrinter.flush();
    LOGGER.trace(
        "completed output stats to csv process; output "
            + counter
            + " records in "
            + TimeDuration.fromCurrent(startTime).asCompactString());
    return counter;
  }
Пример #19
0
  @Override
  public String get(final DatabaseTable table, final String key) throws DatabaseException {
    if (traceLogging) {
      LOGGER.trace("attempting get operation for table=" + table + ", key=" + key);
    }
    preOperationCheck();
    final StringBuilder sb = new StringBuilder();
    sb.append("SELECT * FROM ").append(table.toString()).append(" WHERE " + KEY_COLUMN + " = ?");

    PreparedStatement statement = null;
    ResultSet resultSet = null;
    String returnValue = null;
    try {
      statement = connection.prepareStatement(sb.toString());
      statement.setString(1, key);
      statement.setMaxRows(1);
      resultSet = statement.executeQuery();

      if (resultSet.next()) {
        returnValue = resultSet.getString(VALUE_COLUMN);
      }
    } catch (SQLException e) {
      final ErrorInformation errorInformation =
          new ErrorInformation(
              PwmError.ERROR_DB_UNAVAILABLE, "get operation failed: " + e.getMessage());
      lastError = errorInformation;
      throw new DatabaseException(errorInformation);
    } finally {
      close(statement);
      close(resultSet);
    }

    if (traceLogging) {
      final LinkedHashMap<String, Object> debugOutput = new LinkedHashMap<>();
      debugOutput.put("table", table);
      debugOutput.put("key", key);
      debugOutput.put("result", returnValue);
      LOGGER.trace(
          "get operation result: " + JsonUtil.serializeMap(debugOutput, JsonUtil.Flag.PrettyPrint));
    }

    updateStats(true, false);
    return returnValue;
  }
Пример #20
0
  public ResponseSet readResponseSet(
      final ChaiUser theUser, final UserIdentity userIdentity, final String userGUID)
      throws PwmUnrecoverableException {
    if (userGUID == null || userGUID.length() < 1) {
      final String errorMsg =
          "user "
              + theUser.getEntryDN()
              + " does not have a guid, unable to search for responses in remote database";
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_MISSING_GUID, errorMsg);
      throw new PwmUnrecoverableException(errorInformation);
    }

    try {
      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      final String responseStringBlob = databaseAccessor.get(DatabaseTable.PWM_RESPONSES, userGUID);
      if (responseStringBlob != null && responseStringBlob.length() > 0) {
        final ResponseSet userResponseSet =
            ChaiResponseSet.parseChaiResponseSetXML(responseStringBlob, theUser);
        LOGGER.debug(
            "found responses for "
                + theUser.getEntryDN()
                + " in remote database: "
                + userResponseSet.toString());
        return userResponseSet;
      } else {
        LOGGER.trace(
            "user guid for "
                + theUser.getEntryDN()
                + " not found in remote database (key="
                + userGUID
                + ")");
      }
    } catch (ChaiValidationException e) {
      final String errorMsg =
          "unexpected error reading responses for "
              + theUser.getEntryDN()
              + " from remote database: "
              + e.getMessage();
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
      throw new PwmUnrecoverableException(errorInformation);
    } catch (PwmOperationalException e) {
      final String errorMsg =
          "unexpected error reading responses for "
              + theUser.getEntryDN()
              + " from remote database: "
              + e.getMessage();
      final ErrorInformation errorInformation =
          new ErrorInformation(e.getErrorInformation().getError(), errorMsg);
      throw new PwmUnrecoverableException(errorInformation);
    }
    return null;
  }
Пример #21
0
  @Override
  public boolean remove(final DatabaseTable table, final String key) throws DatabaseException {
    if (traceLogging) {
      LOGGER.trace("attempting remove operation for table=" + table + ", key=" + key);
    }

    boolean result = contains(table, key);
    if (result) {
      final StringBuilder sqlText = new StringBuilder();
      sqlText.append("DELETE FROM ").append(table.toString()).append(" WHERE " + KEY_COLUMN + "=?");

      PreparedStatement statement = null;
      try {
        statement = connection.prepareStatement(sqlText.toString());
        statement.setString(1, key);
        statement.executeUpdate();
        LOGGER.trace("remove operation succeeded for table=" + table + ", key=" + key);
      } catch (SQLException e) {
        final ErrorInformation errorInformation =
            new ErrorInformation(
                PwmError.ERROR_DB_UNAVAILABLE, "remove operation failed: " + e.getMessage());
        lastError = errorInformation;
        throw new DatabaseException(errorInformation);
      } finally {
        close(statement);
      }
    }

    if (traceLogging) {
      final Map<String, Object> debugOutput = new LinkedHashMap<>();
      debugOutput.put("table", table);
      debugOutput.put("key", key);
      debugOutput.put("result", result);
      LOGGER.trace(
          "remove operation result: "
              + JsonUtil.serializeMap(debugOutput, JsonUtil.Flag.PrettyPrint));
    }

    updateStats(true, false);
    return result;
  }
Пример #22
0
  public static void restUploadConfig(final PwmRequest pwmRequest)
      throws PwmUnrecoverableException, IOException, ServletException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final HttpServletRequest req = pwmRequest.getHttpServletRequest();

    if (pwmApplication.getApplicationMode() == PwmApplication.MODE.RUNNING) {
      final String errorMsg = "config upload is not permitted when in running mode";
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.CONFIG_UPLOAD_FAILURE, errorMsg, new String[] {errorMsg});
      pwmRequest.respondWithError(errorInformation, true);
      return;
    }

    if (ServletFileUpload.isMultipartContent(req)) {
      final InputStream uploadedFile = ServletHelper.readFileUpload(req, "uploadFile");
      if (uploadedFile != null) {
        try {
          final StoredConfigurationImpl storedConfig =
              StoredConfigurationImpl.fromXml(uploadedFile);
          final List<String> configErrors = storedConfig.validateValues();
          if (configErrors != null && !configErrors.isEmpty()) {
            throw new PwmOperationalException(
                new ErrorInformation(PwmError.CONFIG_FORMAT_ERROR, configErrors.get(0)));
          }
          writeConfig(ContextManager.getContextManager(req.getSession()), storedConfig);
          LOGGER.trace(pwmSession, "read config from file: " + storedConfig.toString());
          final RestResultBean restResultBean = new RestResultBean();
          restResultBean.setSuccessMessage("read message");
          pwmRequest.getPwmResponse().outputJsonResult(restResultBean);
          req.getSession().invalidate();
        } catch (PwmException e) {
          final RestResultBean restResultBean =
              RestResultBean.fromError(e.getErrorInformation(), pwmRequest);
          pwmRequest.getPwmResponse().outputJsonResult(restResultBean);
          LOGGER.error(pwmSession, e.getErrorInformation().toDebugStr());
        }
      } else {
        final ErrorInformation errorInformation =
            new ErrorInformation(
                PwmError.CONFIG_UPLOAD_FAILURE,
                "error reading config file: no file present in upload");
        final RestResultBean restResultBean =
            RestResultBean.fromError(errorInformation, pwmRequest);
        pwmRequest.getPwmResponse().outputJsonResult(restResultBean);
        LOGGER.error(pwmSession, errorInformation.toDebugStr());
      }
    }
  }
Пример #23
0
 @Override
 public boolean contains(final DatabaseTable table, final String key) throws DatabaseException {
   final boolean result = get(table, key) != null;
   if (traceLogging) {
     final Map<String, Object> debugOutput = new LinkedHashMap<>();
     debugOutput.put("table", table);
     debugOutput.put("key", key);
     debugOutput.put("result", result);
     LOGGER.trace(
         "contains operation result: "
             + JsonUtil.serializeMap(debugOutput, JsonUtil.Flag.PrettyPrint));
   }
   updateStats(true, false);
   return result;
 }
Пример #24
0
  private static Date readExpirationFromRequest(final PwmRequest pwmRequest)
      throws PwmOperationalException, ChaiUnavailableException, ChaiOperationException,
          PwmUnrecoverableException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final Configuration config = pwmApplication.getConfig();
    final long durationValueDays = config.readSettingAsLong(PwmSetting.GUEST_MAX_VALID_DAYS);
    final String expirationAttribute =
        config.readSettingAsString(PwmSetting.GUEST_EXPIRATION_ATTRIBUTE);

    if (durationValueDays == 0
        || expirationAttribute == null
        || expirationAttribute.length() <= 0) {
      return null;
    }

    final String expirationDateStr = pwmRequest.readParameterAsString(HTTP_PARAM_EXPIRATION_DATE);

    Date expirationDate;
    try {
      expirationDate = new SimpleDateFormat("yyyy-MM-dd").parse(expirationDateStr);
    } catch (ParseException e) {
      final String errorMsg = "unable to read expiration date value: " + e.getMessage();
      throw new PwmOperationalException(
          new ErrorInformation(
              PwmError.ERROR_FIELD_REQUIRED, errorMsg, new String[] {"expiration date"}));
    }

    if (expirationDate.before(new Date())) {
      final String errorMsg = "expiration date must be in the future";
      throw new PwmOperationalException(
          new ErrorInformation(PwmError.ERROR_FIELD_REQUIRED, errorMsg));
    }

    final long durationValueMs = durationValueDays * 24 * 60 * 60 * 1000;
    final long futureDateMs = System.currentTimeMillis() + durationValueMs;
    final Date futureDate = new Date(futureDateMs);

    if (expirationDate.after(futureDate)) {
      final String errorMsg = "expiration date must be sooner than " + futureDate.toString();
      throw new PwmOperationalException(
          new ErrorInformation(PwmError.ERROR_FIELD_REQUIRED, errorMsg));
    }

    LOGGER.trace(pwmRequest, "read expiration date as " + expirationDate.toString());
    return expirationDate;
  }
Пример #25
0
    public boolean test(final Map<Challenge, String> responseTest) throws ChaiUnavailableException {
      if (service == null) {
        LOGGER.error(
            localIdentifier
                + "beginning web service 'processChaRes' response test, however service bean is not in session memory, aborting response test...");
        return false;
      }
      LOGGER.trace(localIdentifier + "beginning web service 'processChaRes' response test ");
      final String[] responseArray = new String[challengeSet.getAdminDefinedChallenges().size()];
      {
        int i = 0;
        for (final Challenge loopChallenge : challengeSet.getAdminDefinedChallenges()) {
          final String loopResponse = responseTest.get(loopChallenge);
          responseArray[i] = loopResponse;
          i++;
        }
      }
      final ProcessChaResRequest request = new ProcessChaResRequest();
      request.setChaAnswers(responseArray);
      request.setUserDN(userDN);

      try {
        final ForgotPasswordWSBean response = service.processChaRes(request);
        if (response.isTimeout()) {
          LOGGER.error(localIdentifier + "web service reports timeout: " + response.getMessage());
          return false;
        }
        if (response.isError()) {
          if ("Account restrictions prevent you from logging in. See your administrator for more details."
              .equals(response.getMessage())) {
            // throw PwmUnrecoverableException.createPwmException(PwmError.ERROR_INTRUDER_USER);
          }
          LOGGER.error(localIdentifier + "web service reports error: " + response.getMessage());
          return false;
        }
        LOGGER.debug(localIdentifier + "web service has validated the users responses");
        return true;
      } catch (RemoteException e) {
        LOGGER.error(localIdentifier + "error processing web service response: " + e.getMessage());
      }

      return false; // To change body of implemented methods use File | Settings | File Templates.
    }
Пример #26
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;
    }
  }
Пример #27
0
 public static String makeOutboundRestWSCall(
     final PwmApplication pwmApplication,
     final Locale locale,
     final String url,
     final String jsonRequestBody)
     throws PwmOperationalException, PwmUnrecoverableException {
   final HttpPost httpPost = new HttpPost(url);
   httpPost.setHeader("Accept", PwmConstants.AcceptValue.json.getHeaderValue());
   if (locale != null) {
     httpPost.setHeader("Accept-Locale", locale.toString());
   }
   httpPost.setHeader("Content-Type", PwmConstants.ContentTypeValue.json.getHeaderValue());
   final HttpResponse httpResponse;
   try {
     final StringEntity stringEntity = new StringEntity(jsonRequestBody);
     stringEntity.setContentType(PwmConstants.AcceptValue.json.getHeaderValue());
     httpPost.setEntity(stringEntity);
     LOGGER.debug(
         "beginning external rest call to: " + httpPost.toString() + ", body: " + jsonRequestBody);
     httpResponse = PwmHttpClient.getHttpClient(pwmApplication.getConfig()).execute(httpPost);
     final String responseBody = EntityUtils.toString(httpResponse.getEntity());
     LOGGER.trace(
         "external rest call returned: "
             + httpResponse.getStatusLine().toString()
             + ", body: "
             + responseBody);
     if (httpResponse.getStatusLine().getStatusCode() != 200) {
       final String errorMsg =
           "received non-200 response code ("
               + httpResponse.getStatusLine().getStatusCode()
               + ") when executing web-service";
       LOGGER.error(errorMsg);
       throw new PwmOperationalException(new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg));
     }
     return responseBody;
   } catch (IOException e) {
     final String errorMsg =
         "http response error while executing external rest call, error: " + e.getMessage();
     LOGGER.error(errorMsg);
     throw new PwmOperationalException(new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg), e);
   }
 }
Пример #28
0
  private boolean isEnabled(final ServletRequest servletRequest) {

    try {
      final PwmURL pwmURL = new PwmURL((HttpServletRequest) servletRequest);
      if (pwmURL.isResourceURL() || pwmURL.isWebServiceURL()) {
        return false;
      }
    } catch (Exception e) {
      LOGGER.error("unable to parse request url, defaulting to non-gzip: " + e.getMessage());
    }

    final PwmApplication pwmApplication;
    try {
      pwmApplication = ContextManager.getPwmApplication((HttpServletRequest) servletRequest);
      return Boolean.parseBoolean(
          pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_ENABLE_GZIP));
    } catch (PwmUnrecoverableException e) {
      LOGGER.trace(
          "unable to read http-gzip app-property, defaulting to non-gzip: " + e.getMessage());
    }
    return false;
  }
Пример #29
0
  @Override
  public OTPUserRecord readOtpUserConfiguration(UserIdentity theUser, String userGUID)
      throws PwmUnrecoverableException {
    LOGGER.trace(String.format("Enter: readOtpUserConfiguration(%s, %s)", theUser, userGUID));
    if (userGUID == null || userGUID.length() < 1) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.ERROR_MISSING_GUID, "cannot save otp to db, user does not have a GUID"));
    }

    OTPUserRecord otpConfig = null;
    try {
      final DatabaseAccessorImpl databaseAccessor = pwmApplication.getDatabaseAccessor();
      String value = databaseAccessor.get(DatabaseTable.OTP, userGUID);
      if (value != null && value.length() > 0) {
        if (getPwmApplication().getConfig().readSettingAsBoolean(PwmSetting.OTP_SECRET_ENCRYPT)) {
          value = decryptAttributeValue(value);
        }
        if (value != null) {
          otpConfig = decomposeOtpAttribute(value);
        }
        if (otpConfig != null) {
          LOGGER.debug("found user OTP secret in db: " + otpConfig.toString());
        }
      }
    } catch (LocalDBException e) {
      final String errorMsg = "unexpected LocalDB error reading responses: " + e.getMessage();
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
      throw new PwmUnrecoverableException(errorInformation);
    } catch (PwmOperationalException e) {
      final String errorMsg = "unexpected error reading responses: " + e.getMessage();
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
      throw new PwmUnrecoverableException(errorInformation);
    }
    return otpConfig;
  }
Пример #30
0
  public synchronized void updateAverageValue(final Statistic statistic, final long timeDuration) {
    if (Statistic.Type.AVERAGE != statistic.getType()) {
      LOGGER.error("attempt to update average value of non-average stat " + statistic);
      return;
    }

    final String avgStrValue = valueMap.get(statistic);

    AverageBean avgBean = new AverageBean();
    if (avgStrValue != null && avgStrValue.length() > 0) {
      try {
        avgBean = JsonUtil.deserialize(avgStrValue, AverageBean.class);
      } catch (Exception e) {
        LOGGER.trace(
            "unable to parse statistics value for stat "
                + statistic.toString()
                + ", value="
                + avgStrValue);
      }
    }

    avgBean.appendValue(timeDuration);
    valueMap.put(statistic, JsonUtil.serialize(avgBean));
  }