You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2009/08/06 12:45:43 UTC
svn commit: r801595 - in /directory/apacheds/trunk:
protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/
protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/
protocol-ldap/src/main/java/org/apache/directory/server...
Author: seelmann
Date: Thu Aug 6 10:45:36 2009
New Revision: 801595
URL: http://svn.apache.org/viewvc?rev=801595&view=rev
Log:
Fix for DIRKRB-1 (GSSAPI Test)
o Fixed GSSAPI Bind
o Activated test
o Moved methods from BindHandler to GssapiMechanismHandler
o Refactored BindHandler
Modified:
directory/apacheds/trunk/protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/SaslGssapiBindITest.java
directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/BindHandler.java
directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiCallbackHandler.java
directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiMechanismHandler.java
Modified: directory/apacheds/trunk/protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/SaslGssapiBindITest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/SaslGssapiBindITest.java?rev=801595&r1=801594&r2=801595&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/SaslGssapiBindITest.java (original)
+++ directory/apacheds/trunk/protocol-kerberos/src/test/java/org/apache/directory/server/kerberos/kdc/SaslGssapiBindITest.java Thu Aug 6 10:45:36 2009
@@ -83,7 +83,7 @@
{
String krbConfPath = getClass().getResource( "krb5.conf" ).getFile();
System.setProperty( "java.security.krb5.conf", krbConfPath );
- System.setProperty( "sun.security.krb5.debug" , "false" );
+ System.setProperty( "sun.security.krb5.debug", "false" );
}
@@ -101,7 +101,7 @@
KdcServer kdcConfig = new KdcServer();
kdcConfig.setDirectoryService( directoryService );
- kdcConfig.setTransports( new TcpTransport(6088), new UdpTransport(6088) );
+ kdcConfig.setTransports( new TcpTransport( 6088 ), new UdpTransport( 6088 ) );
kdcConfig.setEnabled( true );
kdcConfig.setSearchBaseDn( "ou=users,dc=example,dc=com" );
kdcConfig.start();
@@ -126,10 +126,10 @@
{
Attribute disabled = new BasicAttribute( "m-disabled" );
ModificationItem[] mods = new ModificationItem[]
- {new ModificationItem( DirContext.REMOVE_ATTRIBUTE, disabled )};
+ { new ModificationItem( DirContext.REMOVE_ATTRIBUTE, disabled ) };
schemaRoot.modifyAttributes( "cn=Krb5kdc", mods );
}
-
+
LdapDN contextDn = new LdapDN( "dc=example,dc=com" );
ServerEntry entry = ldapServer.getDirectoryService().newEntry( contextDn );
entry.add( "objectClass", "top", "domain", "extensibleObject" );
@@ -160,7 +160,7 @@
users.createSubcontext( "uid=ldap", attrs );
}
-
+
protected void configureDirectoryService() throws NamingException
{
directoryService.setAllowAnonymousAccess( false );
@@ -171,10 +171,10 @@
partition.setId( "example" );
partition.setSuffix( "dc=example,dc=com" );
- Set<Index<?,ServerEntry>> indexedAttrs = new HashSet<Index<?,ServerEntry>>();
- indexedAttrs.add( new JdbmIndex<String,ServerEntry>( "ou" ) );
- indexedAttrs.add( new JdbmIndex<String,ServerEntry>( "dc" ) );
- indexedAttrs.add( new JdbmIndex<String,ServerEntry>( "objectClass" ) );
+ Set<Index<?, ServerEntry>> indexedAttrs = new HashSet<Index<?, ServerEntry>>();
+ indexedAttrs.add( new JdbmIndex<String, ServerEntry>( "ou" ) );
+ indexedAttrs.add( new JdbmIndex<String, ServerEntry>( "dc" ) );
+ indexedAttrs.add( new JdbmIndex<String, ServerEntry>( "objectClass" ) );
partition.setIndexedAttributes( indexedAttrs );
partitions.add( partition );
@@ -256,7 +256,6 @@
// Bad username: Client not found in Kerberos database
// Bad password: Integrity check on decrypted field failed
fail( "Authentication failed: " + le.getMessage() );
- assertTrue( false );
}
// 2. Perform JNDI work as authenticated Subject.
@@ -266,48 +265,47 @@
{
//FIXME activate this code as soon as the GSSAPIMechanismHandler is fixed.
//Currently GSSAPI authentication for the ldap server is broken
-// try
-// {
-// // Create the initial context
-// Hashtable<String, String> env = new Hashtable<String, String>();
-// env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
-// env.put( Context.PROVIDER_URL, "ldap://127.0.0.1:" + port );
-//
-// // Request the use of the "GSSAPI" SASL mechanism
-// // Authenticate by using already established Kerberos credentials
-// env.put( Context.SECURITY_AUTHENTICATION, "GSSAPI" );
-//
-// // Request privacy protection
-// env.put( "javax.security.sasl.qop", "auth-conf" );
-//
-// // Request mutual authentication
-// env.put( "javax.security.sasl.server.authentication", "true" );
-//
-// // Request high-strength cryptographic protection
-// env.put( "javax.security.sasl.strength", "high" );
-//
-// DirContext ctx = new InitialDirContext( env );
-//
-// String[] attrIDs =
-// { "uid" };
-//
-// Attributes attrs = ctx.getAttributes( "uid=hnelson,ou=users,dc=example,dc=com", attrIDs );
-//
-// String uid = null;
-//
-// if ( attrs.get( "uid" ) != null )
-// {
-// uid = ( String ) attrs.get( "uid" ).get();
-// }
-//
-// assertEquals( uid, "hnelson" );
-// }
-// catch ( NamingException e )
-// {
-// fail( "Should not have caught exception: " + e.getMessage() + e.getRootCause() );
-// e.printStackTrace();
-//
-// }
+ try
+ {
+ // Create the initial context
+ Hashtable<String, String> env = new Hashtable<String, String>();
+ env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
+ env.put( Context.PROVIDER_URL, "ldap://localhost:" + port );
+
+ // Request the use of the "GSSAPI" SASL mechanism
+ // Authenticate by using already established Kerberos credentials
+ env.put( Context.SECURITY_AUTHENTICATION, "GSSAPI" );
+
+ // Request privacy protection
+ env.put( "javax.security.sasl.qop", "auth-conf" );
+
+ // Request mutual authentication
+ env.put( "javax.security.sasl.server.authentication", "true" );
+
+ // Request high-strength cryptographic protection
+ env.put( "javax.security.sasl.strength", "high" );
+
+ DirContext ctx = new InitialDirContext( env );
+
+ String[] attrIDs =
+ { "uid" };
+
+ Attributes attrs = ctx.getAttributes( "uid=hnelson,ou=users,dc=example,dc=com", attrIDs );
+
+ String uid = null;
+
+ if ( attrs.get( "uid" ) != null )
+ {
+ uid = ( String ) attrs.get( "uid" ).get();
+ }
+
+ assertEquals( uid, "hnelson" );
+ }
+ catch ( NamingException e )
+ {
+ e.printStackTrace();
+ fail( "Should not have caught exception: " + e.getMessage() + e.getRootCause() );
+ }
return null;
}
Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/BindHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/BindHandler.java?rev=801595&r1=801594&r2=801595&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/BindHandler.java (original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/BindHandler.java Thu Aug 6 10:45:36 2009
@@ -24,9 +24,6 @@
import javax.naming.Name;
import javax.naming.NameNotFoundException;
-import javax.security.auth.Subject;
-import javax.security.auth.kerberos.KerberosKey;
-import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
@@ -35,16 +32,10 @@
import org.apache.directory.server.core.authn.LdapPrincipal;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.interceptor.context.BindOperationContext;
-import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
-import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
-import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
-import org.apache.directory.server.kerberos.shared.store.operations.GetPrincipal;
import org.apache.directory.server.ldap.LdapProtocolUtils;
-import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.ldap.LdapSession;
import org.apache.directory.server.ldap.handlers.bind.MechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
-import org.apache.directory.server.protocol.shared.ServiceConfigurationException;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.exception.LdapAuthenticationException;
import org.apache.directory.shared.ldap.exception.LdapException;
@@ -55,7 +46,6 @@
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.util.ExceptionUtils;
import org.apache.directory.shared.ldap.util.StringTools;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -75,6 +65,7 @@
/** A Hashed Adapter mapping SASL mechanisms to their handlers. */
private Map<String, MechanismHandler> handlers;
+
/**
* Set the mechanisms handler map.
*
@@ -84,7 +75,7 @@
{
this.handlers = handlers;
}
-
+
/**
* Handle the Simple authentication.
@@ -101,24 +92,24 @@
// We already have a bound session for this user. We have to
// abandon it first.
ldapSession.getCoreSession().unbind();
-
+
// Reset the status to Anonymous
ldapSession.setAnonymous();
}
// Now, bind the user
-
+
// create a new Bind context, with a null session, as we don't have
// any context yet.
BindOperationContext opContext = new BindOperationContext( null );
-
+
// Stores the DN of the user to check, and its password
opContext.setDn( bindRequest.getName() );
opContext.setCredentials( bindRequest.getCredentials() );
// Stores the request controls into the operation context
LdapProtocolUtils.setRequestControls( opContext, bindRequest );
-
+
try
{
/*
@@ -139,13 +130,12 @@
* and delegate appropriately.
*/
ClonedServerEntry principalEntry = null;
-
+
try
{
- principalEntry = getLdapServer().getDirectoryService()
- .getAdminSession().lookup( bindRequest.getName() );
+ principalEntry = getLdapServer().getDirectoryService().getAdminSession().lookup( bindRequest.getName() );
}
- catch ( NameNotFoundException e )
+ catch ( NameNotFoundException e )
{
// this is OK
}
@@ -159,9 +149,9 @@
ldapSession.getIoSession().write( bindRequest.getResultResponse() );
return;
}
-
- if (principalEntry.getOriginalEntry().contains( SchemaConstants.OBJECT_CLASS_AT,
- SchemaConstants.REFERRAL_OC ) )
+
+ if ( principalEntry.getOriginalEntry().contains( SchemaConstants.OBJECT_CLASS_AT,
+ SchemaConstants.REFERRAL_OC ) )
{
LOG.info( "Bind principalDn points to referral." );
InternalLdapResult result = bindRequest.getResultResponse().getLdapResult();
@@ -180,15 +170,15 @@
// And call the OperationManager bind operation.
getLdapServer().getDirectoryService().getOperationManager().bind( opContext );
-
+
// As a result, store the created session in the Core Session
ldapSession.setCoreSession( opContext.getSession() );
-
- if ( ! ldapSession.getCoreSession().isAnonymous() )
+
+ if ( !ldapSession.getCoreSession().isAnonymous() )
{
ldapSession.setAuthenticated();
}
-
+
// Return the successful response
sendBindSuccess( ldapSession, bindRequest, null );
}
@@ -218,12 +208,12 @@
}
Name name = null;
-
+
if ( e instanceof LdapAuthenticationException )
{
name = ( ( LdapAuthenticationException ) e ).getResolvedName();
}
-
+
if ( ( name != null )
&& ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM )
|| ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM ) ) )
@@ -235,19 +225,18 @@
ldapSession.getIoSession().write( bindRequest.getResultResponse() );
}
}
-
-
+
+
/**
* Check if the mechanism exists.
*/
private boolean checkMechanism( LdapSession ldapSession, String saslMechanism ) throws Exception
{
// Guard clause: Reject unsupported SASL mechanisms.
- if ( ! ldapServer.getSupportedMechanisms().contains( saslMechanism ) )
+ if ( !ldapServer.getSupportedMechanisms().contains( saslMechanism ) )
{
- LOG.error( "Bind error : {} mechanism not supported. Please check the server.xml " +
- "configuration file (supportedMechanisms field)",
- saslMechanism );
+ LOG.error( "Bind error : {} mechanism not supported. Please check the server.xml "
+ + "configuration file (supportedMechanisms field)", saslMechanism );
return false;
}
@@ -256,16 +245,18 @@
return true;
}
}
-
-
+
+
/**
- * For challenge/response exchange, generate the challenge
+ * For challenge/response exchange, generate the challenge.
+ * If the exchange is complete then send bind success.
*
* @param ldapSession
* @param ss
* @param bindRequest
*/
- private void generateSaslChallenge( LdapSession ldapSession, SaslServer ss, InternalBindRequest bindRequest )
+ private void generateSaslChallengeOrComplete( LdapSession ldapSession, SaslServer ss,
+ InternalBindRequest bindRequest ) throws Exception
{
InternalLdapResult result = bindRequest.getResultResponse().getLdapResult();
@@ -279,7 +270,7 @@
{
// Compute the challenge
byte[] tokenBytes = ss.evaluateResponse( bindRequest.getCredentials() );
-
+
if ( ss.isComplete() )
{
// This is the end of the C/R exchange
@@ -292,7 +283,28 @@
*/
ldapSession.putSaslProperty( SaslConstants.SASL_CREDS, tokenBytes );
}
-
+
+ LdapPrincipal ldapPrincipal = ( LdapPrincipal ) ldapSession
+ .getSaslProperty( SaslConstants.SASL_AUTHENT_USER );
+ if ( ldapPrincipal != null )
+ {
+ DirectoryService ds = ldapSession.getLdapServer().getDirectoryService();
+ String saslMechanism = bindRequest.getSaslMechanism();
+ CoreSession userSession = ds.getSession( ldapPrincipal.getJndiName(), ldapPrincipal
+ .getUserPassword(), saslMechanism, null );
+
+ // Set the user session into the ldap session
+ ldapSession.setCoreSession( userSession );
+ }
+
+ // Mark the user as authenticated
+ ldapSession.setAuthenticated();
+
+ // Call the cleanup method for the selected mechanism
+ MechanismHandler handler = ( MechanismHandler ) ldapSession
+ .getSaslProperty( SaslConstants.SASL_MECH_HANDLER );
+ handler.cleanup( ldapSession );
+
// Return the successful response
sendBindSuccess( ldapSession, bindRequest, tokenBytes );
}
@@ -300,17 +312,17 @@
{
// The SASL bind must continue, we are sending the computed challenge
LOG.info( "Continuation token had length " + tokenBytes.length );
-
+
// Build the response
result.setResultCode( ResultCodeEnum.SASL_BIND_IN_PROGRESS );
InternalBindResponse resp = ( InternalBindResponse ) bindRequest.getResultResponse();
// Store the challenge
resp.setServerSaslCreds( tokenBytes );
-
+
// Switch to AuthPending
ldapSession.setAuthPending();
-
+
// And write back the response
ldapSession.getIoSession().write( resp );
LOG.debug( "Returning final authentication data to client to complete context." );
@@ -318,21 +330,11 @@
}
catch ( SaslException se )
{
- LOG.error( se.getMessage() );
- result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
- result.setErrorMessage( ResultCodeEnum.INVALID_CREDENTIALS.toString() + ": "
- + se.getMessage() );
-
- // Reinitialize the state to Anonymous and clear the sasl properties
- ldapSession.clearSaslProperties();
- ldapSession.setAnonymous();
-
- // Write back the error response
- ldapSession.getIoSession().write( bindRequest.getResultResponse() );
+ sendInvalidCredentials( ldapSession, bindRequest, se );
}
}
-
-
+
+
/**
* Send back an AUTH-METH-NOT-SUPPORTED error message to the client
*/
@@ -342,20 +344,20 @@
// saslProperty map
ldapSession.clearSaslProperties();
ldapSession.setAnonymous();
-
+
// And send the response to the client
InternalLdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
bindResult.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
- bindResult.setErrorMessage( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED.toString() + ": "
+ bindResult.setErrorMessage( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED.toString() + ": "
+ bindRequest.getSaslMechanism() + " is not a supported mechanism." );
-
+
// Write back the error
ldapSession.getIoSession().write( bindRequest.getResultResponse() );
return;
}
-
-
+
+
/**
* Send back an INVALID-CREDENTIAL error message to the user. If we have an exception
* as a third argument, then send back the associated message to the client.
@@ -363,9 +365,9 @@
private void sendInvalidCredentials( LdapSession ldapSession, InternalBindRequest bindRequest, Exception e )
{
InternalLdapResult result = bindRequest.getResultResponse().getLdapResult();
-
+
String message = "";
-
+
if ( e != null )
{
message = ResultCodeEnum.INVALID_CREDENTIALS + ": " + e.getMessage();
@@ -374,20 +376,20 @@
{
message = ResultCodeEnum.INVALID_CREDENTIALS.toString();
}
-
+
LOG.error( message );
result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
result.setErrorMessage( message );
-
+
// Reinitialize the state to Anonymous and clear the sasl properties
ldapSession.clearSaslProperties();
ldapSession.setAnonymous();
-
+
// Write back the error response
ldapSession.getIoSession().write( bindRequest.getResultResponse() );
}
-
-
+
+
/**
* Send a SUCCESS message back to the client.
*/
@@ -397,8 +399,8 @@
InternalBindResponse response = ( InternalBindResponse ) bindRequest.getResultResponse();
response.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
response.setServerSaslCreds( tokenBytes );
-
- if ( ! ldapSession.getCoreSession().isAnonymous() )
+
+ if ( !ldapSession.getCoreSession().isAnonymous() )
{
// If we have not been asked to authenticate as Anonymous, authenticate the user
ldapSession.setAuthenticated();
@@ -408,34 +410,35 @@
// Otherwise, switch back to Anonymous
ldapSession.setAnonymous();
}
-
+
// Clean the SaslProperties, we don't need them anymore
- MechanismHandler handler = (MechanismHandler)ldapSession.getSaslProperty( SaslConstants.SASL_MECH_HANDLER );
-
+ MechanismHandler handler = ( MechanismHandler ) ldapSession.getSaslProperty( SaslConstants.SASL_MECH_HANDLER );
+
if ( handler != null )
{
handler.cleanup( ldapSession );
}
ldapSession.getIoSession().write( response );
-
+
LOG.debug( "Returned SUCCESS message: {}.", response );
}
-
- private void handleSaslAuthPending( LdapSession ldapSession, InternalBindRequest bindRequest, DirectoryService ds ) throws Exception
+
+ private void handleSaslAuthPending( LdapSession ldapSession, InternalBindRequest bindRequest, DirectoryService ds )
+ throws Exception
{
// First, check that we have the same mechanism
String saslMechanism = bindRequest.getSaslMechanism();
-
+
// The empty mechanism is also a request for a new Bind session
- if ( StringTools.isEmpty( saslMechanism ) ||
- !ldapSession.getSaslProperty( SaslConstants.SASL_MECH ).equals( saslMechanism ) )
+ if ( StringTools.isEmpty( saslMechanism )
+ || !ldapSession.getSaslProperty( SaslConstants.SASL_MECH ).equals( saslMechanism ) )
{
sendAuthMethNotSupported( ldapSession, bindRequest );
return;
}
-
+
// We have already received a first BindRequest, and sent back some challenge.
// First, check if the mechanism is the same
MechanismHandler mechanismHandler = handlers.get( saslMechanism );
@@ -443,70 +446,22 @@
if ( mechanismHandler == null )
{
String message = "Handler unavailable for " + saslMechanism;
-
+
// Clear the saslProperties, and move to the anonymous state
ldapSession.clearSaslProperties();
ldapSession.setAnonymous();
-
+
LOG.error( message );
throw new IllegalArgumentException( message );
}
// Get the previously created SaslServer instance
SaslServer ss = mechanismHandler.handleMechanism( ldapSession, bindRequest );
-
- /*
- * SaslServer will throw an exception if the credentials are null.
- */
- if ( bindRequest.getCredentials() == null )
- {
- bindRequest.setCredentials( StringTools.EMPTY_BYTES );
- }
-
- byte[] tokenBytes = ss.evaluateResponse( bindRequest.getCredentials() );
-
- if ( ss.isComplete() )
- {
- if ( tokenBytes != null )
- {
- /*
- * 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.
- */
- ldapSession.putSaslProperty( SaslConstants.SASL_CREDS, tokenBytes );
- }
-
- // Create the user's coreSession
- try
- {
- LdapPrincipal ldapPrincipal = (LdapPrincipal)ldapSession.getSaslProperty( SaslConstants.SASL_AUTHENT_USER );
-
- CoreSession userSession = ds.getSession( ldapPrincipal.getJndiName(), ldapPrincipal.getUserPassword(), saslMechanism, null );
-
- // Set the user session into the ldap session
- ldapSession.setCoreSession( userSession );
-
- // Mark the user as authenticated
- ldapSession.setAuthenticated();
-
- // Call the cleanup method for the selected mechanism
- MechanismHandler handler = (MechanismHandler)ldapSession.getSaslProperty( SaslConstants.SASL_MECH_HANDLER );
- handler.cleanup( ldapSession );
- // And send a Success response
- sendBindSuccess( ldapSession, bindRequest, tokenBytes );
- }
- catch ( Exception e )
- {
- // TODO - why is this exception being ignored? Isn't this
- // really bad?
- LOG.error( "Exception encountered while processing Sasl BindRequest", e );
- }
- }
+ generateSaslChallengeOrComplete( ldapSession, ss, bindRequest );
}
-
-
+
+
/**
* Handle the SASL authentication. If the mechanism is known, we are
* facing three cases :
@@ -537,20 +492,20 @@
{
String saslMechanism = bindRequest.getSaslMechanism();
DirectoryService ds = getLdapServer().getDirectoryService();
-
+
// Case #2 : the user does have a session. We have to unbind him
if ( ldapSession.isAuthenticated() )
{
// We already have a bound session for this user. We have to
// close the previous session first.
ldapSession.getCoreSession().unbind();
-
+
// Reset the status to Anonymous
ldapSession.setAnonymous();
-
+
// Clean the sasl properties
ldapSession.clearSaslProperties();
-
+
// Now we can continue as if the client was Anonymous from the beginning
}
@@ -570,23 +525,22 @@
// Store the mechanism in the ldap session
ldapSession.putSaslProperty( SaslConstants.SASL_MECH, saslMechanism );
-
// Get the handler for this mechanism
MechanismHandler mechanismHandler = handlers.get( saslMechanism );
-
+
// Store the mechanism handler in the salsProperties
ldapSession.putSaslProperty( SaslConstants.SASL_MECH_HANDLER, mechanismHandler );
-
+
// Initialize the mechanism specific data
mechanismHandler.init( ldapSession );
// Get the SaslServer instance which manage the C/R exchange
SaslServer ss = mechanismHandler.handleMechanism( ldapSession, bindRequest );
-
+
// We have to generate a challenge
- generateSaslChallenge( ldapSession, ss, bindRequest );
-
+ generateSaslChallengeOrComplete( ldapSession, ss, bindRequest );
+
// And get back
return;
}
@@ -601,94 +555,11 @@
{
sendInvalidCredentials( ldapSession, bindRequest, se );
}
-
- return;
- }
- }
-
- /**
- * Create a list of all the configured realms.
- *
- * @param ldapServer the LdapServer for which we want to get the realms
- * @return a list of realms, separated by spaces
- */
- private String getActiveRealms( LdapServer ldapServer )
- {
- StringBuilder realms = new StringBuilder();
- boolean isFirst = true;
-
- for ( String realm:ldapServer.getSaslRealms() )
- {
- if ( isFirst )
- {
- isFirst = false;
- }
- else
- {
- realms.append( ' ' );
- }
-
- realms.append( realm );
- }
-
- return realms.toString();
- }
-
-
- private Subject getSubject( LdapServer ldapServer ) throws Exception
- {
- String servicePrincipalName = ldapServer.getSaslPrincipal();
-
- KerberosPrincipal servicePrincipal = new KerberosPrincipal( servicePrincipalName );
- GetPrincipal getPrincipal = new GetPrincipal( servicePrincipal );
-
- PrincipalStoreEntry entry = null;
-
- try
- {
- entry = findPrincipal( ldapServer, getPrincipal );
- }
- catch ( ServiceConfigurationException sce )
- {
- String message = "Service principal " + servicePrincipalName + " not found at search base DN "
- + ldapServer.getSearchBaseDn() + ".";
- throw new ServiceConfigurationException( message, sce );
- }
-
- if ( entry == null )
- {
- String message = "Service principal " + servicePrincipalName + " not found at search base DN "
- + ldapServer.getSearchBaseDn() + ".";
- throw new ServiceConfigurationException( message );
- }
-
- Subject subject = new Subject();
-
- for ( EncryptionType encryptionType:entry.getKeyMap().keySet() )
- {
- EncryptionKey key = entry.getKeyMap().get( encryptionType );
-
- byte[] keyBytes = key.getKeyValue();
- int type = key.getKeyType().getOrdinal();
- int kvno = key.getKeyVersion();
-
- KerberosKey serviceKey = new KerberosKey( servicePrincipal, keyBytes, type, kvno );
-
- subject.getPrivateCredentials().add( serviceKey );
+ return;
}
-
- return subject;
}
-
-
- private PrincipalStoreEntry findPrincipal( LdapServer ldapServer, GetPrincipal getPrincipal ) throws Exception
- {
- CoreSession adminSession = ldapServer.getDirectoryService().getAdminSession();
- return ( PrincipalStoreEntry ) getPrincipal.execute( adminSession, null );
- }
-
/**
* Deal with a received BindRequest
@@ -703,7 +574,7 @@
LOG.debug( "Received: {}", bindRequest );
// Guard clause: LDAP version 3
- if ( ! bindRequest.getVersion3() )
+ if ( !bindRequest.getVersion3() )
{
LOG.error( "Bind error : Only LDAP v3 is supported." );
InternalLdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiCallbackHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiCallbackHandler.java?rev=801595&r1=801594&r2=801595&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiCallbackHandler.java (original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiCallbackHandler.java Thu Aug 6 10:45:36 2009
@@ -20,23 +20,25 @@
package org.apache.directory.server.ldap.handlers.bind.gssapi;
-import org.apache.directory.server.core.DirectoryService;
+import javax.naming.Context;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.sasl.AuthorizeCallback;
+
+import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.authn.LdapPrincipal;
import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
import org.apache.directory.server.kerberos.shared.store.operations.GetPrincipal;
import org.apache.directory.server.ldap.LdapSession;
import org.apache.directory.server.ldap.handlers.bind.AbstractSaslCallbackHandler;
+import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.message.InternalBindRequest;
import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.naming.Context;
-import javax.naming.ldap.LdapContext;
-import javax.security.auth.kerberos.KerberosPrincipal;
-import javax.security.sasl.AuthorizeCallback;
-import java.util.Hashtable;
-
/**
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
@@ -46,8 +48,6 @@
{
private static final Logger LOG = LoggerFactory.getLogger( GssapiCallbackHandler.class );
- private LdapSession ldapSession;
-
/**
* Creates a new instance of GssapiCallbackHandler.
@@ -56,10 +56,11 @@
* @param bindRequest the bind message
* @param directoryService the directory service core
*/
- public GssapiCallbackHandler( DirectoryService directoryService, LdapSession ldapSession, InternalBindRequest bindRequest )
+ public GssapiCallbackHandler( LdapSession ldapSession, CoreSession adminSession, InternalBindRequest bindRequest )
{
- super( directoryService, bindRequest );
+ super( adminSession.getDirectoryService(), bindRequest );
this.ldapSession = ldapSession;
+ this.adminSession = adminSession;
}
@@ -74,18 +75,20 @@
{
LOG.debug( "Processing conversion of principal name to DN." );
- Hashtable<String, Object> env = getEnvironment( ldapSession.getIoSession() );
-
- LdapContext ctx = getContext( ldapSession.getIoSession(), bindRequest, env );
-
String username = authorizeCB.getAuthorizationID();
+ // find the user's entry
GetPrincipal getPrincipal = new GetPrincipal( new KerberosPrincipal( username ) );
- PrincipalStoreEntry entry = ( PrincipalStoreEntry ) getPrincipal.execute( ldapSession.getCoreSession(), new LdapDN() );
+ PrincipalStoreEntry entry = ( PrincipalStoreEntry ) getPrincipal.execute( adminSession, new LdapDN( ldapSession
+ .getLdapServer().getSearchBaseDn() ) );
String bindDn = entry.getDistinguishedName();
LOG.debug( "Converted username {} to DN {}.", username, bindDn );
- ldapSession.getIoSession().setAttribute( Context.SECURITY_PRINCIPAL, bindDn );
+
+ LdapPrincipal ldapPrincipal = new LdapPrincipal( new LdapDN( entry.getDistinguishedName() ),
+ AuthenticationLevel.STRONG, StringTools.EMPTY_BYTES );
+ ldapSession.putSaslProperty( SaslConstants.SASL_AUTHENT_USER, ldapPrincipal );
+ ldapSession.putSaslProperty( Context.SECURITY_PRINCIPAL, bindDn );
authorizeCB.setAuthorizedID( bindDn );
authorizeCB.setAuthorized( true );
Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiMechanismHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiMechanismHandler.java?rev=801595&r1=801594&r2=801595&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiMechanismHandler.java (original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/bind/gssapi/GssapiMechanismHandler.java Thu Aug 6 10:45:36 2009
@@ -20,18 +20,30 @@
package org.apache.directory.server.ldap.handlers.bind.gssapi;
-import org.apache.directory.server.ldap.LdapSession;
-import org.apache.directory.server.ldap.handlers.bind.AbstractMechanismHandler;
-import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
-import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
-import org.apache.directory.shared.ldap.message.InternalBindRequest;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslServer;
-import java.security.PrivilegedExceptionAction;
-import java.util.Map;
+
+import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType;
+import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
+import org.apache.directory.server.kerberos.shared.store.PrincipalStoreEntry;
+import org.apache.directory.server.kerberos.shared.store.operations.GetPrincipal;
+import org.apache.directory.server.ldap.LdapServer;
+import org.apache.directory.server.ldap.LdapSession;
+import org.apache.directory.server.ldap.handlers.bind.AbstractMechanismHandler;
+import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
+import org.apache.directory.server.protocol.shared.ServiceConfigurationException;
+import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
+import org.apache.directory.shared.ldap.message.InternalBindRequest;
+import org.apache.directory.shared.ldap.name.LdapDN;
/**
@@ -45,33 +57,37 @@
{
public SaslServer handleMechanism( LdapSession ldapSession, InternalBindRequest bindRequest ) throws Exception
{
- SaslServer ss = (SaslServer)ldapSession.getSaslProperty( SaslConstants.SASL_SERVER );
+ SaslServer ss = ( SaslServer ) ldapSession.getSaslProperty( SaslConstants.SASL_SERVER );
if ( ss == null )
{
- Subject subject = ( Subject ) ldapSession.getIoSession().getAttribute( "saslSubject" );
+ //Subject subject = ( Subject ) ldapSession.getIoSession().getAttribute( "saslSubject" );
+
+ Subject subject = getSubject( ldapSession.getLdapServer() );
+ final String saslHost = ( String ) ldapSession.getSaslProperty( SaslConstants.SASL_HOST );
+ final Map<String, String> saslProps = ( Map<String, String> ) ldapSession
+ .getSaslProperty( SaslConstants.SASL_PROPS );
- final Map<String, String> saslProps = ( Map<String, String> ) ldapSession.getIoSession().getAttribute( "saslProps" );
- final String saslHost = ( String ) ldapSession.getIoSession().getAttribute( "saslHost" );
+ CoreSession adminSession = ldapSession.getLdapServer().getDirectoryService().getAdminSession();
- final CallbackHandler callbackHandler = new GssapiCallbackHandler(
- ldapSession.getCoreSession().getDirectoryService(), ldapSession, bindRequest );
+ final CallbackHandler callbackHandler = new GssapiCallbackHandler( ldapSession, adminSession, bindRequest );
ss = ( SaslServer ) Subject.doAs( subject, new PrivilegedExceptionAction<SaslServer>()
{
public SaslServer run() throws Exception
{
- return Sasl.createSaslServer( SupportedSaslMechanisms.GSSAPI, SaslConstants.LDAP_PROTOCOL, saslHost, saslProps, callbackHandler );
+ return Sasl.createSaslServer( SupportedSaslMechanisms.GSSAPI, SaslConstants.LDAP_PROTOCOL,
+ saslHost, saslProps, callbackHandler );
}
} );
- ldapSession.getIoSession().setAttribute( SaslConstants.SASL_SERVER, ss );
+ ldapSession.putSaslProperty( SaslConstants.SASL_SERVER, ss );
}
return ss;
}
-
+
/**
* {@inheritDoc}
*/
@@ -80,6 +96,11 @@
// Store the host in the ldap session
String saslHost = ldapSession.getLdapServer().getSaslHost();
ldapSession.putSaslProperty( SaslConstants.SASL_HOST, saslHost );
+
+ Map<String, String> saslProps = new HashMap<String, String>();
+ saslProps.put( Sasl.QOP, ldapSession.getLdapServer().getSaslQopString() );
+ //saslProps.put( "com.sun.security.sasl.digest.realm", getActiveRealms( ldapSession.getLdapServer() ) );
+ ldapSession.putSaslProperty( SaslConstants.SASL_PROPS, saslProps );
}
@@ -100,4 +121,56 @@
ldapSession.removeSaslProperty( SaslConstants.SASL_PROPS );
ldapSession.removeSaslProperty( SaslConstants.SASL_AUTHENT_USER );
}
+
+
+ private Subject getSubject( LdapServer ldapServer ) throws Exception
+ {
+ String servicePrincipalName = ldapServer.getSaslPrincipal();
+ KerberosPrincipal servicePrincipal = new KerberosPrincipal( servicePrincipalName );
+ GetPrincipal getPrincipal = new GetPrincipal( servicePrincipal );
+
+ PrincipalStoreEntry entry = null;
+
+ try
+ {
+ entry = findPrincipal( ldapServer, getPrincipal );
+ }
+ catch ( ServiceConfigurationException sce )
+ {
+ String message = "Service principal " + servicePrincipalName + " not found at search base DN "
+ + ldapServer.getSearchBaseDn() + ".";
+ throw new ServiceConfigurationException( message, sce );
+ }
+
+ if ( entry == null )
+ {
+ String message = "Service principal " + servicePrincipalName + " not found at search base DN "
+ + ldapServer.getSearchBaseDn() + ".";
+ throw new ServiceConfigurationException( message );
+ }
+
+ Subject subject = new Subject();
+
+ for ( EncryptionType encryptionType : entry.getKeyMap().keySet() )
+ {
+ EncryptionKey key = entry.getKeyMap().get( encryptionType );
+
+ byte[] keyBytes = key.getKeyValue();
+ int type = key.getKeyType().getOrdinal();
+ int kvno = key.getKeyVersion();
+
+ KerberosKey serviceKey = new KerberosKey( servicePrincipal, keyBytes, type, kvno );
+
+ subject.getPrivateCredentials().add( serviceKey );
+ }
+
+ return subject;
+ }
+
+
+ private PrincipalStoreEntry findPrincipal( LdapServer ldapServer, GetPrincipal getPrincipal ) throws Exception
+ {
+ CoreSession adminSession = ldapServer.getDirectoryService().getAdminSession();
+ return ( PrincipalStoreEntry ) getPrincipal.execute( adminSession, new LdapDN( ldapServer.getSearchBaseDn() ) );
+ }
}