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 Apache Directory Project + * @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 Apache Directory Project + * @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. + * + * @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 true 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 Apache Directory Project + * @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 Apache Directory Project + * @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 Apache Directory Project + * @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 supportedMechanisms = new HashSet(); + 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 saslProps = new HashMap(); + + /** + * 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 Apache Directory Project + * @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 Apache Directory Project + * @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 saslProps = new HashMap(); + + 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 Apache Directory Project + * @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 Apache Directory Project + * @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 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 Apache Directory Project + * @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 Apache Directory Project + * @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 Apache Directory Project + * @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 Apache Directory Project + * @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 Apache Directory Project + * @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 Apache Directory Project + * @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 map = new HashMap(); + 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 Apache Directory Project + * @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 Apache Directory Project + * @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