/**
   * Validates a number of password policy state constraints for the user. This will be called
   * before the offered credentials are checked.
   *
   * @param userEntry The entry for the user that is authenticating.
   * @param saslHandler The SASL mechanism handler if this is a SASL bind, or {@code null} for a
   *     simple bind.
   * @throws DirectoryException If a problem occurs that should cause the bind to fail.
   */
  protected void checkUnverifiedPasswordPolicyState(
      Entry userEntry, SASLMechanismHandler<?> saslHandler) throws DirectoryException {
    PasswordPolicyState pwPolicyState = (PasswordPolicyState) authPolicyState;
    PasswordPolicy policy = pwPolicyState.getAuthenticationPolicy();

    boolean isSASLBind = saslHandler != null;

    // If the password policy is configured to track authentication failures or
    // keep the last login time and the associated backend is disabled, then we
    // may need to reject the bind immediately.
    if ((policy.getStateUpdateFailurePolicy()
            == PasswordPolicyCfgDefn.StateUpdateFailurePolicy.PROACTIVE)
        && ((policy.getLockoutFailureCount() > 0)
            || ((policy.getLastLoginTimeAttribute() != null)
                && (policy.getLastLoginTimeFormat() != null)))
        && ((DirectoryServer.getWritabilityMode() == WritabilityMode.DISABLED)
            || (backend.getWritabilityMode() == WritabilityMode.DISABLED))) {
      // This policy isn't applicable to root users, so if it's a root
      // user then ignore it.
      if (!DirectoryServer.isRootDN(userEntry.getName())) {
        throw new DirectoryException(
            ResultCode.INVALID_CREDENTIALS,
            ERR_BIND_OPERATION_WRITABILITY_DISABLED.get(userEntry.getName()));
      }
    }

    // Check to see if the authentication must be done in a secure
    // manner.  If so, then the client connection must be secure.
    if (policy.isRequireSecureAuthentication() && !clientConnection.isSecure()) {
      if (isSASLBind) {
        if (!saslHandler.isSecure(saslMechanism)) {
          throw new DirectoryException(
              ResultCode.INVALID_CREDENTIALS,
              ERR_BIND_OPERATION_INSECURE_SASL_BIND.get(saslMechanism, userEntry.getName()));
        }
      } else {
        throw new DirectoryException(
            ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_INSECURE_SIMPLE_BIND.get());
      }
    }
  }