You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2008/08/06 13:15:25 UTC

svn commit: r683225 - in /directory/apacheds/branches/bigbang: core/src/main/java/org/apache/directory/server/core/ protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/ server-unit/src/test/java/org/apache/directory/se...

Author: elecharny
Date: Wed Aug  6 04:15:24 2008
New Revision: 683225

URL: http://svn.apache.org/viewvc?rev=683225&view=rev
Log:
o Added the sasl mechanism in the context session, to avoid an exception when binding using NTLM
o Made the two last tests for SASL (NtlmBind and SpnegoBind) happy

Modified:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/NtlmSaslServer.java
    directory/apacheds/branches/bigbang/server-unit/src/test/java/org/apache/directory/server/operations/bind/SaslBindITest.java

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=683225&r1=683224&r2=683225&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Wed Aug  6 04:15:24 2008
@@ -618,6 +618,7 @@
         BindOperationContext bindContext = new BindOperationContext( null );
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn );
+        bindContext.setSaslMechanism( saslMechanism );
         operationManager.bind( bindContext );
         
         return bindContext.getSession();

Modified: directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/NtlmSaslServer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/NtlmSaslServer.java?rev=683225&r1=683224&r2=683225&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/NtlmSaslServer.java (original)
+++ directory/apacheds/branches/bigbang/protocol-newldap/src/main/java/org/apache/directory/server/newldap/handlers/bind/ntlm/NtlmSaslServer.java Wed Aug  6 04:15:24 2008
@@ -21,10 +21,12 @@
 
 
 import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.authn.LdapPrincipal;
 import org.apache.directory.server.core.interceptor.context.BindOperationContext;
 import org.apache.directory.server.newldap.LdapSession;
 import org.apache.directory.server.newldap.handlers.bind.AbstractSaslServer;
 import org.apache.directory.server.newldap.handlers.bind.SaslConstants;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
 import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
 import org.apache.directory.shared.ldap.message.BindRequest;
 import org.apache.directory.shared.ldap.name.LdapDN;
