JndiConnection.simpleBind() seems to be causing pooled connection validation to fail

269 views
Skip to first unread message

ben.howe...@northgateps.com

unread,
Feb 9, 2017, 10:55:53 AM2/9/17
to ldaptive
Hi,

I'm trying to work out if I've found a bug in Ldaptive or CAS5's use of it.

We use CAS security which uses Ldaptive and it's configured to use a BlockingConnectionPool and validate connections on checkout.

To log a user in, Ldaptive first validates the connection using a SearchValidator and ends up calling JndiConnection.simpleBind().  That sets a username and password on the connection's context by calling context.addToEnvironment().

The next time we log in using the same connection from the pool, it goes through the same process.  However this time the SearchValidator fails, it seems, because the connection still has the credentials from the previous failed simpleBind attempt in its environment map and so it can't connect to LDAP.  

It fails at the LdapContext.search() call in JndiConnection$JndiSearchIterator.search().

It seems like JndiConnection.simpleBind() should restore the previous credentials because the rest of the code isn't expecting that to change.  The anonymouseBind() method would be affected too.

Does that all make sense and look like an Ldaptive bug?

thanks,

Ben

ps : in case it's helpful, here's CAS's ldaptive configuration code

    public static PoolConfig newPoolConfig(final AbstractLdapProperties l) {
        final PoolConfig pc = new PoolConfig();
        pc.setMinPoolSize(l.getMinPoolSize());
        pc.setMaxPoolSize(l.getMaxPoolSize());
        pc.setValidateOnCheckOut(l.isValidateOnCheckout());
        pc.setValidatePeriodically(l.isValidatePeriodically());
        pc.setValidatePeriod(newDuration(l.getValidatePeriod()));
        return pc;
    }

   public static ConnectionPool newBlockingConnectionPool(final AbstractLdapProperties l) {
        final DefaultConnectionFactory bindCf = newConnectionFactory(l);
        final PoolConfig pc = newPoolConfig(l);
        final BlockingConnectionPool cp = new BlockingConnectionPool(pc, bindCf);

        cp.setBlockWaitTime(newDuration(l.getBlockWaitTime()));
        cp.setPoolConfig(pc);

        final IdlePruneStrategy strategy = new IdlePruneStrategy();
        strategy.setIdleTime(newDuration(l.getIdleTime()));
        strategy.setPrunePeriod(newDuration(l.getPrunePeriod()));

        cp.setPruneStrategy(strategy);
        cp.setValidator(new SearchValidator());
        cp.setFailFastInitialize(l.isFailFast());

        LOGGER.debug("Initializing ldap connection pool for {} and bindDn {}", l.getLdapUrl(), l.getBindDn());
        cp.initialize();
        return cp;
    }
and here's the top of the stacktrace of the error :

org.ldaptive.pool.ValidationException: Validation of connection failed
        at org.ldaptive.pool.AbstractConnectionPool.activateAndValidateConnection(AbstractConnectionPool.java:633) ~[ldaptive-1.2.0.jar:?]
        at org.ldaptive.pool.BlockingConnectionPool.getConnection(BlockingConnectionPool.java:151) ~[ldaptive-1.2.0.jar:?]
        at org.ldaptive.pool.PooledConnectionFactory.getConnection(PooledConnectionFactory.java:68) ~[ldaptive-1.2.0.jar:?]
        at org.ldaptive.auth.PooledBindAuthenticationHandler.getConnection(PooledBindAuthenticationHandler.java:61) ~[ldaptive-1.2.0.jar:?]
        at org.ldaptive.auth.AbstractAuthenticationHandler.authenticate(AbstractAuthenticationHandler.java:54) ~[ldaptive-1.2.0.jar:?]
        at org.ldaptive.auth.Authenticator.authenticate(Authenticator.java:257) ~[ldaptive-1.2.0.jar:?]

Daniel Fisher

unread,
Feb 9, 2017, 3:22:46 PM2/9/17
to ldap...@googlegroups.com
On Thu, Feb 9, 2017 at 10:55 AM <ben.howe...@northgateps.com> wrote:
To log a user in, Ldaptive first validates the connection using a SearchValidator and ends up calling JndiConnection.simpleBind().  That sets a username and password on the connection's context by calling context.addToEnvironment().

The next time we log in using the same connection from the pool, it goes through the same process.  However this time the SearchValidator fails, it seems, because the connection still has the credentials from the previous failed simpleBind attempt in its environment map and so it can't connect to LDAP.  

Using a connection pool for binds can be tricky in some environments. Most directories will always allow searching the root DSE, but some can be configured not do. In which case you just need to configure the components a little differently.
 
It seems like JndiConnection.simpleBind() should restore the previous credentials because the rest of the code isn't expecting that to change.  The anonymouseBind() method would be affected too.

Does that all make sense and look like an Ldaptive bug?

I don't think so. It's the pool's responsibility to manage the state of the connection. See my code change below.
 
   public static ConnectionPool newBlockingConnectionPool(final AbstractLdapProperties l) {
        final DefaultConnectionFactory bindCf = newConnectionFactory(l);
        final PoolConfig pc = newPoolConfig(l);
        final BlockingConnectionPool cp = new BlockingConnectionPool(pc, bindCf);

        cp.setBlockWaitTime(newDuration(l.getBlockWaitTime()));
        cp.setPoolConfig(pc);

        final IdlePruneStrategy strategy = new IdlePruneStrategy();
        strategy.setIdleTime(newDuration(l.getIdleTime()));
        strategy.setPrunePeriod(newDuration(l.getPrunePeriod()));

        cp.setPruneStrategy(strategy);
        cp.setValidator(new SearchValidator());

// perform an anonymous bind when the connection is returned to the pool
cp.setPassivator(new BindPassivator());

You can customize the BindPassivator (or the SearchValidator) to make sure the connection is in the right state for your directory requirements.

--Daniel Fisher
 

Ben Howell-Thomas

unread,
Feb 10, 2017, 3:49:03 AM2/10/17
to ldap...@googlegroups.com
Thankyou - that's really helpful :)  I'll give it a try and then pass it on to the CAS team.

On 9 February 2017 at 20:22, Daniel Fisher <dfi...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "ldaptive" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ldaptive+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


This email is sent on behalf of Northgate Public Services (UK) Limited and its associated companies including Rave Technologies (India) Pvt Limited (together "Northgate Public Services") and is strictly confidential and intended solely for the addressee(s). 
If you are not the intended recipient of this email you must: (i) not disclose, copy or distribute its contents to any other person nor use its contents in any way or you may be acting unlawfully;  (ii) contact Northgate Public Services immediately on +44(0)1908 264500 quoting the name of the sender and the addressee then delete it from your system.
Northgate Public Services has taken reasonable precautions to ensure that no viruses are contained in this email, but does not accept any responsibility once this email has been transmitted.  You should scan attachments (if any) for viruses.

Northgate Public Services (UK) Limited, registered in England and Wales under number 00968498 with a registered address of Peoplebuilding 2, Peoplebuilding Estate, Maylands Avenue, Hemel Hempstead, Hertfordshire, HP2 4NN.  Rave Technologies (India) Pvt Limited, registered in India under number 117068 with a registered address of 2nd Floor, Ballard House, Adi Marzban Marg, Ballard Estate, Mumbai, Maharashtra, India, 400001.
Reply all
Reply to author
Forward
0 new messages