directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From erodrig...@apache.org
Subject svn commit: r516288 [1/2] - in /directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support: ./ bind/
Date Fri, 09 Mar 2007 04:12:59 GMT
Author: erodriguez
Date: Thu Mar  8 20:12:57 2007
New Revision: 516288

URL: http://svn.apache.org/viewvc?view=rev&rev=516288
Log:
Replaced the BindHandler with an IoHandlerChain (BindHandlerChain) that supports DIGEST-MD5, CRAM-MD5, and GSSAPI authentication.

Added:
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ReturnSuccess.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/SaslFilter.java   (with props)
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/package-info.java   (with props)
Modified:
    directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java

Modified: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java?view=diff&rev=516288&r1=516287&r2=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java (original)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/BindHandler.java Thu Mar  8 20:12:57 2007
@@ -20,143 +20,37 @@
 package org.apache.directory.server.ldap.support;
 
 
-import java.util.Hashtable;
-
-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.core.configuration.StartupConfiguration;
-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;
-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.directory.server.ldap.support.bind.BindHandlerChain;
 import org.apache.mina.common.IoSession;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.mina.handler.chain.IoHandlerCommand;
 
 
 /**
  * A single reply handler for {@link org.apache.directory.shared.ldap.message.BindRequest}s.
- *
+ * 
+ * Implements server-side of RFC 2222, sections 4.2 and 4.3.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class BindHandler implements LdapMessageHandler
 {
-    private static final Logger log = LoggerFactory.getLogger( BindHandler.class );
-    private static final Control[] EMPTY = new Control[0];
+    private IoHandlerCommand bindHandler;
+
+
+    /**
+     * Creates a new instance of BindHandler.
+     */
+    public BindHandler()
+    {
+        bindHandler = new BindHandlerChain();
+    }
 
-    /** Speedup for logs */
-    private static final boolean IS_DEBUG = log.isDebugEnabled();
 
