From 3235ccd26fe404f9871618246bf4bec58d908545 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 19 Sep 2011 15:34:26 +0000
Subject: [PATCH] Issue OPENDJ-262: Implement pass through authentication (PTA)
---
opendj-sdk/opends/src/messages/messages/extension.properties | 2
opendj-sdk/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java | 49 +++++++++++++++++-------
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java | 10 ++--
3 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/opendj-sdk/opends/src/messages/messages/extension.properties b/opendj-sdk/opends/src/messages/messages/extension.properties
index cbde8c7..edd2010 100644
--- a/opendj-sdk/opends/src/messages/messages/extension.properties
+++ b/opendj-sdk/opends/src/messages/messages/extension.properties
@@ -1482,7 +1482,7 @@
from the server and will be closed. The unexpected response message was: %s
MILD_ERR_LDAP_PTA_CONNECTION_DISCONNECTING_601=The connection to the remote LDAP \
server at %s:%d for LDAP PTA policy "%s" has received a disconnect notification \
- from the server and will be closed: %s
+ with response code %d (%s) and error message "%s"
MILD_ERR_LDAP_PTA_CONNECTION_BIND_FAILED_602=The remote LDAP server at %s:%d \
for LDAP PTA policy "%s" has failed to authenticate user "%s", returning the \
response code %d (%s) and error message "%s"
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
index 1b32e4c..02702cd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
@@ -202,7 +202,7 @@
{
// If the error does not indicate that the connection has failed, then
// pass this back to the caller.
- if (!isFatalResultCode(e.getResultCode()))
+ if (!isServiceError(e.getResultCode()))
{
throw e;
}
@@ -643,7 +643,7 @@
catch (final DirectoryException e)
{
// Don't put the connection back in the pool if it has failed.
- closeConnectionOnFatalError(e);
+ closeConnectionIfServiceError(e);
throw e;
}
}
@@ -664,16 +664,16 @@
catch (final DirectoryException e)
{
// Don't put the connection back in the pool if it has failed.
- closeConnectionOnFatalError(e);
+ closeConnectionIfServiceError(e);
throw e;
}
}
- private void closeConnectionOnFatalError(final DirectoryException e)
+ private void closeConnectionIfServiceError(final DirectoryException e)
{
- if (isFatalResultCode(e.getResultCode()))
+ if (isServiceError(e.getResultCode()))
{
if (!connectionIsClosed)
{
@@ -1097,10 +1097,28 @@
if ((responseOID != null)
&& responseOID.equals(OID_NOTICE_OF_DISCONNECTION))
{
- throw new DirectoryException(ResultCode.valueOf(extendedResponse
- .getResultCode()), ERR_LDAP_PTA_CONNECTION_DISCONNECTING.get(
- host, port, String.valueOf(cfg.dn()),
- extendedResponse.getErrorMessage()));
+ ResultCode resultCode = ResultCode.valueOf(extendedResponse
+ .getResultCode());
+
+ /*
+ * Since the connection has been disconnected we want to ensure that
+ * upper layers treat all disconnect notifications as fatal and
+ * close the connection. Therefore we map the result code to a fatal
+ * error code if needed. A good example of a non-fatal error code
+ * being returned is INVALID_CREDENTIALS which is used to indicate
+ * that the currently bound user has had their entry removed. We
+ * definitely don't want to pass this straight back to the caller
+ * since it will be misinterpreted as an authentication failure if
+ * the operation being performed is a bind.
+ */
+ ResultCode mappedResultCode = isServiceError(resultCode) ?
+ resultCode : ResultCode.UNAVAILABLE;
+
+ throw new DirectoryException(mappedResultCode,
+ ERR_LDAP_PTA_CONNECTION_DISCONNECTING.get(host, port,
+ String.valueOf(cfg.dn()), resultCode.getIntValue(),
+ resultCode.getResultCodeName(),
+ extendedResponse.getErrorMessage()));
}
}
@@ -2052,17 +2070,20 @@
* @return {@code true} if the result code is expected to trigger the
* associated connection to be closed immediately.
*/
- static boolean isFatalResultCode(final ResultCode resultCode)
+ static boolean isServiceError(final ResultCode resultCode)
{
switch (resultCode)
{
+ case OPERATIONS_ERROR:
+ case PROTOCOL_ERROR:
+ case TIME_LIMIT_EXCEEDED:
+ case ADMIN_LIMIT_EXCEEDED:
+ case UNAVAILABLE_CRITICAL_EXTENSION:
case BUSY:
case UNAVAILABLE:
- case PROTOCOL_ERROR:
- case OTHER:
case UNWILLING_TO_PERFORM:
- case OPERATIONS_ERROR:
- case TIME_LIMIT_EXCEEDED:
+ case LOOP_DETECT:
+ case OTHER:
case CLIENT_SIDE_CONNECT_ERROR:
case CLIENT_SIDE_DECODING_ERROR:
case CLIENT_SIDE_ENCODING_ERROR:
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
index 62d697a..e750ecb 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
@@ -28,7 +28,7 @@
-import static org.opends.server.extensions.LDAPPassThroughAuthenticationPolicyFactory.isFatalResultCode;
+import static org.opends.server.extensions.LDAPPassThroughAuthenticationPolicyFactory.isServiceError;
import static org.opends.server.protocols.ldap.LDAPConstants.OID_NOTICE_OF_DISCONNECTION;
import static org.testng.Assert.*;
@@ -1534,7 +1534,7 @@
.expectEvent(
new SearchEvent(ceSearch, "o=ad", SearchScope.WHOLE_SUBTREE,
"(uid=aduser)", searchResultCode));
- if (isFatalResultCode(searchResultCode))
+ if (isServiceError(searchResultCode))
{
// The connection will fail and be closed immediately.
provider.expectEvent(new CloseEvent(ceSearch));
@@ -1568,7 +1568,7 @@
state.finalizeStateAfterBind();
// Cached connections should be closed when the policy is finalized.
- if (!isFatalResultCode(searchResultCode))
+ if (!isServiceError(searchResultCode))
{
provider.expectEvent(new CloseEvent(ceSearch));
}
@@ -3234,7 +3234,7 @@
new SimpleBindEvent(ceBind,
mappingPolicy == MappingPolicy.UNMAPPED ? opendjDNString
: adDNString, userPassword, bindResultCode));
- if (isFatalResultCode(bindResultCode))
+ if (isServiceError(bindResultCode))
{
// The connection will fail and be closed immediately.
provider.expectEvent(new CloseEvent(ceBind));
@@ -3286,7 +3286,7 @@
{
provider.expectEvent(new CloseEvent(ceSearch));
}
- if (!isFatalResultCode(bindResultCode))
+ if (!isServiceError(bindResultCode))
{
provider.expectEvent(new CloseEvent(ceBind));
}
--
Gitblit v1.10.0