Search in sources :

Example 76 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 77 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 78 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 79 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 80 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)88 Rdn (javax.naming.ldap.Rdn)44 InvalidNameException (javax.naming.InvalidNameException)27 Attribute (javax.naming.directory.Attribute)18 NamingException (javax.naming.NamingException)17 Attributes (javax.naming.directory.Attributes)12 SearchResult (javax.naming.directory.SearchResult)10 Test (org.junit.Test)10 ArrayList (java.util.ArrayList)8 X509Certificate (java.security.cert.X509Certificate)6 HashMap (java.util.HashMap)6 IOException (java.io.IOException)5 Test (org.junit.jupiter.api.Test)5 PolyString (com.evolveum.midpoint.prism.polystring.PolyString)4 HashSet (java.util.HashSet)4 List (java.util.List)4 NoSuchElementException (java.util.NoSuchElementException)4 TreeSet (java.util.TreeSet)4 SearchControls (javax.naming.directory.SearchControls)4 SSLException (javax.net.ssl.SSLException)4