Discussion:
using Kerberos to authenticate to Active Directory from python ldap
Olivier Sessink
2009-04-09 20:39:53 UTC
Permalink
Hi all,

I'm trying to script a function that can retrieve if a user is member of
a group in active directory. The previous script was a shell script with
a ldapsearch call for every user. You can image that took long on a
thousand users.

So I'm rewriting the script for python. However, I cannot get the
kerberos authentication right.

ld = ldap.initialize('activedirectory-dns')
ld.sasl_interactive_bind_s('', ldap.sasl.gssapi('***@REALM'))
ld.search_s(self.base, ldap.SCOPE_SUBTREE, '(CN=groupname)', ['Member'])

I get an error that I don't have the right credentials.

However it works with ldapsearch, so the Kerberos ticket is valid and
correct for this query..

Anybody a tip how to continue? Or an example script that uses Kerberos?

thanks,
Olivier
Michael Ströder
2009-04-09 21:30:33 UTC
Permalink
Post by Olivier Sessink
So I'm rewriting the script for python. However, I cannot get the
kerberos authentication right.
ld = ldap.initialize('activedirectory-dns')
ld.search_s(self.base, ldap.SCOPE_SUBTREE, '(CN=groupname)', ['Member'])
I get an error that I don't have the right credentials.
However it works with ldapsearch, so the Kerberos ticket is valid and
correct for this query..
I cannot see how your parameters are. Note that SASL-Bind with GSSAPI is
quite picky about using the right DNS names.

Especially it should be something like

ld = ldap.initialize('ldap://dc1.dom2.adtest.domain')

with dc1.dom2.adtest.domain being one of the names listed with service
prefix ldap/ in servicePrincipalName on the domain controller.
Post by Olivier Sessink
Or an example script that uses Kerberos?
Demo/sasl_bind.py

Ciao, Michael.
Olivier Sessink
2009-04-10 09:24:49 UTC
Permalink
As a related solution, you could have a look at python-ad [1].
Python-AD is built on top of python-ldap and provides lots of
functionality that you normally need to connect to AD built in. For
example, service discovery, credential management and multi-domain
functionality. There's a few examples on the site, including how to
use Kerberos credentials with AD.
I noticed that there is some C code related to Kerberos in python-ad.
Is this code required to initialize a kerberos authentication, or is
this just to change passwords and things like that?

thanks,

Olivier
Michael Ströder
2009-04-10 09:45:38 UTC
Permalink
Post by Olivier Sessink
As a related solution, you could have a look at python-ad [1].
Python-AD is built on top of python-ldap and provides lots of
functionality that you normally need to connect to AD built in. For
example, service discovery, credential management and multi-domain
functionality. There's a few examples on the site, including how to
use Kerberos credentials with AD.
I noticed that there is some C code related to Kerberos in python-ad.
Is this code required to initialize a kerberos authentication, or is
this just to change passwords and things like that?
You can bind with SASL/GSSAPI to AD with plain python-ldap provided you
obtained a valid TGT with kinit before (just like with command-line tool
ldapsearch).

Ciao, Michael.
Olivier Sessink
2009-04-10 12:00:30 UTC
Permalink
Post by Michael Ströder
You can bind with SASL/GSSAPI to AD with plain python-ldap provided you
obtained a valid TGT with kinit before (just like with command-line tool
ldapsearch).
thanks, that's what I need to know.

I can't get it to work though..

ld = ldap.initialize('ldap://foobar')
sasl = ldap.sasl.gssapi()
ld.sasl_interactive_bind_s('', sasl)
ld.search_s('DC=foo,DC=foo', ldap.SCOPE_SUBTREE, '(CN=blabla)', ['Member'])

ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627,
comment: In order to perform this operation a successful bind must be
completed on the connection., data 0, vece', 'desc': 'Operations
error'}

this shell command works:

ldapsearch -YGSSAPI -H ldap://foobar -bDC=foo,DC=foo '(CN=blabla)' Member

I've tried different ldap URL's, but from an ldapsearch strace I'm
pretty sure I use the right ldap server.

However, this is on a suse linux enterprise box, which has python-ldap
2.0.11. Could it be that this is too old?

