Search in sources :

Example 1 with PartialResultException

use of javax.naming.PartialResultException in project tomcat by apache.

the class JNDIRealm method getRoles.

/**
     * Return a List of roles associated with the given User.  Any
     * roles present in the user's directory entry are supplemented by
     * a directory search. If no roles are associated with this user,
     * a zero-length List is returned.
     *
     * @param context The directory context we are searching
     * @param user The User to be checked
     * @return the list of role names
     * @exception NamingException if a directory server error occurs
     */
protected List<String> getRoles(DirContext context, User user) throws NamingException {
    if (user == null)
        return null;
    String dn = user.getDN();
    String username = user.getUserName();
    String userRoleId = user.getUserRoleId();
    if (dn == null || username == null)
        return null;
    if (containerLog.isTraceEnabled())
        containerLog.trace("  getRoles(" + dn + ")");
    // Start with roles retrieved from the user entry
    List<String> list = new ArrayList<>();
    List<String> userRoles = user.getRoles();
    if (userRoles != null) {
        list.addAll(userRoles);
    }
    if (commonRole != null)
        list.add(commonRole);
    if (containerLog.isTraceEnabled()) {
        containerLog.trace("  Found " + list.size() + " user internal roles");
        containerLog.trace("  Found user internal roles " + list.toString());
    }
    // Are we configured to do role searches?
    if ((roleFormat == null) || (roleName == null))
        return list;
    // Set up parameters for an appropriate search
    String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username, userRoleId });
    SearchControls controls = new SearchControls();
    if (roleSubtree)
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    else
        controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
    controls.setReturningAttributes(new String[] { roleName });
    String base = null;
    if (roleBaseFormat != null) {
        NameParser np = context.getNameParser("");
        Name name = np.parse(dn);
        String[] nameParts = new String[name.size()];
        for (int i = 0; i < name.size(); i++) {
            nameParts[i] = name.get(i);
        }
        base = roleBaseFormat.format(nameParts);
    } else {
        base = "";
    }
    // Perform the configured search and process the results
    NamingEnumeration<SearchResult> results = searchAsUser(context, user, base, filter, controls, isRoleSearchAsUser());
    if (results == null)
        // Should never happen, but just in case ...
        return list;
    HashMap<String, String> groupMap = new HashMap<>();
    try {
        while (results.hasMore()) {
            SearchResult result = results.next();
            Attributes attrs = result.getAttributes();
            if (attrs == null)
                continue;
            String dname = getDistinguishedName(context, roleBase, result);
            String name = getAttributeValue(roleName, attrs);
            if (name != null && dname != null) {
                groupMap.put(dname, name);
            }
        }
    } catch (PartialResultException ex) {
        if (!adCompat)
            throw ex;
    } finally {
        results.close();
    }
    if (containerLog.isTraceEnabled()) {
        Set<Entry<String, String>> entries = groupMap.entrySet();
        containerLog.trace("  Found " + entries.size() + " direct roles");
        for (Entry<String, String> entry : entries) {
            containerLog.trace("  Found direct role " + entry.getKey() + " -> " + entry.getValue());
        }
    }
    // if nested group search is enabled, perform searches for nested groups until no new group is found
    if (getRoleNested()) {
        // The following efficient algorithm is known as memberOf Algorithm, as described in "Practices in
        // Directory Groups". It avoids group slurping and handles cyclic group memberships as well.
        // See http://middleware.internet2.edu/dir/ for details
        Map<String, String> newGroups = new HashMap<>(groupMap);
        while (!newGroups.isEmpty()) {
            // Stores the groups we find in this iteration
            Map<String, String> newThisRound = new HashMap<>();
            for (Entry<String, String> group : newGroups.entrySet()) {
                filter = roleFormat.format(new String[] { group.getKey(), group.getValue(), group.getValue() });
                if (containerLog.isTraceEnabled()) {
                    containerLog.trace("Perform a nested group search with base " + roleBase + " and filter " + filter);
                }
                results = searchAsUser(context, user, roleBase, filter, controls, isRoleSearchAsUser());
                try {
                    while (results.hasMore()) {
                        SearchResult result = results.next();
                        Attributes attrs = result.getAttributes();
                        if (attrs == null)
                            continue;
                        String dname = getDistinguishedName(context, roleBase, result);
                        String name = getAttributeValue(roleName, attrs);
                        if (name != null && dname != null && !groupMap.keySet().contains(dname)) {
                            groupMap.put(dname, name);
                            newThisRound.put(dname, name);
                            if (containerLog.isTraceEnabled()) {
                                containerLog.trace("  Found nested role " + dname + " -> " + name);
                            }
                        }
                    }
                } catch (PartialResultException ex) {
                    if (!adCompat)
                        throw ex;
                } finally {
                    results.close();
                }
            }
            newGroups = newThisRound;
        }
    }
    list.addAll(groupMap.values());
    return list;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Attributes(javax.naming.directory.Attributes) SearchResult(javax.naming.directory.SearchResult) PartialResultException(javax.naming.PartialResultException) CompositeName(javax.naming.CompositeName) Name(javax.naming.Name) Entry(java.util.Map.Entry) SearchControls(javax.naming.directory.SearchControls) NameParser(javax.naming.NameParser)

