SEC-1444: Backport of changes to 2.0.x

This commit is contained in:
Luke Taylor 2010-04-16 15:14:01 +01:00
parent 4361211c21
commit d6f6a54455
5 changed files with 89 additions and 52 deletions

View File

@ -193,22 +193,27 @@ public class SpringSecurityLdapTemplate extends LdapTemplate {
return (DirContextOperations) executeReadOnly(new ContextExecutor() {
public Object executeWithContext(DirContext ctx) throws NamingException {
DistinguishedName ctxBaseDn = new DistinguishedName(ctx.getNameInNamespace());
if (logger.isDebugEnabled()) {
logger.debug("Searching for entry in under DN '" + ctxBaseDn
+ "', base = '" + base + "', filter = '" + filter + "'");
}
NamingEnumeration resultsEnum = ctx.search(base, filter, params, searchControls);
Set results = new HashSet();
try {
while (resultsEnum.hasMore()) {
SearchResult searchResult = (SearchResult) resultsEnum.next();
// Work out the DN of the matched entry
StringBuffer dn = new StringBuffer(searchResult.getName());
DistinguishedName dn = new DistinguishedName(searchResult.getName());
if (base.length() > 0) {
dn.append(",");
dn.append(base);
dn.prepend(new DistinguishedName(base));
}
results.add(new DirContextAdapter(searchResult.getAttributes(),
new DistinguishedName(dn.toString()), ctxBaseDn));
if (logger.isDebugEnabled()) {
logger.debug("Found DN: " + dn);
}
results.add(new DirContextAdapter(searchResult.getAttributes(), dn, ctxBaseDn));
}
} catch (PartialResultException e) {
logger.info("Ignoring PartialResultException");

View File

@ -15,22 +15,26 @@
package org.springframework.security.providers.ldap.authenticator;
import org.springframework.security.Authentication;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.ldap.SpringSecurityContextSource;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.dao.DataAccessException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.util.Assert;
import java.util.Iterator;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.naming.directory.DirContext;
import java.util.Iterator;
import org.springframework.dao.DataAccessException;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.security.Authentication;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.ldap.SpringSecurityContextSource;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.util.Assert;
/**
@ -91,21 +95,42 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
return user;
}
private DirContextOperations bindWithDn(String userDn, String username, String password) {
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(
new BindWithSpecificDnContextSource((SpringSecurityContextSource) getContextSource(), userDn, password));
private DirContextOperations bindWithDn(String userDnStr, String username, String password) {
BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();
DistinguishedName userDn = new DistinguishedName(userDnStr);
DistinguishedName fullDn = new DistinguishedName(userDn);
fullDn.prepend(ctxSource.getBaseLdapPath());
BindWithSpecificDnContextSource specificDnContextSource = new BindWithSpecificDnContextSource(
(SpringSecurityContextSource) getContextSource(), fullDn,
password);
logger.debug("Attemptimg to bind as " + fullDn);
DirContext ctx = null;
try {
return template.retrieveEntry(userDn, getUserAttributes());
ctx = specificDnContextSource.getReadOnlyContext();
} catch (BadCredentialsException e) {
Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());
DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath());
return result;
} catch (NamingException e) {
// This will be thrown if an invalid user name is used and the method may
// be called multiple times to try different names, so we trap the exception
// unless a subclass wishes to implement more specialized behaviour.
handleBindException(userDn, username, e.getCause());
if ((e instanceof org.springframework.ldap.AuthenticationException)
|| (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
handleBindException(userDnStr, username, e);
} else {
throw e;
}
} catch (javax.naming.NamingException e) {
throw LdapUtils.convertLdapException(e);
} finally {
LdapUtils.closeContext(ctx);
}
return null;
}
/**
@ -120,13 +145,12 @@ public class BindAuthenticator extends AbstractLdapAuthenticator {
private class BindWithSpecificDnContextSource implements ContextSource {
private SpringSecurityContextSource ctxFactory;
DistinguishedName userDn;
private DistinguishedName userDn;
private String password;
public BindWithSpecificDnContextSource(SpringSecurityContextSource ctxFactory, String userDn, String password) {
public BindWithSpecificDnContextSource(SpringSecurityContextSource ctxFactory, DistinguishedName userDn, String password) {
this.ctxFactory = ctxFactory;
this.userDn = new DistinguishedName(userDn);
this.userDn.prepend(ctxFactory.getBaseLdapPath());
this.userDn = userDn;
this.password = password;
}

View File

@ -71,13 +71,11 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
@Test
public void extraFilterPartToExcludeBob() throws Exception {
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people",
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry))))", dirCtxFactory);
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry)(uid=slashguy))))", dirCtxFactory);
// Search for bob, get back ben...
DirContextOperations ben = locator.searchForUser("bob");
assertEquals("Ben Alex", ben.getStringAttribute("cn"));
// assertEquals("uid=ben,ou=people,"+ROOT_DN, ben.getDn());
}
@Test(expected=IncorrectResultSizeDataAccessException.class)

View File

@ -15,18 +15,17 @@
package org.springframework.security.providers.ldap.authenticator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.Authentication;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.ldap.AbstractLdapIntegrationTests;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
/**
* Tests for {@link BindAuthenticator}.
@ -39,7 +38,6 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
private BindAuthenticator authenticator;
private Authentication bob;
// private Authentication ben;
//~ Methods ========================================================================================================
@ -48,7 +46,6 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
authenticator = new BindAuthenticator(getContextSource());
authenticator.setMessageSource(new SpringSecurityMessageSource());
bob = new UsernamePasswordAuthenticationToken("bob", "bobspassword");
// ben = new UsernamePasswordAuthenticationToken("ben", "benspassword");
}
@ -72,11 +69,14 @@ public class BindAuthenticatorTests extends AbstractLdapIntegrationTests {
@Test
public void testAuthenticationWithUserSearch() throws Exception {
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people"));
authenticator.setUserSearch(new MockUserSearch(ctx));
// DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("uid=bob,ou=people"));
authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(uid={0})", getContextSource()));
authenticator.afterPropertiesSet();
authenticator.authenticate(bob);
// SEC-1444
authenticator.setUserSearch(new FilterBasedLdapUserSearch("ou=people", "(cn={0})", getContextSource()));
authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword"));
authenticator.authenticate(new UsernamePasswordAuthenticationToken("slash/guy", "slashguyspassword"));
}
@Test

View File

@ -58,6 +58,16 @@ sn: Mouse
uid: jerry
userPassword: jerryspassword
dn: cn=slash/guy,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: slash/guy
sn: Slash
uid: slashguy
userPassword: slashguyspassword
dn: cn=developers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames