Search in sources :

Example 96 with LdapName

use of javax.naming.ldap.LdapName in project Openfire by igniterealtime.

the class LdapManagerTest method testGetProviderURL.

/**
 * Test if {@link LdapManager#getProviderURL(LdapName)} generates a URL using basic attributes (happy-flow test).
 */
@Test
public void testGetProviderURL() throws Exception {
    // Setup fixture.
    final Map<String, String> properties = new HashMap<>();
    properties.put("ldap.host", "localhost");
    properties.put("ldap.port", "389");
    final LdapManager manager = new LdapManager(properties);
    final LdapName name = new LdapName("ou=people,dc=example,dc=org");
    // Execute system under test.
    final String result = manager.getProviderURL(name);
    // Verify result.
    assertEquals("ldaps://localhost:389/ou=people,dc=example,dc=org", result);
}
Also used : HashMap(java.util.HashMap) LdapName(javax.naming.ldap.LdapName) Test(org.junit.Test)

Example 97 with LdapName

use of javax.naming.ldap.LdapName in project Openfire by igniterealtime.

the class LdapGroupProvider method processGroup.

private Group processGroup(LdapContext ctx, Attributes a, Set<String> membersToIgnore) throws NamingException {
    XMPPServer server = XMPPServer.getInstance();
    String serverName = server.getServerInfo().getXMPPDomain();
    // Build `3 groups.
    // group 1: uid=
    // group 2: rest of the text until first comma
    // group 3: rest of the text
    Pattern pattern = Pattern.compile("(?i)(^" + manager.getUsernameField() + "=)([^,]+)(.+)");
    // We have to process Active Directory differently.
    boolean isAD = manager.getUsernameField().equals("sAMAccountName");
    String[] returningAttributes = isAD ? new String[] { "distinguishedName", manager.getUsernameField() } : new String[] { manager.getUsernameField() };
    SearchControls searchControls = new SearchControls();
    searchControls.setReturningAttributes(returningAttributes);
    // See if recursive searching is enabled. Otherwise, only search one level.
    if (manager.isSubTreeSearch()) {
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    } else {
        searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
    }
    String name;
    String description;
    try {
        name = ((String) ((a.get(manager.getGroupNameField())).get()));
    } catch (Exception e) {
        name = "";
    }
    try {
        description = ((String) ((a.get(manager.getGroupDescriptionField())).get()));
    } catch (Exception e) {
        description = "";
    }
    Set<JID> members = new TreeSet<>();
    Attribute memberField = a.get(manager.getGroupMemberField());
    Log.debug("Loading members of group: {}", name);
    if (memberField != null) {
        NamingEnumeration ne = memberField.getAll();
        while (ne.hasMore()) {
            String username = (String) ne.next();
            LdapName userDN = null;
            // If not posix mode, each group member is stored as a full DN.
            if (!manager.isPosixMode()) {
                // Create an LDAP name with the full DN.
                userDN = new LdapName(username);
                try {
                    // Try to find the username with a regex pattern match.
                    Matcher matcher = pattern.matcher(username);
                    if (matcher.matches() && matcher.groupCount() == 3) {
                        // The username is in the DN, no additional search needed
                        username = matcher.group(2);
                    } else // The regex pattern match failed. This will happen if the
                    // the member DN's don't use the standard username field. For
                    // example, Active Directory has a username field of
                    // sAMAccountName, but stores group members as "CN=...".
                    {
                        // Turn the LDAP name into something we can use in a
                        // search by stripping off the comma.
                        StringBuilder userFilter = new StringBuilder();
                        userFilter.append("(&(");
                        userFilter.append(userDN.get(userDN.size() - 1));
                        userFilter.append(')');
                        userFilter.append(MessageFormat.format(manager.getSearchFilter(), "*"));
                        userFilter.append(')');
                        NamingEnumeration usrAnswer = ctx.search("", userFilter.toString(), searchControls);
                        if (usrAnswer.hasMoreElements()) {
                            SearchResult searchResult = null;
                            // Iterate through the entire set to find a matching distinguished name.
                            while (usrAnswer.hasMoreElements()) {
                                searchResult = (SearchResult) usrAnswer.nextElement();
                                Attributes attrs = searchResult.getAttributes();
                                if (isAD) {
                                    Attribute userdnAttr = attrs.get("distinguishedName");
                                    if (username.equals((String) userdnAttr.get())) {
                                        // Exact match found, use it.
                                        username = (String) attrs.get(manager.getUsernameField()).get();
                                        break;
                                    }
                                } else {
                                    // No iteration occurs here, which is probably a bug.
                                    username = (String) attrs.get(manager.getUsernameField()).get();
                                    break;
                                }
                            }
                        }
                        // Close the enumeration.
                        usrAnswer.close();
                    }
                } catch (Exception e) {
                    // TODO: A NPE is occuring here
                    Log.error(e.getMessage(), e);
                }
            }
            // it passes the filter.
            try {
                if (!membersToIgnore.contains(username)) {
                    JID userJID;
                    int position = username.indexOf("@" + serverName);
                    // Create JID of local user if JID does not match a component's JID
                    if (position == -1) {
                        // In order to lookup a username from the manager, the username
                        // must be a properly escaped JID node.
                        String escapedUsername = JID.escapeNode(username);
                        // Check if escaped username is valid
                        userManager.getUser(escapedUsername);
                        // No exception, so the user must exist. Add the user as a group
                        // member using the escaped username.
                        userJID = server.createJID(escapedUsername, null);
                    } else {
                        // This is a JID of a component or node of a server's component
                        String node = username.substring(0, position);
                        String escapedUsername = JID.escapeNode(node);
                        userJID = new JID(escapedUsername + "@" + serverName);
                    }
                    members.add(userJID);
                }
            } catch (UserNotFoundException e) {
                // not a user!
                // maybe it is a group?
                boolean isGroup = false;
                if (manager.isFlattenNestedGroups()) {
                    if (manager.isPosixMode()) {
                        // in posix mode, the DN has not been set...
                        // Look up the userDN using the UID
                        String userDNStr = manager.retrieveSingle(null, "(" + manager.getUsernameField() + "=" + LdapManager.sanitizeSearchFilter(username) + ")", true);
                        if (userDNStr != null)
                            userDN = new LdapName(userDNStr);
                    }
                    if (userDN != null && manager.isGroupDN(userDN)) {
                        isGroup = true;
                        if (!membersToIgnore.contains(userDN.toString()) && !membersToIgnore.contains(username)) {
                            // prevent endless adding of cyclic referenced groups
                            membersToIgnore.add(username);
                            membersToIgnore.add(userDN.toString());
                            // it's a sub group not already added, so add its members
                            Log.debug("Adding members of sub-group: {}", userDN);
                            Group subGroup = getGroupByDN(userDN, membersToIgnore);
                            members.addAll(subGroup.getMembers());
                        }
                    }
                }
                if (!isGroup) {
                    // So, we want to simply ignore the user as a group member.
                    if (manager.isDebugEnabled()) {
                        Log.debug("LdapGroupProvider: User not found: " + username);
                    }
                }
            }
        }
        // Close the enumeration.
        ne.close();
    }
    if (manager.isDebugEnabled()) {
        Log.debug("LdapGroupProvider: Adding group \"" + name + "\" with " + members.size() + " members.");
    }
    Collection<JID> admins = Collections.emptyList();
    return new Group(name, description, members, admins);
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) Pattern(java.util.regex.Pattern) Group(org.jivesoftware.openfire.group.Group) JID(org.xmpp.packet.JID) Attribute(javax.naming.directory.Attribute) Matcher(java.util.regex.Matcher) Attributes(javax.naming.directory.Attributes) NamingEnumeration(javax.naming.NamingEnumeration) SearchResult(javax.naming.directory.SearchResult) NamingException(javax.naming.NamingException) GroupNotFoundException(org.jivesoftware.openfire.group.GroupNotFoundException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) LdapName(javax.naming.ldap.LdapName) XMPPServer(org.jivesoftware.openfire.XMPPServer) TreeSet(java.util.TreeSet) SearchControls(javax.naming.directory.SearchControls)