-    public void messageReceived( IoSession session, Object request ) throws Exception
+    public void messageReceived( IoSession session, Object message ) throws Exception
     {
-        LdapContext ctx;
-        BindRequest req = ( BindRequest ) request;
-        LdapResult result = req.getResultResponse().getLdapResult();
-        
-        if ( !req.getVersion3() )
-        {
-            result.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
-            result.setErrorMessage( "Only LDAP v3 is supported" );
-            session.write( req.getResultResponse() );
-            return;
-        }
-        
-        // if the bind request is not simple then we freak: no strong auth yet
-        if ( !req.isSimple() )
-        {
-            result.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
-            result.setErrorMessage( "Only simple binds currently supported" );
-            session.write( req.getResultResponse() );
-            return;
-        }
-
-        // clone the environment first then add the required security settings
-        Hashtable env = SessionRegistry.getSingleton().getEnvironmentByCopy();
-        byte[] creds = req.getCredentials();
-        env.put( Context.SECURITY_PRINCIPAL, req.getName() );
-        env.put( Context.SECURITY_CREDENTIALS, creds );
-        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
-        env.put( PropertyKeys.PARSED_BIND_DN, req.getName() );
-
-        if ( req.getControls().containsKey( ManageDsaITControl.CONTROL_OID ) )
-        {
-            env.put( Context.REFERRAL, "ignore" );
-        }
-        else
-        {
-            env.put( Context.REFERRAL, "throw" );
-        }
-
-        try
-        {
-            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" );
-                }
-
-                // Bind is a special case where we have to use the referral property to deal
-                ctx = ( LdapContext ) factory.getInitialContext( env );
-            }
-            else
-            {
-                Control[] connCtls = ( Control[] ) req.getControls().values().toArray( EMPTY );
-                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, req.getType() );
-                result.setResultCode( code );
-            }
-
-            String msg = "Bind failed: " + e.getMessage();
-            
-            if ( IS_DEBUG )
-            {
-                msg += ":\n" + ExceptionUtils.getStackTrace( e );
-                msg += "\n\nBindRequest = \n" + req.toString();
-            }
-
-            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( req.getResultResponse() );
-            return;
-        }
-
-        SessionRegistry.getSingleton().setLdapContext( session, ctx );
-        result.setResultCode( ResultCodeEnum.SUCCESS );
-        session.write( req.getResultResponse() );
+        bindHandler.execute( null, session, message );
     }
 
 

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,273 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import javax.naming.spi.InitialContextFactory;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.RealmCallback;
+
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.message.BindRequest;
+import org.apache.directory.shared.ldap.message.Control;
+import org.apache.directory.shared.ldap.message.LdapResult;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Base class for all SASL {@link CallbackHandler}s.  Implementations of SASL mechanisms
+ * selectively override the methods relevant to their mechanism.
+ * 
+ * @see javax.security.auth.callback.CallbackHandler
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class AbstractSaslCallbackHandler implements CallbackHandler
+{
+    private static final Logger log = LoggerFactory.getLogger( AbstractSaslCallbackHandler.class );
+
+    private static final Control[] EMPTY = new Control[0];
+
+    private String username;
+    private String realm;
+
+
+    /**
+     * Implementors use this method to access the username resulting from a callback.
+     * Callback default name will be username, eg 'hnelson', for CRAM-MD5 and DIGEST-MD5.
+     * The {@link NameCallback} is not used by GSSAPI.
+     */
+    protected String getUsername()
+    {
+        return username;
+    }
+
+
+    /**
+     * Implementors use this method to access the realm resulting from a callback.
+     * Callback default text will be realm name, eg 'example.com', for DIGEST-MD5.
+     * The {@link RealmCallback} is not used by GSSAPI nor by CRAM-MD5.
+     */
+    protected String getRealm()
+    {
+        return realm;
+    }
+
+
+    /**
+     * Implementors set the password based on a lookup, using the username and
+     * realm as keys.
+     * <ul>
+     * <li>For DIGEST-MD5, lookup password based on username and realm.
+     * <li>For CRAM-MD5, lookup password based on username.
+     * <li>For GSSAPI, this callback is unused.
+     * </ul>
+     * @param username The username.
+     * @param realm The realm.
+     * @return The password resulting from the lookup.
+     */
+    protected abstract String lookupPassword( String username, String realm );
+
+
+    /**
+     * Final check to authorize user.  Used by all SASL mechanisms.  This
+     * is the only callback used by GSSAPI.
+     * 
+     * Implementors use setAuthorizedID() to set the base DN after canonicalization.
+     * Implementors must setAuthorized() to <code>true</code> if authentication was successful.
+     * 
+     * @param callback An {@link AuthorizeCallback}.
+     */
+    protected abstract void authorize( AuthorizeCallback callback );
+
+
+    /**
+     * SaslServer will use this method to call various callbacks, depending on the SASL
+     * mechanism in use for a session.
+     * 
+     * @param callbacks An array of one or more callbacks.
+     */
+    public void handle( Callback[] callbacks )
+    {
+        for ( int i = 0; i < callbacks.length; i++ )
+        {
+            Callback callback = callbacks[i];
+
+            log.debug( "Processing callback " + ( i + 1 ) + " of " + callbacks.length + ":  "
+                + callback.getClass().toString() );
+
+            if ( callback instanceof NameCallback )
+            {
+                NameCallback nameCB = ( NameCallback ) callback;
+                log.debug( "NameCallback default name   " + nameCB.getDefaultName() );
+
+                username = nameCB.getDefaultName();
+            }
+            else if ( callback instanceof RealmCallback )
+            {
+                RealmCallback realmCB = ( RealmCallback ) callback;
+                log.debug( "RealmCallback default text  " + realmCB.getDefaultText() );
+
+                realm = realmCB.getDefaultText();
+            }
+            else if ( callback instanceof PasswordCallback )
+            {
+                PasswordCallback passwordCB = ( PasswordCallback ) callback;
+                String userPassword = lookupPassword( getUsername(), getRealm() );
+
+                if ( userPassword != null )
+                {
+                    passwordCB.setPassword( userPassword.toCharArray() );
+                }
+            }
+            else if ( callback instanceof AuthorizeCallback )
+            {
+                AuthorizeCallback authorizeCB = ( AuthorizeCallback ) callback;
+
+                // hnelson (CRAM-MD5, DIGEST-MD5)
+                // hnelson@EXAMPLE.COM (GSSAPI)
+                log.debug( "AuthorizeCallback authnID      " + authorizeCB.getAuthenticationID() );
+
+                // hnelson (CRAM-MD5, DIGEST-MD5)
+                // hnelson@EXAMPLE.COM (GSSAPI)
+                log.debug( "AuthorizeCallback authzID      " + authorizeCB.getAuthorizationID() );
+
+                // null (CRAM-MD5, DIGEST-MD5, GSSAPI)
+                log.debug( "AuthorizeCallback authorizedID " + authorizeCB.getAuthorizedID() );
+
+                // false (CRAM-MD5, DIGEST-MD5, GSSAPI)
+                log.debug( "AuthorizeCallback isAuthorized " + authorizeCB.isAuthorized() );
+
+                authorize( authorizeCB );
+            }
+        }
+    }
+
+
+    /**
+     * Convenience method for acquiring an {@link LdapContext} for the client to use for the
+     * duration of a session.
+     * 
+     * @param session The current session.
+     * @param message The current message.
+     * @param env An environment to be used to acquire an {@link LdapContext}.
+     * @return An {@link LdapContext} for the client.
+     */
+    protected LdapContext getContext( IoSession session, Object message, Hashtable env )
+    {
+        BindRequest request = ( BindRequest ) message;
+        LdapResult result = request.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 )
+                {
+                    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 = ( Control[] ) request.getControls().values().toArray( EMPTY );
+                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, request.getType() );
+                result.setResultCode( code );
+            }
+
+            String msg = "Bind failed: " + e.getMessage();
+
+            if ( log.isDebugEnabled() )
+            {
+                msg += ":\n" + ExceptionUtils.getStackTrace( e );
+                msg += "\n\nBindRequest = \n" + request.toString();
+            }
+
+            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( request.getResultResponse() );
+            ctx = null;
+        }
+
+        return ctx;
+    }
+
+
+    /**
+     * Convenience method for getting an environment suitable for acquiring
+     * an {@link LdapContext} for the client.
+     * 
+     * @param session The current session.
+     * @param message The current message.
+     * @return An environment suitable for acquiring an {@link LdapContext} for the client.
+     */
+    protected Hashtable getEnvironment( IoSession session, Object message )
+    {
+        Hashtable env = new Hashtable();
+        env.put( Context.PROVIDER_URL, ( String ) session.getAttribute( "baseDn" ) );
+        env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.directory.server.core.jndi.CoreContextFactory" );
+        env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
+        env.put( Context.SECURITY_CREDENTIALS, "secret" );
+        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
+
+        return env;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/AbstractSaslCallbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import org.apache.mina.handler.chain.IoHandlerChain;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class BindHandlerChain extends IoHandlerChain
+{
+    /**
+     * Creates a new instance of BindHandlerChain.
+     */
+    public BindHandlerChain()
+    {
+        addLast( "configureChain", new ConfigureChain() );
+        addLast( "chainGuard", new ChainGuard() );
+        addLast( "handleSasl", new HandleSasl() );
+        addLast( "handleSimple", new HandleSimple() );
+        addLast( "getLdapContext", new GetLdapContext() );
+        addLast( "returnSuccess", new ReturnSuccess() );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/BindHandlerChain.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,96 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Set;
+
+import org.apache.directory.shared.ldap.message.BindRequest;
+import org.apache.directory.shared.ldap.message.LdapResult;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.chain.IoHandlerCommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ChainGuard implements IoHandlerCommand
+{
+    private static final Logger log = LoggerFactory.getLogger( ChainGuard.class );
+
+
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        BindRequest request = ( BindRequest ) message;
+        LdapResult result = request.getResultResponse().getLdapResult();
+
+        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;
+        }
+
+        // Guard clause:  Reject unsupported SASL mechanisms.
+        if ( !( request.isSimple() || supportedMechanisms.contains( request.getSaslMechanism() ) ) )
+        {
+            result.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
+            result.setErrorMessage( request.getSaslMechanism() + " is not a supported mechanism." );
+            session.write( request.getResultResponse() );
+            return;
+        }
+
+        /**
+         * 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() );
+        }
+
+        next.execute( session, message );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ChainGuard.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.sasl.Sasl;
+
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.chain.IoHandlerCommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ConfigureChain implements IoHandlerCommand
+{
+    private static final Logger log = LoggerFactory.getLogger( ConfigureChain.class );
+
+
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        /**
+         * TODO - Take intersection of supported mechanisms and mechanisms enabled in configuration.
+         */
+        Set<String> supportedMechanisms = new HashSet<String>();
+        supportedMechanisms.add( "SIMPLE" );
+        supportedMechanisms.add( "CRAM-MD5" );
+        supportedMechanisms.add( "DIGEST-MD5" );
+        supportedMechanisms.add( "GSSAPI" );
+        session.setAttribute( "supportedMechanisms", supportedMechanisms );
+
+        /**
+         * TODO - Take host from configuration.
+         */
+        String saslHost = "ldap.example.com";
+        session.setAttribute( "saslHost", saslHost );
+
+        Map<String, String> saslProps = new HashMap<String, String>();
+
+        /**
+         * TODO - Take service principal name from configuration.
+         * TODO - Create Subject with key material from directory.
+         */
+        String servicePrincipalName = "ldap/" + saslHost + "@EXAMPLE.COM";
+        session.setAttribute( "saslSubject", getSubject( servicePrincipalName ) );
+
+        /**
+         * TODO - Take QoP props from configuration.
+         */
+        saslProps.put( Sasl.QOP, "auth,auth-int,auth-conf" );
+
+        /**
+         * TODO - Take realms from configuration.
+         */
+        saslProps.put( "com.sun.security.sasl.digest.realm", "example.com apache.org" );
+
+        session.setAttribute( "saslProps", saslProps );
+
+        /**
+         * TODO - Get one or more base DN's for user lookups.
+         * TODO - Make decision on base DN lookup vs. regex mapping.
+         */
+        session.setAttribute( "baseDn", "ou=users,dc=example,dc=com" );
+
+        next.execute( session, message );
+    }
+
+
+    private Subject getSubject( String servicePrincipalName )
+    {
+        KerberosPrincipal servicePrincipal = new KerberosPrincipal( servicePrincipalName );
+        char[] password = new String( "randall" ).toCharArray();
+        KerberosKey serviceKey = new KerberosKey( servicePrincipal, password, "DES" );
+        Subject subject = new Subject();
+        subject.getPrivateCredentials().add( serviceKey );
+
+        return subject;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/ConfigureChain.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.ldap.LdapContext;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.apache.mina.common.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CramMd5CallbackHandler extends AbstractSaslCallbackHandler
+{
+    private static final Logger log = LoggerFactory.getLogger( CramMd5CallbackHandler.class );
+
+    private IoSession session;
+    private Object message;
+
+    private String bindDn;
+    private String userPassword;
+
+
+    /**
+     * Creates a new instance of CramMd5CallbackHandler.
+     *
+     * @param session
+     * @param message
+     */
+    public CramMd5CallbackHandler( IoSession session, Object message )
+    {
+        this.session = session;
+        this.message = message;
+    }
+
+
+    protected String lookupPassword( String username, String realm )
+    {
+        Hashtable env = getEnvironment( session, message );
+
+        LdapContext ctx = getContext( session, message, env );
+
+        GetBindDn getDn = new GetBindDn( username );
+
+        // Don't actually want the entry, rather the hacked in dn.
+        getDn.execute( ctx, null );
+        bindDn = getDn.getBindDn();
+        userPassword = getDn.getUserPassword();
+
+        return userPassword;
+    }
+
+
+    protected void authorize( AuthorizeCallback authorizeCB )
+    {
+        log.debug( "Converted username " + getUsername() + " to DN " + bindDn + " with password " + userPassword );
+        session.setAttribute( Context.SECURITY_PRINCIPAL, bindDn );
+        session.setAttribute( Context.SECURITY_CREDENTIALS, userPassword );
+
+        authorizeCB.setAuthorizedID( bindDn );
+        authorizeCB.setAuthorized( true );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5CallbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,65 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServer;
+
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class CramMd5MechanismHandler implements MechanismHandler
+{
+    public SaslServer handleMechanism( IoSession session, Object message ) throws Exception
+    {
+        SaslServer ss;
+
+        if ( session.containsAttribute( SASL_CONTEXT ) )
+        {
+            ss = ( SaslServer ) session.getAttribute( SASL_CONTEXT );
+        }
+        else
+        {
+            String saslHost = ( String ) session.getAttribute( "saslHost" );
+
+            /*
+             * Sasl will throw an exception is Sasl.QOP properties are set.
+             * CRAM-MD5 doesn't support QoP.
+             */
+            Map<String, String> saslProps = new HashMap<String, String>();
+
+            CallbackHandler callbackHandler = new CramMd5CallbackHandler( session, message );
+
+            ss = Sasl.createSaslServer( "CRAM-MD5", "ldap", saslHost, saslProps, callbackHandler );
+            session.setAttribute( SASL_CONTEXT, ss );
+        }
+
+        return ss;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/CramMd5MechanismHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.ldap.LdapContext;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.apache.mina.common.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DigestMd5CallbackHandler extends AbstractSaslCallbackHandler
+{
+    private static final Logger log = LoggerFactory.getLogger( DigestMd5CallbackHandler.class );
+
+    private IoSession session;
+    private Object message;
+
+    private String bindDn;
+    private String userPassword;
+
+
+    /**
+     * Creates a new instance of DigestMd5CallbackHandler.
+     *
+     * @param session
+     * @param message
+     */
+    public DigestMd5CallbackHandler( IoSession session, Object message )
+    {
+        this.session = session;
+        this.message = message;
+    }
+
+
+    protected String lookupPassword( String username, String realm )
+    {
+        Hashtable env = getEnvironment( session, message );
+
+        LdapContext ctx = getContext( session, message, env );
+
+        // TODO - Use realm with multi-realm support.
+
+        GetBindDn getDn = new GetBindDn( username );
+
+        // Don't actually want the entry, rather the hacked in dn.
+        getDn.execute( ctx, null );
+        bindDn = getDn.getBindDn();
+        userPassword = getDn.getUserPassword();
+
+        return userPassword;
+    }
+
+
+    protected void authorize( AuthorizeCallback authorizeCB )
+    {
+        log.debug( "Converted username " + getUsername() + " to DN " + bindDn + " with password " + userPassword );
+        session.setAttribute( Context.SECURITY_PRINCIPAL, bindDn );
+        session.setAttribute( Context.SECURITY_CREDENTIALS, userPassword );
+
+        authorizeCB.setAuthorizedID( bindDn );
+        authorizeCB.setAuthorized( true );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5CallbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServer;
+
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DigestMd5MechanismHandler implements MechanismHandler
+{
+    public SaslServer handleMechanism( IoSession session, Object message ) throws Exception
+    {
+        SaslServer ss;
+
+        if ( session.containsAttribute( SASL_CONTEXT ) )
+        {
+            ss = ( SaslServer ) session.getAttribute( SASL_CONTEXT );
+        }
+        else
+        {
+            String saslHost = ( String ) session.getAttribute( "saslHost" );
+            Map<String, String> saslProps = ( Map ) session.getAttribute( "saslProps" );
+
+            CallbackHandler callbackHandler = new DigestMd5CallbackHandler( session, message );
+
+            ss = Sasl.createSaslServer( "DIGEST-MD5", "ldap", saslHost, saslProps, callbackHandler );
+            session.setAttribute( SASL_CONTEXT, ss );
+        }
+
+        return ss;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/DigestMd5MechanismHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,133 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchResult;
+
+import org.apache.directory.server.protocol.shared.store.ContextOperation;
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+
+
+/**
+ * Encapsulates the action of looking up a user in an embedded ApacheDS DIT.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 494161 $, $Date: 2007-01-08 11:39:36 -0800 (Mon, 08 Jan 2007) $
+ */
+public class GetBindDn implements ContextOperation
+{
+    private static final long serialVersionUID = 4598007518413451945L;
+
+    /** The name of the principal to get. */
+    private String username;
+
+    private String bindDn;
+    private String userPassword;
+
+
+    /**
+     * Creates the action to be used against the embedded ApacheDS DIT.
+     * 
+     * @param username The username to search for in the directory.
+     */
+    public GetBindDn( String username )
+    {
+        this.username = username;
+    }
+
+
+    /**
+     * Accessor method for retrieving the DN for the username.
+     *
+     * @return The DN to bind the user as.
+     */
+    public String getBindDn()
+    {
+        return bindDn;
+    }
+
+
+    /**
+     * Accessor method for retrieving the user's password.
+     *
+     * @return The user's password.
+     */
+    public String getUserPassword()
+    {
+        return userPassword;
+    }
+
+
+    /**
+     * Note that the base is a relative path from the existing context.
+     * It is not a DN.
+     */
+    public Object execute( DirContext ctx, Name base )
+    {
+        if ( username == null )
+        {
+            return null;
+        }
+
+        String[] attrIDs =
+            { "userPassword" };
+
+        Attributes matchAttrs = new AttributesImpl( true );
+        matchAttrs.put( new AttributeImpl( "uid", username ) );
+
+        try
+        {
+            NamingEnumeration answer = ctx.search( "", matchAttrs, attrIDs );
+
+            if ( answer.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) answer.next();
+
+                // Changed from original GetPrincipal, along with accessor and member variable.
+                bindDn = result.getName();
+
+                Attributes attrs = result.getAttributes();
+
+                if ( attrs == null )
+                {
+                    return null;
+                }
+
+                if ( attrs.get( "userPassword" ) != null )
+                {
+                    userPassword = ( String ) attrs.get( "userPassword" ).get();
+                }
+            }
+        }
+        catch ( NamingException e )
+        {
+            return null;
+        }
+
+        return null;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetBindDn.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,161 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Hashtable;
+
+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.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;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class GetLdapContext implements IoHandlerCommand
+{
+    private static final Logger log = LoggerFactory.getLogger( GetLdapContext.class );
+
+    private static final Control[] EMPTY = new Control[0];
+
+
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        Hashtable env = getEnvironment( session, message );
+
+        BindRequest request = ( BindRequest ) message;
+        LdapResult result = request.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 )
+                {
+                    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 = ( Control[] ) request.getControls().values().toArray( EMPTY );
+                ctx = new InitialLdapContext( env, connCtls );
+            }
+
+            SessionRegistry.getSingleton().setLdapContext( session, ctx );
+
+            next.execute( session, message );
+        }
+        catch ( NamingException e )
+        {
+            ResultCodeEnum code;
+
+            if ( e instanceof LdapException )
+            {
+                code = ( ( LdapException ) e ).getResultCode();
+                result.setResultCode( code );
+            }
+            else
+            {
+                code = ResultCodeEnum.getBestEstimate( e, request.getType() );
+                result.setResultCode( code );
+            }
+
+            String msg = "Bind failed: " + e.getMessage();
+
+            if ( log.isDebugEnabled() )
+            {
+                msg += ":\n" + ExceptionUtils.getStackTrace( e );
+                msg += "\n\nBindRequest = \n" + request.toString();
+            }
+
+            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( request.getResultResponse() );
+            ctx = null;
+        }
+    }
+
+
+    private Hashtable getEnvironment( IoSession session, Object message )
+    {
+        /**
+         * For simple, this is an LdapDN.  For GSSAPI, this is a principal String.
+         */
+        Object principal = session.getAttribute( Context.SECURITY_PRINCIPAL );
+
+        Object credentials = session.getAttribute( Context.SECURITY_CREDENTIALS );
+
+        log.debug( Context.SECURITY_PRINCIPAL + " " + principal );
+        log.debug( Context.SECURITY_CREDENTIALS + " " + credentials );
+        log.debug( Context.SECURITY_AUTHENTICATION + " " + "simple" );
+        log.debug( PropertyKeys.PARSED_BIND_DN + " " + principal );
+
+        // clone the environment first then add the required security settings
+        Hashtable env = SessionRegistry.getSingleton().getEnvironmentByCopy();
+        env.put( Context.SECURITY_PRINCIPAL, principal );
+        env.put( Context.SECURITY_CREDENTIALS, credentials );
+        env.put( Context.SECURITY_AUTHENTICATION, "simple" );
+        env.put( PropertyKeys.PARSED_BIND_DN, principal );
+
+        BindRequest request = ( BindRequest ) message;
+
+        if ( request.getControls().containsKey( ManageDsaITControl.CONTROL_OID ) )
+        {
+            env.put( Context.REFERRAL, "ignore" );
+        }
+        else
+        {
+            env.put( Context.REFERRAL, "throw" );
+        }
+
+        return env;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetLdapContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,214 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.text.ParseException;
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InvalidAttributeValueException;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.kerberos.KerberosPrincipal;
+
+import org.apache.directory.server.kerberos.shared.messages.value.KerberosTime;
+import org.apache.directory.server.kerberos.shared.messages.value.SamType;
+import org.apache.directory.server.kerberos.shared.store.KerberosAttribute;
+import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
+import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntryModifier;
+import org.apache.directory.server.protocol.shared.store.ContextOperation;
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+
+
+/**
+ * Encapsulates the action of looking up a principal in an embedded ApacheDS DIT.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 494161 $, $Date: 2007-01-08 11:39:36 -0800 (Mon, 08 Jan 2007) $
+ */
+public class GetPrincipal implements ContextOperation
+{
+    private static final long serialVersionUID = 4598007518413451945L;
+
+    /** The name of the principal to get. */
+    private final KerberosPrincipal principal;
+
+    private String dn;
+    private String userPassword;
+
+
+    /**
+     * Creates the action to be used against the embedded ApacheDS DIT.
+     * 
+     * @param principal The principal to search for in the directory.
+     */
+    public GetPrincipal( KerberosPrincipal principal )
+    {
+        this.principal = principal;
+    }
+
+
+    /**
+     * Accessor method for retrieving the DN for the username.
+     *
+     * @return The DN to bind the user as.
+     */
+    public String getDn()
+    {
+        return dn;
+    }
+
+
+    /**
+     * Accessor method for retrieving the user's password.
+     *
+     * @return The user's password.
+     */
+    public String getUserPassword()
+    {
+        return userPassword;
+    }
+
+
+    /**
+     * Note that the base is a relative path from the existing context.
+     * It is not a DN.
+     */
+    public Object execute( DirContext ctx, Name base )
+    {
+        if ( principal == null )
+        {
+            return null;
+        }
+
+        String[] attrIDs =
+            { KerberosAttribute.PRINCIPAL, KerberosAttribute.VERSION, KerberosAttribute.TYPE, KerberosAttribute.KEY,
+                KerberosAttribute.SAM_TYPE, KerberosAttribute.ACCOUNT_DISABLED,
+                KerberosAttribute.ACCOUNT_EXPIRATION_TIME, KerberosAttribute.ACCOUNT_LOCKEDOUT, "userPassword" };
+
+        Attributes matchAttrs = new AttributesImpl( true );
+        matchAttrs.put( new AttributeImpl( KerberosAttribute.PRINCIPAL, principal.getName() ) );
+
+        PrincipalStoreEntry entry = null;
+
+        try
+        {
+            NamingEnumeration answer = ctx.search( "", matchAttrs, attrIDs );
+
+            if ( answer.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) answer.next();
+
+                // Changed from original GetPrincipal, along with accessor and member variable.
+                dn = result.getName();
+
+                Attributes attrs = result.getAttributes();
+
+                if ( attrs == null )
+                {
+                    return null;
+                }
+
+                entry = getEntry( attrs );
+            }
+        }
+        catch ( NamingException e )
+        {
+            return null;
+        }
+
+        return entry;
+    }
+
+
+    /**
+     * Marshals an a PrincipalStoreEntry from an Attributes object.
+     *
+     * @param attrs the attributes of the Kerberos principal
+     * @return the entry for the principal
+     * @throws NamingException if there are any access problems
+     */
+    private PrincipalStoreEntry getEntry( Attributes attrs ) throws NamingException
+    {
+        if ( attrs.get( "userPassword" ) != null )
+        {
+            userPassword = ( String ) attrs.get( "userPassword" ).get();
+        }
+
+        PrincipalStoreEntryModifier modifier = new PrincipalStoreEntryModifier();
+        String principal = ( String ) attrs.get( KerberosAttribute.PRINCIPAL ).get();
+        String encryptionType = ( String ) attrs.get( KerberosAttribute.TYPE ).get();
+        String keyVersionNumber = ( String ) attrs.get( KerberosAttribute.VERSION ).get();
+
+        if ( attrs.get( KerberosAttribute.ACCOUNT_DISABLED ) != null )
+        {
+            String val = ( String ) attrs.get( KerberosAttribute.ACCOUNT_DISABLED ).get();
+            modifier.setDisabled( "true".equalsIgnoreCase( val ) );
+        }
+
+        if ( attrs.get( KerberosAttribute.ACCOUNT_LOCKEDOUT ) != null )
+        {
+            String val = ( String ) attrs.get( KerberosAttribute.ACCOUNT_LOCKEDOUT ).get();
+            modifier.setLockedOut( "true".equalsIgnoreCase( val ) );
+        }
+
+        if ( attrs.get( KerberosAttribute.ACCOUNT_EXPIRATION_TIME ) != null )
+        {
+            String val = ( String ) attrs.get( KerberosAttribute.ACCOUNT_EXPIRATION_TIME ).get();
+            try
+            {
+                modifier.setExpiration( KerberosTime.getTime( val ) );
+            }
+            catch ( ParseException e )
+            {
+                throw new InvalidAttributeValueException( "Account expiration attribute "
+                    + KerberosAttribute.ACCOUNT_EXPIRATION_TIME + " contained an invalid value for generalizedTime: "
+                    + val );
+            }
+        }
+
+        if ( attrs.get( KerberosAttribute.SAM_TYPE ) != null )
+        {
+            String samType = ( String ) attrs.get( KerberosAttribute.SAM_TYPE ).get();
+            modifier.setSamType( SamType.getTypeByOrdinal( Integer.parseInt( samType ) ) );
+        }
+
+        Object key = attrs.get( KerberosAttribute.KEY ).get();
+        byte[] keyBytes = null;
+
+        if ( key instanceof String )
+        {
+            String msg = "JNDI should not return a string for the kerberos key: JNDI property java.naming.ldap.attributes.binary must include the krb5key attribute.";
+            throw new NamingException( msg );
+        }
+
+        keyBytes = ( byte[] ) key;
+        modifier.setKey( keyBytes );
+
+        modifier.setPrincipal( new KerberosPrincipal( principal ) );
+        modifier.setEncryptionType( Integer.parseInt( encryptionType ) );
+        modifier.setKeyVersionNumber( Integer.parseInt( keyVersionNumber ) );
+        return modifier.getEntry();
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GetPrincipal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.ldap.LdapContext;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.apache.mina.common.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class GssapiCallbackHandler extends AbstractSaslCallbackHandler
+{
+    private static final Logger log = LoggerFactory.getLogger( GssapiCallbackHandler.class );
+
+    private IoSession session;
+    private Object message;
+
+
+    /**
+     * Creates a new instance of GssapiCallbackHandler.
+     *
+     * @param session
+     * @param message
+     */
+    public GssapiCallbackHandler( IoSession session, Object message )
+    {
+        this.session = session;
+        this.message = message;
+    }
+
+
+    protected String lookupPassword( String username, String password )
+    {
+        // do nothing, password not used by GSSAPI
+        return null;
+    }
+
+
+    protected void authorize( AuthorizeCallback authorizeCB )
+    {
+        log.debug( "Processing conversion of principal name to DN." );
+
+        Hashtable env = getEnvironment( session, message );
+
+        LdapContext ctx = getContext( session, message, env );
+
+        String username = authorizeCB.getAuthorizationID();
+
+        GetPrincipal getPrincipal = new GetPrincipal( new KerberosPrincipal( username ) );
+        // Don't actually want the entry, rather the hacked in dn.
+        getPrincipal.execute( ctx, null );
+        String bindDn = getPrincipal.getDn();
+        String userPassword = getPrincipal.getUserPassword();
+
+        log.debug( "Converted username " + username + " to DN " + bindDn + " with password " + userPassword );
+        session.setAttribute( Context.SECURITY_PRINCIPAL, bindDn );
+        session.setAttribute( Context.SECURITY_CREDENTIALS, userPassword );
+
+        authorizeCB.setAuthorizedID( bindDn );
+        authorizeCB.setAuthorized( true );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiCallbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.security.PrivilegedExceptionAction;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServer;
+
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class GssapiMechanismHandler implements MechanismHandler
+{
+    public SaslServer handleMechanism( IoSession session, Object message ) throws Exception
+    {
+        SaslServer ss;
+
+        if ( session.containsAttribute( SASL_CONTEXT ) )
+        {
+            ss = ( SaslServer ) session.getAttribute( SASL_CONTEXT );
+        }
+        else
+        {
+            Subject subject = ( Subject ) session.getAttribute( "saslSubject" );
+
+            final Map saslProps = ( Map ) session.getAttribute( "saslProps" );
+            final String saslHost = ( String ) session.getAttribute( "saslHost" );
+
+            final CallbackHandler callbackHandler = new GssapiCallbackHandler( session, message );
+
+            ss = ( SaslServer ) Subject.doAs( subject, new PrivilegedExceptionAction()
+            {
+                public Object run() throws Exception
+                {
+                    return Sasl.createSaslServer( "GSSAPI", "ldap", saslHost, saslProps, callbackHandler );
+                }
+            } );
+
+            session.setAttribute( SASL_CONTEXT, ss );
+        }
+
+        return ss;
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/GssapiMechanismHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,145 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.directory.shared.ldap.message.BindRequest;
+import org.apache.directory.shared.ldap.message.BindResponse;
+import org.apache.directory.shared.ldap.message.LdapResult;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.chain.IoHandlerCommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HandleSasl implements IoHandlerCommand
+{
+    private static final Logger log = LoggerFactory.getLogger( HandleSasl.class );
+
+    /**
+     * A Hashed Adapter mapping SASL mechanisms to their handlers.
+     */
+    private static final Map DEFAULT_HANDLERS;
+
+    static
+    {
+        Map<String, MechanismHandler> map = new HashMap<String, MechanismHandler>();
+        map.put( "CRAM-MD5", new CramMd5MechanismHandler() );
+        map.put( "DIGEST-MD5", new DigestMd5MechanismHandler() );
+        map.put( "GSSAPI", new GssapiMechanismHandler() );
+
+        DEFAULT_HANDLERS = Collections.unmodifiableMap( map );
+    }
+
+
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        String sessionMechanism = ( String ) session.getAttribute( "sessionMechanism" );
+
+        if ( DEFAULT_HANDLERS.containsKey( sessionMechanism ) )
+        {
+            SaslServer ss = handleMechanism( sessionMechanism, session, message );
+            handleMechanism( ss, next, session, message );
+        }
+        else
+        {
+            next.execute( session, message );
+        }
+    }
+
+
+    private SaslServer handleMechanism( String mechanism, IoSession session, Object message ) throws Exception
+    {
+        MechanismHandler mechanismHandler = ( MechanismHandler ) DEFAULT_HANDLERS.get( mechanism );
+
+        if ( mechanismHandler == null )
+        {
+            throw new IllegalArgumentException( "Handler unavailable for " + mechanism );
+        }
+
+        return mechanismHandler.handleMechanism( session, message );
+    }
+
+
+    private void handleMechanism( SaslServer ss, NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        BindRequest request = ( BindRequest ) message;
+        LdapResult result = request.getResultResponse().getLdapResult();
+
+        if ( !ss.isComplete() )
+        {
+            try
+            {
+                /*
+                 * SaslServer will throw an exception if the credentials are null.
+                 */
+                if ( request.getCredentials() == null )
+                {
+                    request.setCredentials( new byte[0] );
+                }
+
+                byte[] tokenBytes = ss.evaluateResponse( request.getCredentials() );
+
+                if ( ss.isComplete() )
+                {
+                    /*
+                     * There may be a token to return to the client.  We set it here
+                     * so it will be returned in a SUCCESS message, after an LdapContext
+                     * has been initialized for the client.
+                     */
+                    session.setAttribute( "saslCreds", tokenBytes );
+
+                    /*
+                     * If we got here, we're ready to try getting an initial LDAP context.
+                     */
+                    next.execute( session, message );
+                }
+                else
+                {
+                    log.info( "Continuation token had length " + tokenBytes.length );
+                    result.setResultCode( ResultCodeEnum.SASL_BIND_IN_PROGRESS );
+                    BindResponse resp = ( BindResponse ) request.getResultResponse();
+                    resp.setServerSaslCreds( tokenBytes );
+                    session.write( resp );
+                    log.debug( "Returning final authentication data to client to complete context." );
+                }
+            }
+            catch ( SaslException se )
+            {
+                log.error( se.getMessage() );
+                result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
+                result.setErrorMessage( se.getMessage() );
+                session.write( request.getResultResponse() );
+            }
+        }
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSasl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import javax.naming.Context;
+
+import org.apache.directory.shared.ldap.message.BindRequest;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.chain.IoHandlerCommand;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HandleSimple implements IoHandlerCommand
+{
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        String sessionMechanism = ( String ) session.getAttribute( "sessionMechanism" );
+
+        if ( sessionMechanism.equals( "SIMPLE" ) )
+        {
+            BindRequest request = ( BindRequest ) message;
+
+            /*
+             * This is the principal name that will be used to bind to the DIT.
+             */
+            session.setAttribute( Context.SECURITY_PRINCIPAL, request.getName() );
+
+            /*
+             * These are the credentials that will be used to bind to the DIT.
+             * For the simple mechanism, this will be a password, possibly one-way hashed.
+             */
+            session.setAttribute( Context.SECURITY_CREDENTIALS, request.getCredentials() );
+        }
+
+        next.execute( session, message );
+    }
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/HandleSimple.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java?view=auto&rev=516288
==============================================================================
--- directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java (added)
+++ directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java Thu Mar  8 20:12:57 2007
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.server.ldap.support.bind;
+
+
+import javax.security.sasl.SaslServer;
+
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * An interface for retrieving a {@link SaslServer} for a session.
+ * 
+ * @see javax.security.sasl.SaslServer
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface MechanismHandler
+{
+    /**
+     * A key constant ({@value}) for storing the SASL context in the session.
+     */
+    public static final String SASL_CONTEXT = "saslContext";
+
+
+    /**
+     * Implementors will use the session and message to determine what kind of
+     * {@link SaslServer} to create and what initialization parameters it will require.
+     *
+     * @param session
+     * @param message
+     * @return The {@link SaslServer} to use for the duration of the bound session.
+     * @throws Exception
+     */
+    public SaslServer handleMechanism( IoSession session, Object message ) throws Exception;
+}

Propchange: directory/apacheds/branches/apacheds-sasl-branch/protocol-ldap/src/main/java/org/apache/directory/server/ldap/support/bind/MechanismHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message