Search in sources :

Example 71 with SearchResult

use of javax.naming.directory.SearchResult in project Openfire by igniterealtime.

the class LdapManager method findGroupDN.

/**
     * Finds a groups's dn using it's group name. Normally, this search will
     * be performed using the field "cn", but this can be changed by setting
     * the <tt>groupNameField</tt> property.<p>
     *
     * Searches are performed over all subtrees relative to the <tt>baseDN</tt>.
     * If the search fails in the <tt>baseDN</tt> then another search will be
     * performed in the <tt>alternateBaseDN</tt>. For example, if the <tt>baseDN</tt>
     * is "o=jivesoftware, o=com" and we do a search for "managers", then we might
     * find a groupDN of "uid=managers,ou=Groups". This kind of searching is a good
     * thing since it doesn't make the assumption that all user records are stored
     * in a flat structure. However, it does add the requirement that "cn" field
     * (or the other field specified) must be unique over the entire subtree from
     * the <tt>baseDN</tt>. For example, it's entirely possible to create two dn's
     * in your LDAP directory with the same cn: "cn=managers,ou=Financial" and
     * "cn=managers,ou=Engineers". In such a case, it's not possible to
     * uniquely identify a group, so this method will throw an error.<p>
     *
     * The dn that's returned is relative to the default <tt>baseDN</tt>.
     *
     * @param groupname the groupname to lookup the dn for.
     * @param baseDN the base DN to use for this search.
     * @return the dn associated with <tt>groupname</tt>.
     * @throws Exception if the search for the dn fails.
     * @see #findGroupDN(String) to search using the default baseDN and alternateBaseDN.
     */
public String findGroupDN(String groupname, String baseDN) throws Exception {
    boolean debug = Log.isDebugEnabled();
    if (debug) {
        Log.debug("LdapManager: Trying to find a groups's DN based on it's groupname. " + groupNameField + ": " + groupname + ", Base DN: " + baseDN + "...");
    }
    DirContext ctx = null;
    try {
        ctx = getContext(baseDN);
        if (debug) {
            Log.debug("LdapManager: Starting LDAP search...");
        }
        // Search for the dn based on the groupname.
        SearchControls constraints = new SearchControls();
        // If sub-tree searching is enabled (default is true) then search the entire tree.
        if (subTreeSearch) {
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
        } else // Otherwise, only search a single level.
        {
            constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        }
        constraints.setReturningAttributes(new String[] { groupNameField });
        String filter = MessageFormat.format(getGroupSearchFilter(), sanitizeSearchFilter(groupname));
        NamingEnumeration<SearchResult> answer = ctx.search("", filter, constraints);
        if (debug) {
            Log.debug("LdapManager: ... search finished");
        }
        if (answer == null || !answer.hasMoreElements()) {
            if (debug) {
                Log.debug("LdapManager: Group DN based on groupname '" + groupname + "' not found.");
            }
            throw new GroupNotFoundException("Groupname " + groupname + " not found");
        }
        String groupDN = answer.next().getName();
        // The baseDN must be set correctly so that this doesn't happen.
        if (answer.hasMoreElements()) {
            if (debug) {
                Log.debug("LdapManager: Search for groupDN based on groupname '" + groupname + "' found multiple " + "responses, throwing exception.");
            }
            throw new GroupNotFoundException("LDAP groupname lookup for " + groupname + " matched multiple entries.");
        }
        // Close the enumeration.
        answer.close();
        // following code converts a referral back to a "partial" LDAP string.
        if (groupDN.startsWith("ldap://")) {
            groupDN = groupDN.replace("," + baseDN, "");
            groupDN = groupDN.substring(groupDN.lastIndexOf("/") + 1);
            groupDN = java.net.URLDecoder.decode(groupDN, "UTF-8");
        }
        if (encloseGroupDN) {
            groupDN = getEnclosedDN(groupDN);
        }
        return groupDN;
    } catch (Exception e) {
        if (debug) {
            Log.debug("LdapManager: Exception thrown when searching for groupDN based on groupname '" + groupname + "'", e);
        }
        throw e;
    } finally {
        try {
            ctx.close();
        } catch (Exception ignored) {
        // Ignore.
        }
    }
}
Also used : SearchControls(javax.naming.directory.SearchControls) SearchResult(javax.naming.directory.SearchResult) GroupNotFoundException(org.jivesoftware.openfire.group.GroupNotFoundException) InitialDirContext(javax.naming.directory.InitialDirContext) DirContext(javax.naming.directory.DirContext) NamingException(javax.naming.NamingException) GroupNotFoundException(org.jivesoftware.openfire.group.GroupNotFoundException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException)