Example 98 with LdapName

use of javax.naming.ldap.LdapName in project druid by druid-io.

the class LDAPCredentialsValidator method validateCredentials.

@Override
public AuthenticationResult validateCredentials(String authenticatorName, String authorizerName, String username, char[] password) {
    SearchResult userResult;
    LdapName userDn;
    Map<String, Object> contextMap = new HashMap<>();
    LdapUserPrincipal principal = this.cache.getOrExpire(username);
    if (principal != null && principal.hasSameCredentials(password)) {
        contextMap.put(BasicAuthUtils.SEARCH_RESULT_CONTEXT_KEY, principal.getSearchResult());
        return new AuthenticationResult(username, authorizerName, authenticatorName, contextMap);
    } else {
        ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            // Set the context classloader same as the loader of this class so that BasicSecuritySSLSocketFactory
            // class can be found
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
            InitialDirContext dirContext = new InitialDirContext(bindProperties(this.ldapConfig));
            try {
                userResult = getLdapUserObject(this.ldapConfig, dirContext, username);
                if (userResult == null) {
                    LOG.debug("User not found: %s", username);
                    return null;
                }
                userDn = new LdapName(userResult.getNameInNamespace());
            } finally {
                try {
                    dirContext.close();
                } catch (Exception ignored) {
                // ignored
                }
            }
        } catch (NamingException e) {
            LOG.error(e, "Exception during user lookup");
            return null;
        } finally {
            Thread.currentThread().setContextClassLoader(currentClassLoader);
        }
        if (!validatePassword(this.ldapConfig, userDn, password)) {
            LOG.debug("Password incorrect for LDAP user %s", username);
            throw new BasicSecurityAuthenticationException("User LDAP authentication failed.");
        }
        byte[] salt = BasicAuthUtils.generateSalt();
        byte[] hash = BasicAuthUtils.hashPassword(password, salt, this.ldapConfig.getCredentialIterations());
        LdapUserPrincipal newPrincipal = new LdapUserPrincipal(username, new BasicAuthenticatorCredentials(salt, hash, this.ldapConfig.getCredentialIterations()), userResult);
        this.cache.put(username, newPrincipal);
        contextMap.put(BasicAuthUtils.SEARCH_RESULT_CONTEXT_KEY, userResult);
        return new AuthenticationResult(username, authorizerName, authenticatorName, contextMap);
    }
}
Also used : BasicSecurityAuthenticationException(org.apache.druid.security.basic.BasicSecurityAuthenticationException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) SearchResult(javax.naming.directory.SearchResult) InitialDirContext(javax.naming.directory.InitialDirContext) BasicSecurityAuthenticationException(org.apache.druid.security.basic.BasicSecurityAuthenticationException) NamingException(javax.naming.NamingException) AuthenticationException(javax.naming.AuthenticationException) LdapName(javax.naming.ldap.LdapName) AuthenticationResult(org.apache.druid.server.security.AuthenticationResult) BasicAuthenticatorCredentials(org.apache.druid.security.basic.authentication.entity.BasicAuthenticatorCredentials) NamingException(javax.naming.NamingException) LdapUserPrincipal(org.apache.druid.security.basic.authentication.LdapUserPrincipal)