thanks,
Olivier
Michael Ströder
2009-04-10 12:24:50 UTC
Permalink
Post by Olivier Sessink
Post by Michael Ströder
You can bind with SASL/GSSAPI to AD with plain python-ldap provided you
obtained a valid TGT with kinit before (just like with command-line tool
ldapsearch).
thanks, that's what I need to know.
I can't get it to work though..
ld = ldap.initialize('ldap://foobar')
sasl = ldap.sasl.gssapi()
ld.sasl_interactive_bind_s('', sasl)
ld.search_s('DC=foo,DC=foo', ldap.SCOPE_SUBTREE, '(CN=blabla)', ['Member'])
ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627,
comment: In order to perform this operation a successful bind must be
completed on the connection., data 0, vece', 'desc': 'Operations
error'}
ldapsearch -YGSSAPI -H ldap://foobar -bDC=foo,DC=foo '(CN=blabla)' Member
I've tried different ldap URL's, but from an ldapsearch strace I'm
pretty sure I use the right ldap server.
Hmm, this should simply work just like the ldapsearch usage. Since
you're searching from domain level it would be worth to try to
explicitly switch off referral chasing within libldap:

ld = ldap.initialize('ldap://foobar')
ld.set_option(ldap.OPT_REFERRALS,0)

Note that automatic referral chasing within libldap was always using
anonymous bind.
Post by Olivier Sessink
However, this is on a suse linux enterprise box, which has python-ldap
2.0.11. Could it be that this is too old?
Glancing over CHANGES there were no related fixes to SASL but maybe the
default for ldap.OPT_REFERRALS was changed. But you should upgrade
anyway for various reasons...

Ciao, Michael.
Michael Ströder
2009-04-10 12:28:13 UTC
Permalink
Post by Michael Ströder
Hmm, this should simply work just like the ldapsearch usage.
BTW: If you're using MS AD of W2K8 (not W2K3) you can check whether your
bound with ld.whoami_s() which on W2K8 returns 'u:DOMAIN\SAMACCOUNTNAME'.

Ciao, Michael.
Olivier Sessink
2009-04-10 12:45:22 UTC
Permalink
Post by Michael Ströder
Post by Olivier Sessink
Post by Michael Ströder
You can bind with SASL/GSSAPI to AD with plain python-ldap provided you
obtained a valid TGT with kinit before (just like with command-line tool
ldapsearch).
thanks, that's what I need to know.
I can't get it to work though..
ld = ldap.initialize('ldap://foobar')
sasl = ldap.sasl.gssapi()
ld.sasl_interactive_bind_s('', sasl)
ld.search_s('DC=foo,DC=foo', ldap.SCOPE_SUBTREE, '(CN=blabla)', ['Member'])
ldap.OPERATIONS_ERROR: {'info': '00000000: LdapErr: DSID-0C090627,
comment: In order to perform this operation a successful bind must be
completed on the connection., data 0, vece', 'desc': 'Operations
error'}
ldapsearch -YGSSAPI  -H ldap://foobar -bDC=foo,DC=foo '(CN=blabla)' Member
I've tried different ldap URL's, but from an ldapsearch strace I'm
pretty sure I use the right ldap server.
Hmm, this should simply work just like the ldapsearch usage. Since
you're searching from domain level it would be worth to try to
ld = ldap.initialize('ldap://foobar')
ld.set_option(ldap.OPT_REFERRALS,0)
you saved my day!

it works.

sorry for my limited knowledge, but what does "referrals should be
automatically chased" mean?

many thanks

Olivier
Michael Ströder
2009-04-10 13:05:43 UTC
Permalink
Post by Olivier Sessink
Post by Olivier Sessink
ld = ldap.initialize('ldap://foobar')
ld.set_option(ldap.OPT_REFERRALS,0)
you saved my day!
it works.
Glad that worked.
Post by Olivier Sessink
sorry for my limited knowledge, but what does "referrals should be
automatically chased" mean?
Referrals are basically LDAP URLs returned potentially pointing to other
LDAP servers where to look for. The client has to chase the referrals.
This is a broken concept since the LDAPv3 standard says nothing about
which credentials to use when chasing the referral. libldap by default
chased referrals anonymously.

Ciao, Michael.
Geert Jansen
2009-04-11 15:36:56 UTC
Permalink
On Fri, Apr 10, 2009 at 11:24 AM, Olivier Sessink
Post by Olivier Sessink
I noticed that there is some C code related to Kerberos in python-ad.
Is this code required to initialize a kerberos authentication, or is
this just to change passwords and things like that?
Actually, both. The C code exposes a small subset of the Kerberos API
to Python. I use it for credential management so things like acquire a
ticket using a password or a keytab, and to set or change a password.

Regards,
Geert

Loading...