From c3fd5d709ffdbb6d5a1609388b7bcaacda00c8b9 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 21 Mar 2013 12:04:24 +0000
Subject: [PATCH] Partial fix for OPENDJ-694: Implement HTTP BASIC authentication

---
 opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPContextFactory.java |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 178 insertions(+), 0 deletions(-)

diff --git a/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPContextFactory.java b/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPContextFactory.java
new file mode 100644
index 0000000..be39d23
--- /dev/null
+++ b/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPContextFactory.java
@@ -0,0 +1,178 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2012 ForgeRock AS.
+ */
+package org.forgerock.opendj.rest2ldap.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.forgerock.json.resource.Context;
+import org.forgerock.json.resource.InternalServerErrorException;
+import org.forgerock.json.resource.ResourceException;
+import org.forgerock.json.resource.RootContext;
+import org.forgerock.json.resource.SecurityContext;
+import org.forgerock.json.resource.servlet.HttpServletContextFactory;
+import org.forgerock.json.resource.servlet.SecurityContextFactory;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.rest2ldap.AuthenticatedConnectionContext;
+
+/**
+ * An HTTP servlet context factory which will create a {@link Context} chain
+ * comprising of a {@linkn SecurityContext} and optionally an
+ * {@link AuthenticatedConnectionContext}.
+ * <p>
+ * This class provides integration between Rest2LDAP HTTP Servlets and the
+ * {@link Rest2LDAPAuthnFilter}, by providing a mechanism allowing the filter to
+ * pass a pre-authenticated LDAP connection through to the underlying Rest2LDAP
+ * implementation for use when performing subsequent LDAP operations. The
+ * following code illustrates how an authentication Servlet filter can populate
+ * the attributes:
+ *
+ * <pre>
+ * public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
+ *     // Authenticate the user.
+ *     String username = getUserName(request);
+ *     String password = getPassword(request);
+ *     final Connection connection = getLDAPConnection();
+ *
+ *     // Publish the authenticated connection.
+ *     try {
+ *         connection.bind(username, password.toCharArray());
+ *         request.setAttribute(ATTRIBUTE_AUTHN_CONNECTION, connection);
+ *     } catch (ErrorResultException e) {
+ *         // Fail the HTTP request.
+ *         response.setStatus(...);
+ *         return;
+ *     }
+ *
+ *     // Invoke the rest of the filter chain and then release the LDAP connection once
+ *     // processing has completed. Note that this assumes that the filter chain is
+ *     // processes requests synchronous.
+ *     try {
+ *         chain.doFilter(request, response);
+ *     } finally {
+ *         connection.close();
+ *     }
+ * }
+ * </pre>
+ */
+public final class Rest2LDAPContextFactory implements HttpServletContextFactory {
+
+    /**
+     * The name of the HTTP Servlet Request attribute where this factory expects
+     * to find the authenticated user's authentication ID. The name of this
+     * attribute is {@code org.forgerock.security.authcid} and it MUST contain a
+     * {@code String} if it is present.
+     *
+     * @see AuthenticatedConnectionContext
+     */
+    public static final String ATTRIBUTE_AUTHN_CONNECTION =
+            "org.forgerock.opendj.rest2ldap.authn-connection";
+
+    // Singleton instance.
+    private static final Rest2LDAPContextFactory INSTANCE = new Rest2LDAPContextFactory();
+
+    /**
+     * Returns the singleton context factory which can be used for obtaining
+     * context information from a HTTP servlet request.
+     * <p>
+     * This method is named {@code getHttpServletContextFactory} so that it can
+     * easily be used for
+     * {@link org.forgerock.json.resource.servlet.HttpServlet#getHttpServletContextFactory
+     * configuring} JSON Resource Servlets.
+     *
+     * @return The singleton context factory.
+     */
+    public static Rest2LDAPContextFactory getHttpServletContextFactory() {
+        return INSTANCE;
+    }
+
+    private Rest2LDAPContextFactory() {
+        // Prevent instantiation.
+    }
+
+    /**
+     * Creates a new {@link Context} chain comprising of the provided parent
+     * context(s), a {@link SecurityContext} obtained using a
+     * {@link SecurityContextFactory} , and optionally a
+     * {@code AuthenticatedConnectionContext}. The authenticated connection will
+     * be obtained from the {@link #ATTRIBUTE_AUTHN_CONNECTION} attribute
+     * contained in the provided HTTP servlet request. If the attribute is not
+     * present then the {@code AuthenticatedConnectionContext} will not be
+     * created.
+     *
+     * @param parent
+     *            The parent context.
+     * @param request
+     *            The HTTP servlet request from which the security and
+     *            authenticated connection attributes should be obtained.
+     * @return A new {@link Context} chain comprising of the provided parent
+     *         context(s), a {@link SecurityContext} obtained using a
+     *         {@link SecurityContextFactory} , and optionally a
+     *         {@code AuthenticatedConnectionContext}.
+     * @throws ResourceException
+     *             If one of the attributes was present but had the wrong type.
+     */
+    public Context createContext(final Context parent, final HttpServletRequest request)
+            throws ResourceException {
+        // First get the security context.
+        final Context securityContext =
+                SecurityContextFactory.getHttpServletContextFactory()
+                        .createContext(parent, request);
+
+        // Now append the pre-authenticated connection context if required.
+        final Connection connection;
+        try {
+            connection = (Connection) request.getAttribute(ATTRIBUTE_AUTHN_CONNECTION);
+        } catch (final ClassCastException e) {
+            throw new InternalServerErrorException(
+                    "The rest2ldap authenticated connection context could not be "
+                            + "created because the connection attribute, "
+                            + ATTRIBUTE_AUTHN_CONNECTION + ", contained in the HTTP "
+                            + "servlet request did not have the correct type", e);
+        }
+        if (connection != null) {
+            return new AuthenticatedConnectionContext(securityContext, connection);
+        } else {
+            return securityContext;
+        }
+    }
+
+    /**
+     * Creates a new {@link Context} chain comprising of a {@link RootContext},
+     * a {@link SecurityContext} obtained using a {@link SecurityContextFactory}
+     * , and optionally a {@code AuthenticatedConnectionContext}. The
+     * authenticated connection will be obtained from the
+     * {@link #ATTRIBUTE_AUTHN_CONNECTION} attribute contained in the provided
+     * HTTP servlet request. If the attribute is not present then the
+     * {@code AuthenticatedConnectionContext} will not be created.
+     *
+     * @param request
+     *            The HTTP servlet request from which the security and
+     *            authenticated connection attributes should be obtained.
+     * @return A new {@link Context} chain comprising of a {@link RootContext},
+     *         a {@link SecurityContext} obtained using a
+     *         {@link SecurityContextFactory} , and optionally a
+     *         {@code AuthenticatedConnectionContext}.
+     * @throws ResourceException
+     *             If one of the attributes was present but had the wrong type.
+     */
+    @Override
+    public Context createContext(final HttpServletRequest request) throws ResourceException {
+        final Context securityContext =
+                SecurityContextFactory.getHttpServletContextFactory().createContext(request);
+        return createContext(securityContext, request);
+    }
+
+}

--
Gitblit v1.10.0