Blob Blame History Raw
--- 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<String> 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<String>();
@@ -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<String> haveSeenNames = new HashSet<String>();
+        Queue<String> pendingNameExpansion = new LinkedList<String>();
         NamingEnumeration<SearchResult> 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;