You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/10/24 21:20:46 UTC
svn commit: r328138 - in /directory:
apacheds/trunk/main/src/test/org/apache/ldap/server/
protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/
protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/
Author: akarasulu
Date: Mon Oct 24 12:20:33 2005
New Revision: 328138
URL: http://svn.apache.org/viewcvs?rev=328138&view=rev
Log:
changes ...
o fixes DIREVE-283
o made search handler use a special getLdapContext method when the search
operation is on the root DSE with (objectClass=*), scope = base, and
base = ""
o allowed bind operation as anonymous even when anonymous binds are disabled
in the configuration ... delayed checks for anonymous user operations until
other operations are performed.
o added test case to make sure anonymous access is still disabled for binds
to anything other than root dse
Modified:
directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java
directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/SessionRegistry.java
directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/BindHandler.java
directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/SearchHandler.java
Modified: directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java?rev=328138&r1=328137&r2=328138&view=diff
==============================================================================
--- directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java (original)
+++ directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java Mon Oct 24 12:20:33 2005
@@ -53,6 +53,10 @@
{
configuration.setAllowAnonymousAccess( false );
}
+ else if ( this.getName().equals( "testEnableAnonymousBindsOnRootDSE" ) )
+ {
+ configuration.setAllowAnonymousAccess( false );
+ }
super.setUp();
}
@@ -73,14 +77,62 @@
env.put( Context.SECURITY_AUTHENTICATION, "none" );
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
+ InitialDirContext ic = new InitialDirContext( env );
try
{
- new InitialContext( env );
+ ic.search( "", "(objectClass=*)", new SearchControls() );
fail( "If anonymous binds are disabled we should never get here!" );
}
catch ( NoPermissionException e )
{
}
+
+ Attributes attrs = new BasicAttributes( true );
+ Attribute oc = new BasicAttribute( "objectClass" );
+ attrs.put( oc );
+ oc.add( "top" );
+ oc.add( "organizationalUnit" );
+
+ try
+ {
+ ic.createSubcontext( "ou=blah", attrs );
+ }
+ catch( NoPermissionException e )
+ {
+ }
+ }
+
+
+ /**
+ * Test to make sure anonymous binds are allowed on the RootDSE even when disabled
+ * in general when going through the wire protocol.
+ *
+ * @throws Exception if anything goes wrong
+ */
+ public void testEnableAnonymousBindsOnRootDSE() throws Exception
+ {
+ // Use the SUN JNDI provider to hit server port and bind as anonymous
+
+ final Hashtable env = new Hashtable();
+
+ env.put( Context.PROVIDER_URL, "ldap://localhost:" + port + "/" );
+ env.put( Context.SECURITY_AUTHENTICATION, "none" );
+ env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
+
+ InitialDirContext ctx = new InitialDirContext( env );
+ SearchControls cons = new SearchControls();
+ cons.setSearchScope( SearchControls.OBJECT_SCOPE );
+ NamingEnumeration list = ctx.search( "", "(objectClass=*)", cons );
+ SearchResult result = null;
+ if ( list.hasMore() )
+ {
+ result = ( SearchResult ) list.next();
+ }
+ assertFalse( list.hasMore() );
+ list.close();
+
+ assertNotNull( result );
+ assertEquals( "", result.getName().trim() );
}
Modified: directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/SessionRegistry.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/SessionRegistry.java?rev=328138&r1=328137&r2=328138&view=diff
==============================================================================
--- directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/SessionRegistry.java (original)
+++ directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/SessionRegistry.java Mon Oct 24 12:20:33 2005
@@ -29,6 +29,7 @@
import javax.naming.spi.InitialContextFactory;
import org.apache.ldap.common.exception.LdapNoPermissionException;
+import org.apache.ldap.server.jndi.ServerLdapContext;
import org.apache.mina.protocol.ProtocolSession;
@@ -118,6 +119,10 @@
* client. If the context is not present then there was no bind operation
* that set it. Hence this operation requesting the IC is anonymous.
*
+ * @todo this allowAnonymous parameter is a bit confusing - figure out
+ * something better to call it. I think only bind requests a context
+ * that is not anonymous. Have to refactor the heck out of this lousy code.
+ *
* @param session the client's key
* @param connCtls connection controls if any to use if creating anon context
* @param allowAnonymous true if anonymous requests will create anonymous
@@ -134,13 +139,83 @@
ctx = ( LdapContext ) contexts.get( session );
}
+ // there is no context so its an implicit bind, no bind operation is being performed
if ( ctx == null && allowAnonymous )
{
+ // if configuration says disable anonymous binds we throw exection
if ( env.containsKey( "server.disable.anonymous" ) )
{
throw new LdapNoPermissionException( "Anonymous binds have been disabled!" );
}
+ if ( env.containsKey( "server.use.factory.instance" ) )
+ {
+ InitialContextFactory factory = ( InitialContextFactory ) env.get( "server.use.factory.instance" );
+
+ if ( factory == null )
+ {
+ throw new NullPointerException( "server.use.factory.instance was set in env but was null" );
+ }
+
+ ctx = ( LdapContext ) factory.getInitialContext( env );
+ }
+ else
+ {
+ Hashtable cloned = ( Hashtable ) env.clone();
+ cloned.put( Context.SECURITY_AUTHENTICATION, "none" );
+ cloned.remove( Context.SECURITY_PRINCIPAL );
+ cloned.remove( Context.SECURITY_CREDENTIALS );
+ ctx = new InitialLdapContext( cloned, connCtls );
+ }
+ }
+ // the context came up non null so we binded explicitly and op now is not bind
+ else if ( ctx != null && allowAnonymous )
+ {
+ ServerLdapContext slc = null;
+ if ( ! ( ctx instanceof ServerLdapContext ) )
+ {
+ slc = ( ServerLdapContext ) ctx.lookup( "" );
+ }
+ else
+ {
+ slc = ( ServerLdapContext ) ctx;
+ }
+ boolean isAnonymousUser = slc.getPrincipal().getName().trim().equals( "" );
+ boolean cfgAllowsAnonymous = env.containsKey( "server.disable.anonymous" );
+
+ // if the user principal is anonymous and the configuration does not allow anonymous binds we
+ // prevent the operation by blowing a NoPermissionsException
+ if ( isAnonymousUser && !cfgAllowsAnonymous )
+ {
+ throw new LdapNoPermissionException( "Anonymous binds have been disabled!" );
+ }
+ }
+
+ return ctx;
+ }
+
+
+ /**
+ * Gets the InitialContext to the root of the system that was gotten for
+ * client ONLY to be used for RootDSE Search operations. This bypasses
+ * checks to only allow anonymous binds for this special case.
+ *
+ * @param session the client's key
+ * @param connCtls connection controls if any to use if creating anon context
+ * @return the InitialContext or null
+ */
+ public LdapContext getLdapContextOnRootDSEAccess( ProtocolSession session, Control[] connCtls )
+ throws NamingException
+ {
+ LdapContext ctx = null;
+
+ synchronized( contexts )
+ {
+ ctx = ( LdapContext ) contexts.get( session );
+ }
+
+ if ( ctx == null )
+ {
if ( env.containsKey( "server.use.factory.instance" ) )
{
InitialContextFactory factory = ( InitialContextFactory ) env.get( "server.use.factory.instance" );
Modified: directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/BindHandler.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/BindHandler.java?rev=328138&r1=328137&r2=328138&view=diff
==============================================================================
--- directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/BindHandler.java (original)
+++ directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/BindHandler.java Mon Oct 24 12:20:33 2005
@@ -66,7 +66,7 @@
Hashtable env = SessionRegistry.getSingleton().getEnvironment();
StartupConfiguration cfg = ( StartupConfiguration ) Configuration.toConfiguration( env );
- // if the bind request is not simple then we freak: no strong auth yet
+ // if the bind request is not simple then we freak: no sasl based auth yet
if ( ! req.isSimple() )
{
result.setResultCode( ResultCodeEnum.AUTHMETHODNOTSUPPORTED );
@@ -75,18 +75,18 @@
return;
}
- boolean allowAnonymousBinds = cfg.isAllowAnonymousAccess();
- boolean emptyCredentials = req.getCredentials() == null || req.getCredentials().length == 0;
- boolean emptyDn = req.getName() == null || req.getName().length() == 0;
-
- if ( emptyCredentials && emptyDn && ! allowAnonymousBinds )
- {
- result.setResultCode( ResultCodeEnum.INSUFFICIENTACCESSRIGHTS );
- String msg = "Bind failure: Anonymous binds have been disabled!";
- result.setErrorMessage( msg );
- session.write( resp );
- return;
- }
+// boolean allowAnonymousBinds = cfg.isAllowAnonymousAccess();
+// boolean emptyCredentials = req.getCredentials() == null || req.getCredentials().length == 0;
+// boolean emptyDn = req.getName() == null || req.getName().length() == 0;
+//
+// if ( emptyCredentials && emptyDn && ! allowAnonymousBinds )
+// {
+// result.setResultCode( ResultCodeEnum.INSUFFICIENTACCESSRIGHTS );
+// String msg = "Bind failure: Anonymous binds have been disabled!";
+// result.setErrorMessage( msg );
+// session.write( resp );
+// return;
+// }
// clone the environment first then add the required security settings
Modified: directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/SearchHandler.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/SearchHandler.java?rev=328138&r1=328137&r2=328138&view=diff
==============================================================================
--- directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/SearchHandler.java (original)
+++ directory/protocol-providers/ldap/trunk/src/main/java/org/apache/ldap/server/protocol/support/SearchHandler.java Mon Oct 24 12:20:33 2005
@@ -24,26 +24,21 @@
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.apache.ldap.common.exception.LdapException;
-import org.apache.ldap.common.message.LdapResultImpl;
-import org.apache.ldap.common.message.ReferralImpl;
-import org.apache.ldap.common.message.ResultCodeEnum;
-import org.apache.ldap.common.message.SearchRequest;
-import org.apache.ldap.common.message.SearchResponseDone;
-import org.apache.ldap.common.message.SearchResponseDoneImpl;
-import org.apache.ldap.common.message.SearchResponseEntry;
-import org.apache.ldap.common.message.SearchResponseEntryImpl;
-import org.apache.ldap.common.message.SearchResponseReference;
-import org.apache.ldap.common.message.SearchResponseReferenceImpl;
+import org.apache.ldap.common.message.*;
import org.apache.ldap.common.name.LdapName;
import org.apache.ldap.common.util.ArrayUtils;
import org.apache.ldap.common.util.ExceptionUtils;
+import org.apache.ldap.common.filter.PresenceNode;
import org.apache.ldap.server.jndi.ServerLdapContext;
import org.apache.ldap.server.protocol.SessionRegistry;
+import org.apache.ldap.server.configuration.StartupConfiguration;
+import org.apache.ldap.server.configuration.Configuration;
import org.apache.mina.protocol.ProtocolSession;
import org.apache.mina.protocol.handler.MessageHandler;
import org.slf4j.Logger;
@@ -63,7 +58,7 @@
public void messageReceived( ProtocolSession session, Object request )
{
- ServerLdapContext ctx;
+ LdapContext ctx;
SearchRequest req = ( SearchRequest ) request;
NamingEnumeration list = null;
@@ -93,9 +88,49 @@
try
{
- ctx = ( ServerLdapContext ) SessionRegistry.getSingleton().getLdapContext( session, null, true ).lookup( "" );
+ boolean isBaseIsRoot = req.getBase().trim().equals( "" );
+ boolean isBaseScope = req.getScope() == ScopeEnum.BASEOBJECT;
+ boolean isRootDSEFilter = false;
+ if ( req.getFilter() instanceof PresenceNode )
+ {
+ isRootDSEFilter = ( ( PresenceNode ) req.getFilter() ).getAttribute().equalsIgnoreCase( "objectClass" );
+ }
+ boolean isRootDSESearch = isBaseIsRoot && isBaseScope && isRootDSEFilter;
+
+ // bypass checks to disallow anonymous binds for search on RootDSE with base obj scope
+ if ( isRootDSESearch )
+ {
+ ctx = SessionRegistry.getSingleton().getLdapContextOnRootDSEAccess( session, null );
+ }
+ // all those search operations are subject to anonymous bind checks when anonymous binda are disallowed
+ else
+ {
+ ctx = ( LdapContext ) SessionRegistry.getSingleton().getLdapContext( session, null, true ).lookup( "" );
+ }
+
+ if ( ! ( ctx instanceof ServerLdapContext ) )
+ {
+ ctx = ( ServerLdapContext ) ctx.lookup( "" );
+ }
+
+ StartupConfiguration cfg = ( StartupConfiguration ) Configuration.toConfiguration( ctx.getEnvironment() );
+ boolean allowAnonymousBinds = cfg.isAllowAnonymousAccess();
+ boolean isAnonymousUser = ( ( ServerLdapContext ) ctx ).getPrincipal().getName().trim().equals( "" );
+
+ if ( isAnonymousUser && ! allowAnonymousBinds && ! isRootDSESearch )
+ {
+ SearchResponseDone resp = new SearchResponseDoneImpl( req.getMessageId() );
+ LdapResultImpl result = new LdapResultImpl( resp );
+ resp.setLdapResult( result );
+ result.setResultCode( ResultCodeEnum.INSUFFICIENTACCESSRIGHTS );
+ String msg = "Bind failure: Anonymous binds have been disabled!";
+ result.setErrorMessage( msg );
+ session.write( resp );
+ return;
+ }
+
ctx.addToEnvironment( DEREFALIASES_KEY, req.getDerefAliases().getName() );
- list = ctx.search( new LdapName( req.getBase() ), req.getFilter(), controls );
+ list = ( ( ServerLdapContext ) ctx ).search( new LdapName( req.getBase() ), req.getFilter(), controls );
if( list.hasMore() )
{