@@ -154,7 +156,10 @@
                 try
                 {
                     result = provider.authenticate( getLdapSession().getIoSession(), response );
-                    
+                    LdapDN dn = getBindRequest().getName();
+                    dn.normalize( getLdapSession().getLdapServer().getDirectoryService().getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
+                    LdapPrincipal ldapPrincipal = new LdapPrincipal( dn, AuthenticationLevel.STRONG ); 
+                    getLdapSession().putSaslProperty( SaslConstants.SASL_AUTHENT_USER, ldapPrincipal );
                     getLdapSession().putSaslProperty( Context.SECURITY_PRINCIPAL, getBindRequest().getName().toString() );
                 }
                 catch ( Exception e )

Modified: directory/apacheds/branches/bigbang/server-unit/src/test/java/org/apache/directory/server/operations/bind/SaslBindITest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/server-unit/src/test/java/org/apache/directory/server/operations/bind/SaslBindITest.java?rev=683225&r1=683224&r2=683225&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/server-unit/src/test/java/org/apache/directory/server/operations/bind/SaslBindITest.java (original)
+++ directory/apacheds/branches/bigbang/server-unit/src/test/java/org/apache/directory/server/operations/bind/SaslBindITest.java Wed Aug  6 04:15:24 2008
@@ -33,22 +33,34 @@
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 
+import org.apache.commons.net.SocketClient;
 import org.apache.directory.server.core.entry.DefaultServerEntry;
 import org.apache.directory.server.core.entry.ServerEntry;
 import org.apache.directory.server.core.partition.Partition;
 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
 import org.apache.directory.server.newldap.handlers.bind.ntlm.NtlmMechanismHandler;
+import org.apache.directory.server.newldap.handlers.bind.ntlm.NtlmProvider;
 import org.apache.directory.server.newldap.handlers.bind.plain.PlainMechanismHandler;
 import org.apache.directory.server.unit.AbstractServerTest;
 import org.apache.directory.server.xdbm.Index;
 import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
+import org.apache.directory.shared.ldap.message.BindRequestImpl;
+import org.apache.directory.shared.ldap.message.BindResponse;
+import org.apache.directory.shared.ldap.message.MessageDecoder;
+import org.apache.directory.shared.ldap.message.MessageEncoder;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
 import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.ArrayUtils;
+import org.apache.mina.common.IoSession;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -60,7 +72,9 @@
 public class SaslBindITest extends AbstractServerTest
 {
      private DirContext ctx;
-     //private BogusNtlmProvider provider;
+     
+     /** The NTLM fake provider */
+     private BogusNtlmProvider provider;
 
      /**
       * Set up a partition for EXAMPLE.COM and add a user to
@@ -69,7 +83,7 @@
      @Before
      public void setUp() throws Exception
      {
-         //provider = new BogusNtlmProvider();
+         provider = new BogusNtlmProvider();
          super.setUp();
          directoryService.setAllowAnonymousAccess( true );
 
@@ -125,7 +139,7 @@
          ldapServer.setSaslHost( "localhost" );
          
          NtlmMechanismHandler ntlmMechanismHandler = new NtlmMechanismHandler();
-         //ntlmMechanismHandler.setNtlmProvider( provider  );
+         ntlmMechanismHandler.setNtlmProvider( provider  );
          
          // Inject the NTLM MechanismHandler
          ldapServer.removeSaslMechanismHandler( SupportedSaslMechanisms.NTLM );
@@ -501,4 +515,184 @@
              assertTrue( e.getMessage().contains( "digest response format violation" ) );
          }
      }
+
+
+     /**
+      * Tests that the plumbing for NTLM bind works.
+      */
+     @Test
+     public void testNtlmBind() throws Exception
+     {
+         NtlmSaslBindClient client = new NtlmSaslBindClient( SupportedSaslMechanisms.NTLM );
+         BindResponse type2response = client.bindType1( "type1_test".getBytes() );
+         assertEquals( 1, type2response.getMessageId() );
+         assertEquals( ResultCodeEnum.SASL_BIND_IN_PROGRESS, type2response.getLdapResult().getResultCode() );
+         assertTrue( ArrayUtils.isEquals( "type1_test".getBytes(), provider.getType1Response() ) );
+         assertTrue( ArrayUtils.isEquals( "challenge".getBytes(), type2response.getServerSaslCreds() ) );
+         
+         BindResponse finalResponse = client.bindType3( "type3_test".getBytes() );
+         assertEquals( 2, finalResponse.getMessageId() );
+         assertEquals( ResultCodeEnum.SUCCESS, finalResponse.getLdapResult().getResultCode() );
+         assertTrue( ArrayUtils.isEquals( "type3_test".getBytes(), provider.getType3Response() ) );
+     }
+
+
+     /**
+      * Tests that the plumbing for NTLM bind works.
+      */
+     @Test
+     public void testGssSpnegoBind() throws Exception
+     {
+         NtlmSaslBindClient client = new NtlmSaslBindClient( SupportedSaslMechanisms.GSS_SPNEGO );
+         BindResponse type2response = client.bindType1( "type1_test".getBytes() );
+         assertEquals( 1, type2response.getMessageId() );
+         assertEquals( ResultCodeEnum.SASL_BIND_IN_PROGRESS, type2response.getLdapResult().getResultCode() );
+         assertTrue( ArrayUtils.isEquals( "type1_test".getBytes(), provider.getType1Response() ) );
+         assertTrue( ArrayUtils.isEquals( "challenge".getBytes(), type2response.getServerSaslCreds() ) );
+         
+         BindResponse finalResponse = client.bindType3( "type3_test".getBytes() );
+         assertEquals( 2, finalResponse.getMessageId() );
+         assertEquals( ResultCodeEnum.SUCCESS, finalResponse.getLdapResult().getResultCode() );
+         assertTrue( ArrayUtils.isEquals( "type3_test".getBytes(), provider.getType3Response() ) );
+     }
+
+     
+     /**
+      * A fake implementation of the NtlmProvider. We can't use a real one because
+      * its license is not ASL 2.0 compatible.
+      */
+     class BogusNtlmProvider implements NtlmProvider
+     {
+         private byte[] type1response;
+         private byte[] type3response;
+         
+         
+         public boolean authenticate( IoSession session, byte[] type3response ) throws Exception
+         {
+             this.type3response = type3response;
+             return true;
+         }
+
+
+         public byte[] generateChallenge( IoSession session, byte[] type1reponse ) throws Exception
+         {
+             this.type1response = type1reponse;
+             return "challenge".getBytes();
+         }
+         
+         
+         public byte[] getType1Response()
+         {
+             return type1response;
+         }
+         
+         
+         public byte[] getType3Response()
+         {
+             return type3response;
+         }
+     }
+
+
+     /**
+      * A NTLM client
+      */
+     class NtlmSaslBindClient extends SocketClient
+     {
+         private final Logger LOG = LoggerFactory.getLogger( NtlmSaslBindClient.class );
+         
+         private final String mechanism;
+         
+         
+         NtlmSaslBindClient( String mechanism ) throws Exception
+         {
+             this.mechanism = mechanism;
+             setDefaultPort( port );
+             connect( "localhost", port );
+             setTcpNoDelay( false );
+             
+             LOG.debug( "isConnected() = {}", _isConnected_ );
+             LOG.debug( "LocalPort     = {}", getLocalPort() );
+             LOG.debug( "LocalAddress  = {}", getLocalAddress() );
+             LOG.debug( "RemotePort    = {}", getRemotePort() );
+             LOG.debug( "RemoteAddress = {}", getRemoteAddress() );
+         }
+
+         
+         BindResponse bindType1( byte[] type1response ) throws Exception
+         {
+             if ( ! isConnected() )
+             {
+                 throw new IllegalStateException( "Client is not connected." );
+             }
+             
+             // Setup the bind request
+             BindRequestImpl request = new BindRequestImpl( 1 ) ;
+             request.setName( new LdapDN( "uid=admin,ou=system" ) ) ;
+             request.setSimple( false ) ;
+             request.setCredentials( type1response ) ;
+             request.setSaslMechanism( mechanism );
+             request.setVersion3( true ) ;
+             
+             // Setup the ASN1 Enoder and Decoder
+             MessageEncoder encoder = new MessageEncoder();
+             MessageDecoder decoder = new MessageDecoder( new BinaryAttributeDetector() {
+                 public boolean isBinary( String attributeId )
+                 {
+                     return false;
+                 }
+             } );
+      
+             // Send encoded request to server
+             encoder.encodeBlocking( null, _output_, request );
+             _output_.flush();
+             
+             while ( _input_.available() <= 0 )
+             {
+                 Thread.sleep( 100 );
+             }
+             
+             // Retrieve the response back from server to my last request.
+             return ( BindResponse ) decoder.decode( null, _input_ );
+         }
+         
+         
+         BindResponse bindType3( byte[] type3response ) throws Exception
+         {
+             if ( ! isConnected() )
+             {
+                 throw new IllegalStateException( "Client is not connected." );
+             }
+             
+             // Setup the bind request
+             BindRequestImpl request = new BindRequestImpl( 2 ) ;
+             request.setName( new LdapDN( "uid=admin,ou=system" ) ) ;
+             request.setSimple( false ) ;
+             request.setCredentials( type3response ) ;
+             request.setSaslMechanism( mechanism );
+             request.setVersion3( true ) ;
+             
+             // Setup the ASN1 Enoder and Decoder
+             MessageEncoder encoder = new MessageEncoder();
+             MessageDecoder decoder = new MessageDecoder( new BinaryAttributeDetector() {
+                 public boolean isBinary( String attributeId )
+                 {
+                     return false;
+                 }
+             } );
+      
+             // Send encoded request to server
+             encoder.encodeBlocking( null, _output_, request );
+             
+             _output_.flush();
+             
+             while ( _input_.available() <= 0 )
+             {
+                 Thread.sleep( 100 );
+             }
+             
+             // Retrieve the response back from server to my last request.
+             return ( BindResponse ) decoder.decode( null, _input_ );
+         }
+     }
 }