From f11baa48675eda7a3c4de818c57c50f116676c3f Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 26 Sep 2011 20:38:51 +0000
Subject: [PATCH] Fix OPENDJ-292: LDAP PTA NPE when base-dn or bind-dn not exist on secondary server
---
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java | 132 +++++++++++++++++++++++++++++++++++++++++--
opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java | 5 +
2 files changed, 128 insertions(+), 9 deletions(-)
diff --git a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
index 6968ca3..dc8d1e5 100644
--- a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
+++ b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
@@ -214,7 +214,8 @@
// The associated server is unavailable, so close the connection and
// try the next connection factory.
connection.close();
- factory.isAvailable = false;
+ factory.lastException = e;
+ factory.isAvailable = false; // publishes lastException
while (nextIndex != startIndex)
{
@@ -309,7 +310,7 @@
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
lastException = e;
- isAvailable = false; // publish lastException
+ isAvailable = false; // publishes lastException
throw e;
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
index fc2dcfe..871a605 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
@@ -3721,13 +3721,16 @@
/**
- * Test for issue OPENDJ-292 (https://bugster.forgerock.org/jira/browse/OPENDJ-292).
+ * Test for issue OPENDJ-292
+ * (https://bugster.forgerock.org/jira/browse/OPENDJ-292). This test checks
+ * that the last exception is correctly cached in the case where initial
+ * connection attempts fail.
*
* @throws Exception
* If an unexpected exception occurred.
*/
@Test(enabled = true)
- public void testIssueOPENDJ292() throws Exception
+ public void testIssueOPENDJ292_1() throws Exception
{
// Mock configuration.
final LDAPPassThroughAuthenticationPolicyCfg cfg = mockCfg()
@@ -3768,13 +3771,12 @@
// Authenticate twice, the second time was causing a NPE because none of the
// factories were available and an attempt was made to throw a null
// exception.
- final AuthenticationPolicyState state = policy
- .createAuthenticationPolicyState(userEntry);
- assertEquals(state.getAuthenticationPolicy(), policy);
-
- // Perform authentication.
for (int i = 0; i < 2; i++)
{
+ final AuthenticationPolicyState state = policy
+ .createAuthenticationPolicyState(userEntry);
+ assertEquals(state.getAuthenticationPolicy(), policy);
+
try
{
state.passwordMatches(ByteString.valueOf(userPassword));
@@ -3798,6 +3800,122 @@
/**
+ * Test for issue OPENDJ-292
+ * (https://bugster.forgerock.org/jira/browse/OPENDJ-292). This test checks
+ * that the last exception is correctly cached in the case where a usable
+ * connection fails during a search/bind.
+ *
+ * @throws Exception
+ * If an unexpected exception occurred.
+ */
+ @Test(enabled = true)
+ public void testIssueOPENDJ292_2() throws Exception
+ {
+ // Mock configuration.
+ final LDAPPassThroughAuthenticationPolicyCfg cfg = mockCfg()
+ .withPrimaryServer(phost1)
+ .withSecondaryServer(shost1)
+ .withMappingPolicy(MappingPolicy.MAPPED_SEARCH)
+ .withMappedAttribute("uid").withBaseDN("o=ad");
+
+ // Create all the events.
+ final MockProvider provider = new MockProvider();
+
+ // First of all the connection factories are created.
+ final GetLDAPConnectionFactoryEvent fe1 = new GetLDAPConnectionFactoryEvent(
+ phost1, cfg);
+ final GetLDAPConnectionFactoryEvent fe2 = new GetLDAPConnectionFactoryEvent(
+ shost1, cfg);
+ provider.expectEvent(fe1).expectEvent(fe2);
+
+ // Get connection for phost1, then search, then bind.
+ final GetConnectionEvent ceSearch1 = new GetConnectionEvent(fe1);
+ final GetConnectionEvent ceBind1 = new GetConnectionEvent(fe1);
+ final GetConnectionEvent ceSearch2 = new GetConnectionEvent(fe2);
+
+ provider
+ .expectEvent(ceSearch1)
+ .expectEvent(
+ new SimpleBindEvent(ceSearch1, searchBindDNString, "searchPassword"))
+ .expectEvent(
+ new SearchEvent(ceSearch1, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString))
+ .expectEvent(ceBind1)
+ .expectEvent(
+ new SimpleBindEvent(ceBind1, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Repeat and fail-over to shost1.
+ provider
+ .expectEvent(
+ new SearchEvent(ceSearch1, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", ResultCode.UNAVAILABLE))
+ .expectEvent(new CloseEvent(ceSearch1))
+ .expectEvent(ceSearch2)
+ .expectEvent(
+ new SimpleBindEvent(ceSearch2, searchBindDNString, "searchPassword"))
+ .expectEvent(
+ new SearchEvent(ceSearch2, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString))
+ .expectEvent(
+ new SimpleBindEvent(ceBind1, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Repeat, but fail on shost1 as well, leaving no available servers.
+ provider.expectEvent(
+ new SearchEvent(ceSearch2, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", ResultCode.UNAVAILABLE)).expectEvent(
+ new CloseEvent(ceSearch2));
+
+ // Obtain policy and state.
+ final LDAPPassThroughAuthenticationPolicyFactory factory = new LDAPPassThroughAuthenticationPolicyFactory(
+ provider);
+ assertTrue(factory.isConfigurationAcceptable(cfg, null));
+ final AuthenticationPolicy policy = factory.createAuthenticationPolicy(cfg);
+
+ // Authenticate four times, the fourth time was causing a NPE because none
+ // of the factories were available and an attempt was made to throw a null
+ // exception.
+ for (int i = 0; i < 4; i++)
+ {
+ final AuthenticationPolicyState state = policy
+ .createAuthenticationPolicyState(userEntry);
+ assertEquals(state.getAuthenticationPolicy(), policy);
+
+ // Perform authentication.
+ if (i < 2)
+ {
+ assertTrue(state.passwordMatches(ByteString.valueOf(userPassword)));
+ }
+ else
+ {
+ try
+ {
+ state.passwordMatches(ByteString.valueOf(userPassword));
+ fail("password match unexpectedly succeeded");
+ }
+ catch (final DirectoryException e)
+ {
+ // No mapping attributes so this should always fail with
+ // INVALID_CREDENTIALS.
+ assertEquals(e.getResultCode(), ResultCode.INVALID_CREDENTIALS,
+ e.getMessage());
+ }
+ }
+ state.finalizeStateAfterBind();
+ }
+
+ // Cached connections should be closed when the policy is finalized.
+ provider.expectEvent(new CloseEvent(ceBind1));
+
+ // Tear down and check final state.
+ policy.finalizeAuthenticationPolicy();
+ provider.assertAllExpectedEventsReceived();
+ }
+
+
+
+ /**
* Test for issue OPENDJ-294
* (https://bugster.forgerock.org/jira/browse/OPENDJ-294). Password
* configuration changes do not seem to be taking effect.
--
Gitblit v1.10.0