Example 2 with PartialResultException

use of javax.naming.PartialResultException in project zeppelin by apache.

the class LdapRealm method rolesFor.

private Set<String> rolesFor(PrincipalCollection principals, String userNameIn, final LdapContext ldapCtx, final LdapContextFactory ldapContextFactory) throws NamingException {
    final Set<String> roleNames = new HashSet<>();
    final Set<String> groupNames = new HashSet<>();
    final String userName;
    if (getUserLowerCase()) {
        log.debug("userLowerCase true");
        userName = userNameIn.toLowerCase();
    } else {
        userName = userNameIn;
    }
    String userDn;
    if (userSearchAttributeName == null || userSearchAttributeName.isEmpty()) {
        // memberAttributeValuePrefix and memberAttributeValueSuffix 
        // were computed from memberAttributeValueTemplate
        userDn = memberAttributeValuePrefix + userName + memberAttributeValueSuffix;
    } else {
        userDn = getUserDn(userName);
    }
    // Activate paged results
    int pageSize = getPagingSize();
    if (log.isDebugEnabled()) {
        log.debug("Ldap PagingSize: " + pageSize);
    }
    int numResults = 0;
    byte[] cookie = null;
    try {
        ldapCtx.addToEnvironment(Context.REFERRAL, "ignore");
        ldapCtx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
        do {
            // ldapsearch -h localhost -p 33389 -D
            // uid=guest,ou=people,dc=hadoop,dc=apache,dc=org -w guest-password
            // -b dc=hadoop,dc=apache,dc=org -s sub '(objectclass=*)'
            NamingEnumeration<SearchResult> searchResultEnum = null;
            SearchControls searchControls = getGroupSearchControls();
            try {
                if (groupSearchEnableMatchingRuleInChain) {
                    searchResultEnum = ldapCtx.search(getGroupSearchBase(), String.format(MATCHING_RULE_IN_CHAIN_FORMAT, groupObjectClass, memberAttribute, userDn), searchControls);
                    while (searchResultEnum != null && searchResultEnum.hasMore()) {
                        // searchResults contains all the groups in search scope
                        numResults++;
                        final SearchResult group = searchResultEnum.next();
                        Attribute attribute = group.getAttributes().get(getGroupIdAttribute());
                        String groupName = attribute.get().toString();
                        String roleName = roleNameFor(groupName);
                        if (roleName != null) {
                            roleNames.add(roleName);
                        } else {
                            roleNames.add(groupName);
                        }
                    }
                } else {
                    searchResultEnum = ldapCtx.search(getGroupSearchBase(), "objectClass=" + groupObjectClass, searchControls);
                    while (searchResultEnum != null && searchResultEnum.hasMore()) {
                        // searchResults contains all the groups in search scope
                        numResults++;
                        final SearchResult group = searchResultEnum.next();
                        addRoleIfMember(userDn, group, roleNames, groupNames, ldapContextFactory);
                    }
                }
            } catch (PartialResultException e) {
                log.debug("Ignoring PartitalResultException");
            } finally {
                if (searchResultEnum != null) {
                    searchResultEnum.close();
                }
            }
            // Re-activate paged results
            ldapCtx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
        } while (cookie != null);
    } catch (SizeLimitExceededException e) {
        log.info("Only retrieved first " + numResults + " groups due to SizeLimitExceededException.");
    } catch (IOException e) {
        log.error("Unabled to setup paged results");
    }
    // save role names and group names in session so that they can be
    // easily looked up outside of this object
    SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_ROLES, roleNames);
    SecurityUtils.getSubject().getSession().setAttribute(SUBJECT_USER_GROUPS, groupNames);
    if (!groupNames.isEmpty() && (principals instanceof MutablePrincipalCollection)) {
        ((MutablePrincipalCollection) principals).addAll(groupNames, getName());
    }
    if (log.isDebugEnabled()) {
        log.debug("User RoleNames: " + userName + "::" + roleNames);
    }
    return roleNames;
}
Also used : Attribute(javax.naming.directory.Attribute) SearchResult(javax.naming.directory.SearchResult) PartialResultException(javax.naming.PartialResultException) IOException(java.io.IOException) MutablePrincipalCollection(org.apache.shiro.subject.MutablePrincipalCollection) SizeLimitExceededException(javax.naming.SizeLimitExceededException) SearchControls(javax.naming.directory.SearchControls) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) PagedResultsControl(javax.naming.ldap.PagedResultsControl)

