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

Jean-Noel Rouvignac
23.08.2013 2638f9432aed1829c9a7d4b7882d69f74b018b28
OPENDJ-830 (CR-1595) Implement authentication and authorization for HTTP connection handler


Fixed information leak on unsuccessful authentication: if the username was incorrect, the server was returning 404 (not found) instead of 401 (invalid credentials).
When authentication was unsuccessful, the client was not receiving a response and the connection was not closed leaving it hanging.


CollectClientConnectionFilter.java:
In DoBindResultHandler.handleErrorResult(), send back an authentication failure when a search on the user name does not return a unique result.
In sendAuthenticationFailure(), correctly complete the AsyncContext.
In doFilter(), removed the call to AsyncContext.setTimeout().
1 files modified
42 ■■■■ changed files
opends/src/server/org/opends/server/protocols/http/CollectClientConnectionsFilter.java 42 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/http/CollectClientConnectionsFilter.java
@@ -55,6 +55,7 @@
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.ResultHandler;
import org.forgerock.opendj.ldap.requests.BindRequest;
import org.forgerock.opendj.ldap.requests.Requests;
@@ -156,7 +157,16 @@
    @Override
    public void handleErrorResult(ErrorResultException error)
    {
      onFailure(error, ctx);
      final ResultCode rc = error.getResult().getResultCode();
      if (ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED.equals(rc)
          || ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED.equals(rc))
      {
        sendAuthenticationFailure(ctx);
      }
      else
      {
        onFailure(error, ctx);
      }
    }
    @Override
@@ -255,9 +265,7 @@
        final String userName = userPassword[0];
        ctx.password = userPassword[1];
        final AsyncContext asyncContext = getAsyncContext(request);
        asyncContext.setTimeout(60 * 1000);
        ctx.asyncContext = asyncContext;
        ctx.asyncContext = getAsyncContext(request);
        ctx.connection.searchSingleEntryAsync(buildSearchRequest(userName),
            new DoBindResultHandler(ctx));
@@ -298,15 +306,25 @@
  private void sendAuthenticationFailure(HTTPRequestContext ctx)
  {
    // The user could not be authenticated. Send an HTTP Basic authentication
    // challenge if HTTP Basic authentication is enabled.
    ResourceException unauthorizedException =
        ResourceException.getException(HttpServletResponse.SC_UNAUTHORIZED,
            "Invalid Credentials");
    sendErrorReponse(ctx.response, ctx.prettyPrint, unauthorizedException);
    try
    {
      // The user could not be authenticated. Send an HTTP Basic authentication
      // challenge if HTTP Basic authentication is enabled.
      ResourceException unauthorizedException =
          ResourceException.getException(HttpServletResponse.SC_UNAUTHORIZED,
              "Invalid Credentials");
      sendErrorReponse(ctx.response, ctx.prettyPrint, unauthorizedException);
    ctx.clientConnection.disconnect(DisconnectReason.INVALID_CREDENTIALS,
        false, null);
      ctx.clientConnection.disconnect(DisconnectReason.INVALID_CREDENTIALS,
          false, null);
    }
    finally
    {
      if (ctx.asyncContext != null)
      {
        ctx.asyncContext.complete();
      }
    }
  }
  private void onFailure(Exception e, HTTPRequestContext ctx)