Blame activemq-5.6.0-jaas-CVE-2015-6524.patch

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