ruby-ldap rebinding ?

D

Dick Davies

Can anyone tell me where I'm going wrong here?
I'm trying to write a very simple ldap authenticator, which does

get user and pass
open connection to server
bind anonymously
map the user to a dn
bind as dn and pass <- this goes boom

when I rebind I get an error. Here's a cut down version:


$ irb -r ldap
irb(main):001:0> conn = LDAP::SSLConn.new('ldap.server',389,true)
=> #<LDAP::SSLConn:0x812ec70>
irb(main):002:0> a = conn.bind
=> #<LDAP::SSLConn:0x812ec70>
irb(main):003:0> a.unbind
=> nil
irb(main):004:0> b = conn.bind
LDAP::InvalidDataError: The LDAP handler is already unbind()'ed.
from (irb):4:in `bind'
from (irb):4



if I omit the unbind(), I get 'The LDAP handler is already binded'

That's some catch, that catch 22....
 
O

Ollivier Robert

get user and pass
open connection to server
bind anonymously
map the user to a dn
bind as dn and pass <- this goes boom

Don't unbind, I guess it is using some kind of global variable somewhere
and unbind() does bad things. You can have several simultaneous
connections though although it will leak a descriptor :(

I have the same issue here.
 
I

Ian Macdonald

Can anyone tell me where I'm going wrong here?
I'm trying to write a very simple ldap authenticator, which does

get user and pass
open connection to server
bind anonymously
map the user to a dn
bind as dn and pass <- this goes boom

when I rebind I get an error. Here's a cut down version:


$ irb -r ldap
irb(main):001:0> conn = LDAP::SSLConn.new('ldap.server',389,true)
=> #<LDAP::SSLConn:0x812ec70>
irb(main):002:0> a = conn.bind
=> #<LDAP::SSLConn:0x812ec70>
irb(main):003:0> a.unbind
=> nil
irb(main):004:0> b = conn.bind
LDAP::InvalidDataError: The LDAP handler is already unbind()'ed.
from (irb):4:in `bind'
from (irb):4



if I omit the unbind(), I get 'The LDAP handler is already binded'

Conn#unbind doesn't just unbind from the server; it also destroys the
connection object when it calls ldap_unbind().

From ldap_unbind(3):

UNBINDING
The ldap_unbind() call is used to unbind from the directory,
terminate the current association, and free the resources
contained in the ld structure. Once it is called, the connection
to the LDAP server is closed, and the ld structure is
invalid. The ldap_unbind_s() call is just another name for
ldap_unbind(); both of these calls are synchronous in
nature.

So, think of Conn#unbind as being more of a Conn#destroy, in that the
Conn object effectively no longer exists after the unbind.

Cheers,

Ian
--
Ian Macdonald | Time is but the stream I go a-fishing in.
System Administrator | -- Henry David Thoreau
(e-mail address removed) |
http://www.caliban.org |
|
 
D

Dick Davies

Conn#unbind doesn't just unbind from the server; it also destroys the
connection object when it calls ldap_unbind().

From ldap_unbind(3):

UNBINDING
The ldap_unbind() call is used to unbind from the directory,

Ok thanks - I've used Perl::LDAP in the past which lets you rebind and
existing connection.

Can I do that with ruby-ldap, or do I need a new connection every time
I check a username/password pair?
 
I

Ian Macdonald

Ok thanks - I've used Perl::LDAP in the past which lets you rebind and
existing connection.

Can I do that with ruby-ldap, or do I need a new connection every time
I check a username/password pair?

Yes, I'm afraid you need a new connection to bind as a different user.
On the other hand, is you only want to check the validity of a username
and password combination, you should be able to pull that information
from the directory as a user with the privileges required to view
passwords.

Ian
--
Ian Macdonald | All this wheeling and dealing around, why,
System Administrator | it isn't for money, it's for fun. Money's
(e-mail address removed) | just the way we keep score. -- Henry
http://www.caliban.org | Tyroon
|
 
D

Dick Davies

* Ian Macdonald said:
Yes, I'm afraid you need a new connection to bind as a different user.
On the other hand, is you only want to check the validity of a username
and password combination, you should be able to pull that information
from the directory as a user with the privileges required to view
passwords.

Yeah, but then I need to code an admin user/pass pair into my script,
and that sort of thing gives me the heeby-jeebies..

I suspect perl-ldap actually drops and reloads the connection in any case,
I'm not sure whether the C API lets you reuse a connection by rebinding
as another user.

Looks like I might have to actually open that LDAP programmers guide I got
on ebay before christmas, rather than just letting it sit on the shelf... :)

Thanks for your help anyway!
 
I

Ian Macdonald

Yeah, but then I need to code an admin user/pass pair into my script,
and that sort of thing gives me the heeby-jeebies..

You could consider using SASL and something like GSSAPI instead, but
that might be a lot of work if you're not already set up for it.
I suspect perl-ldap actually drops and reloads the connection in any case,
I'm not sure whether the C API lets you reuse a connection by rebinding
as another user.

It doesn't.

Perhaps Net::LDAP remembers the details of the connection when it was
opened and silently performs another open when you perform a bind after
an unbind, but at some point, you're still opening a new connection.
It's just a question of whether it's implicit or explicit.

Ruby/LDAP could be made to do this, too, I think. The details passed to
LDAP::Conn.new could be put into instance variables. If the connection
is dead at bind time, these could be read and used to transparently
reestablish the connection before conducting the bind.

I'll look at how hard this would be to ship up in practice.

Ian
--
Ian Macdonald | There's something different about us --
System Administrator | different from people of Europe, Africa,
(e-mail address removed) | Asia ... a deep and abiding belief in the
http://www.caliban.org | Easter Bunny. -- G. Gordon Liddy
|
 
I

Ian Macdonald

Perhaps Net::LDAP remembers the details of the connection when it was
opened and silently performs another open when you perform a bind after
an unbind, but at some point, you're still opening a new connection.
It's just a question of whether it's implicit or explicit.

Ruby/LDAP could be made to do this, too, I think. The details passed to
LDAP::Conn.new could be put into instance variables. If the connection
is dead at bind time, these could be read and used to transparently
reestablish the connection before conducting the bind.

I'll look at how hard this would be to ship up in practice.

This feature is now in Ruby/LDAP's CVS and will be released in 0.9.1.

This allows you to perform an LDAP::Conn#unbind, followed by either an
LDAP::Conn#bind or an LDAP::Conn#simple_bind to reconnect to the server,
using different credentials if you wish.

Ian
--
Ian Macdonald | This generation doesn't have emotional
System Administrator | baggage. We have emotional moving vans.
(e-mail address removed) | -- Bruce Feirstein
http://www.caliban.org |
|
 
D

Dick Davies

* Ian Macdonald said:
This feature is now in Ruby/LDAP's CVS and will be released in 0.9.1.

This allows you to perform an LDAP::Conn#unbind, followed by either an
LDAP::Conn#bind or an LDAP::Conn#simple_bind to reconnect to the server,
using different credentials if you wish.

Brilliant, thanks Ian!
 
I

Ian Macdonald

Brilliant, thanks Ian!

You're welcome.

I quickly realised that LDAP::Conn#sasl_bind should also be able to
rebind in this way and that #bind, #simple_bind and #sasl_bind should
also work on SSLConn objects, not just plain old Conn objects. This work
has now also gone into CVS.

Ian
--
Ian Macdonald | A crow perched himself on a telephone wire.
System Administrator | He was going to make a long-distance caw.
(e-mail address removed) |
http://www.caliban.org |
|
 
I

Ian Macdonald

I quickly realised that LDAP::Conn#sasl_bind should also be able to
rebind in this way and that #bind, #simple_bind and #sasl_bind should
also work on SSLConn objects, not just plain old Conn objects. This work
has now also gone into CVS.

And I spoke too soon, because SSLConn connections are more complicated.
For the time being, you can only rebind regular Conn objects, not
SSLConn objects.

Ian
--
Ian Macdonald | When the fog came in on little cat feet
System Administrator | last night, it left these little muddy paw
(e-mail address removed) | prints on the hood of my car.
http://www.caliban.org |
|
 
I

Ian Macdonald

And I spoke too soon, because SSLConn connections are more complicated.
For the time being, you can only rebind regular Conn objects, not
SSLConn objects.

This has now been fixed in CVS. SSL connections can now also be rebound.

Ian
--
Ian Macdonald | An intellectual is someone whose mind
System Administrator | watches itself. -- Albert Camus
(e-mail address removed) |
http://www.caliban.org |
|
 
D

Dick Davies

* Ian Macdonald said:
This has now been fixed in CVS. SSL connections can now also be rebound.

Lovely, ta. Out of interest, is there a reason you need to unbind before binding?

perl-ldap explicitly unbinds for you if you bind an existing connection
(though by the sound of it that's because you actually make a new connection anyway) -
are there reasons you wouldn't want to to that?
 
I

Ian Macdonald

Lovely, ta. Out of interest, is there a reason you need to unbind before binding?

perl-ldap explicitly unbinds for you if you bind an existing connection
(though by the sound of it that's because you actually make a new connection anyway) -
are there reasons you wouldn't want to to that?

It all depends on how much transparency you want.

Right now, you'll get an LDAP::Error exception and the message "already
bound." if you try to bind an already bound connection. This operates on
the historic assumption that you're accidentally trying to bind twice.

In your case, you just want to rebind, but with different credentials.
In that case, you want it to implicitly unbind and reconnect before
performing your bind.

I'm not sure whether it's better for the default reaction to be to treat
this as an error or to give you exactly what you appear to be asking
for.

Another possibility is to add a Conn#rebind method, whereby you get to
explicitly request that a connection be unbound, reconnected and bound.

What do you think of that idea?

Ian
--
Ian Macdonald | Hell is empty and all the devils are here.
System Administrator | -- Wm. Shakespeare, "The Tempest"
(e-mail address removed) |
http://www.caliban.org |
|
 
D

Dick Davies

It all depends on how much transparency you want.

Right now, you'll get an LDAP::Error exception and the message "already
bound." if you try to bind an already bound connection. This operates on
the historic assumption that you're accidentally trying to bind twice.

I think that's what feels wrong about a bind just clobbering the existing
connection, and why I hesitated to suggest it. There's a possibility that this
would mask coding errors if you accidentally try to use a connection you think
is free.
In your case, you just want to rebind, but with different credentials.
In that case, you want it to implicitly unbind and reconnect before
performing your bind.

I think I'm probably being lazy. It's just the code ends up a little cleaner
that way. Whether it's worth adding the complexity to the library just for that
is up to you...
I'm not sure whether it's better for the default reaction to be to treat
this as an error or to give you exactly what you appear to be asking
for.
Another possibility is to add a Conn#rebind method, whereby you get to
explicitly request that a connection be unbound, reconnected and bound.

I think a rebind method would be better than bind 'magically' throwing away
the old connection. It's self-documenting in many ways, and ticks my box of
keeping it to a single method.

Thanks a lot for being so patient - my reaction in your shoes would probably
be closer to "why don't you marry perl-ldap, you love it so much?" :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,610
Members
45,255
Latest member
TopCryptoTwitterChannels

Latest Threads

Top