Example 72 with SearchResult

use of javax.naming.directory.SearchResult in project Openfire by igniterealtime.

the class LdapManager method findUserDN.

/**
     * Finds a user's dn using their username in the specified baseDN. Normally, this search
     * will be performed using the field "uid", but this can be changed by setting
     * the <tt>usernameField</tt> property.<p>
     *
     * Searches are performed over all sub-trees relative to the <tt>baseDN</tt> unless
     * sub-tree searching has been disabled. For example, if the <tt>baseDN</tt> is
     * "o=jivesoftware, o=com" and we do a search for "mtucker", then we might find a userDN of
     * "uid=mtucker,ou=People". This kind of searching is a good thing since
     * it doesn't make the assumption that all user records are stored in a flat
     * structure. However, it does add the requirement that "uid" field (or the
     * other field specified) must be unique over the entire subtree from the
     * <tt>baseDN</tt>. For example, it's entirely possible to create two dn's
     * in your LDAP directory with the same uid: "uid=mtucker,ou=People" and
     * "uid=mtucker,ou=Administrators". In such a case, it's not possible to
     * uniquely identify a user, so this method will throw an error.<p>
     *
     * The DN that's returned is relative to the <tt>baseDN</tt>.
     *
     * @param username the username to lookup the dn for.
     * @param baseDN the base DN to use for this search.
     * @return the dn associated with <tt>username</tt>.
     * @throws Exception if the search for the dn fails.
     * @see #findUserDN(String) to search using the default baseDN and alternateBaseDN.
     */
public String findUserDN(String username, String baseDN) throws Exception {
    boolean debug = Log.isDebugEnabled();
    //Support for usernameSuffix
    username = username + usernameSuffix;
    if (debug) {
        Log.debug("LdapManager: Trying to find a user's DN based on their username. " + usernameField + ": " + username + ", Base DN: " + baseDN + "...");
    }
    DirContext ctx = null;
    try {
        ctx = getContext(baseDN);
        if (debug) {
            Log.debug("LdapManager: Starting LDAP search...");
        }
        // Search for the dn based on the username.
        SearchControls constraints = new SearchControls();
        // If sub-tree searching is enabled (default is true) then search the entire tree.
        if (subTreeSearch) {
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
        } else // Otherwise, only search a single level.
        {
            constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        }
        constraints.setReturningAttributes(new String[] { usernameField });
        // NOTE: this assumes that the username has already been JID-unescaped
        NamingEnumeration<SearchResult> answer = ctx.search("", getSearchFilter(), new String[] { sanitizeSearchFilter(username) }, constraints);
        if (debug) {
            Log.debug("LdapManager: ... search finished");
        }
        if (answer == null || !answer.hasMoreElements()) {
            if (debug) {
                Log.debug("LdapManager: User DN based on username '" + username + "' not found.");
            }
            throw new UserNotFoundException("Username " + username + " not found");
        }
        String userDN = answer.next().getName();
        // The baseDN must be set correctly so that this doesn't happen.
        if (answer.hasMoreElements()) {
            if (debug) {
                Log.debug("LdapManager: Search for userDN based on username '" + username + "' found multiple " + "responses, throwing exception.");
            }
            throw new UserNotFoundException("LDAP username lookup for " + username + " matched multiple entries.");
        }
        // Close the enumeration.
        answer.close();
        // following code converts a referral back to a "partial" LDAP string.
        if (userDN.startsWith("ldap://")) {
            userDN = userDN.replace("," + baseDN, "");
            userDN = userDN.substring(userDN.lastIndexOf("/") + 1);
            userDN = java.net.URLDecoder.decode(userDN, "UTF-8");
        }
        if (encloseUserDN) {
            userDN = getEnclosedDN(userDN);
        }
        return userDN;
    } catch (Exception e) {
        if (debug) {
            Log.debug("LdapManager: Exception thrown when searching for userDN based on username '" + username + "'", e);
        }
        throw e;
    } finally {
        try {
            ctx.close();
        } catch (Exception ignored) {
        // Ignore.
        }
    }
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) SearchControls(javax.naming.directory.SearchControls) SearchResult(javax.naming.directory.SearchResult) InitialDirContext(javax.naming.directory.InitialDirContext) DirContext(javax.naming.directory.DirContext) NamingException(javax.naming.NamingException) GroupNotFoundException(org.jivesoftware.openfire.group.GroupNotFoundException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException)

