Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.List;
 import java.util.Map;
 
 import  javax.annotation.Nonnull;
 import  javax.annotation.Nullable;
 
LdapIdentityProvider implements an external identity provider that reads users and groups from an ldap source. Please refer to LdapProviderConfig for configuration options.
 
         // note that the metatype information is generated from LdapProviderConfig
         policy = .
 )
 public class LdapIdentityProvider implements ExternalIdentityProvider {

    
default logger
 
     private static final Logger log = LoggerFactory.getLogger(LdapIdentityProvider.class);

    
internal configuration
 
     private LdapProviderConfig config;

    
the connection pool with connections authenticated with the bind DN
 
     private LdapConnectionPool adminPool;

    
admin connection factory
the connection pool with unbound connections
    private UnboundLdapConnectionPool userPool;

    
user connection factory
Default constructor for OSGi
    @SuppressWarnings("UnusedDeclaration")
    public LdapIdentityProvider() {
    }

    
Constructor for non-OSGi cases.

Parameters:
config the configuration
    public LdapIdentityProvider(LdapProviderConfig config) {
        this. = config;
        init();
    }
    @Activate
    private void activate(Map<StringObjectproperties) {
        ConfigurationParameters cfg = ConfigurationParameters.of(properties);
         = LdapProviderConfig.of(cfg);
        init();
    }
    @Deactivate
    private void deactivate() {
        close();
    }

    
Initializes the ldap identity provider.
    private void init() {
        if ( != null) {
            throw new IllegalStateException("Provider already initialized.");
        }
        // setup admin connection pool
        if (!.getBindDN().isEmpty()) {
            cc.setName(.getBindDN());
            cc.setCredentials(.getBindPassword());
        }
        if (.getAdminPoolConfig().getMaxActive() != 0) {
             = new LdapConnectionPool();
            .setTestOnBorrow(true);
        }
        // setup unbound connection pool. let's create a new version of the config
        cc = createConnectionConfig();
        if (.getUserPoolConfig().getMaxActive() != 0) {
            .setTestOnBorrow(true);
        }
        .info("LdapIdentityProvider initialized: {}");
    }

    
Creates a new connection config based on the config.

Returns:
the connection config.
    @Nonnull
        LdapConnectionConfig cc = new LdapConnectionConfig();
        cc.setLdapHost(.getHostname());
        cc.setLdapPort(.getPort());
        cc.setUseSsl(.useSSL());
        cc.setUseTls(.useTLS());
        // todo: implement better trustmanager/keystore management (via sling/felix)
        if (.noCertCheck()) {
            cc.setTrustManagers(new NoVerificationTrustManager());
        }
        return cc;
    }

    