Example 99 with LdapName

use of javax.naming.ldap.LdapName in project druid by druid-io.

the class LDAPRoleProvider method getRoles.

@Override
public Set<String> getRoles(String authorizerPrefix, AuthenticationResult authenticationResult) {
    Set<String> roleNames = new HashSet<>();
    Map<String, BasicAuthorizerGroupMapping> groupMappingMap = cacheManager.getGroupMappingMap(authorizerPrefix);
    if (groupMappingMap == null) {
        throw new IAE("Could not load groupMappingMap for authorizer [%s]", authorizerPrefix);
    }
    Map<String, BasicAuthorizerUser> userMap = cacheManager.getUserMap(authorizerPrefix);
    if (userMap == null) {
        throw new IAE("Could not load userMap for authorizer [%s]", authorizerPrefix);
    }
    // Get the groups assigned to the LDAP user
    SearchResult searchResult = Optional.ofNullable(authenticationResult.getContext()).map(contextMap -> contextMap.get(BasicAuthUtils.SEARCH_RESULT_CONTEXT_KEY)).map(p -> {
        if (p instanceof SearchResult) {
            return (SearchResult) p;
        } else {
            return null;
        }
    }).orElse(null);
    if (searchResult != null) {
        try {
            Set<LdapName> groupNamesFromLdap = getGroupsFromLdap(searchResult);
            if (groupNamesFromLdap.isEmpty()) {
                LOG.debug("User %s is not mapped to any groups", authenticationResult.getIdentity());
            } else {
                // Get the roles mapped to LDAP groups from the metastore.
                // This allows us to authorize groups LDAP user belongs
                roleNames.addAll(getRoles(groupMappingMap, groupNamesFromLdap));
            }
        } catch (NamingException e) {
            LOG.error(e, "Exception in looking up groups for user %s", authenticationResult.getIdentity());
        }
    }
    // Get the roles assigned to LDAP user from the metastore.
    // This allow us to authorize LDAP users regardless of whether they belong to any groups or not in LDAP.
    BasicAuthorizerUser user = userMap.get(authenticationResult.getIdentity());
    if (user != null) {
        roleNames.addAll(user.getRoles());
    }
    return roleNames;
}
Also used : Logger(org.apache.druid.java.util.common.logger.Logger) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) Arrays(java.util.Arrays) LdapName(javax.naming.ldap.LdapName) BasicAuthorizerRole(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerRole) BasicAuthUtils(org.apache.druid.security.basic.BasicAuthUtils) NamingException(javax.naming.NamingException) TreeSet(java.util.TreeSet) BasicAuthorizerUser(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerUser) AuthenticationResult(org.apache.druid.server.security.AuthenticationResult) HashSet(java.util.HashSet) JsonTypeName(com.fasterxml.jackson.annotation.JsonTypeName) Attribute(javax.naming.directory.Attribute) Locale(java.util.Locale) Map(java.util.Map) IAE(org.apache.druid.java.util.common.IAE) JacksonInject(com.fasterxml.jackson.annotation.JacksonInject) BasicAuthorizerCacheManager(org.apache.druid.security.basic.authorization.db.cache.BasicAuthorizerCacheManager) RE(org.apache.druid.java.util.common.RE) StringUtils(org.apache.druid.java.util.common.StringUtils) Set(java.util.Set) InvalidNameException(javax.naming.InvalidNameException) JsonCreator(com.fasterxml.jackson.annotation.JsonCreator) Optional(java.util.Optional) VisibleForTesting(com.google.common.annotations.VisibleForTesting) BasicAuthorizerGroupMapping(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerGroupMapping) SearchResult(javax.naming.directory.SearchResult) SearchResult(javax.naming.directory.SearchResult) IAE(org.apache.druid.java.util.common.IAE) LdapName(javax.naming.ldap.LdapName) BasicAuthorizerGroupMapping(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerGroupMapping) BasicAuthorizerUser(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerUser) NamingException(javax.naming.NamingException) HashSet(java.util.HashSet)

Example 100 with LdapName

use of javax.naming.ldap.LdapName in project druid by druid-io.

the class LDAPRoleProvider method getRoles.

@VisibleForTesting
public Set<String> getRoles(Map<String, BasicAuthorizerGroupMapping> groupMappingMap, Set<LdapName> groupNamesFromLdap) {
    Set<String> roles = new HashSet<>();
    if (groupMappingMap.size() == 0) {
        return roles;
    }
    for (LdapName groupName : groupNamesFromLdap) {
        for (Map.Entry<String, BasicAuthorizerGroupMapping> groupMappingEntry : groupMappingMap.entrySet()) {
            BasicAuthorizerGroupMapping groupMapping = groupMappingEntry.getValue();
            String mask = groupMapping.getGroupPattern();
            try {
                if (mask.startsWith("*,")) {
                    LdapName ln = new LdapName(mask.substring(2));
                    if (groupName.startsWith(ln)) {
                        roles.addAll(groupMapping.getRoles());
                    }
                } else if (mask.endsWith(",*")) {
                    LdapName ln = new LdapName(mask.substring(0, mask.length() - 2));
                    if (groupName.endsWith(ln)) {
                        roles.addAll(groupMapping.getRoles());
                    }
                } else {
                    LdapName ln = new LdapName(mask);
                    if (groupName.equals(ln)) {
                        roles.addAll(groupMapping.getRoles());
                    }
                }
            } catch (InvalidNameException e) {
                throw new RuntimeException(String.format(Locale.getDefault(), "Configuration problem - Invalid groupMapping '%s'", mask));
            }
        }
    }
    return roles;
}
Also used : BasicAuthorizerGroupMapping(org.apache.druid.security.basic.authorization.entity.BasicAuthorizerGroupMapping) InvalidNameException(javax.naming.InvalidNameException) Map(java.util.Map) HashSet(java.util.HashSet) LdapName(javax.naming.ldap.LdapName) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

LdapName (javax.naming.ldap.LdapName)103 Rdn (javax.naming.ldap.Rdn)48 InvalidNameException (javax.naming.InvalidNameException)32 NamingException (javax.naming.NamingException)26 Attribute (javax.naming.directory.Attribute)22 Attributes (javax.naming.directory.Attributes)14 SearchResult (javax.naming.directory.SearchResult)14 ArrayList (java.util.ArrayList)12 Test (org.junit.Test)10 LdapContext (javax.naming.ldap.LdapContext)9 IOException (java.io.IOException)7 List (java.util.List)7 X509Certificate (java.security.cert.X509Certificate)6 HashMap (java.util.HashMap)6 TreeSet (java.util.TreeSet)6 SearchControls (javax.naming.directory.SearchControls)6 HashSet (java.util.HashSet)5 NoSuchElementException (java.util.NoSuchElementException)5 InitialLdapContext (javax.naming.ldap.InitialLdapContext)5 X500Principal (javax.security.auth.x500.X500Principal)5