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 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 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); } } 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; 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); } 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); } } } opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1724,3 +1724,4 @@ 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 ERR_SASL_BIND_MULTI_STAGE=An error occurred during multi-stage authentication: '%s' 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)) {