[jboss-cvs] JBossAS SVN: r103928 - projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Apr 13 14:33:55 EDT 2010
Author: darran.lofthouse at jboss.com
Date: 2010-04-13 14:33:55 -0400 (Tue, 13 Apr 2010)
New Revision: 103928
Added:
projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedADLoginModule.java
Modified:
projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedLdapLoginModule.java
Log:
[SECURITY-447] Add new login module to support Active Directory primary group of user.
Added: projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedADLoginModule.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedADLoginModule.java (rev 0)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedADLoginModule.java 2010-04-13 18:33:55 UTC (rev 103928)
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.security.negotiation;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Properties;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapContext;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.util.Base64;
+
+/**
+ * An extension of the AdvancedLdapLoginModule to also query the primary group
+ * of the user being authenticated - this is not discoverable using the usual
+ * member and memberOf attributes.
+ *
+ * @author darran.lofthouse at jboss.com
+ */
+public class AdvancedADLoginModule extends AdvancedLdapLoginModule
+{
+
+ private static final String PRIMARY_GROUP_ID = "primaryGroupID";
+
+ private static final String OBJECT_SID = "objectSid";
+
+ /*
+ * The rolesSearch method is called recursively, we need to ensure it is only called once
+ * as we are only looking for the primary group of the user.
+ */
+ private boolean skipPrimaryGroupSearch = false;
+
+ @Override
+ protected Properties createBaseProperties()
+ {
+ Properties env = super.createBaseProperties();
+ env.put("java.naming.ldap.attributes.binary", "objectSid");
+ return env;
+ }
+
+ @Override
+ protected void rolesSearch(LdapContext searchContext, String dn) throws LoginException
+ {
+ if (skipPrimaryGroupSearch == false)
+ {
+ skipPrimaryGroupSearch = true;
+
+ try
+ {
+ String[] attrNames =
+ {OBJECT_SID, PRIMARY_GROUP_ID};
+ Attributes result = searchContext.getAttributes(dn, attrNames);
+ Attribute primaryGroupIdAttribute = result.get(PRIMARY_GROUP_ID);
+ Attribute objectSidAttribute = result.get(OBJECT_SID);
+ if (primaryGroupIdAttribute != null && objectSidAttribute != null)
+ {
+ int primaryGroupId = Integer.parseInt((String) primaryGroupIdAttribute.get());
+ byte[] objectSid = (byte[]) objectSidAttribute.get();
+
+ /*
+ * The objectSid of the primary group can be found by taking the object sid
+ * of the user and replacing the last four bytes with the little endian representation
+ * of the primary group id - this new byte[] can then be used in the search.
+ */
+
+ byte[] searchObjectSid = new byte[objectSid.length];
+ System.arraycopy(objectSid, 0, searchObjectSid, 0, objectSid.length - 4);
+
+ ByteBuffer byteBuffer = ByteBuffer.wrap(searchObjectSid, objectSid.length - 4, 4);
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ byteBuffer.putInt(primaryGroupId);
+
+ if (log.isTraceEnabled())
+ {
+ String objectSidBase64 = Base64.encodeBytes(objectSid);
+ String searchObjectSidBase64 = Base64.encodeBytes(searchObjectSid);
+ log.trace("Using base objectSid " + objectSidBase64 + " and replaced with primary group id "
+ + primaryGroupId + " to create new search objectSid " + searchObjectSidBase64);
+ }
+
+ String primaryGroupFilter = "(objectSid={0})";
+ Object[] filterArgs =
+ {searchObjectSid};
+
+ NamingEnumeration searchResults = searchContext.search(baseCtxDN, primaryGroupFilter, filterArgs,
+ roleSearchControls);
+ if (searchResults.hasMore() == true)
+ {
+ SearchResult searchResult = (SearchResult) searchResults.next();
+ String baseResultDN = canonicalize(searchResult.getName());
+ String resultDN = "\"" + baseResultDN + "\"";
+
+ if (log.isTraceEnabled())
+ {
+ log.trace("Search found primary group " + resultDN);
+ }
+
+ loadRoleByRoleNameAttributeID(searchContext, resultDN);
+ recurseRolesSearch(searchContext, baseResultDN);
+ }
+
+ }
+ else
+ {
+ log.trace("primaryGroupIdAttribute or objectSidAttribute was null, skipping primary group search.");
+ }
+
+ super.rolesSearch(searchContext, dn);
+ }
+ catch (NamingException e)
+ {
+ log.trace("Failed to load primary group", e);
+ }
+ finally
+ {
+ skipPrimaryGroupSearch = false;
+ }
+ }
+ else
+ {
+ super.rolesSearch(searchContext, dn);
+ }
+
+ }
+}
Property changes on: projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedADLoginModule.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedLdapLoginModule.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedLdapLoginModule.java 2010-04-13 17:44:51 UTC (rev 103927)
+++ projects/security/security-negotiation/trunk/jboss-negotiation-extras/src/main/java/org/jboss/security/negotiation/AdvancedLdapLoginModule.java 2010-04-13 18:33:55 UTC (rev 103928)
@@ -426,13 +426,7 @@
protected LdapContext constructLdapContext(String dn, Object credential, String authentication)
throws LoginException
{
- Properties env = new Properties();
- Iterator iter = options.entrySet().iterator();
- while (iter.hasNext())
- {
- Entry entry = (Entry) iter.next();
- env.put(entry.getKey(), entry.getValue());
- }
+ Properties env = createBaseProperties();
// Set defaults for key values if they are missing
String factoryName = env.getProperty(Context.INITIAL_CONTEXT_FACTORY);
@@ -488,6 +482,19 @@
}
}
+ protected Properties createBaseProperties()
+ {
+ Properties env = new Properties();
+ Iterator iter = options.entrySet().iterator();
+ while (iter.hasNext())
+ {
+ Entry entry = (Entry) iter.next();
+ env.put(entry.getKey(), entry.getValue());
+ }
+
+ return env;
+ }
+
protected String findUserDN(LdapContext ctx) throws LoginException
{
@@ -632,42 +639,11 @@
if (roleAttributeIsDN)
{
// Query the roleDN location for the value of roleNameAttributeID
- String roleDN = roleName;
- roleDN = "\"" + roleDN + "\"";
- String[] returnAttribute =
- {roleNameAttributeID};
- log.trace("Using roleDN: " + roleDN);
- try
- {
- Attributes result2 = searchContext.getAttributes(roleDN, returnAttribute);
- Attribute roles2 = result2.get(roleNameAttributeID);
- if (roles2 != null)
- {
- for (int m = 0; m < roles2.size(); m++)
- {
- roleName = (String) roles2.get(m);
- addRole(roleName);
- }
- }
- }
- catch (NamingException e)
- {
- log.trace("Failed to query roleNameAttrName", e);
- }
+ String baseRoleDN = roleName;
+ String roleDN = "\"" + baseRoleDN + "\"";
- if (recurseRoles)
- {
- if (processedRoleDNs.contains(roleDN) == false)
- {
- processedRoleDNs.add(roleDN);
- log.trace("Recursive search for '" + roleDN + "'");
- rolesSearch(searchContext, roleDN);
- }
- else
- {
- log.trace("Already visited role '" + roleDN + "' ending recursion.");
- }
- }
+ loadRoleByRoleNameAttributeID(searchContext, roleDN);
+ recurseRolesSearch(searchContext, baseRoleDN);
}
else
{
@@ -677,6 +653,47 @@
}
}
}
+
+ protected void loadRoleByRoleNameAttributeID(LdapContext searchContext, String roleDN)
+ {
+ String[] returnAttribute =
+ {roleNameAttributeID};
+ log.trace("Using roleDN: " + roleDN);
+ try
+ {
+ Attributes result2 = searchContext.getAttributes(roleDN, returnAttribute);
+ Attribute roles2 = result2.get(roleNameAttributeID);
+ if (roles2 != null)
+ {
+ for (int m = 0; m < roles2.size(); m++)
+ {
+ String roleName = (String) roles2.get(m);
+ addRole(roleName);
+ }
+ }
+ }
+ catch (NamingException e)
+ {
+ log.trace("Failed to query roleNameAttrName", e);
+ }
+ }
+
+ protected void recurseRolesSearch(LdapContext searchContext, String roleDN) throws LoginException
+ {
+ if (recurseRoles)
+ {
+ if (processedRoleDNs.contains(roleDN) == false)
+ {
+ processedRoleDNs.add(roleDN);
+ log.trace("Recursive search for '" + roleDN + "'");
+ rolesSearch(searchContext, roleDN);
+ }
+ else
+ {
+ log.trace("Already visited role '" + roleDN + "' ending recursion.");
+ }
+ }
+ }
protected void traceLdapEnv(Properties env)
{
@@ -691,7 +708,7 @@
}
}
- private String canonicalize(String searchResult)
+ protected String canonicalize(String searchResult)
{
String result = searchResult;
int len = searchResult.length();
More information about the jboss-cvs-commits
mailing list