directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r546070 - in /directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support: BindHandler.java bind/ChainGuard.java bind/GetLdapContext.java
Date Mon, 11 Jun 2007 10:01:04 GMT
Author: elecharny
Date: Mon Jun 11 03:01:03 2007
New Revision: 546070

URL: http://svn.apache.org/viewvc?view=rev&rev=546070
Log:
- Removed the PARSED_BIND_DN, which was useless (seems to have been needed a while back when
DN weren't parsed by the message decoder)
- Modified the BindHandler so that the simple authentication is handled locally, and not in
the chain, to improve performances
- Added some javadoc

Modified:
    directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java
    directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
    directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java

Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java?view=diff&rev=546070&r1=546069&r2=546070
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java
(original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java
Mon Jun 11 03:01:03 2007
@@ -20,10 +20,32 @@
 package org.apache.directory.server.ldap.support;
 
 
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.directory.server.ldap.LdapConfiguration;
+import org.apache.directory.server.ldap.SessionRegistry;
 import org.apache.directory.server.ldap.support.bind.BindHandlerChain;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.message.BindRequest;
+import org.apache.directory.shared.ldap.message.BindResponse;
+import org.apache.directory.shared.ldap.message.Control;
+import org.apache.directory.shared.ldap.message.LdapResult;
+import org.apache.directory.shared.ldap.message.ManageDsaITControl;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.ExceptionUtils;
 import org.apache.mina.common.IoSession;
 import org.apache.mina.handler.chain.IoHandlerCommand;
 import org.apache.mina.handler.demux.MessageHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -36,7 +58,18 @@
  */
 public class BindHandler implements MessageHandler
 {
-    private IoHandlerCommand bindHandler;
+    private static final Logger log = LoggerFactory.getLogger( BindHandler.class );
+
+    /** A class to handle SASL bind requests */
+    private IoHandlerCommand saslBindHandler;
+    
+    /** Definition of SIMPLE and STRONG authentication constants */
+    private static final String SIMPLE_AUTHENTICATION_LEVEL = "simple";
+        
+    private static final String STRONG_AUTHENTICATION_LEVEL = "strong";
+    
+    /** An empty Contol array used to get back the controls if any */
+    private static final Control[] EMPTY_CONTROL = new Control[0];
 
 
     /**
@@ -44,12 +77,215 @@
      */
     public BindHandler()
     {
-        bindHandler = new BindHandlerChain();
+        saslBindHandler = new BindHandlerChain();
+    }
+    
+    /**
+     * Create an environment object and inject the Bond informations collected
+     * from the BindRequest message :
+     *  - the principal : the user's who issued the Bind request
+     *  - the credentials : principal's password, if auth level is 'simple'
+     *  - the authentication level : either 'simple' or 'strong'
+     *  - how to handle referral : either 'ignore' or 'throw'
+     */
+    private Hashtable<String, Object> getEnvironment( IoSession session, BindRequest
bindRequest, String authenticationLevel )
+    {
+        LdapDN principal = bindRequest.getName();
+
+        /**
+         * For simple, this is a password.  For strong, this is unused.
+         */
+        Object credentials = bindRequest.getCredentials();
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "{} {}", Context.SECURITY_PRINCIPAL, principal );
+            log.debug( "{} {}", Context.SECURITY_CREDENTIALS, credentials );
+            log.debug( "{} {}", Context.SECURITY_AUTHENTICATION, authenticationLevel );
+        }
+
+        // clone the environment first then add the required security settings
+        Hashtable<String, Object> env = SessionRegistry.getSingleton().getEnvironmentByCopy();
+        
+        // Store the principal
+        env.put( Context.SECURITY_PRINCIPAL, principal );
+
+        // Store the credentials
+        if ( credentials != null )
+        {
+            env.put( Context.SECURITY_CREDENTIALS, credentials );
+        }
+
+        // Store the authentication level
+        env.put( Context.SECURITY_AUTHENTICATION, authenticationLevel );
+
+        // Store the referral handling method
+        if ( bindRequest.getControls().containsKey( ManageDsaITControl.CONTROL_OID ) )
+        {
+            env.put( Context.REFERRAL, "ignore" );
+        }
+        else
+        {
+            env.put( Context.REFERRAL, "throw" );
+        }
+
+        return env;
+    }
+
+    /**
+     * Create the Context associated with the BindRequest.
+     */
+    private LdapContext getLdapContext( IoSession session, BindRequest bindRequest, Hashtable<String,
Object> env )
+    {
+        LdapResult result = bindRequest.getResultResponse().getLdapResult();
+        LdapContext ctx = null;
+
+        try
+        {
+            if ( env.containsKey( "server.use.factory.instance" ) )
+            {
+                InitialContextFactory factory = ( InitialContextFactory ) env.get( "server.use.factory.instance"
);
+
+                if ( factory == null )
+                {
+                    log.error( "The property 'server.use.factory.instance'  was set in env
but was null" );
+                    throw new NullPointerException( "server.use.factory.instance was set
in env but was null" );
+                }
+
+                // Bind is a special case where we have to use the referral property to deal
+                ctx = ( LdapContext ) factory.getInitialContext( env );
+            }
+            else
+            {
+                Control[] connCtls = bindRequest.getControls().values().toArray( EMPTY_CONTROL
);
+                ctx = new InitialLdapContext( env, connCtls );
+            }
+        }
+        catch ( NamingException e )
+        {
+            ResultCodeEnum code;
+
+            if ( e instanceof LdapException )
+            {
+                code = ( ( LdapException ) e ).getResultCode();
+                result.setResultCode( code );
+            }
+            else
+            {
+                code = ResultCodeEnum.getBestEstimate( e, bindRequest.getType() );
+                result.setResultCode( code );
+            }
+
+            String msg = "Bind failed: " + e.getMessage();
+
+            if ( log.isDebugEnabled() )
+            {
+                msg += ":\n" + ExceptionUtils.getStackTrace( e );
+                msg += "\n\nBindRequest = \n" + bindRequest.toString();
+                log.debug(  msg  );
+            }
+
+            if ( ( e.getResolvedName() != null )
+                && ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM
)
+                    || ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM
) ) )
+            {
+                result.setMatchedDn( ( LdapDN ) e.getResolvedName() );
+            }
+
+            result.setErrorMessage( msg );
+            session.write( bindRequest.getResultResponse() );
+            ctx = null;
+        }
+        
+        return ctx;
     }
 
