You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2014/02/10 23:57:49 UTC
svn commit: r1566804 - in /jackrabbit/oak/trunk: ./ oak-auth-ldap/
oak-auth-ldap/src/ oak-auth-ldap/src/main/ oak-auth-ldap/src/main/java/
oak-auth-ldap/src/main/java/org/ oak-auth-ldap/src/main/java/org/apache/
oak-auth-ldap/src/main/java/org/apache/j...
Author: tripod
Date: Mon Feb 10 22:57:48 2014
New Revision: 1566804
URL: http://svn.apache.org/r1566804
Log:
OAK-516 Create LdapLoginModule based on ExternalLoginModule
- create new bundle for auth-ldap
Added:
jackrabbit/oak/trunk/oak-auth-ldap/
jackrabbit/oak/trunk/oak-auth-ldap/README.md
jackrabbit/oak/trunk/oak-auth-ldap/pom.xml
jackrabbit/oak/trunk/oak-auth-ldap/src/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapGroup.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapSettings.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapUser.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapGroup.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapIdentity.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapIdentityProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginModule.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapProviderConfig.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapSettings.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapUser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModule.java
Modified:
jackrabbit/oak/trunk/oak-core/pom.xml
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java
jackrabbit/oak/trunk/pom.xml
Added: jackrabbit/oak/trunk/oak-auth-ldap/README.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/README.md?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/README.md (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/README.md Mon Feb 10 22:57:48 2014
@@ -0,0 +1,2 @@
+Oak LDAP Authentication Support
+===============================
Added: jackrabbit/oak/trunk/oak-auth-ldap/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/pom.xml?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/pom.xml (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/pom.xml Mon Feb 10 22:57:48 2014
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-parent</artifactId>
+ <version>0.16-SNAPSHOT</version>
+ <relativePath>../oak-parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>oak-auth-ldap</artifactId>
+ <name>Oak LDAP Authentication Support</name>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ !antlr.*,
+ !org.dom4j.*,
+ !org.apache.mina.*,
+ !org.xmlpull.v1,
+ *
+ </Import-Package>
+ <Embed-Dependency>
+ api-all,commons-pool,commons-lang
+ </Embed-Dependency>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes/>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <dependencies>
+ <!-- embedded apache directory client and dependencies-->
+ <dependency>
+ <groupId>org.apache.directory.api</groupId>
+ <artifactId>api-all</artifactId>
+ <version>1.0.0-M20</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-pool</groupId>
+ <artifactId>commons-pool</artifactId>
+ <version>1.6</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Optional OSGi dependencies, used only when running within OSGi -->
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.jaas</artifactId>
+ <version>0.0.1-R1560269</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bndlib</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-commons</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.5</version>
+ </dependency>
+
+ <!-- JCR and Jackrabbit dependencies -->
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-api</artifactId>
+ <version>${jackrabbit.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-jcr-commons</artifactId>
+ <version>${jackrabbit.version}</version>
+ </dependency>
+
+ <!-- Logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <!-- Findbugs annotations -->
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>2.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>1.3.158</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jul-to-slf4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-server-unit</artifactId>
+ <version>1.5.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapGroup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapGroup.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapGroup.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapGroup.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+
+public class LdapGroup extends LdapIdentity implements ExternalGroup {
+
+ public LdapGroup(LdapIdentityProvider provider, ExternalIdentityRef ref, String id) {
+ super(provider, ref, id);
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+
+/**
+ * Implements an identity that is provided by the {@link LdapIdentityProvider}.
+ */
+public abstract class LdapIdentity implements ExternalIdentity {
+
+ private final LdapIdentityProvider provider;
+
+ private final ExternalIdentityRef ref;
+
+ private final String id;
+
+ private final Map<String, Object> properties = new HashMap<String, Object>();
+
+ protected LdapIdentity(LdapIdentityProvider provider, ExternalIdentityRef ref, String id) {
+ this.provider = provider;
+ this.ref = ref;
+ this.id = id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public ExternalIdentityRef getExternalId() {
+ return ref;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getIntermediatePath() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public Iterable<? extends ExternalGroup> getGroups() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ private Principal principal;
+ @Override
+ public Principal getPrincipal() {
+ if (principal == null) {
+ principal = new PrincipalImpl(getId());
+ }
+ return principal;
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,273 @@
+/*************************************************************************
+ *
+ * ADOBE CONFIDENTIAL
+ * ___________________
+ *
+ * Copyright ${today.year} Adobe Systems Incorporated
+ * All Rights Reserved.
+ *
+ * NOTICE: All information contained herein is, and remains
+ * the property of Adobe Systems Incorporated and its suppliers,
+ * if any. The intellectual and technical concepts contained
+ * herein are proprietary to Adobe Systems Incorporated and its
+ * suppliers and are protected by trade secret or copyright law.
+ * Dissemination of this information or reproduction of this material
+ * is strictly forbidden unless prior written permission is obtained
+ * from Adobe Systems Incorporated.
+ **************************************************************************/
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Credentials;
+import javax.security.auth.login.LoginException;
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.message.Response;
+import org.apache.directory.api.ldap.model.message.SearchRequest;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code LdapIdentityProvider} implements an external identity provider that reads users and groups from an ldap
+ * source.
+ *
+ * Please refer to {@link LdapProviderConfig} for configuration options.
+ */
+@Component(
+ // note that the metatype information is generated from LdapProviderConfig
+ policy = ConfigurationPolicy.REQUIRE
+)
+@Service
+public class LdapIdentityProvider implements ExternalIdentityProvider {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(LdapIdentityProvider.class);
+
+ /**
+ * internal configuration
+ */
+ private LdapProviderConfig config;
+
+ /**
+ * Default constructor for OSGi
+ */
+ public LdapIdentityProvider() {
+ }
+
+ /**
+ * Constructor for non-OSGi cases.
+ * @param config the configuration
+ */
+ public LdapIdentityProvider(LdapProviderConfig config) {
+ this.config = config;
+ }
+
+ @Activate
+ private void activate(Map<String, Object> properties) {
+ ConfigurationParameters cfg = ConfigurationParameters.of(properties);
+ config = LdapProviderConfig.of(cfg);
+ log.error("***** activate {}: {}", this, properties);
+ }
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return config.getName();
+ }
+
+ @Override
+ public ExternalIdentity getIdentity(@Nonnull ExternalIdentityRef ref) throws ExternalIdentityException {
+ if (!isMyRef(ref)) {
+ return null;
+ }
+
+ LdapConnection connection = connect();
+ try {
+ Entry entry = connection.lookup(ref.getId(), "*");
+ if (entry.hasObjectClass(config.getUserConfig().getObjectClasses())) {
+ return createUser(entry, null);
+ } else if (entry.hasObjectClass(config.getGroupConfig().getObjectClasses())) {
+ return createGroup(entry, null);
+ } else {
+ log.warn("referenced identity is neither user or group: {}", ref.getString());
+ return null;
+ }
+ } catch (LdapException e) {
+ log.error("Error during ldap lookup", e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } finally {
+ disconnect(connection);
+ }
+ }
+
+ @Override
+ public ExternalUser getUser(@Nonnull String userId) throws ExternalIdentityException {
+ LdapConnection connection = connect();
+ try {
+ Entry entry = getEntry(connection, config.getUserConfig(), userId);
+ if (entry != null) {
+ return createUser(entry, userId);
+ } else {
+ return null;
+ }
+ } catch (LdapException e) {
+ log.error("Error during ldap lookup", e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } catch (CursorException e) {
+ log.error("Error during ldap lookup", e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } finally {
+ disconnect(connection);
+ }
+ }
+
+ @Override
+ public ExternalGroup getGroup(@Nonnull String name) throws ExternalIdentityException {
+ LdapConnection connection = connect();
+ try {
+ Entry entry = getEntry(connection, config.getGroupConfig(), name);
+ if (entry != null) {
+ return createGroup(entry, name);
+ } else {
+ return null;
+ }
+ } catch (LdapException e) {
+ log.error("Error during ldap lookup", e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } catch (CursorException e) {
+ log.error("Error during ldap lookup", e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } finally {
+ disconnect(connection);
+ }
+ }
+
+ private Entry getEntry(LdapConnection connection, LdapProviderConfig.Identity idConfig, String id)
+ throws CursorException, LdapException {
+ String searchFilter = idConfig.getSearchFilter(id);
+
+ // Create the SearchRequest object
+ SearchRequest req = new SearchRequestImpl();
+ req.setScope(SearchScope.SUBTREE);
+ req.addAttributes("*");
+ req.setTimeLimit(config.getSearchTimeout());
+ req.setBase(idConfig.getBaseDN());
+ req.setFilter(searchFilter);
+
+ log.debug("Searching entries below {} with {}", idConfig.getBaseDN(), searchFilter);
+
+ // Process the request
+ SearchCursor searchCursor = connection.search(req);
+ while (searchCursor.next()) {
+ Response response = searchCursor.get();
+
+ // process the SearchResultEntry
+ if (response instanceof SearchResultEntry) {
+ Entry resultEntry = ((SearchResultEntry) response).getEntry();
+ if (searchCursor.next()) {
+ log.warn("search for {} returned more than one entry. discarding additional ones.", searchFilter);
+ }
+ return resultEntry;
+ }
+ }
+ return null;
+ }
+
+ private ExternalUser createUser(Entry e, String id)
+ throws LdapInvalidAttributeValueException {
+ ExternalIdentityRef ref = new ExternalIdentityRef(e.getDn().getName(), this.getName());
+ if (id == null) {
+ id = e.get(config.getUserConfig().getIdAttribute()).getString();
+ }
+ LdapUser user = new LdapUser(this, ref, id, null);
+ Map<String, Object> props = user.getProperties();
+ for (Attribute attr: e.getAttributes()) {
+ if (attr.isHumanReadable()) {
+ props.put(attr.getId(), attr.getString());
+ }
+ }
+ return user;
+ }
+
+ private ExternalGroup createGroup(Entry e, String name)
+ throws LdapInvalidAttributeValueException {
+ ExternalIdentityRef ref = new ExternalIdentityRef(e.getDn().getName(), this.getName());
+ if (name == null) {
+ name = e.get(config.getGroupConfig().getIdAttribute()).getString();
+ }
+ LdapGroup group = new LdapGroup(this, ref, name);
+ Map<String, Object> props = group.getProperties();
+ for (Attribute attr: e.getAttributes()) {
+ if (attr.isHumanReadable()) {
+ props.put(attr.getId(), attr.getString());
+ }
+ }
+ return group;
+
+ }
+
+ private LdapConnection connect() throws ExternalIdentityException {
+ try {
+ LdapConnection connection = new LdapNetworkConnection(config.getHost(), config.getPort(), config.isUseSSL());
+ if (config.getBindDN().length() > 0) {
+ connection.bind(config.getBindDN(), config.getBindPassword());
+ } else {
+ connection.bind();
+ }
+ return connection;
+ } catch (LdapException e) {
+ log.error("Error while connecting to the ldap server.", e);
+ throw new ExternalIdentityException("Error while connecting and binding to the ldap server", e);
+ }
+ }
+
+ private void disconnect(LdapConnection connection) throws ExternalIdentityException {
+ try {
+ connection.unBind();
+ } catch (LdapException e) {
+ log.error("Error while unbinding from the ldap server.", e);
+ }
+ try {
+ connection.close();
+ } catch (IOException e) {
+ log.error("Error while disconnecting from the ldap server.", e);
+ }
+ }
+
+ @Override
+ public ExternalUser authenticate(@Nonnull Credentials credentials) throws ExternalIdentityException, LoginException {
+ return null;
+ }
+
+ private boolean isMyRef(ExternalIdentityRef ref) {
+ final String refProviderName = ref.getProviderName();
+ return refProviderName == null || refProviderName.length() == 0 || getName().equals(refProviderName);
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.api.ldap.model.filter.FilterEncoder;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+
+/**
+ * Configuration of the ldap provider.
+ */
+@Component(
+ label = "Apache Jackrabbit Oak LDAP Identity Provider",
+ name = "org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider",
+ configurationFactory = true,
+ metatype = true,
+ ds = false
+)
+public class LdapProviderConfig {
+
+ public static final String PARAM_NAME_DEFAULT = "ldap";
+ @Property(
+ label = "LDAP Provider Name",
+ description = "Name of this LDAP provider configuration. This is used to reference this provider by the login modules.",
+ value = PARAM_NAME_DEFAULT
+ )
+ public static final String PARAM_NAME = "provider.name";
+
+ public static final String PARAM_LDAP_HOST_DEFAULT = "localhost";
+ @Property(
+ label = "LDAP Server Hostname",
+ description = "Hostname of the LDAP server",
+ value = PARAM_LDAP_HOST_DEFAULT
+ )
+ public static final String PARAM_LDAP_HOST = "host.name";
+
+ public static final int PARAM_LDAP_PORT_DEFAULT = 389;
+ @Property(
+ label = "LDAP Server Port",
+ description = "Port of the LDAP server",
+ intValue = PARAM_LDAP_PORT_DEFAULT
+ )
+ public static final String PARAM_LDAP_PORT = "host.port";
+
+ public static final boolean PARAM_USE_SSL_DEFAULT = false;
+ @Property(
+ label = "Use SSL",
+ description = "Indicates if an SSL connection should be used.",
+ boolValue = PARAM_USE_SSL_DEFAULT
+ )
+ public static final String PARAM_USE_SSL = "host.ssl";
+
+ public static final String PARAM_BIND_DN_DEFAULT = "";
+ @Property(
+ label = "Bind DN",
+ description = "DN of the user for authentication. Leave empty for anonymous bind.",
+ value = PARAM_BIND_DN_DEFAULT
+ )
+ public static final String PARAM_BIND_DN = "bind.dn";
+
+ public static final String PARAM_BIND_PASSWORD_DEFAULT = "";
+ @Property(
+ label = "Bind Password",
+ description = "Password of the user for authentication.",
+ passwordValue = PARAM_BIND_PASSWORD_DEFAULT
+ )
+ public static final String PARAM_BIND_PASSWORD = "bind.password";
+
+ public static final int PARAM_SEARCH_TIMEOUT_DEFAULT = 60000;
+ @Property(
+ label = "Search Timeout",
+ description = "Time in milliseconds until a search times out.",
+ intValue = PARAM_SEARCH_TIMEOUT_DEFAULT
+ )
+ public static final String PARAM_SEARCH_TIMEOUT = "search.timeout";
+
+ /**
+ * Defines the configuration of an identity.
+ */
+ public static class Identity {
+
+ private Dn baseDN;
+
+ private String[] objectClasses;
+
+ private String idAttribute;
+
+ private String extraFilter;
+
+ private String filterTemplate;
+
+ public Dn getBaseDN() {
+ return baseDN;
+ }
+
+ public void setBaseDN(String baseDN) throws LdapInvalidDnException {
+ this.baseDN = new Dn(baseDN);
+ }
+
+ public String[] getObjectClasses() {
+ return objectClasses;
+ }
+
+ public void setObjectClasses(String[] objectClasses) {
+ this.objectClasses = objectClasses;
+ filterTemplate = null;
+ }
+
+ public String getIdAttribute() {
+ return idAttribute;
+ }
+
+ public void setIdAttribute(String idAttribute) {
+ this.idAttribute = idAttribute;
+ filterTemplate = null;
+ }
+
+ public String getExtraFilter() {
+ return extraFilter;
+ }
+
+ public void setExtraFilter(String extraFilter) {
+ this.extraFilter = extraFilter;
+ filterTemplate = null;
+ }
+
+ public String getSearchFilter(String id) {
+ if (filterTemplate == null) {
+ StringBuilder filter = new StringBuilder("(&(")
+ .append(idAttribute)
+ .append("=%s)");
+ for (String objectClass: objectClasses) {
+ filter.append("(objectclass=")
+ .append(FilterEncoder.encodeFilterValue(objectClass))
+ .append(')');
+ }
+ if (extraFilter != null && extraFilter.length() > 0) {
+ filter.append(extraFilter);
+ }
+ filter.append(')');
+ filterTemplate = filter.toString();
+ }
+ return String.format(filterTemplate, FilterEncoder.encodeFilterValue(id));
+ }
+ }
+
+ public static LdapProviderConfig of(ConfigurationParameters params) {
+ LdapProviderConfig cfg = new LdapProviderConfig();
+ cfg.name = params.getConfigValue(PARAM_NAME, cfg.name);
+ cfg.host = params.getConfigValue(PARAM_LDAP_HOST, PARAM_LDAP_HOST_DEFAULT);
+ cfg.port = params.getConfigValue(PARAM_LDAP_PORT, PARAM_LDAP_PORT_DEFAULT);
+ cfg.useSSL = params.getConfigValue(PARAM_USE_SSL, PARAM_USE_SSL_DEFAULT);
+ cfg.bindDN = params.getConfigValue(PARAM_BIND_DN, PARAM_BIND_DN_DEFAULT);
+ cfg.bindPassword = params.getConfigValue(PARAM_BIND_PASSWORD, PARAM_BIND_PASSWORD_DEFAULT);
+ cfg.searchTimeout = params.getConfigValue(PARAM_SEARCH_TIMEOUT, PARAM_SEARCH_TIMEOUT_DEFAULT);
+ return cfg;
+ }
+
+
+ private String name = "ldap";
+ private String host = PARAM_LDAP_HOST_DEFAULT;
+ private int port = PARAM_LDAP_PORT_DEFAULT;
+ private boolean useSSL = PARAM_USE_SSL_DEFAULT;
+ private String bindDN = PARAM_BIND_DN_DEFAULT;
+ private String bindPassword = PARAM_BIND_PASSWORD_DEFAULT;
+ private int searchTimeout = PARAM_SEARCH_TIMEOUT_DEFAULT;
+
+ private final Identity userConfig = new Identity();
+ private final Identity groupConfig = new Identity();
+
+ private String groupMembershipAttribute = "uniquemember";
+
+ @Nonnull
+ public String getName() {
+ return name;
+ }
+
+ public void setName(@Nonnull String name) {
+ this.name = name;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isUseSSL() {
+ return useSSL;
+ }
+
+ public void setUseSSL(boolean useSSL) {
+ this.useSSL = useSSL;
+ }
+
+ public String getBindDN() {
+ return bindDN;
+ }
+
+ public void setBindDN(String bindDN) {
+ this.bindDN = bindDN;
+ }
+
+ public String getBindPassword() {
+ return bindPassword;
+ }
+
+ public void setBindPassword(String bindPassword) {
+ this.bindPassword = bindPassword;
+ }
+
+ public int getSearchTimeout() {
+ return searchTimeout;
+ }
+
+ public void setSearchTimeout(int searchTimeout) {
+ this.searchTimeout = searchTimeout;
+ }
+
+ public String getGroupMembershipAttribute() {
+ return groupMembershipAttribute;
+ }
+
+ public void setGroupMembershipAttribute(String groupMembershipAttribute) {
+ this.groupMembershipAttribute = groupMembershipAttribute;
+ }
+
+ public Identity getUserConfig() {
+ return userConfig;
+ }
+
+ public Identity getGroupConfig() {
+ return groupConfig;
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapSettings.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapSettings.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapSettings.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapSettings.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class LdapSettings {
+
+ //TODO support autocreate.user.membership
+ //TODO support autocreate.path
+
+ public static final String KEY_HOST = "host";
+ public static final String KEY_PORT = "port";
+ public static final String KEY_SECURE = "secure";
+ public static final String KEY_AUTHDN = "authDn";
+ public static final String KEY_AUTHPW = "authPw";
+ public static final String KEY_SEARCHTIMEOUT = "searchTimeout";
+ public static final String KEY_USERROOT = "userRoot";
+ public static final String KEY_USERFILTER = "userFilter";
+ public static final String KEY_USERIDATTRIBUTE = "userIdAttribute";
+ public static final String KEY_GROUPROOT = "groupRoot";
+ public static final String KEY_GROUPFILTER = "groupFilter";
+ public static final String KEY_GROUPMEMBERSHIPATTRIBUTE = "groupMembershipAttribute";
+ public static final String KEY_GROUPNAMEATTRIBUTE = "groupNameAttribute";
+ public static final String KEY_AUTOCREATEPATH = "autocreate.path";
+ public static final String KEY_AUTOCREATEUSER = "autocreate.user.";
+ public static final String KEY_AUTOCREATEGROUP = "autocreate.group.";
+
+ //Connection settings
+ private String host;
+ private int port = 389;
+ private boolean secure = false;
+ private String authDn = "";
+ private String authPw = "";
+ private int searchTimeout = 60000;
+
+ //authentication settings
+ private String userRoot = "";
+ private String userFilter = "(objectclass=person)";
+ private String userIdAttribute = "uid";
+ private String groupRoot = "";
+ private String groupFilter = "(objectclass=groupOfUniqueNames)";
+ private String groupMembershipAttribute = "uniquemember";
+ private String groupNameAttribute = "cn";
+
+ //synchronization
+ private boolean splitPath = false;
+ private final Map<String, String> userAttributes = new HashMap<String, String>();
+ private final Map<String, String> groupAttributes = new HashMap<String, String>();
+
+ public LdapSettings(Map<String, ?> options) {
+ if (options.containsKey(KEY_HOST)) {
+ host = (String) options.get(KEY_HOST);
+ }
+ if (options.containsKey(KEY_PORT)) {
+ String s = (String) options.get(KEY_PORT);
+ if (s != null && s.length() > 0) {
+ port = Integer.parseInt(s);
+ }
+ }
+ if (options.containsKey(KEY_SECURE)) {
+ String s = (String) options.get(KEY_SECURE);
+ if (s != null && s.length() > 0) {
+ secure = Boolean.parseBoolean(s);
+ }
+ }
+ if (options.containsKey(KEY_AUTHDN)) {
+ authDn = (String) options.get(KEY_AUTHDN);
+ }
+ if (options.containsKey(KEY_AUTHPW)) {
+ authPw = (String) options.get(KEY_AUTHPW);
+ }
+ if (options.containsKey(KEY_SEARCHTIMEOUT)) {
+ String s = (String) options.get(KEY_SEARCHTIMEOUT);
+ if (s != null && s.length() > 0) {
+ searchTimeout = Integer.parseInt(s);
+ }
+ }
+ if (options.containsKey(KEY_USERROOT)) {
+ userRoot = (String) options.get(KEY_USERROOT);
+ }
+ if (options.containsKey(KEY_USERFILTER)) {
+ userFilter = (String) options.get(KEY_USERFILTER);
+ }
+ if (options.containsKey(KEY_USERIDATTRIBUTE)) {
+ userIdAttribute = (String) options.get(KEY_USERIDATTRIBUTE);
+ }
+ if (options.containsKey(KEY_GROUPROOT)) {
+ groupRoot = (String) options.get(KEY_GROUPROOT);
+ }
+ if (options.containsKey(KEY_GROUPFILTER)) {
+ groupFilter = (String) options.get(KEY_GROUPFILTER);
+ }
+ if (options.containsKey(KEY_GROUPMEMBERSHIPATTRIBUTE)) {
+ groupMembershipAttribute = (String) options.get(KEY_GROUPMEMBERSHIPATTRIBUTE);
+ }
+ if (options.containsKey(KEY_GROUPNAMEATTRIBUTE)) {
+ groupNameAttribute = (String) options.get(KEY_GROUPNAMEATTRIBUTE);
+ }
+ if (options.containsKey(KEY_AUTOCREATEPATH)) {
+ splitPath = "splitdn".equals(options.get(KEY_AUTOCREATEPATH));
+ }
+ for (String key : options.keySet()) {
+ if (key.startsWith(KEY_AUTOCREATEUSER)) {
+ userAttributes.put(key.substring(KEY_AUTOCREATEUSER.length()), (String) options.get(key));
+ }
+ if (key.startsWith(KEY_AUTOCREATEGROUP)) {
+ groupAttributes.put(key.substring(KEY_AUTOCREATEGROUP.length()), (String) options.get(key));
+ }
+ }
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public boolean isSecure() {
+ return secure;
+ }
+
+ public String getAuthDn() {
+ return authDn;
+ }
+
+ public String getAuthPw() {
+ return authPw;
+ }
+
+ public int getSearchTimeout() {
+ return searchTimeout;
+ }
+
+ public String getUserRoot() {
+ return userRoot;
+ }
+
+ public String getUserFilter() {
+ return userFilter;
+ }
+
+ public String getUserIdAttribute() {
+ return userIdAttribute;
+ }
+
+ public String getGroupRoot() {
+ return groupRoot;
+ }
+
+ public String getGroupFilter() {
+ return groupFilter;
+ }
+
+ public String getGroupMembershipAttribute() {
+ return groupMembershipAttribute;
+ }
+
+ public String getGroupNameAttribute() {
+ return groupNameAttribute;
+ }
+
+ public boolean isSplitPath() {
+ return splitPath;
+ }
+
+ public Map<String, String> getUserAttributes() {
+ return userAttributes;
+ }
+
+ public Map<String, String> getGroupAttributes() {
+ return groupAttributes;
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapUser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapUser.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapUser.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapUser.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap.impl;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+
+public class LdapUser extends LdapIdentity implements ExternalUser {
+
+ private final String pwd;
+
+ public LdapUser(LdapIdentityProvider provider, ExternalIdentityRef ref, String id, String pwd) {
+ super(provider, ref, id);
+ this.pwd = pwd;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getPassword() {
+ return pwd;
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/package-info.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@Version("0.17")
+@Export(optional = "provide:=true")
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import aQute.bnd.annotation.Version;
+import aQute.bnd.annotation.Export;
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1566804&r1=1566803&r2=1566804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Mon Feb 10 22:57:48 2014
@@ -92,8 +92,7 @@
<Jaas-ModuleClass>
org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule,
org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl,
- org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule,
- org.apache.jackrabbit.oak.security.authentication.ldap.LdapLoginModule
+ org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule
</Jaas-ModuleClass>
<Bundle-Activator>
org.apache.jackrabbit.oak.osgi.Activator
@@ -103,8 +102,7 @@
</DynamicImport-Package>
<Embed-Dependency>
org.apache.sling.commons.osgi;inline=org/apache/sling/commons/osgi/PropertiesUtil.class,
- json-simple;inline=true,
- api-all
+ json-simple;inline=true
</Embed-Dependency>
</instructions>
</configuration>
@@ -312,13 +310,6 @@
<optional>true</optional>
</dependency>
- <dependency>
- <groupId>org.apache.directory.api</groupId>
- <artifactId>api-all</artifactId>
- <version>1.0.0-M20</version>
- <scope>provided</scope>
- </dependency>
-
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.DefaultSyncHandler;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ExternalLoginModule implements a LoginModule that uses and external identity provider for login.
+ */
+public class ExternalLoginModule extends AbstractLoginModule {
+
+ private static final Logger log = LoggerFactory.getLogger(ExternalLoginModule.class);
+
+ public static final SyncMode DEFAULT_SYNC_MODE = SyncMode.DEFAULT_SYNC;
+
+ private static final String PARAM_SYNC_HANDLER = "syncHandler";
+ private static final String DEFAULT_SYNC_HANDLER = DefaultSyncHandler.class.getName();
+
+ /**
+ * Name of the parameter that configures the name of the external identity provider.
+ */
+ public static final String PARAM_IDP_NAME = "idp.name";
+
+ /**
+ * Name of the parameter that configures the name of the synchronization handler.
+ */
+ public static final String PARAM_SYNC_HANDLER_NAME = "sync.handlerName";
+
+ /**
+ * Name of the parameter that configures the synchronization mode.
+ */
+ public static final String PARAM_SYNC_MODE = "sync.mode";
+
+ /**
+ * internal configuration when invoked from a factory rather than jaas
+ */
+ private ConfigurationParameters osgiConfig;
+
+ /**
+ * The external identity provider as specified by the {@link #PARAM_IDP_NAME}
+ */
+ private ExternalIdentityProvider idp;
+
+ /**
+ * The external user as resolved in the login call.
+ */
+ private ExternalUser externalUser;
+
+ /**
+ * Default constructor for the OSGIi LoginModuleFactory case and the default non-OSGi JAAS case.
+ */
+ public ExternalLoginModule() {
+ }
+
+ /**
+ * Creates a new ExternalLoginModule with the given OSGi config.
+ * @param osgiConfig the config
+ */
+ public ExternalLoginModule(ConfigurationParameters osgiConfig) {
+ this.osgiConfig = osgiConfig;
+ }
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> ss, Map<String, ?> opts) {
+ super.initialize(subject, callbackHandler, ss, opts);
+
+ // merge options with osgi options if needed
+ if (osgiConfig != null) {
+ options = ConfigurationParameters.of(osgiConfig, options);
+ }
+
+ String idpName = options.getConfigValue(PARAM_IDP_NAME, "");
+ if (idpName.length() == 0) {
+ log.error("External login module needs IPD name. Will not be used for login.");
+ } else {
+ ExternalIdentityProviderManager idpMgr = getSecurityProvider().getConfiguration(ExternalIdentityProviderManager.class);
+ idp = idpMgr.getProvider(idpName);
+ if (idp == null) {
+ log.error("No IDP found with name {}. Will not be used for login.", idpName);
+ }
+ }
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ if (idp == null) {
+ return false;
+ }
+
+ Credentials credentials = getCredentials();
+ if (credentials == null) {
+ log.info("No credentials found for external login module. ignoring.");
+ return false;
+ }
+
+ try {
+ ExternalUser externalUser = idp.authenticate(credentials);
+ if (externalUser != null) {
+ log.debug("Adding Credentials to shared state.");
+ //noinspection unchecked
+ sharedState.put(SHARED_KEY_CREDENTIALS, credentials);
+
+ log.debug("Adding login name to shared state.");
+ //noinspection unchecked
+ sharedState.put(SHARED_KEY_LOGIN_NAME, externalUser.getId());
+
+ return true;
+ }
+ } catch (ExternalIdentityException e) {
+ log.error("Error while authenticating credentials {} with {}: {}", new Object[]{
+ credentials, idp.getName(), e.toString()});
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return An immutable set containing only the {@link SimpleCredentials} class.
+ */
+ @Override
+ protected Set<Class> getSupportedCredentials() {
+ // todo: maybe delegate getSupportedCredentials to IDP
+ Class scClass = SimpleCredentials.class;
+ return Collections.singleton(scClass);
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ if (externalUser == null) {
+ return false;
+ }
+
+ try {
+ SyncHandler handler = getSyncHandler();
+ Root root = getRoot();
+ UserManager userManager = getUserManager();
+ if (root == null || userManager == null) {
+ throw new LoginException("Cannot synchronize user.");
+ }
+ Object smValue = options.getConfigValue(PARAM_SYNC_MODE, null, null);
+ SyncMode syncMode;
+ if (smValue == null) {
+ syncMode = DEFAULT_SYNC_MODE;
+ } else {
+ syncMode = SyncMode.fromObject(smValue);
+ }
+ if (externalUser != null && handler.initialize(userManager, root, syncMode, options)) {
+ handler.sync(externalUser);
+ root.commit();
+ return true;
+ } else {
+ log.warn("Failed to initialize sync handler.");
+ return false;
+ }
+ } catch (SyncException e) {
+ throw new LoginException("User synchronization failed: " + e);
+ } catch (CommitFailedException e) {
+ throw new LoginException("User synchronization failed: " + e);
+ }
+ }
+
+ @Nonnull
+ protected SyncHandler getSyncHandler() throws SyncException {
+ Object syncHandler = options.getConfigValue(PARAM_SYNC_HANDLER, null, null);
+ if (syncHandler == null) {
+ return new DefaultSyncHandler();
+ } else if (syncHandler instanceof SyncHandler) {
+ return (SyncHandler) syncHandler;
+ } else {
+ try {
+ Object sh = Class.forName(syncHandler.toString()).newInstance();
+ if (sh instanceof SyncHandler) {
+ return (SyncHandler) sh;
+ } else {
+ throw new SyncException("Invalid SyncHandler configuration: " + sh);
+ }
+ } catch (Exception e) {
+ throw new SyncException("Error while getting SyncHandler:", e);
+ }
+ }
+ }
+
+ @Override
+ protected void clearState() {
+ super.clearState();
+ idp = null;
+ externalUser = null;
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java?rev=1566804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java Mon Feb 10 22:57:48 2014
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
+
+import java.util.Map;
+
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.felix.jaas.LoginModuleFactory;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+
+/**
+ * Implements a LoginModuleFactory that creates {@link ExternalLoginModule}s and allows to configure login modules
+ * via OSGi config.
+ */
+@Component(
+ label = "Apache Jackrabbit Oak External Login Module",
+ metatype = true,
+ policy = ConfigurationPolicy.REQUIRE,
+ configurationFactory = true
+)
+@Service
+public class ExternalLoginModuleFactory implements LoginModuleFactory {
+
+ @Property(
+ intValue = 900,
+ label = "JAAS Ranking",
+ description = "Specifying the ranking (i.e. sort order) of this login module entry. The entries are sorted " +
+ "in a descending order (i.e. higher value ranked configurations come first)."
+ )
+ public static final String JAAS_RANKING = LoginModuleFactory.JAAS_RANKING;
+
+ @Property(
+ value = "SUFFICIENT",
+ label = "JAAS Control Flag",
+ description = "Property specifying whether or not a LoginModule is REQUIRED, REQUISITE, SUFFICIENT or " +
+ "OPTIONAL.Refer to the JAAS configuration documentation for more details around the meaning of " +
+ "these flags."
+ )
+ public static final String JAAS_CONTROL_FLAG = LoginModuleFactory.JAAS_CONTROL_FLAG;
+
+ @Property(
+ label = "JAAS Realm",
+ description = "The realm name (or application name) against which the LoginModule is be registered. If no " +
+ "realm name is provided then LoginModule is registered with a default realm as configured in " +
+ "the Felix JAAS configuration."
+ )
+ public static final String JAAS_REALM_NAME = LoginModuleFactory.JAAS_REALM_NAME;
+
+ @Property(
+ label = "Identity Provider Name",
+ description = "Name of the identity provider (for example: 'ldap')."
+ )
+ public static final String PARAM_IDP_NAME = ExternalLoginModule.PARAM_IDP_NAME;
+
+ @Property(
+ value = "default",
+ label = "Sync Handler Name",
+ description = "Name of the sync handler."
+ )
+ public static final String PARAM_SYNC_HANDLER_NAME = ExternalLoginModule.PARAM_SYNC_HANDLER_NAME;
+
+ @Property(
+ value = "default",
+ label = "Sync Mode",
+ // TODO!!!
+ description = "a comma separated list of sync modes. allowed values: 'user','group','default','update'"
+ )
+ public static final String PARAM_SYNC_MODE = ExternalLoginModule.PARAM_SYNC_MODE;
+
+ /**
+ * default configuration for the login modules
+ */
+ private ConfigurationParameters osgiConfig;
+
+ /**
+ * Activates the LoginModuleFactory service
+ * @param properties the OSGi config
+ */
+ @Activate
+ protected void activate(Map<String, Object> properties) {
+ osgiConfig = ConfigurationParameters.of(properties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return a new {@link ExternalLoginModule} instance.
+ */
+ @Override
+ public LoginModule createLoginModule() {
+ return new ExternalLoginModule(osgiConfig);
+ }
+
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java?rev=1566804&r1=1566803&r2=1566804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java Mon Feb 10 22:57:48 2014
@@ -32,7 +32,7 @@ import org.apache.jackrabbit.oak.api.Aut
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalLoginModule;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncMode;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java?rev=1566804&r1=1566803&r2=1566804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java Mon Feb 10 22:57:48 2014
@@ -28,6 +28,7 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java?rev=1566804&r1=1566803&r2=1566804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java Mon Feb 10 22:57:48 2014
@@ -26,6 +26,7 @@ import javax.jcr.Credentials;
import javax.jcr.SimpleCredentials;
import javax.security.auth.login.LoginException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
/**
Modified: jackrabbit/oak/trunk/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/pom.xml?rev=1566804&r1=1566803&r2=1566804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/pom.xml (original)
+++ jackrabbit/oak/trunk/pom.xml Mon Feb 10 22:57:48 2014
@@ -49,6 +49,7 @@
<module>oak-solr-core</module>
<module>oak-solr-remote</module>
<module>oak-solr-embedded</module>
+ <module>oak-auth-ldap</module>
<module>oak-run</module>
<module>oak-it</module>
<!-- <module>oak-mk-perf</module> -->