From ff0653af9a57afaf256008ce4d39e7d6fc899446 Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Mon, 31 Oct 2016 14:00:38 +0000
Subject: [PATCH] OPENDJ-2937 Fix SDK SASL bind requests implementations
---
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java | 20 ------
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java | 19 -----
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java | 18 -----
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java | 8 --
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java | 46 +++++++++++++++
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties | 3
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java | 20 ------
opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java | 10 ++-
8 files changed, 63 insertions(+), 81 deletions(-)
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java
index 568c795..ef56753 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
@@ -20,7 +20,6 @@
import static com.forgerock.opendj.util.StaticUtils.copyOfBytes;
import static org.forgerock.opendj.ldap.LdapException.newLdapException;
-import static org.forgerock.opendj.ldap.responses.Responses.*;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
@@ -79,21 +78,7 @@
@Override
public boolean evaluateResult(final BindResult result) throws LdapException {
- if (saslClient.isComplete()) {
- return true;
- }
-
- try {
- setNextSASLCredentials(saslClient.evaluateChallenge(result
- .getServerSASLCredentials() == null ? new byte[0] : result
- .getServerSASLCredentials().toByteArray()));
- return saslClient.isComplete();
- } catch (final SaslException e) {
- // FIXME: I18N need to have a better error message.
- // FIXME: Is this the best result code?
- throw newLdapException(newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
- "An error occurred during multi-stage authentication").setCause(e));
- }
+ return evaluateSaslBindResult(saslClient, result);
}
@Override
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java
index 5ad1118..2261c0a 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
@@ -138,21 +138,7 @@
@Override
public boolean evaluateResult(final BindResult result) throws LdapException {
- if (saslClient.isComplete()) {
- return true;
- }
-
- try {
- setNextSASLCredentials(saslClient.evaluateChallenge(result
- .getServerSASLCredentials() == null ? new byte[0] : result
- .getServerSASLCredentials().toByteArray()));
- return saslClient.isComplete();
- } catch (final SaslException e) {
- // FIXME: I18N need to have a better error message.
- // FIXME: Is this the best result code?
- throw newLdapException(ResultCode.CLIENT_SIDE_LOCAL_ERROR,
- "An error occurred during multi-stage authentication", e);
- }
+ return evaluateSaslBindResult(saslClient, result);
}
@Override
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java
index af07105..20d29fc 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
@@ -27,7 +27,6 @@
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.responses.BindResult;
-import org.forgerock.opendj.ldap.responses.Responses;
/**
* External SASL bind request implementation.
@@ -67,22 +66,7 @@
@Override
public boolean evaluateResult(final BindResult result) throws LdapException {
- if (saslClient.isComplete()) {
- return true;
- }
-
- try {
- setNextSASLCredentials(saslClient.evaluateChallenge(result
- .getServerSASLCredentials() == null ? new byte[0] : result
- .getServerSASLCredentials().toByteArray()));
- return saslClient.isComplete();
- } catch (final SaslException e) {
- // FIXME: I18N need to have a better error message.
- // FIXME: Is this the best result code?
- throw newLdapException(Responses.newResult(
- ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
- "An error occurred during multi-stage authentication").setCause(e));
- }
+ return evaluateSaslBindResult(saslClient, result);
}
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java
index 0b5e057..1e39ed2 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
@@ -115,23 +115,7 @@
new PrivilegedExceptionAction<Boolean>() {
@Override
public Boolean run() throws LdapException {
- if (saslClient.isComplete()) {
- return true;
- }
-
- try {
- setNextSASLCredentials(saslClient.evaluateChallenge(lastResult
- .getServerSASLCredentials() == null ? new byte[0] : lastResult
- .getServerSASLCredentials().toByteArray()));
- return saslClient.isComplete();
- } catch (final SaslException e) {
- // FIXME: I18N need to have a better error message.
- // FIXME: Is this the best result code?
- throw newLdapException(Responses.newResult(
- ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
- "An error occurred during multi-stage authentication")
- .setCause(e));
- }
+ return evaluateSaslBindResult(saslClient, lastResult);
}
};
private BindResult lastResult;
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java
index 2c8bcb2..fa374d3 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
@@ -29,7 +29,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.responses.BindResult;
import org.forgerock.util.Reject;
import com.forgerock.opendj.util.StaticUtils;
@@ -77,11 +76,6 @@
}
@Override
- public boolean evaluateResult(final BindResult result) {
- return saslClient.isComplete();
- }
-
- @Override
void handle(final NameCallback callback) throws UnsupportedCallbackException {
callback.setName(authenticationID);
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java
index a82efcf..6987eb9 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java
@@ -12,12 +12,14 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2009 Sun Microsystems, Inc.
- * Portions copyright 2011-2013 ForgeRock AS.
+ * Portions copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap.requests;
+import static com.forgerock.opendj.ldap.CoreMessages.ERR_SASL_BIND_MULTI_STAGE;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_SASL_UNSUPPORTED_CALLBACK;
+import static org.forgerock.opendj.ldap.LdapException.newLdapException;
import java.io.IOException;
@@ -34,11 +36,16 @@
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
import javax.security.sasl.RealmChoiceCallback;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
import org.forgerock.opendj.io.ASN1;
import org.forgerock.opendj.io.ASN1Writer;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteStringBuilder;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.responses.BindResult;
/**
* SASL bind client implementation.
@@ -191,4 +198,41 @@
return setNextAuthenticationValue(builder.toByteString().toByteArray());
}
+
+
+ /**
+ * Evaluates the {@link BindResult} returned by the server and returns {@code true} iff the server
+ * has sent a challenge and the client needs to send additional data.
+ * <p>
+ * If the server has sent a challenge, this method evaluates it and prepare data to send in the next request.
+ *
+ * @param saslClient
+ * The {@link SaslClient} to use to evaluate the challenge.
+ * @param result
+ * The last {@link BindResult} returned by the server.
+ * @return {@code true} iff the server has sent a challenge and the client needs to send additional data.
+ * @throws LdapException
+ * If an error occurred when the {@link SaslClient} evaluates the challenge.
+ */
+ boolean evaluateSaslBindResult(final SaslClient saslClient, final BindResult result) throws LdapException {
+ if (saslClient.isComplete()) {
+ return true;
+ }
+
+ try {
+ final ByteString serverSASLCredentials = result.getServerSASLCredentials();
+ final byte[] nextResponse = saslClient.evaluateChallenge(
+ serverSASLCredentials == null ? new byte[0]
+ : serverSASLCredentials.toByteArray());
+ if (nextResponse == null) {
+ return true;
+ }
+ setNextSASLCredentials(nextResponse);
+ return false;
+ } catch (final SaslException e) {
+ throw newLdapException(ResultCode.CLIENT_SIDE_LOCAL_ERROR,
+ ERR_SASL_BIND_MULTI_STAGE.get(e.getLocalizedMessage()),
+ e);
+ }
+ }
}
diff --git a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index 92c89d6..d3d8375 100644
--- a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1723,4 +1723,5 @@
element as a connection affinity control because it did not have a value, when \
a value must always be provided
ERR_UNKNOWN_REQUEST_TYPE=The following request has a unknown request type: %s
-WARN_DECODING_AFFINITY_CONTROL=An error occurred while decoding an affinity control: %s
\ No newline at end of file
+WARN_DECODING_AFFINITY_CONTROL=An error occurred while decoding an affinity control: %s
+ERR_SASL_BIND_MULTI_STAGE=An error occurred during multi-stage authentication: '%s'
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
index 25abde3..be59f39 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
@@ -12,7 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
*/
package org.forgerock.opendj.ldap;
@@ -255,8 +255,12 @@
byte[] challenge = saslServer.evaluateResponse(saslCred.toByteArray());
if (saslServer.isComplete()) {
- resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS)
- .setServerSASLCredentials(ByteString.wrap(challenge)));
+ final BindResult result = Responses.newBindResult(ResultCode.SUCCESS);
+ if (challenge != null) {
+ // If there was a SASL bind in progress, challenge has already been provided
+ result.setServerSASLCredentials(ByteString.wrap(challenge));
+ }
+ resultHandler.handleResult(result);
String qop = (String) saslServer.getNegotiatedProperty(Sasl.QOP);
if ("auth-int".equalsIgnoreCase(qop) || "auth-conf".equalsIgnoreCase(qop)) {
--
Gitblit v1.10.0