[jboss-cvs] JBossAS SVN: r75352 - projects/security/security-negotiation/trunk/jboss-negotiation/src/main/java/org/jboss/security/negotiation/spnego.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Jul 3 14:02:34 EDT 2008
Author: darran.lofthouse at jboss.com
Date: 2008-07-03 14:02:34 -0400 (Thu, 03 Jul 2008)
New Revision: 75352
Modified:
projects/security/security-negotiation/trunk/jboss-negotiation/src/main/java/org/jboss/security/negotiation/spnego/AdvancedLdapLoginModule.java
Log:
[SECURITY-133] Added role search.
Modified: projects/security/security-negotiation/trunk/jboss-negotiation/src/main/java/org/jboss/security/negotiation/spnego/AdvancedLdapLoginModule.java
===================================================================
--- projects/security/security-negotiation/trunk/jboss-negotiation/src/main/java/org/jboss/security/negotiation/spnego/AdvancedLdapLoginModule.java 2008-07-03 15:51:14 UTC (rev 75351)
+++ projects/security/security-negotiation/trunk/jboss-negotiation/src/main/java/org/jboss/security/negotiation/spnego/AdvancedLdapLoginModule.java 2008-07-03 18:02:34 UTC (rev 75352)
@@ -33,6 +33,8 @@
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
@@ -88,8 +90,21 @@
private static final String BASE_FILTER = "baseFilter";
- private static final String SEARCH_TIME_LIMIT = "searchTimeLimit";
+ private static final String SEARCH_TIME_LIMIT = "searchTimerolesCtxDNLimit";
+ // Role Search Settings
+ private static final String ROLES_CTS_DN = "rolesCtxDN";
+
+ private static final String ROLE_FILTER = "roleFilter";
+
+ private static final String RECURSE_ROLES = "recurseRoles";
+
+ private static final String ROLE_ATTRIBUTE_ID = "roleAttributeID";
+
+ private static final String ROLE_ATTRIBUTE_IS_DN = "roleAttributeIsDN";
+
+ private static final String ROLE_NAME_ATTRIBUTE_ID = "roleNameAttributeID";
+
/*
* Other Constants
*/
@@ -125,6 +140,23 @@
protected int searchTimeLimit = 10000;
+ protected SearchControls userSearchControls;
+
+ // Role Search Settings
+ protected String rolesCtxDN;
+
+ protected String roleFilter;
+
+ protected boolean recurseRoles;
+
+ protected SearchControls roleSearchControls;
+
+ protected String roleAttributeID;
+
+ protected boolean roleAttributeIsDN;
+
+ protected String roleNameAttributeID;
+
/*
* Module State
*/
@@ -135,7 +167,7 @@
private char[] credential;
private transient SimpleGroup userRoles = new SimpleGroup("Roles");
-
+
@Override
public void initialize(Subject subject, CallbackHandler handler, Map sharedState, Map options)
{
@@ -163,6 +195,30 @@
log.warn("Failed to parse: " + temp + ", using searchTimeLimit=" + searchTimeLimit);
}
}
+
+ userSearchControls = new SearchControls();
+ userSearchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ userSearchControls.setReturningAttributes(new String[0]);
+ userSearchControls.setTimeLimit(searchTimeLimit);
+
+ rolesCtxDN = (String) options.get(ROLES_CTS_DN);
+ roleFilter = (String) options.get(ROLE_FILTER);
+
+ temp = (String) options.get(RECURSE_ROLES);
+ recurseRoles = Boolean.parseBoolean(temp);
+
+ roleSearchControls = new SearchControls();
+ roleSearchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ roleSearchControls.setReturningAttributes(new String[0]);
+ roleSearchControls.setTimeLimit(searchTimeLimit);
+
+ roleAttributeID = (String) options.get(ROLE_ATTRIBUTE_ID);
+
+ temp = (String) options.get(ROLE_ATTRIBUTE_IS_DN);
+ roleAttributeIsDN = Boolean.parseBoolean(temp);
+
+ roleNameAttributeID = (String) options.get(ROLE_NAME_ATTRIBUTE_ID);
+
}
@Override
@@ -212,12 +268,18 @@
@Override
protected Group[] getRoleSets() throws LoginException
{
- Group[] roleSets = {userRoles};
+ Group[] roleSets =
+ {userRoles};
return roleSets;
}
protected Boolean authorize() throws Exception
{
+ /*
+ * TODO - General failures should throw LoginException, an
+ * actual failed authentication should throw FailedLoginException.
+ */
+
// Obtain the username and password
processIdentityAndCredential();
log.trace("Identity - " + getIdentity().getName());
@@ -233,16 +295,28 @@
}
}
- LdapContext searchContext = constructLdapContext(bindDn, bindCredential, bindAuthentication);
- log.debug("Obtained LdapContext");
+ LdapContext searchContext = null;
- // Search for user in LDAP
- String userDN = findUserDN(searchContext);
+ try
+ {
+ searchContext = constructLdapContext(bindDn, bindCredential, bindAuthentication);
+ log.debug("Obtained LdapContext");
- // If authentication required authenticate as user
- // Search for roles in LDAP
+ // Search for user in LDAP
+ String userDN = findUserDN(searchContext);
- return Boolean.FALSE;
+ // If authentication required authenticate as user
+ // TODO
+
+ // Search for roles in LDAP
+ rolesSearch(searchContext, userDN);
+ }
+ finally
+ {
+ if (searchContext != null)
+ searchContext.close();
+ }
+ return Boolean.TRUE;
}
/**
@@ -280,7 +354,6 @@
String password = null;
callbackHandler.handle(callbacks);
-
String username = nc.getName();
identity = createIdentity(username);
credential = pc.getPassword();
@@ -347,16 +420,12 @@
protected String findUserDN(LdapContext ctx) throws Exception
{
- SearchControls constraints = new SearchControls();
- constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
- constraints.setReturningAttributes(new String[0]);
- constraints.setTimeLimit(searchTimeLimit);
NamingEnumeration results = null;
Object[] filterArgs =
{getIdentity().getName()};
- results = ctx.search(baseCtxDN, baseFilter, filterArgs, constraints);
+ results = ctx.search(baseCtxDN, baseFilter, filterArgs, userSearchControls);
if (results.hasMore() == false)
{
results.close();
@@ -378,6 +447,74 @@
return userDN;
}
+ protected void rolesSearch(LdapContext searchContext, String dn) throws NamingException
+ {
+ Object[] filterArgs =
+ {getIdentity().getName(), dn};
+
+ NamingEnumeration results = searchContext.search(rolesCtxDN, roleFilter, filterArgs, roleSearchControls);
+ try
+ {
+ while (results.hasMore())
+ {
+ SearchResult sr = (SearchResult) results.next();
+ String resultDN = canonicalize(sr.getName());
+
+ log.debug("resultDN = " + resultDN);
+
+ String[] attrNames =
+ {roleAttributeID};
+
+ Attributes result = searchContext.getAttributes(resultDN, attrNames);
+ if (result != null && result.size() > 0)
+ {
+ Attribute roles = result.get(roleAttributeID);
+ for (int n = 0; n < roles.size(); n++)
+ {
+ String roleName = (String) roles.get(n);
+ if (roleAttributeIsDN)
+ {
+ // Query the roleDN location for the value of roleNameAttributeID
+ String roleDN = roleName;
+ 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);
+ }
+ }
+ else
+ {
+ // The role attribute value is the role name
+ addRole(roleName);
+ }
+ }
+
+ }
+ }
+ }
+ finally
+ {
+ if (results != null)
+ results.close();
+ }
+
+ }
+
protected void traceLdapEnv(Properties env)
{
if (log.isTraceEnabled())
@@ -391,6 +528,40 @@
}
}
+ private String canonicalize(String searchResult)
+ {
+ String result = searchResult;
+ int len = searchResult.length();
+
+ if (searchResult.endsWith("\""))
+ {
+ result = searchResult.substring(0, len - 1) + "," + rolesCtxDN + "\"";
+ }
+ else
+ {
+ result = searchResult + "," + rolesCtxDN;
+ }
+ return result;
+ }
+
+ private void addRole(String roleName)
+ {
+ if (roleName != null)
+ {
+ try
+ {
+ Principal p = super.createIdentity(roleName);
+ if (log.isTraceEnabled())
+ log.trace("Assign user '" + getIdentity().getName() + "' to role " + roleName);
+ userRoles.addMember(p);
+ }
+ catch (Exception e)
+ {
+ log.debug("Failed to create principal: " + roleName, e);
+ }
+ }
+ }
+
private class AuthorizeAction implements PrivilegedAction<Boolean>
{
More information about the jboss-cvs-commits
mailing list