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
|