+    /**
+     * This method handle a 'simple' authentication. Of course, the 'SIMPLE' mechanism 
+     * must have been allowed in the configuration, otherwise an error is thrown.
+     * 
+     */
+    private void handleSimpleAuth( IoSession session, BindRequest bindRequest )
+    {
+        LdapConfiguration config = ( LdapConfiguration ) session.getAttribute( LdapConfiguration.class.toString()
);
+        
+        @SuppressWarnings( "unchecked" )
+        Set<String> supportedMechanisms = config.getSupportedMechanisms();
+        LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
+
+        // First, deal with Simple Authentication
+        // Guard clause:  Reject SIMPLE mechanism.
+        if ( !supportedMechanisms.contains( "SIMPLE" ) )
+        {
+            log.error( "Bind error : SIMPLE authentication not supported. Please check the
server.xml configuration file (supportedMechanisms field)" );
+
+            bindResult.setResultCode( ResultCodeEnum.STRONG_AUTH_REQUIRED );
+            bindResult.setErrorMessage( "Simple binds are disabled." );
+            session.write( bindRequest.getResultResponse() );
+            return;
+        }
+
+        // Initialize the environment which will be used to create the context
+        Hashtable<String, Object> env = getEnvironment( session, bindRequest, SIMPLE_AUTHENTICATION_LEVEL
);
+        
+        // Now, get the context
+        LdapContext ctx = getLdapContext( session, bindRequest, env );
+        
+        // Test that we successfully got one. If not, an error has already been returned.
+        if ( ctx != null )
+        {
+            SessionRegistry.getSingleton().setLdapContext( session, ctx );
+            bindResult.setResultCode( ResultCodeEnum.SUCCESS );
+            BindResponse response = ( BindResponse ) bindRequest.getResultResponse();
+
+            session.write( response );
+            log.debug( "Returned SUCCESS message." );
+        }
+    }
 
+    /**
+     * Deal with a received BindRequest
+     */
     public void messageReceived( IoSession session, Object message ) throws Exception
     {
-        bindHandler.execute( null, session, message );
+        BindRequest bindRequest = ( BindRequest ) message;
+
+        if ( log.isDebugEnabled() )
+        {
+            if ( bindRequest.isSimple() )
+            {
+                log.debug( "Simple authentication" );
+                
+            }
+            else
+            {
+                log.debug( "SASL authentication" );
+                log.debug( "SASL mechanism:  {}", bindRequest.getSaslMechanism() );
+            }
+        }
+        
+        // Guard clause:  LDAP version 3
+        if ( !bindRequest.getVersion3() )
+        {
+            log.error( "Bind error : Only LDAP v3 is supported." );
+            LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
+
+            bindResult.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
+            bindResult.setErrorMessage( "Only LDAP v3 is supported." );
+            session.write( bindRequest.getResultResponse() );
+            return;
+        }
+
+        // Deal with the two kinds of authen :
+        // - if it's simple, handle it in this class for speed
+        // - for sasl, we go through a chain right now (but it may change in the near future)
+        if ( bindRequest.isSimple() )
+        {
+            handleSimpleAuth( session, bindRequest );
+        }
+        else
+        {
+            saslBindHandler.execute( null, session, message );
+        }
     }
 }

Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java?view=diff&rev=546070&r1=546069&r2=546070
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
(original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
Mon Jun 11 03:01:03 2007
@@ -42,42 +42,21 @@
 
     public void execute( NextCommand next, IoSession session, Object message ) throws Exception
     {
-        BindRequest request = ( BindRequest ) message;
-        LdapResult result = request.getResultResponse().getLdapResult();
+        BindRequest bindRequest = ( BindRequest ) message;
 
-        if ( log.isDebugEnabled() )
-        {
-            log.debug( "Is simple:       " + request.isSimple() );
-            log.debug( "SASL mechanism:  " + request.getSaslMechanism() );
-            log.debug( "Credentials:     " + request.getCredentials() );
-        }
-
-        // Guard clause:  LDAP version 3
-        if ( !request.getVersion3() )
-        {
-            result.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
-            result.setErrorMessage( "Only LDAP v3 is supported." );
-            session.write( request.getResultResponse() );
-            return;
-        }
-
-        Set supportedMechanisms = ( Set ) session.getAttribute( "supportedMechanisms" );
-
-        // Guard clause:  Reject SIMPLE mechanism.
-        if ( request.isSimple() && !supportedMechanisms.contains( "SIMPLE" ) )
-        {
-            result.setResultCode( ResultCodeEnum.STRONG_AUTH_REQUIRED );
-            result.setErrorMessage( "Simple binds are disabled." );
-            session.write( request.getResultResponse() );
-            return;
-        }
+        @SuppressWarnings( "unchecked" )
+        Set<String> supportedMechanisms = ( Set<String> ) session.getAttribute(
"supportedMechanisms" );
 
         // Guard clause:  Reject unsupported SASL mechanisms.
-        if ( !( request.isSimple() || supportedMechanisms.contains( request.getSaslMechanism()
) ) )
+        if ( !supportedMechanisms.contains( bindRequest.getSaslMechanism() ) )
         {
-            result.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
-            result.setErrorMessage( request.getSaslMechanism() + " is not a supported mechanism."
);
-            session.write( request.getResultResponse() );
+            log.error( "Bind error : {} mechanism not supported. Please check the server.xml
configuration file (supportedMechanisms field)", 
+                bindRequest.getSaslMechanism() );
+
+            LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
+            bindResult.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
+            bindResult.setErrorMessage( bindRequest.getSaslMechanism() + " is not a supported
mechanism." );
+            session.write( bindRequest.getResultResponse() );
             return;
         }
 
@@ -85,14 +64,7 @@
          * We now have a canonicalized authentication mechanism for this session,
          * suitable for use in Hashed Adapter's, aka Demux HashMap's.
          */
-        if ( request.isSimple() )
-        {
-            session.setAttribute( "sessionMechanism", "SIMPLE" );
-        }
-        else
-        {
-            session.setAttribute( "sessionMechanism", request.getSaslMechanism() );
-        }
+        session.setAttribute( "sessionMechanism", bindRequest.getSaslMechanism() );
 
         next.execute( session, message );
     }

Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java?view=diff&rev=546070&r1=546069&r2=546070
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java
(original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java
Mon Jun 11 03:01:03 2007
@@ -28,7 +28,6 @@
 import javax.naming.ldap.LdapContext;
 import javax.naming.spi.InitialContextFactory;
 
-import org.apache.directory.server.core.jndi.PropertyKeys;
 import org.apache.directory.server.ldap.SessionRegistry;
 import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.message.BindRequest;
@@ -139,10 +138,9 @@
         log.debug( Context.SECURITY_PRINCIPAL + " " + principal );
         log.debug( Context.SECURITY_CREDENTIALS + " " + credentials );
         log.debug( Context.SECURITY_AUTHENTICATION + " " + authenticationLevel );
-        log.debug( PropertyKeys.PARSED_BIND_DN + " " + principal );
 
         // clone the environment first then add the required security settings
-        Hashtable env = SessionRegistry.getSingleton().getEnvironmentByCopy();
+        Hashtable<String, Object> env = SessionRegistry.getSingleton().getEnvironmentByCopy();
         env.put( Context.SECURITY_PRINCIPAL, principal );
 
         if ( credentials != null )
@@ -151,7 +149,6 @@
         }
 
         env.put( Context.SECURITY_AUTHENTICATION, authenticationLevel );
-        env.put( PropertyKeys.PARSED_BIND_DN, principal );
 
         BindRequest request = ( BindRequest ) message;
 



Mime
View raw message