Example 3 with PartialResultException

use of javax.naming.PartialResultException in project gerrit by GerritCodeReview.

the class Helper method queryForGroups.

Set<AccountGroup.UUID> queryForGroups(final DirContext ctx, final String username, LdapQuery.Result account) throws NamingException {
    final LdapSchema schema = getSchema(ctx);
    final Set<String> groupDNs = new HashSet<>();
    if (!schema.groupMemberQueryList.isEmpty()) {
        final HashMap<String, String> params = new HashMap<>();
        if (account == null) {
            try {
                account = findAccount(schema, ctx, username, false);
            } catch (AccountException e) {
                return Collections.emptySet();
            }
        }
        for (String name : schema.groupMemberQueryList.get(0).getParameters()) {
            params.put(name, account.get(name));
        }
        params.put(LdapRealm.USERNAME, username);
        for (LdapQuery groupMemberQuery : schema.groupMemberQueryList) {
            for (LdapQuery.Result r : groupMemberQuery.query(ctx, params)) {
                recursivelyExpandGroups(groupDNs, schema, ctx, r.getDN());
            }
        }
    }
    if (schema.accountMemberField != null) {
        if (account == null || account.getAll(schema.accountMemberField) == null) {
            try {
                account = findAccount(schema, ctx, username, true);
            } catch (AccountException e) {
                return Collections.emptySet();
            }
        }
        final Attribute groupAtt = account.getAll(schema.accountMemberField);
        if (groupAtt != null) {
            final NamingEnumeration<?> groups = groupAtt.getAll();
            try {
                while (groups.hasMore()) {
                    final String nextDN = (String) groups.next();
                    recursivelyExpandGroups(groupDNs, schema, ctx, nextDN);
                }
            } catch (PartialResultException e) {
            // Ignored
            }
        }
    }
    final Set<AccountGroup.UUID> actual = new HashSet<>();
    for (String dn : groupDNs) {
        actual.add(new AccountGroup.UUID(LDAP_UUID + dn));
    }
    if (actual.isEmpty()) {
        return Collections.emptySet();
    }
    return ImmutableSet.copyOf(actual);
}
Also used : HashMap(java.util.HashMap) Attribute(javax.naming.directory.Attribute) PartialResultException(javax.naming.PartialResultException) ParameterizedString(com.google.gerrit.common.data.ParameterizedString) AccountException(com.google.gerrit.server.account.AccountException) AccountGroup(com.google.gerrit.reviewdb.client.AccountGroup) HashSet(java.util.HashSet)

