mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
12.39.2015 392bde20d260cc00dbdf5c80d512f57ebc760c4e
OPENDJ-2383 REST interface: Implement password modify action

Server-side implementation. See the equivalent change in the SDK.

LdapHttpApplication.java, CollectClientConnectionsFilter.java::
In LdapHttpApplication ctor, do not use the SecurityContextFactory (alas, this duplicates code :( ),
instead create the SecurityContext in CollectClientConnectionsFilter.doChain().

SdkConnectionAdapter.java:
In extendedRequestAsync(), set the authorization entry from the authentication info.

Converters.java:
In newSDKResult(), return a PasswordModifyExtendedResult for a PasswordModifyExtendedOperation.
4 files modified
69 ■■■■ changed files
opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Converters.java 41 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java 4 ●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java 17 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/SdkConnectionAdapter.java 7 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/forgerock/opendj/adapter/server3x/Converters.java
@@ -25,7 +25,11 @@
 */
package org.forgerock.opendj.adapter.server3x;
import static com.forgerock.opendj.ldap.CoreMessages.*;
import static com.forgerock.opendj.util.StaticUtils.*;
import static org.forgerock.opendj.ldap.LdapException.*;
import static org.opends.server.extensions.ExtensionsConstants.*;
import static org.opends.server.util.CollectionUtils.*;
import java.io.IOException;
@@ -51,6 +55,7 @@
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.controls.Control;
import org.forgerock.opendj.ldap.controls.GenericControl;
import org.forgerock.opendj.ldap.responses.PasswordModifyExtendedResult;
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
@@ -70,10 +75,9 @@
import org.opends.server.types.LDAPException;
import org.opends.server.types.Operation;
import org.opends.server.types.SearchFilter;
import org.opends.server.util.ServerConstants;
/**
 * Common utility methods.
 */
/** Common utility methods. */
public final class Converters {
    /** Prevent instantiation. */
@@ -691,18 +695,47 @@
        return getResponseResult(operation, newSDKResult(operation));
    }
    private static Result newSDKResult(final Operation operation) {
    private static Result newSDKResult(final Operation operation) throws LdapException {
        ResultCode rc = operation.getResultCode();
        if (operation instanceof BindOperation) {
            return Responses.newBindResult(rc);
        } else if (operation instanceof CompareOperation) {
            return Responses.newCompareResult(rc);
        } else if (operation instanceof ExtendedOperation) {
            ExtendedOperation extendedOperation = (ExtendedOperation) operation;
            switch (extendedOperation.getRequestOID()) {
            case ServerConstants.OID_PASSWORD_MODIFY_REQUEST:
                PasswordModifyExtendedResult result = Responses.newPasswordModifyExtendedResult(rc);
                ByteString generatedPwd = getGeneratedPassword(extendedOperation);
                if (generatedPwd != null) {
                    result.setGeneratedPassword(generatedPwd.toByteArray());
                }
                return result;
            default:
            return Responses.newGenericExtendedResult(rc);
        }
        }
        return Responses.newResult(rc);
    }
    private static ByteString getGeneratedPassword(ExtendedOperation op) throws LdapException {
        // FIXME this code is duplicated with code in the SDK
        // see PasswordModifyExtendedRequestImpl#ResultDecoder#decodeExtendedResult()
        ByteString responseValue = op.getResponseValue();
        if (responseValue != null) {
            try {
                ASN1Reader reader = ASN1.getReader(responseValue);
                reader.readStartSequence();
                return reader.readOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD);
            } catch (IOException e) {
                throw LdapException.newLdapException(ResultCode.PROTOCOL_ERROR,
                        ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST.get(getExceptionMessage(e)), e);
            }
        }
        return null;
    }
    /**
     * Converts from <code>byte[]</code> to OpenDJ server {@link ByteString}.
     *
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/CollectClientConnectionsFilter.java
@@ -55,6 +55,7 @@
import org.forgerock.opendj.rest2ldap.AuthenticatedConnectionContext;
import org.forgerock.opendj.rest2ldap.Rest2LDAP;
import org.forgerock.services.context.Context;
import org.forgerock.services.context.SecurityContext;
import org.forgerock.util.AsyncFunction;
import org.forgerock.util.promise.NeverThrowsException;
import org.forgerock.util.promise.Promise;
@@ -230,7 +231,8 @@
        clientConnection.setAuthUser(userName);
        try
        {
          return doFilter(context, request, next, connection);
          SecurityContext securityContext = new SecurityContext(context, userName, null);
          return doFilter(securityContext, request, next, connection);
        }
        catch (Exception e)
        {
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/LdapHttpApplication.java
@@ -43,9 +43,13 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.json.JsonValue;
import org.forgerock.json.resource.CollectionResourceProvider;
import org.forgerock.json.resource.ConnectionFactory;
import org.forgerock.json.resource.RequestHandler;
import org.forgerock.json.resource.ResourceException;
import org.forgerock.json.resource.Resources;
import org.forgerock.json.resource.Router;
import org.forgerock.json.resource.http.CrestHttp;
import org.forgerock.json.resource.http.HttpContextFactory;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.rest2ldap.AuthorizationPolicy;
import org.forgerock.opendj.rest2ldap.Rest2LDAP;
@@ -63,7 +67,6 @@
  /** Http Handler which sets a connection to an OpenDJ server. */
  private static class LdapHttpHandler implements Handler
  {
    private final Handler delegate;
    /**
@@ -75,7 +78,15 @@
     */
    public LdapHttpHandler(final JsonValue configuration)
    {
      delegate = CrestHttp.newHttpHandler(createRouter(configuration));
      ConnectionFactory connectionFactory = Resources.newInternalConnectionFactory(createRouter(configuration));
      delegate = CrestHttp.newHttpHandler(connectionFactory, new HttpContextFactory()
      {
        @Override
        public Context createContext(Context parentContext, Request request) throws ResourceException
        {
          return parentContext;
        }
      });
    }
    private RequestHandler createRouter(final JsonValue configuration)
@@ -93,12 +104,12 @@
      }
      return router;
    }
    @Override
    public final Promise<Response, NeverThrowsException> handle(final Context context, final Request request)
    {
      return delegate.handle(context, request);
    }
  }
  private HTTPConnectionHandler connectionHandler;
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/SdkConnectionAdapter.java
@@ -323,9 +323,10 @@
      IntermediateResponseHandler intermediateResponseHandler)
  {
    final int messageID = nextMessageID.getAndIncrement();
    return enqueueOperation(new ExtendedOperationBasis(this.clientConnection, messageID, messageID,
        to(request.getControls()), request.getOID(),
        request.getValue()));
    ExtendedOperation op = new ExtendedOperationBasis(
        clientConnection, messageID, messageID, to(request.getControls()), request.getOID(), request.getValue());
    op.setAuthorizationEntry(clientConnection.getAuthenticationInfo().getAuthorizationEntry());
    return enqueueOperation(op);
  }
  /**