Example 73 with SearchResult

use of javax.naming.directory.SearchResult in project Openfire by igniterealtime.

the class LdapAuthorizationMapping method map.

@Override
public String map(String principal) {
    String username = principal;
    DirContext ctx = null;
    try {
        Log.debug("LdapAuthorizationMapping: Starting LDAP search...");
        String usernameField = manager.getUsernameField();
        //String baseDN = manager.getBaseDN();
        boolean subTreeSearch = manager.isSubTreeSearch();
        ctx = manager.getContext();
        SearchControls constraints = new SearchControls();
        if (subTreeSearch) {
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
        } else // Otherwise, only search a single level.
        {
            constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        }
        constraints.setReturningAttributes(new String[] { usernameField });
        NamingEnumeration answer = ctx.search("", princSearchFilter, new String[] { LdapManager.sanitizeSearchFilter(principal) }, constraints);
        Log.debug("LdapAuthorizationMapping: ... search finished");
        if (answer == null || !answer.hasMoreElements()) {
            Log.debug("LdapAuthorizationMapping: Username based on principal '" + principal + "' not found.");
            return principal;
        }
        Attributes atrs = ((SearchResult) answer.next()).getAttributes();
        Attribute usernameAttribute = atrs.get(usernameField);
        username = (String) usernameAttribute.get();
    } catch (Exception e) {
    // Ignore.
    } finally {
        try {
            if (ctx != null) {
                ctx.close();
            }
        } catch (Exception ignored) {
        // Ignore.
        }
    }
    return username;
}
Also used : Attribute(javax.naming.directory.Attribute) Attributes(javax.naming.directory.Attributes) SearchControls(javax.naming.directory.SearchControls) NamingEnumeration(javax.naming.NamingEnumeration) SearchResult(javax.naming.directory.SearchResult) DirContext(javax.naming.directory.DirContext)

Example 74 with SearchResult

use of javax.naming.directory.SearchResult in project neo4j by neo4j.

the class LdapRealm method findRoleNamesForUser.

// TODO: Extract to an LdapAuthorizationStrategy ? This ("group by attribute") is one of multiple possible strategies
Set<String> findRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
    Set<String> roleNames = new LinkedHashSet<>();
    SearchControls searchCtls = new SearchControls();
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    searchCtls.setReturningAttributes(membershipAttributeNames.toArray(new String[1]));
    // Use search argument to prevent potential code injection
    Object[] searchArguments = new Object[] { username };
    NamingEnumeration result = ldapContext.search(userSearchBase, userSearchFilter, searchArguments, searchCtls);
    if (result.hasMoreElements()) {
        SearchResult searchResult = (SearchResult) result.next();
        if (result.hasMoreElements()) {
            securityLog.warn(securityLog.isDebugEnabled() ? withRealm("LDAP user search for user principal '%s' is ambiguous. The first match that will " + "be checked for group membership is '%s' but the search also matches '%s'. " + "Please check your LDAP realm configuration.", username, searchResult.toString(), result.next().toString()) : withRealm("LDAP user search for user principal '%s' is ambiguous. The search matches more " + "than one entry. Please check your LDAP realm configuration.", username));
        }
        Attributes attributes = searchResult.getAttributes();
        if (attributes != null) {
            NamingEnumeration attributeEnumeration = attributes.getAll();
            while (attributeEnumeration.hasMore()) {
                Attribute attribute = (Attribute) attributeEnumeration.next();
                String attributeId = attribute.getID();
                if (membershipAttributeNames.stream().anyMatch(attributeId::equalsIgnoreCase)) {
                    Collection<String> groupNames = LdapUtils.getAllAttributeValues(attribute);
                    Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
                    roleNames.addAll(rolesForGroups);
                }
            }
        }
    }
    return roleNames;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Attribute(javax.naming.directory.Attribute) Attributes(javax.naming.directory.Attributes) SearchControls(javax.naming.directory.SearchControls) NamingEnumeration(javax.naming.NamingEnumeration) SearchResult(javax.naming.directory.SearchResult)

Example 75 with SearchResult

use of javax.naming.directory.SearchResult in project neo4j by neo4j.

the class LdapRealmTest method shouldAllowMultipleGroupMembershipAttributes.