Closes this provider and releases the internal pool. This should be called by Non-OSGi users of this provider.
    public void close() {
        if ( != null) {
            try {
                .close();
            } catch (Exception e) {
                .warn("Error while closing LDAP connection pool"e);
            }
             = null;
        }
        if ( != null) {
            try {
                .close();
            } catch (Exception e) {
                .warn("Error while closing LDAP connection pool"e);
            }
             = null;
        }
    }
    @Nonnull
    @Override
    public String getName() {
        return .getName();
    }
    @Override
        if (!isMyRef(ref)) {
            return null;
        }
        LdapConnection connection = connect();
        try {
            Entry entry = connection.lookup(ref.getId(), "*");
            if (entry == null) {
                return null;
            } else if (entry.hasObjectClass(.getUserConfig().getObjectClasses())) {
                return createUser(entrynull);
            } else if (entry.hasObjectClass(.getGroupConfig().getObjectClasses())) {
                return createGroup(entrynull);
            } else {
                .warn("referenced identity is neither user or group: {}"ref.getString());
                return null;
            }
        } catch (LdapException e) {
            .error("Error during ldap lookup"e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } finally {
            disconnect(connection);
        }
    }
    @Override
    public ExternalUser getUser(@Nonnull String userIdthrows ExternalIdentityException {
        DebugTimer timer = new DebugTimer();
        LdapConnection connection = connect();
        timer.mark("connect");
        try {
            Entry entry = getEntry(connection.getUserConfig(), userId);
            timer.mark("lookup");
            if (.isDebugEnabled()) {
                .debug("getUser({}) {}"userIdtimer.getString());
            }
            if (entry != null) {
                return createUser(entryuserId);
            } else {
                return null;
            }
        } catch (LdapException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } catch (CursorException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } finally {
            disconnect(connection);
        }
    }
    @Override
    public ExternalGroup getGroup(@Nonnull String namethrows ExternalIdentityException {
        DebugTimer timer = new DebugTimer();
        LdapConnection connection = connect();
        timer.mark("connect");
        try {
            Entry entry = getEntry(connection.getGroupConfig(), name);
            timer.mark("lookup");
            if (.isDebugEnabled()) {
                .debug("getGroup({}) {}"nametimer.getString());
            }
            if (entry != null) {
                return createGroup(entryname);
            } else {
                return null;
            }
        } catch (LdapException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } catch (CursorException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } finally {
            disconnect(connection);
        }
    }
    @Override
        DebugTimer timer = new DebugTimer();
        LdapConnection connection = connect();
        timer.mark("connect");
        try {
            final List<Entryentries = getEntries(connection.getUserConfig());
            timer.mark("lookup");
            if (.isDebugEnabled()) {
                .debug("listUsers() {}"timer.getString());
            }
            return new AbstractLazyIterator<ExternalUser>() {
                private final Iterator<Entryiter = entries.iterator();
                @Override
                protected ExternalUser getNext() {
                    while (.hasNext()) {
                        try {
                            return createUser(.next(), null);
                        } catch (LdapInvalidAttributeValueException e) {
                            .warn("Error while creating external user object"e);
                        }
                    }
                    return null;
                }
            };
        } catch (LdapException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } catch (CursorException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } finally {
            disconnect(connection);
        }
    }
    @Override
        DebugTimer timer = new DebugTimer();
        LdapConnection connection = connect();
        timer.mark("connect");
        try {
            final List<Entryentries = getEntries(connection.getGroupConfig());
            timer.mark("lookup");
            if (.isDebugEnabled()) {
                .debug("listGroups() {}"timer.getString());
            }
            return new AbstractLazyIterator<ExternalGroup>() {
                private final Iterator<Entryiter = entries.iterator();
                @Override
                protected ExternalGroup getNext() {
                    while (.hasNext()) {
                        try {
                            return createGroup(.next(), null);
                        } catch (LdapInvalidAttributeValueException e) {
                            .warn("Error while creating external user object"e);
                        }
                    }
                    return null;
                }
            };
        } catch (LdapException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } catch (CursorException e) {
            .error("Error during ldap lookup. " + timer.getString(), e);
            throw new ExternalIdentityException("Error during ldap lookup."e);
        } finally {
            disconnect(connection);
        }
    }
    private Entry getEntry(LdapConnection connectionLdapProviderConfig.Identity idConfigString id)
            throws CursorExceptionLdapException {
        String searchFilter = idConfig.getSearchFilter(id);
        // Create the SearchRequest object
        SearchRequest req = new SearchRequestImpl();
        req.setScope(.);
        req.setTimeLimit((int.getSearchTimeout());
        req.setBase(new Dn(idConfig.getBaseDN()));
        req.setFilter(searchFilter);
        // Process the request
        SearchCursor searchCursor = null;
        try {
            searchCursor = connection.search(req);
            while (searchCursor.next()) {
                Response response = searchCursor.get();
                // process the SearchResultEntry
                if (response instanceof SearchResultEntry) {
                    Entry resultEntry = ((SearchResultEntryresponse).getEntry();
                    if (searchCursor.next()) {
                        .warn("search for {} returned more than one entry. discarding additional ones."searchFilter);
                    }
                    if (.isDebugEnabled()) {
                        .debug("search below {} with {} found {}"idConfig.getBaseDN(), searchFilterresultEntry.getDn());
                    }
                    return resultEntry;
                }
            }
        } finally {
            if (searchCursor != null) {
                searchCursor.close();
            }
        }
        if (.isDebugEnabled()) {
            .debug("search below {} with {} found 0 entries."idConfig.getBaseDN(), searchFilter);
        }
        return null;
    }

    
currently fetch all entries so that we can close the connection afterwards. maybe switch to an iterator approach later.
    private List<EntrygetEntries(LdapConnection connectionLdapProviderConfig.Identity idConfig)
            throws CursorExceptionLdapException {
        StringBuilder filter = new StringBuilder();
        int num = 0;
        for (String objectClassidConfig.getObjectClasses()) {
            num++;
            filter.append("(objectclass=")
                    .append(LdapProviderConfig.encodeFilterValue(objectClass))
                    .append(')');
        }
        String extraFilter = idConfig.getExtraFilter();
        if (extraFilter != null && extraFilter.length() > 0) {
            num++;
            filter.append(extraFilter);
        }
        String searchFilter = num > 1
                ? "(&" + filter + ")"
                : filter.toString();
        // Create the SearchRequest object
        SearchRequest req = new SearchRequestImpl();
        req.setScope(.);
        req.setTimeLimit((int.getSearchTimeout());
        req.setBase(new Dn(idConfig.getBaseDN()));
        req.setFilter(searchFilter);
        // Process the request
        List<Entryresult = new LinkedList<Entry>();
        SearchCursor searchCursor = null;
        try {
            searchCursor = connection.search(req);
            while (searchCursor.next()) {
                Response response = searchCursor.get();
                // process the SearchResultEntry
                if (response instanceof SearchResultEntry) {
                    Entry resultEntry = ((SearchResultEntryresponse).getEntry();
                    result.add(resultEntry);
                    if (.isDebugEnabled()) {
                        .debug("search below {} with {} found {}"idConfig.getBaseDN(), searchFilterresultEntry.getDn());
                    }
                }
            }
        } finally {
            if (searchCursor != null) {
                searchCursor.close();
            }
        }
        if (.isDebugEnabled()) {
            .debug("search below {} with {} found {} entries."idConfig.getBaseDN(), searchFilterresult.size());
        }
        return result;
    }
    private ExternalUser createUser(Entry eString id)
            throws LdapInvalidAttributeValueException {
        ExternalIdentityRef ref = new ExternalIdentityRef(e.getDn().getName(), this.getName());
        if (id == null) {
            id = e.get(.getUserConfig().getIdAttribute()).getString();
        }
        String path = .getUserConfig().makeDnPath()
                ? createDNPath(e.getDn())
                : null;
        LdapUser user = new LdapUser(thisrefidpath);
        Map<StringObjectprops = user.getProperties();
        for (Attribute attre.getAttributes()) {
            if (attr.isHumanReadable()) {
                props.put(attr.getId(), attr.getString());
            }
        }
        return user;
    }
    private ExternalGroup createGroup(Entry eString name)
            throws LdapInvalidAttributeValueException {
        ExternalIdentityRef ref = new ExternalIdentityRef(e.getDn().getName(), this.getName());
        if (name == null) {
            name = e.get(.getGroupConfig().getIdAttribute()).getString();
        }
        String path = .getGroupConfig().makeDnPath()
                ? createDNPath(e.getDn())
                : null;
        LdapGroup group = new LdapGroup(thisrefnamepath);
        Map<StringObjectprops = group.getProperties();
        for (Attribute attre.getAttributes()) {
            if (attr.isHumanReadable()) {
                props.put(attr.getId(), attr.getString());
            }
        }
        return group;
    }
    @Nonnull
    private LdapConnection connect() throws ExternalIdentityException {
        try {
            if ( == null) {
                return .makeObject();
            } else {
                return .getConnection();
            }
        } catch (Throwable e) {
            .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(@Nullable LdapConnection connectionthrows ExternalIdentityException {
        try {
            if (connection != null) {
                if ( == null) {
                    .destroyObject(connection);
                } else {
                    .releaseConnection(connection);
                }
            }
        } catch (Exception e) {
            .warn("Error while disconnecting from the ldap server."e);
        }
    }
    @Override
    public ExternalUser authenticate(@Nonnull Credentials credentialsthrows ExternalIdentityExceptionLoginException {
        if (!(credentials instanceof SimpleCredentials)) {
            .debug("LDAP IDP can only authenticate SimpleCredentials.");
            return null;
        }
        final SimpleCredentials creds = (SimpleCredentialscredentials;
        final ExternalUser user = getUser(creds.getUserID());
        if (user != null) {
            // OAK-2078: check for non-empty passwords to avoid anonymous bind on weakly configured servers
            // see http://tools.ietf.org/html/rfc4513#section-5.1.1 for details.
            if (creds.getPassword().length == 0) {
                throw new LoginException("Refusing to authenticate against LDAP server: Empty passwords not allowed.");
            }
            // authenticate
            LdapConnection connection = null;
            try {
                DebugTimer timer = new DebugTimer();
                if ( == null) {
                    connection = .makeObject();
                } else {
                    connection = .getConnection();
                }
                timer.mark("connect");
                connection.bind(user.getExternalId().getId(), new String(creds.getPassword()));
                timer.mark("bind");
                if (.isDebugEnabled()) {
                    .debug("authenticate({}) {}"user.getId(), timer.getString());
                }
            } catch (LdapAuthenticationException e) {
                throw new LoginException("Unable to authenticate against LDAP server: " + e.getMessage());
            } catch (Exception e) {
                throw new ExternalIdentityException("Error while binding user credentials"e);
            } finally {
                if (connection != null) {
                    try {
                        if ( == null) {
                            .destroyObject(connection);
                        } else {
                            .releaseConnection(connection);
                        }
                    } catch (Exception e) {
                        // ignore
                    }
                }
            }
        }
        return user;
    }
    private boolean isMyRef(@Nonnull ExternalIdentityRef ref) {
        final String refProviderName = ref.getProviderName();
        return refProviderName == null || refProviderName.length() == 0 || getName().equals(refProviderName);
    }

    
Collects the declared (direct) groups of an identity

Parameters:
ref reference to the identity
Returns:
map of identities where the key is the DN of the LDAP entity
        if (!isMyRef(ref)) {
            return Collections.emptyMap();
        }
        String searchFilter = .getMemberOfSearchFilter(ref.getId());
        LdapConnection connection = null;
        SearchCursor searchCursor = null;
        try {
            // Create the SearchRequest object
            SearchRequest req = new SearchRequestImpl();
            req.setScope(.);
            req.addAttributes(.);
            req.setTimeLimit((int.getSearchTimeout());
            req.setBase(new Dn(.getGroupConfig().getBaseDN()));
            req.setFilter(searchFilter);
            Map<StringExternalIdentityRefgroups = new HashMap<StringExternalIdentityRef>();
            DebugTimer timer = new DebugTimer();
            connection = connect();
            timer.mark("connect");
            searchCursor = connection.search(req);
            timer.mark("search");
            while (searchCursor.next()) {
                Response response = searchCursor.get();
                if (response instanceof SearchResultEntry) {
                    Entry resultEntry = ((SearchResultEntryresponse).getEntry();
                    ExternalIdentityRef groupRef = new ExternalIdentityRef(resultEntry.getDn().toString(), this.getName());
                    groups.put(groupRef.getId(), groupRef);
                }
            }
            timer.mark("iterate");
            if (.isDebugEnabled()) {
                .debug("search below {} with {} found {} entries. {}",
                        .getGroupConfig().getBaseDN(), searchFiltergroups.size(), timer.getString());
            }
            return groups;
        } catch (Exception e) {
            .error("Error during ldap membership search." ,e);
            throw new ExternalIdentityException("Error during ldap membership search."e);
        } finally {
            if (searchCursor != null) {
                searchCursor.close();
            }
            disconnect(connection);
        }
    }

    
Collects the declared (direct) members of a group

Parameters:
ref the reference to the group
Returns:
map of identity refers
Throws:
ExternalIdentityException if an error occurs
        if (!isMyRef(ref)) {
            return Collections.emptyMap();
        }
        LdapConnection connection = null;
        try {
            Map<StringExternalIdentityRefmembers = new HashMap<StringExternalIdentityRef>();
            DebugTimer timer = new DebugTimer();
            connection = connect();
            timer.mark("connect");
            Entry entry = connection.lookup(ref.getId());
            timer.mark("lookup");
            Attribute attr = entry.get(.getGroupMemberAttribute());
            for (Value valueattr) {
                ExternalIdentityRef memberRef = new ExternalIdentityRef(value.getString(), this.getName());
                members.put(memberRef.getId(), memberRef);
            }
            timer.mark("iterate");
            if (.isDebugEnabled()) {
                .debug("members lookup of {} found {} members. {}"ref.getId(), members.size(), timer.getString());
            }
            return members;
        } catch (Exception e) {
            .error("Error during ldap group members lookup." ,e);
            throw new ExternalIdentityException("Error during ldap group members lookup."e);
        } finally {
            disconnect(connection);
        }
    }

    
Makes the intermediate path of an DN by splitting along the RDNs

Parameters:
dn the dn of the identity
Returns:
the intermediate path or null if disabled by config
    public String createDNPath(Dn dn) {
        StringBuilder path = new StringBuilder();
        for (Rdn rnddn.getRdns()) {
            if (path.length() > 0) {
                path.append('/');
            }
            path.append(Text.escapeIllegalJcrChars(rnd.toString()));
        }
        return path.toString();
    }
New to GrepCode? Check out our FAQ X