Example 4 with PartialResultException

use of javax.naming.PartialResultException in project gerrit by GerritCodeReview.

the class Helper method recursivelyExpandGroups.

private void recursivelyExpandGroups(final Set<String> groupDNs, final LdapSchema schema, final DirContext ctx, final String groupDN) {
    if (groupDNs.add(groupDN) && schema.accountMemberField != null && schema.accountMemberExpandGroups) {
        ImmutableSet<String> cachedParentsDNs = parentGroups.getIfPresent(groupDN);
        if (cachedParentsDNs == null) {
            // Recursively identify the groups it is a member of.
            ImmutableSet.Builder<String> dns = ImmutableSet.builder();
            try {
                final Name compositeGroupName = new CompositeName().add(groupDN);
                final Attribute in = ctx.getAttributes(compositeGroupName, schema.accountMemberFieldArray).get(schema.accountMemberField);
                if (in != null) {
                    final NamingEnumeration<?> groups = in.getAll();
                    try {
                        while (groups.hasMore()) {
                            dns.add((String) groups.next());
                        }
                    } catch (PartialResultException e) {
                    // Ignored
                    }
                }
            } catch (NamingException e) {
                LdapRealm.log.warn("Could not find group " + groupDN, e);
            }
            cachedParentsDNs = dns.build();
            parentGroups.put(groupDN, cachedParentsDNs);
        }
        for (String dn : cachedParentsDNs) {
            recursivelyExpandGroups(groupDNs, schema, ctx, dn);
        }
    }
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Attribute(javax.naming.directory.Attribute) CompositeName(javax.naming.CompositeName) PartialResultException(javax.naming.PartialResultException) NamingException(javax.naming.NamingException) ParameterizedString(com.google.gerrit.common.data.ParameterizedString) CompositeName(javax.naming.CompositeName) Name(javax.naming.Name)

Example 5 with PartialResultException

use of javax.naming.PartialResultException in project gerrit by GerritCodeReview.

the class LdapQuery method query.

List<Result> query(final DirContext ctx, final Map<String, String> params) throws NamingException {
    final SearchControls sc = new SearchControls();
    final NamingEnumeration<SearchResult> res;
    sc.setSearchScope(searchScope.scope());
    sc.setReturningAttributes(returnAttributes);
    res = ctx.search(base, pattern.getRawPattern(), pattern.bind(params), sc);
    try {
        final List<Result> r = new ArrayList<>();
        try {
            while (res.hasMore()) {
                r.add(new Result(res.next()));
            }
        } catch (PartialResultException e) {
        // Ignored
        }
        return r;
    } finally {
        res.close();
    }
}
Also used : ArrayList(java.util.ArrayList) SearchControls(javax.naming.directory.SearchControls) SearchResult(javax.naming.directory.SearchResult) PartialResultException(javax.naming.PartialResultException) SearchResult(javax.naming.directory.SearchResult)

Aggregations

PartialResultException (javax.naming.PartialResultException)22 SearchResult (javax.naming.directory.SearchResult)14 Attribute (javax.naming.directory.Attribute)12 SearchControls (javax.naming.directory.SearchControls)12 Attributes (javax.naming.directory.Attributes)9 ArrayList (java.util.ArrayList)7 HashSet (java.util.HashSet)7 HashMap (java.util.HashMap)5 CompositeName (javax.naming.CompositeName)5 Name (javax.naming.Name)5 ParameterizedString (com.google.gerrit.common.data.ParameterizedString)4 IOException (java.io.IOException)4 LinkedHashSet (java.util.LinkedHashSet)4 SizeLimitExceededException (javax.naming.SizeLimitExceededException)4 PagedResultsControl (javax.naming.ldap.PagedResultsControl)4 MutablePrincipalCollection (org.apache.shiro.subject.MutablePrincipalCollection)4 Entry (java.util.Map.Entry)3 NameParser (javax.naming.NameParser)3 NamingException (javax.naming.NamingException)3 ImmutableSet (com.google.common.collect.ImmutableSet)2