--- activemq-5.6.0/activemq-jaas/src/main/java/org/apache/activemq/jaas/LDAPLoginModule.java 2012-09-11 01:12:25.000000000 +0200 +++ activemq-5.6.0/activemq-jaas/src/main/java/org/apache/activemq/jaas/LDAPLoginModule.java.CVE-2015-6524 2015-01-15 08:57:10.000000000 +0100 @@ -17,22 +17,13 @@ package org.apache.activemq.jaas; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.security.Principal; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.naming.AuthenticationException; -import javax.naming.CommunicationException; -import javax.naming.Context; -import javax.naming.Name; -import javax.naming.NameParser; -import javax.naming.NamingEnumeration; -import javax.naming.NamingException; +import java.util.*; + +import javax.naming.*; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; @@ -71,6 +62,8 @@ private static final String ROLE_SEARCH_MATCHING = "roleSearchMatching"; private static final String ROLE_SEARCH_SUBTREE = "roleSearchSubtree"; private static final String USER_ROLE_NAME = "userRoleName"; + private static final String EXPAND_ROLES = "expandRoles"; + private static final String EXPAND_ROLES_MATCHING = "expandRolesMatching"; private static Logger log = LoggerFactory.getLogger(LDAPLoginModule.class); @@ -102,7 +95,10 @@ new LDAPLoginProperty (ROLE_SEARCH_MATCHING, (String)options.get(ROLE_SEARCH_MATCHING)), new LDAPLoginProperty (ROLE_SEARCH_SUBTREE, (String)options.get(ROLE_SEARCH_SUBTREE)), new LDAPLoginProperty (USER_ROLE_NAME, (String)options.get(USER_ROLE_NAME)), - }; + new LDAPLoginProperty (EXPAND_ROLES, (String) options.get(EXPAND_ROLES)), + new LDAPLoginProperty (EXPAND_ROLES_MATCHING, (String) options.get(EXPAND_ROLES_MATCHING)), + + }; } @Override @@ -194,7 +190,7 @@ try { String filter = userSearchMatchingFormat.format(new String[] { - username + doRFC2254Encoding(username) }); SearchControls constraints = new SearchControls(); if (userSearchSubtreeBool) { @@ -231,13 +227,43 @@ if (results.hasMore()) { // ignore for now } - NameParser parser = context.getNameParser(""); - Name contextName = parser.parse(context.getNameInNamespace()); - Name baseName = parser.parse(getLDAPPropertyValue(USER_BASE)); - Name entryName = parser.parse(result.getName()); - Name name = contextName.addAll(baseName); - name = name.addAll(entryName); - String dn = name.toString(); + + String dn; + if (result.isRelative()) { + log.debug("LDAP returned a relative name: {}", result.getName()); + + NameParser parser = context.getNameParser(""); + Name contextName = parser.parse(context.getNameInNamespace()); + Name baseName = parser.parse(getLDAPPropertyValue(USER_BASE)); + Name entryName = parser.parse(result.getName()); + Name name = contextName.addAll(baseName); + name = name.addAll(entryName); + dn = name.toString(); + } else { + log.debug("LDAP returned an absolute name: {}", result.getName()); + + try { + URI uri = new URI(result.getName()); + String path = uri.getPath(); + + if (path.startsWith("/")) { + dn = path.substring(1); + } else { + dn = path; + } + } catch (URISyntaxException e) { + if (context != null) { + close(context); + } + FailedLoginException ex = new FailedLoginException("Error parsing absolute name as URI."); + ex.initCause(e); + throw ex; + } + } + + if (log.isDebugEnabled()) { + log.debug("Using DN [" + dn + "] for binding."); + } Attributes attrs = result.getAttributes(); if (attrs == null) { @@ -281,8 +307,10 @@ List list = currentRoles; MessageFormat roleSearchMatchingFormat; boolean roleSearchSubtreeBool; + boolean expandRolesBool; roleSearchMatchingFormat = new MessageFormat(getLDAPPropertyValue(ROLE_SEARCH_MATCHING)); roleSearchSubtreeBool = Boolean.valueOf(getLDAPPropertyValue(ROLE_SEARCH_SUBTREE)).booleanValue(); + expandRolesBool = Boolean.valueOf(getLDAPPropertyValue(EXPAND_ROLES)).booleanValue(); if (list == null) { list = new ArrayList(); @@ -291,7 +319,7 @@ return list; } String filter = roleSearchMatchingFormat.format(new String[] { - doRFC2254Encoding(dn), username + doRFC2254Encoding(dn), doRFC2254Encoding(username) }); SearchControls constraints = new SearchControls(); @@ -306,17 +334,40 @@ log.debug(" base DN: " + getLDAPPropertyValue(ROLE_BASE)); log.debug(" filter: " + filter); } + HashSet haveSeenNames = new HashSet(); + Queue pendingNameExpansion = new LinkedList(); NamingEnumeration results = context.search(getLDAPPropertyValue(ROLE_BASE), filter, constraints); while (results.hasMore()) { SearchResult result = results.next(); Attributes attrs = result.getAttributes(); + if (expandRolesBool) { + haveSeenNames.add(result.getNameInNamespace()); + pendingNameExpansion.add(result.getNameInNamespace()); + } if (attrs == null) { continue; } list = addAttributeValues(getLDAPPropertyValue(ROLE_NAME), attrs, list); } + if (expandRolesBool) { + MessageFormat expandRolesMatchingFormat = new MessageFormat(getLDAPPropertyValue(EXPAND_ROLES_MATCHING)); + while (!pendingNameExpansion.isEmpty()) { + String name = pendingNameExpansion.remove(); + filter = expandRolesMatchingFormat.format(new String[]{name}); + results = context.search(getLDAPPropertyValue(ROLE_BASE), filter, constraints); + while (results.hasMore()) { + SearchResult result = results.next(); + name = result.getNameInNamespace(); + if (!haveSeenNames.contains(name)) { + Attributes attrs = result.getAttributes(); + list = addAttributeValues(getLDAPPropertyValue(ROLE_NAME), attrs, list); + haveSeenNames.add(name); + pendingNameExpansion.add(name); + } + } + } + } return list; - } protected String doRFC2254Encoding(String inputString) { @@ -408,9 +459,14 @@ env.put(Context.INITIAL_CONTEXT_FACTORY, getLDAPPropertyValue(INITIAL_CONTEXT_FACTORY)); if (isLoginPropertySet(CONNECTION_USERNAME)) { env.put(Context.SECURITY_PRINCIPAL, getLDAPPropertyValue(CONNECTION_USERNAME)); + } else { + throw new NamingException("Empty username is not allowed"); } + if (isLoginPropertySet(CONNECTION_PASSWORD)) { env.put(Context.SECURITY_CREDENTIALS, getLDAPPropertyValue(CONNECTION_PASSWORD)); + } else { + throw new NamingException("Empty password is not allowed"); } env.put(Context.SECURITY_PROTOCOL, getLDAPPropertyValue(CONNECTION_PROTOCOL)); env.put(Context.PROVIDER_URL, getLDAPPropertyValue(CONNECTION_URL)); @@ -433,7 +489,7 @@ private boolean isLoginPropertySet(String propertyName) { for (int i=0; i < config.length; i++ ) { - if (config[i].getPropertyName() == propertyName && config[i].getPropertyValue() != null) + if (config[i].getPropertyName() == propertyName && (config[i].getPropertyValue() != null && !"".equals(config[i].getPropertyValue()))) return true; } return false;