@Test
public void shouldAllowMultipleGroupMembershipAttributes() throws NamingException {
    when(config.get(SecuritySettings.ldap_authorization_user_search_filter)).thenReturn("{0}");
    when(config.get(SecuritySettings.ldap_authorization_group_membership_attribute_names)).thenReturn(asList("attr0", "attr1", "attr2"));
    when(config.get(SecuritySettings.ldap_authorization_group_to_role_mapping)).thenReturn("group1=role1;group2=role2,role3");
    LdapContext ldapContext = mock(LdapContext.class);
    NamingEnumeration result = mock(NamingEnumeration.class);
    SearchResult searchResult = mock(SearchResult.class);
    Attributes attributes = mock(Attributes.class);
    Attribute attribute1 = mock(Attribute.class);
    Attribute attribute2 = mock(Attribute.class);
    Attribute attribute3 = mock(Attribute.class);
    NamingEnumeration attributeEnumeration = mock(NamingEnumeration.class);
    NamingEnumeration groupEnumeration1 = mock(NamingEnumeration.class);
    NamingEnumeration groupEnumeration2 = mock(NamingEnumeration.class);
    NamingEnumeration groupEnumeration3 = mock(NamingEnumeration.class);
    // Mock ldap search result "attr1" contains "group1" and "attr2" contains "group2" (a bit brittle...)
    // "attr0" is non-existing and should have no effect
    when(ldapContext.search(anyString(), anyString(), anyObject(), anyObject())).thenReturn(result);
    when(result.hasMoreElements()).thenReturn(true, false);
    when(result.next()).thenReturn(searchResult);
    when(searchResult.getAttributes()).thenReturn(attributes);
    when(attributes.getAll()).thenReturn(attributeEnumeration);
    when(attributeEnumeration.hasMore()).thenReturn(true, true, false);
    when(attributeEnumeration.next()).thenReturn(attribute1, attribute2, attribute3);
    // This attribute should yield role1
    when(attribute1.getID()).thenReturn("attr1");
    when(attribute1.getAll()).thenReturn(groupEnumeration1);
    when(groupEnumeration1.hasMore()).thenReturn(true, false);
    when(groupEnumeration1.next()).thenReturn("group1");
    // This attribute should yield role2 and role3
    when(attribute2.getID()).thenReturn("attr2");
    when(attribute2.getAll()).thenReturn(groupEnumeration2);
    when(groupEnumeration2.hasMore()).thenReturn(true, false);
    when(groupEnumeration2.next()).thenReturn("group2");
    // This attribute should have no effect
    when(attribute3.getID()).thenReturn("attr3");
    when(attribute3.getAll()).thenReturn(groupEnumeration3);
    when(groupEnumeration3.hasMore()).thenReturn(true, false);
    when(groupEnumeration3.next()).thenReturn("groupWithNoRole");
    // When
    LdapRealm realm = new LdapRealm(config, securityLog, secureHasher);
    Set<String> roles = realm.findRoleNamesForUser("username", ldapContext);
    // Then
    assertThat(roles, hasItems("role1", "role2", "role3"));
}
Also used : Attribute(javax.naming.directory.Attribute) Attributes(javax.naming.directory.Attributes) NamingEnumeration(javax.naming.NamingEnumeration) SearchResult(javax.naming.directory.SearchResult) Matchers.anyString(org.mockito.Matchers.anyString) LdapContext(javax.naming.ldap.LdapContext) Test(org.junit.Test)

Aggregations

SearchResult (javax.naming.directory.SearchResult)95 SearchControls (javax.naming.directory.SearchControls)63 NamingException (javax.naming.NamingException)43 Attributes (javax.naming.directory.Attributes)35 Attribute (javax.naming.directory.Attribute)32 ArrayList (java.util.ArrayList)29 DirContext (javax.naming.directory.DirContext)27 NamingEnumeration (javax.naming.NamingEnumeration)24 InitialDirContext (javax.naming.directory.InitialDirContext)16 Test (org.junit.Test)15 LdapContext (javax.naming.ldap.LdapContext)13 IOException (java.io.IOException)9 BasicAttributes (javax.naming.directory.BasicAttributes)9 DistinguishedName (org.springframework.ldap.core.DistinguishedName)9 DirContextAdapter (org.springframework.ldap.core.DirContextAdapter)7 HashMap (java.util.HashMap)6 HashSet (java.util.HashSet)6 Name (javax.naming.Name)6 BasicAttribute (javax.naming.directory.BasicAttribute)6 PartialResultException (javax.naming.PartialResultException)5