/**
   * Ensures that password policy constructed from subentry is active and has a valid configuration.
   *
   * @throws Exception If an unexpected problem occurs.
   */
  @Test()
  public void testValidConfiguration() throws Exception {
    PasswordPolicy defaultPolicy = DirectoryServer.getDefaultPasswordPolicy();
    assertNotNull(defaultPolicy);

    // The values are selected on a basis that they
    // should differ from default password policy.
    Entry policyEntry =
        TestCaseUtils.makeEntry(
            "dn: cn=Temp Policy," + SUFFIX,
            "objectClass: top",
            "objectClass: pwdPolicy",
            "objectClass: subentry",
            "cn: Temp Policy",
            "subtreeSpecification: { base \"ou=people\" }",
            "pwdLockoutDuration: 300",
            "pwdMaxFailure: 3",
            "pwdMustChange: TRUE",
            "pwdAttribute: authPassword",
            "pwdMinAge: 600",
            "pwdMaxAge: 2147483647",
            "pwdInHistory: 5",
            "pwdExpireWarning: 864000",
            "pwdGraceAuthNLimit: 3",
            "pwdFailureCountInterval: 3600",
            "pwdAllowUserChange: FALSE",
            "pwdSafeModify: TRUE");

    InternalClientConnection connection = InternalClientConnection.getRootConnection();

    AddOperation addOperation =
        connection.processAdd(
            policyEntry.getDN(),
            policyEntry.getObjectClasses(),
            policyEntry.getUserAttributes(),
            policyEntry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(DirectoryServer.getEntry(policyEntry.getDN()));

    PasswordPolicy policy =
        (PasswordPolicy)
            DirectoryServer.getAuthenticationPolicy(DN.decode("cn=Temp Policy," + SUFFIX));
    assertNotNull(policy);

    // Check all pwp attributes for correct values.
    assertEquals(policy.getLockoutDuration(), 300);
    assertEquals(policy.getLockoutFailureCount(), 3);
    assertEquals(policy.isForceChangeOnReset(), true);
    assertTrue(policy.getPasswordAttribute().getPrimaryName().equalsIgnoreCase("authPassword"));
    assertEquals(policy.getMinPasswordAge(), 600);
    assertEquals(policy.getMaxPasswordAge(), 2147483647);
    assertEquals(policy.getPasswordHistoryCount(), 5);
    assertEquals(policy.getPasswordExpirationWarningInterval(), 864000);
    assertEquals(policy.getGraceLoginCount(), 3);
    assertEquals(policy.getLockoutFailureExpirationInterval(), 3600);
    assertEquals(policy.isAllowUserPasswordChanges(), false);
    assertEquals(policy.isPasswordChangeRequiresCurrentPassword(), true);

    /* Check the password validator attributes for correct values.
     * The default unit-test config has a single Password validator which is
     * enabled for the default password policy.
     */
    Collection<PasswordValidator<?>> validators = policy.getPasswordValidators();
    assertEquals(validators.size(), 1);
    for (PasswordValidator<?> validator : validators) {
      assertTrue(
          validator.toString().startsWith("org.opends.server.extensions.TestPasswordValidator"));
    }

    // Make sure this policy applies to the test entry
    // its supposed to target and that its the same
    // policy object as previously tested.
    Entry testEntry = DirectoryServer.getEntry(DN.decode("uid=rogasawara," + BASE));
    assertNotNull(testEntry);

    AuthenticationPolicy statePolicy = AuthenticationPolicy.forUser(testEntry, false);
    assertNotNull(statePolicy);
    assertEquals(policy, statePolicy);

    // Make sure this policy is gone and default
    // policy is in effect instead.
    TestCaseUtils.deleteEntry(policyEntry.getDN());
    statePolicy = AuthenticationPolicy.forUser(testEntry, false);
    assertNotNull(statePolicy);
    assertEquals(defaultPolicy, statePolicy);
  }
예제 #2
0
  /**
   * Perform policy checks for accounts when the credentials are correct.
   *
   * @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 checkVerifiedPasswordPolicyState(
      Entry userEntry, SASLMechanismHandler<?> saslHandler) throws DirectoryException {
    PasswordPolicyState pwPolicyState = (PasswordPolicyState) authPolicyState;
    PasswordPolicy policy = pwPolicyState.getAuthenticationPolicy();

    boolean isSASLBind = saslHandler != null;

    // Check to see if the user is administratively disabled or locked.
    if (pwPolicyState.isDisabled()) {
      throw new DirectoryException(
          ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_ACCOUNT_DISABLED.get());
    } else if (pwPolicyState.isAccountExpired()) {
      LocalizableMessage m = ERR_BIND_OPERATION_ACCOUNT_EXPIRED.get();
      pwPolicyState.generateAccountStatusNotification(
          AccountStatusNotificationType.ACCOUNT_EXPIRED,
          userEntry,
          m,
          AccountStatusNotification.createProperties(pwPolicyState, false, -1, null, null));

      throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, m);
    } else if (pwPolicyState.lockedDueToFailures()) {
      if (pwPolicyErrorType == null) {
        pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
      }

      throw new DirectoryException(
          ResultCode.INVALID_CREDENTIALS, ERR_BIND_OPERATION_ACCOUNT_FAILURE_LOCKED.get());
    } else if (pwPolicyState.lockedDueToIdleInterval()) {
      if (pwPolicyErrorType == null) {
        pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
      }

      LocalizableMessage m = ERR_BIND_OPERATION_ACCOUNT_IDLE_LOCKED.get();
      pwPolicyState.generateAccountStatusNotification(
          AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED,
          userEntry,
          m,
          AccountStatusNotification.createProperties(pwPolicyState, false, -1, null, null));

      throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, m);
    }

    // If it's a simple bind, or if it's a password-based SASL bind, then
    // perform a number of password-based checks.
    if (!isSASLBind || saslHandler.isPasswordBased(saslMechanism)) {
      // Check to see if the account is locked due to the maximum reset age.
      if (pwPolicyState.lockedDueToMaximumResetAge()) {
        if (pwPolicyErrorType == null) {
          pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
        }

        LocalizableMessage m = ERR_BIND_OPERATION_ACCOUNT_RESET_LOCKED.get();
        pwPolicyState.generateAccountStatusNotification(
            AccountStatusNotificationType.ACCOUNT_RESET_LOCKED,
            userEntry,
            m,
            AccountStatusNotification.createProperties(pwPolicyState, false, -1, null, null));

        throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, m);
      }

      // Determine whether the password is expired, or whether the user
      // should be warned about an upcoming expiration.
      if (pwPolicyState.isPasswordExpired()) {
        if (pwPolicyErrorType == null) {
          pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
        }

        int maxGraceLogins = policy.getGraceLoginCount();
        if (maxGraceLogins > 0 && pwPolicyState.mayUseGraceLogin()) {
          List<Long> graceLoginTimes = pwPolicyState.getGraceLoginTimes();
          if (graceLoginTimes == null || graceLoginTimes.size() < maxGraceLogins) {
            isGraceLogin = true;
            mustChangePassword = true;

            if (pwPolicyWarningType == null) {
              pwPolicyWarningType = PasswordPolicyWarningType.GRACE_LOGINS_REMAINING;
              pwPolicyWarningValue = maxGraceLogins - (graceLoginTimes.size() + 1);
            }
          } else {
            LocalizableMessage m = ERR_BIND_OPERATION_PASSWORD_EXPIRED.get();

            pwPolicyState.generateAccountStatusNotification(
                AccountStatusNotificationType.PASSWORD_EXPIRED,
                userEntry,
                m,
                AccountStatusNotification.createProperties(pwPolicyState, false, -1, null, null));

            throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, m);
          }
        } else {
          LocalizableMessage m = ERR_BIND_OPERATION_PASSWORD_EXPIRED.get();

          pwPolicyState.generateAccountStatusNotification(
              AccountStatusNotificationType.PASSWORD_EXPIRED,
              userEntry,
              m,
              AccountStatusNotification.createProperties(pwPolicyState, false, -1, null, null));

          throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, m);
        }
      } else if (pwPolicyState.shouldWarn()) {
        int numSeconds = pwPolicyState.getSecondsUntilExpiration();

        if (pwPolicyWarningType == null) {
          pwPolicyWarningType = PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION;
          pwPolicyWarningValue = numSeconds;
        }

        isFirstWarning = pwPolicyState.isFirstWarning();
      }

      // Check to see if the user's password has been reset.
      if (pwPolicyState.mustChangePassword()) {
        mustChangePassword = true;

        if (pwPolicyErrorType == null) {
          pwPolicyErrorType = PasswordPolicyErrorType.CHANGE_AFTER_RESET;
        }
      }
    }
  }