[jboss-cvs] Picketbox SVN: r456 - in branches/4.0.14.Final-bz-1005418: security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Sep 6 17:03:04 EDT 2013
Author: dehort
Date: 2013-09-06 17:03:04 -0400 (Fri, 06 Sep 2013)
New Revision: 456
Modified:
branches/4.0.14.Final-bz-1005418/
branches/4.0.14.Final-bz-1005418/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java
Log:
Backporting LDAP referral fix from EAP 6.1.0 [bz-1005418]
Property changes on: branches/4.0.14.Final-bz-1005418
___________________________________________________________________
Added: svn:mergeinfo
+ /trunk:380,391,414
Modified: branches/4.0.14.Final-bz-1005418/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java
===================================================================
--- branches/4.0.14.Final-bz-1005418/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java 2013-09-06 21:00:44 UTC (rev 455)
+++ branches/4.0.14.Final-bz-1005418/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java 2013-09-06 21:03:04 UTC (rev 456)
@@ -33,11 +33,13 @@
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
+import javax.naming.ReferralException;
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;
+import javax.naming.ldap.LdapContext;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
@@ -167,18 +169,46 @@
private static final String USERNAME_BEGIN_STRING = "usernameBeginString";
private static final String USERNAME_END_STRING = "usernameEndString";
private static final String ALLOW_EMPTY_PASSWORDS = "allowEmptyPasswords";
+ private static final String REFERRAL_USER_ATTRIBUTE_ID_TO_CHECK = "referralUserAttributeIDToCheck";
private static final String[] ALL_VALID_OPTIONS =
{
- ROLES_CTX_DN_OPT,ROLE_ATTRIBUTE_ID_OPT,
- ROLE_NAME_ATTRIBUTE_ID_OPT,PARSE_ROLE_NAME_FROM_DN_OPT,
- BIND_DN,BIND_CREDENTIAL,BASE_CTX_DN,BASE_FILTER_OPT,
- ROLE_FILTER_OPT,ROLE_RECURSION,DEFAULT_ROLE,
- SEARCH_TIME_LIMIT_OPT,SEARCH_SCOPE_OPT,SECURITY_DOMAIN_OPT,
- DISTINGUISHED_NAME_ATTRIBUTE_OPT,PARSE_USERNAME,USERNAME_BEGIN_STRING,USERNAME_END_STRING,
- ALLOW_EMPTY_PASSWORDS,
-
- Context.INITIAL_CONTEXT_FACTORY,Context.SECURITY_AUTHENTICATION,Context.SECURITY_PROTOCOL,
- Context.PROVIDER_URL,Context.SECURITY_PRINCIPAL,Context.SECURITY_CREDENTIALS
+ ROLES_CTX_DN_OPT,
+ ROLE_ATTRIBUTE_ID_OPT,
+ ROLE_ATTRIBUTE_IS_DN_OPT,
+ ROLE_NAME_ATTRIBUTE_ID_OPT,
+ PARSE_ROLE_NAME_FROM_DN_OPT,
+ BIND_DN,
+ BIND_CREDENTIAL,
+ BASE_CTX_DN,
+ BASE_FILTER_OPT,
+ ROLE_FILTER_OPT,
+ ROLE_RECURSION,
+ DEFAULT_ROLE,
+ SEARCH_TIME_LIMIT_OPT,
+ SEARCH_SCOPE_OPT,
+ SECURITY_DOMAIN_OPT,
+ DISTINGUISHED_NAME_ATTRIBUTE_OPT,
+ PARSE_USERNAME,
+ USERNAME_BEGIN_STRING,
+ USERNAME_END_STRING,
+ ALLOW_EMPTY_PASSWORDS,
+ REFERRAL_USER_ATTRIBUTE_ID_TO_CHECK,
+
+ Context.INITIAL_CONTEXT_FACTORY,
+ Context.OBJECT_FACTORIES,
+ Context.STATE_FACTORIES,
+ Context.URL_PKG_PREFIXES,
+ Context.PROVIDER_URL,
+ Context.DNS_URL,
+ Context.AUTHORITATIVE,
+ Context.BATCHSIZE,
+ Context.REFERRAL,
+ Context.SECURITY_PROTOCOL,
+ Context.SECURITY_AUTHENTICATION,
+ Context.SECURITY_PRINCIPAL,
+ Context.SECURITY_CREDENTIALS,
+ Context.LANGUAGE,
+ Context.APPLET
};
protected String bindDN;
@@ -214,10 +244,12 @@
protected String usernameBeginString;
protected String usernameEndString;
-
+
// simple flag to indicate is the validatePassword method was called
protected boolean isPasswordValidated = false;
+ protected String referralUserAttributeIDToCheck = null;
+
public LdapExtLoginModule()
{
}
@@ -378,6 +410,8 @@
roleNameAttributeID = (String) options.get(ROLE_NAME_ATTRIBUTE_ID_OPT);
if (roleNameAttributeID == null)
roleNameAttributeID = "name";
+
+ referralUserAttributeIDToCheck = (String) options.get(REFERRAL_USER_ATTRIBUTE_ID_TO_CHECK);
//JBAS-4619:Parse Role Name from DN
String parseRoleNameFromDNOption = (String) options.get(PARSE_ROLE_NAME_FROM_DN_OPT);
@@ -433,7 +467,6 @@
// Query for roles matching the role filter
SearchControls constraints = new SearchControls();
constraints.setSearchScope(searchScope);
- constraints.setReturningAttributes(new String[0]);
constraints.setTimeLimit(searchTimeLimit);
rolesSearch(ctx, constraints, username, userDN, recursion, 0);
}
@@ -472,14 +505,34 @@
NamingEnumeration results = null;
Object[] filterArgs = {user};
- results = ctx.search(baseDN, filter, filterArgs, constraints);
- if (results.hasMore() == false)
+
+ LdapContext ldapCtx = ctx;
+
+ boolean referralsLeft = true;
+ SearchResult sr = null;
+ while (referralsLeft) {
+ try {
+ results = ldapCtx.search(baseDN, filter, filterArgs, constraints);
+ while (results.hasMore()) {
+ sr = (SearchResult) results.next();
+ break;
+ }
+ referralsLeft = false;
+ }
+ catch (ReferralException e) {
+ ldapCtx = (LdapContext) e.getReferralContext();
+ if (results != null) {
+ results.close();
+ }
+ }
+ }
+
+ if (sr == null)
{
results.close();
throw PicketBoxMessages.MESSAGES.failedToFindBaseContextDN(baseDN);
}
-
- SearchResult sr = (SearchResult) results.next();
+
String name = sr.getName();
String userDN = null;
Attributes attrs = sr.getAttributes();
@@ -493,10 +546,12 @@
}
if (userDN == null)
{
- if (sr.isRelative() == true)
+ if (sr.isRelative() == true) {
userDN = name + ("".equals(baseDN) ? "" : "," + baseDN);
- else
+ }
+ else {
throw PicketBoxMessages.MESSAGES.unableToFollowReferralForAuth(name);
+ }
}
results.close();
@@ -521,98 +576,162 @@
@param nesting
@throws NamingException
*/
- protected void rolesSearch(InitialLdapContext ctx, SearchControls constraints, String user, String userDN,
+ protected void rolesSearch(LdapContext ctx, SearchControls constraints, String user, String userDN,
int recursionMax, int nesting) throws NamingException
{
+ LdapContext ldapCtx = ctx;
+
Object[] filterArgs = {user, userDN};
- NamingEnumeration results = ctx.search(rolesCtxDN, roleFilter, filterArgs, constraints);
- try
- {
- while (results.hasMore())
+ boolean referralsExist = true;
+ while (referralsExist) {
+ NamingEnumeration results = ldapCtx.search(rolesCtxDN, roleFilter, filterArgs, constraints);
+ try
{
- SearchResult sr = (SearchResult) results.next();
- String dn = canonicalize(sr.getName());
- if (nesting == 0 && roleAttributeIsDN && roleNameAttributeID != null)
+ while (results.hasMore())
{
- if(parseRoleNameFromDN)
- {
- parseRole(dn);
+ SearchResult sr = (SearchResult) results.next();
+
+ String dn;
+ if (sr.isRelative()) {
+ dn = canonicalize(sr.getName());
}
- else
+ else {
+ dn = sr.getNameInNamespace();
+ }
+ if (nesting == 0 && roleAttributeIsDN && roleNameAttributeID != null)
{
- // Check the top context for role names
- String[] attrNames = {roleNameAttributeID};
- Attributes result2 = ctx.getAttributes(dn, attrNames);
- Attribute roles2 = result2.get(roleNameAttributeID);
- if( roles2 != null )
+ if(parseRoleNameFromDN)
{
- for(int m = 0; m < roles2.size(); m ++)
+ parseRole(dn);
+ }
+ else
+ {
+ // Check the top context for role names
+ String[] attrNames = {roleNameAttributeID};
+ Attributes result2 = null;
+ if (sr.isRelative()) {
+ result2 = ldapCtx.getAttributes(dn, attrNames);
+ }
+ else {
+ result2 = getAttributesFromReferralEntity(sr, user, userDN);
+ }
+ Attribute roles2 = (result2 != null ? result2.get(roleNameAttributeID) : null);
+ if( roles2 != null )
{
- String roleName = (String) roles2.get(m);
- addRole(roleName);
+ for(int m = 0; m < roles2.size(); m ++)
+ {
+ String roleName = (String) roles2.get(m);
+ addRole(roleName);
+ }
}
}
}
- }
-
- // Query the context for the roleDN values
- String[] attrNames = {roleAttributeID};
- Attributes result = ctx.getAttributes(dn, attrNames);
- if (result != null && result.size() > 0)
- {
- Attribute roles = result.get(roleAttributeID);
- for (int n = 0; n < roles.size(); n++)
+
+ // Query the context for the roleDN values
+ String[] attrNames = {roleAttributeID};
+ Attributes result = null;
+ if (sr.isRelative()) {
+ result = ldapCtx.getAttributes(dn, attrNames);
+ }
+ else {
+ result = getAttributesFromReferralEntity(sr, user, userDN);
+ }
+ if (result != null && result.size() > 0)
{
- String roleName = (String) roles.get(n);
- if(roleAttributeIsDN && parseRoleNameFromDN)
+ Attribute roles = result.get(roleAttributeID);
+ for (int n = 0; n < roles.size(); n++)
{
- parseRole(roleName);
- }
- else if (roleAttributeIsDN)
- {
- // Query the roleDN location for the value of roleNameAttributeID
- String roleDN = roleName;
- String[] returnAttribute = {roleNameAttributeID};
- try
+ String roleName = (String) roles.get(n);
+ if(roleAttributeIsDN && parseRoleNameFromDN)
{
- Attributes result2 = ctx.getAttributes(roleDN, returnAttribute);
- Attribute roles2 = result2.get(roleNameAttributeID);
- if (roles2 != null)
+ parseRole(roleName);
+ }
+ else if (roleAttributeIsDN)
+ {
+ // Query the roleDN location for the value of roleNameAttributeID
+ String roleDN = roleName;
+ String[] returnAttribute = {roleNameAttributeID};
+ try
{
- for (int m = 0; m < roles2.size(); m++)
+ Attributes result2 = null;
+ if (sr.isRelative()) {
+ result2 = ldapCtx.getAttributes(roleDN, returnAttribute);
+ }
+ else {
+ result2 = getAttributesFromReferralEntity(sr, user, userDN);
+ }
+
+ Attribute roles2 = (result2 != null ? result2.get(roleNameAttributeID) : null);
+ if (roles2 != null)
{
- roleName = (String) roles2.get(m);
- addRole(roleName);
+ for (int m = 0; m < roles2.size(); m++)
+ {
+ roleName = (String) roles2.get(m);
+ addRole(roleName);
+ }
}
}
+ catch (NamingException e)
+ {
+ PicketBoxLogger.LOGGER.debugFailureToQueryLDAPAttribute(roleNameAttributeID, roleDN, e);
+ }
}
- catch (NamingException e)
+ else
{
- PicketBoxLogger.LOGGER.debugFailureToQueryLDAPAttribute(roleNameAttributeID, roleDN, e);
+ // The role attribute value is the role name
+ addRole(roleName);
}
}
- else
- {
- // The role attribute value is the role name
- addRole(roleName);
- }
}
+
+ if (nesting < recursionMax)
+ {
+ rolesSearch(ldapCtx, constraints, user, dn, recursionMax, nesting + 1);
+ }
}
+ referralsExist = false;
+ }
+ catch (ReferralException e) {
+ ldapCtx = (LdapContext) e.getReferralContext();
+ }
+ finally
+ {
+ if (results != null)
+ results.close();
+ }
+ } // while (referralsExist)
+ }
+
- if (nesting < recursionMax)
- {
- rolesSearch(ctx, constraints, user, dn, recursionMax, nesting + 1);
+ /**
+ * Returns Attributes from referral entity and check them if they belong to user or userDN currently in evaluation.
+ * Returns null in case of user is not validated.
+ *
+ * @param sr SearchResult
+ * @param users to check
+ * @return
+ * @throws NamingException
+ */
+ private Attributes getAttributesFromReferralEntity(SearchResult sr, String... users) throws NamingException {
+
+ Attributes result = sr.getAttributes();
+ boolean chkSuccessful = false;
+ if (referralUserAttributeIDToCheck != null) {
+ Attribute usersToCheck = result.get(referralUserAttributeIDToCheck);
+ check:
+ for (int i = 0; usersToCheck != null && i < usersToCheck.size(); i++) {
+ String userDNToCheck = (String) usersToCheck.get(i);
+ for (String u: users) {
+ if (u.equals(userDNToCheck)) {
+ chkSuccessful = true;
+ break check;
+ }
}
}
}
- finally
- {
- if (results != null)
- results.close();
- }
-
+ return (chkSuccessful ? result : null);
}
-
+
private InitialLdapContext constructInitialLdapContext(String dn, Object credential) throws NamingException
{
Properties env = new Properties();
@@ -685,11 +804,16 @@
private void parseRole(String dn)
{
+ parseRole(dn, roleNameAttributeID);
+ }
+
+ private void parseRole(String dn, String roleNameAttributeIdentifier)
+ {
StringTokenizer st = new StringTokenizer(dn, ",");
while(st != null && st.hasMoreTokens())
{
String keyVal = st.nextToken();
- if(keyVal.indexOf(roleNameAttributeID) > -1)
+ if(keyVal.indexOf(roleNameAttributeIdentifier) > -1)
{
StringTokenizer kst = new StringTokenizer(keyVal,"=");
kst.nextToken();
More information about the jboss-cvs-commits
mailing list