ldap-auth issue

228 views
Skip to first unread message

Johann Spies

unread,
Aug 3, 2009, 10:06:24 AM8/3/09
to web...@googlegroups.com
I want to do have a website on which I can register a few usernames.
Only they may authentiicate and they must authenticate against a
central ldap server.

At the moment I have the following in db.py:


if request.env.web2py_runtime_gae: # if running on Google App Engine
db = DAL('gae') # connect to Google BigTable
session.connect(request, response, db=db) # and store sessions and
tickets there
else: # else use a normal
relational database
db = DAL('sqlite://storage.sqlite') # if not, use SQLite or other DB

from gluon.contrib.login_methods.ldap_auth import ldap_auth
from gluon.tools import *
auth=Auth(globals(),db) # authentication/authorization
crud=Crud(globals(),db) # for CRUD helpers using auth
service=Service(globals()) # for json, xml, jsonrpc,
xmlrpc, amfrpc
auth.settings.login_methods=[ldap_auth(server='stbldap01.sun.ac.za',base_dn='ou=users,O=SU',
mode='cn', secure=True)]

auth.settings.table_user =
db.define_table("auth_user",db.Field("first_name",length=128,default=""),
db.Field("last_name", length=128,default=""),
db.Field("email", length=128,default=""),
db.Field("username", length=32,default=""),

db.Field("password",'password',readable=False, label="Password"),
db.Field("registration_key", length=128,
writable=False, readable=False, default=""))
t = auth.settings.table_user
t.first_name.requires = IS_NOT_EMPTY()
t.username.requires = IS_NOT_EMPTY()
t.last_name.requires = IS_NOT_EMPTY()
t.password.requires = CRYPT() # password will be stored hashed
t.email.requires = [IS_EMAIL(), IS_NOT_IN_DB(db, db.auth_user.email)]
t.username.requires = [IS_NOT_IN_DB(db, db.auth_user.username)]
auth.define_tables() ### auth_user will not be redefined!
crud.settings.auth=auth # enforces authorization on crud
mail=Mail() # mailer
mail.settings.server='localhost' # your SMTP server
mail.settings.sender='johann...@gmail.com' # your email

Now my question:

When I register a user I don't want the user to enter a password
because when the user logs in in future the password must be checked
against the hash in the LDAP tree. So when I register myself (with or
without a password on registration) I cannot log in afterwords. All
my logins ends with "Invalid login". How can I find out what went
wrong? Is ther some sort of log somewhere?

Regards
Johann

Fran

unread,
Aug 3, 2009, 11:33:12 AM8/3/09
to web2py-users
On Aug 3, 3:06 pm, Johann Spies <johann.sp...@gmail.com> wrote:
> I want to do have a website on which I can register a few usernames.
> Only they may authentiicate and they must authenticate against a
> central ldap server.

> auth.settings.login_methods=[ldap_auth(server='stbldap01.sun.ac.za',base_dn='ou=users,O=SU',
> mode='cn', secure=True)]

This is the right type of line then.

> When I register a user I don't want the user to enter a password
> because when the user logs in in future the password must be checked
> against the hash in the LDAP tree.

> db.Field("password",'password',readable=False, label="Password"),

Add writable=False to make it not show in the register form.

> t = auth.settings.table_user
> t.password.requires = CRYPT() # password will be stored hashed

Why bother since you're not storing password locally?

> So when I register myself (with or
> without a password on registration) I cannot log in afterwords.  All
> my logins ends with "Invalid login".  How can I find out what went
> wrong?  Is ther some sort of log somewhere?

My guess is that this is an LDAP failure.
Try the LDAP login from the CLI on the same machine as the server (to
check for Firewall issues).
The relevant string to test from what you have above is:
ldapwhoami -x -D cn=username,ou=users,O=SU -W -H ldaps://stbldap01.sun.ac.za:389
(replace 'username' with your username)

If you get a working LDAP connection string, then we can let you know
how to do this within ldap-auth (which may require amending the ldap-
auth to cater for the option(s) you need)

Best Wishes,
Fran.

Johann Spies

unread,
Aug 4, 2009, 5:09:45 AM8/4/09
to web...@googlegroups.com
Thanks Fran for your reply.

2009/8/3 Fran <franc...@googlemail.com>:


>> db.Field("password",'password',readable=False, label="Password"),
>
> Add writable=False to make it not show in the register form.

Thanks. I am learning...


>
> My guess is that this is an LDAP failure.
> Try the LDAP login from the CLI on the same machine as the server (to
> check for Firewall issues).
> The relevant string to test from what you have above is:
> ldapwhoami -x -D cn=username,ou=users,O=SU -W -H ldaps://stbldap01.sun.ac.za:389
> (replace 'username' with your username)

$ ldapwhoami -x -D 'cn=jspies,ou=users,O=SU' -W -H
ldaps://stbldap01.sun.ac.za:369
Enter LDAP Password:
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

and

$ ldapwhoami -x -D 'cn=jspies,ou=users,O=SU' -W -H ldaps://stbldap01.sun.ac.za
Enter LDAP Password:
ldap_parse_result: Protocol error (2)
additional info: Unrecognized extended operation
Result: Protocol error (2)
Additional info: Unrecognized extended operation

but

$ ldapwhoami -H ldaps://stbldap01.sun.ac.za -D
'cn=jspies,ou=users,O=SU' -x -v -W -n
Enter LDAP Password:
ldap_initialize( ldaps://stbldap01.sun.ac.za:636/??base )
ldap_sasl_interactive_bind_s: Unknown authentication method (-6)

>
> If you get a working LDAP connection string, then we can let you know
> how to do this within ldap-auth (which may require amending the ldap-
> auth to cater for the option(s) you need)

I hope the information above will help.

Thanks again.

Regards
Johann

Fran

unread,
Aug 4, 2009, 5:14:41 AM8/4/09
to web2py-users
On Aug 4, 10:09 am, Johann Spies <johann.sp...@gmail.com> wrote:
> ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
> Additional info: Unrecognized extended operation
> ldap_sasl_interactive_bind_s: Unknown authentication method (-6)
> I hope the information above will help.

We need a working string in order to know how to code that within
Web2Py.
All of these have failed...

F

Johann Spies

unread,
Aug 4, 2009, 5:25:17 AM8/4/09
to web...@googlegroups.com
Apologies. I was testing from two different computers. On the one
(where the web2py server was running) it was working and I did not see
that the one from which I pasted the entries was failing. The
following worked (same string with a 'TLS_REQCERT allow' added to
/etc/ldap/ldap.conf):


$ ldapwhoami -H ldaps://stbldap01.sun.ac.za -D
'cn=jspies,ou=users,O=SU' -x -v -W -n
Enter LDAP Password:
ldap_initialize( ldaps://stbldap01.sun.ac.za:636/??base )
Result: Success (0)

Regards
Johann
2009/8/4 Fran <franc...@googlemail.com>:

Don

unread,
Aug 25, 2009, 3:24:10 PM8/25/09
to web2py-users
I am also trying to authenticate against a LDAP server (not working).
I cannot get the ldapwhoami command to work, but ldap search does work
for me. I do not think the server can respond to the command.
ldapsearch does work:

ldapsearch -b 'ou=yp,o=company.com' -H ldaps://yp.company.com -x
'mail=test...@us.company.com'

I tried the ldap module directly, and that worked as well.
=================================
>>> import ldap
>>> dap = ldap.initialize('ldap://yp.company.com')
>>> dn=""
>>> pw=""
>>> dap.simple_bind_s(dn, pw)
(97, [])
>>> dap.search_s('ou=yp,o=company.com', ldap.SCOPE_SUBTREE,'(mail=test...@us.company.com)',['emailaddress','cn'])
[('uid=testUser,c=us,ou=yp,o=company.com', {'emailaddress':
['test...@us.company.com'], 'cn': ['Test User']})]
>>>

==================================

my auth congids are as follows:

==================================
authDB = SQLDB('sqlite://auth_database.sqlite')

from gluon.tools import Auth, Mail
from gluon.contrib.login_methods.ldap_auth import ldap_auth

mail=Mail()
mail.settings.server='localhost:25'
mail.settings.sender='test...@us.company.com'


auth=Auth(globals(),authDB)
auth.settings.login_methods.append(ldap_auth(mode='mail',
server='yp.company.com',
base_dn='ou=yp,o=company.com'
))
auth.define_tables()
auth.settings.mailer = mail
================================

I have PostgreSQL authenticating via pam_ldap using the same settings
that i have applied to the auth module. What am I missing? Is there
some other option that i need to pass to ldap_auth to get it to use
simple binding?




On Aug 4, 5:25 am, Johann Spies <johann.sp...@gmail.com> wrote:
> Apologies. I was testing from two different computers. On the one
> (where the web2py server was running) it was working and I did not see
> that the one from which I pasted the entries was failing. The
> following worked (same string with a 'TLS_REQCERT allow'  added to
> /etc/ldap/ldap.conf):
>
> $ ldapwhoami -H ldaps://stbldap01.sun.ac.za  -D
> 'cn=jspies,ou=users,O=SU' -x -v -W -n
> EnterLDAPPassword:
> ldap_initialize( ldaps://stbldap01.sun.ac.za:636/??base )
> Result: Success (0)
>
> Regards
> Johann
> 2009/8/4 Fran <francisb...@googlemail.com>:

Don

unread,
Aug 25, 2009, 3:47:09 PM8/25/09
to web2py-users
I took a look at the source code and I see that the "mode" option has
a specific set of accepted values. our user names are based on the
"mail" field in the ldap record. not uid. So this would not work at
all. unless I change the source.

On Aug 25, 3:24 pm, Don <sam...@gmail.com> wrote:
> I am also trying to authenticate against a LDAP server (not working).
> I cannot get the ldapwhoami command to work, but ldap search does work
> for me.  I do not think the server can respond to the command.
> ldapsearch does work:
>
> ldapsearch -b 'ou=yp,o=company.com' -H ldaps://yp.company.com -x
> 'mail=testU...@us.company.com'
>
> I tried the ldap module directly, and that worked as well.
> =================================>>> import ldap
> >>> dap = ldap.initialize('ldap://yp.company.com')
> >>> dn=""
> >>> pw=""
> >>> dap.simple_bind_s(dn, pw)
> (97, [])
> >>> dap.search_s('ou=yp,o=company.com', ldap.SCOPE_SUBTREE,'(mail=testU...@us.company.com)',['emailaddress','cn'])
>
> [('uid=testUser,c=us,ou=yp,o=company.com', {'emailaddress':
> ['testU...@us.company.com'], 'cn': ['Test User']})]
>
>
>
> ==================================
>
> my auth congids are as follows:
>
> ==================================
> authDB = SQLDB('sqlite://auth_database.sqlite')
>
> from gluon.tools import Auth, Mail
> from gluon.contrib.login_methods.ldap_auth import ldap_auth
>
> mail=Mail()
> mail.settings.server='localhost:25'
> mail.settings.sender='testU...@us.company.com'

mdipierro

unread,
Aug 25, 2009, 3:57:54 PM8/25/09
to web2py-users
Please send me a patch to allow this.

Massimo

Don

unread,
Aug 25, 2009, 5:02:45 PM8/25/09
to web2py-users
I made a mistake. ldapsearch does in fact return a uid. I do not
manage the ldap server, so I did not know how it was setup. I think
when we authenticate against postgress, it takes our e-mai addresses,
finds the uid/dn (which in our case is a cryptic serial number) and
then attempts to authenticate against the ldap server. I do not think
web2py needs to be patched. I just need to somehow, when the user
registers with their e-mail address, find their their uid and store
that as the user name. While still allowing them to login with their
e-mail address. I will think about it and see what I can do. Thanks
for the help.

Don Lee

unread,
Aug 25, 2009, 6:54:58 PM8/25/09
to web2py-users
I thought the following code would work, but I am not getting any response.

=======================================================
if mode == 'company':
    # search company ldap database via the e-mail address to figure out the dn
    con.simple_bind_s("", "")
    filter = '(mail='+username+')'
    attrs = ['uid']
    company_search_result=con.search_s(ldap_basedn, ldap.SCOPE_SUBTREE, filter, attrs)
    dn=company_search_result[0][0]
=======================================================

I added the code before:

gluon/contrib/login_methods/ldap_auth.py
=======================================================
elif mode == 'uid':
=======================================================

then I changed the model to read:

=======================================================
auth.settings.login_methods.append(ldap_auth(mode='company',
    server='yp.company.com',
    base_dn='ou=bluepages,o=ibm.com'))
=======================================================

It didn't work.

Don Lee

unread,
Aug 25, 2009, 10:54:21 PM8/25/09
to web2py-users
I finally have this working!!!!!!  I just had to read a lot of code and the manual as well.  For my companies special LDAP server setup, I had to modify ldap_auth.py and add the following section of code:


==============================================================================
            if ldap_mode == 'company':
                # no DNs or password needed to search directory
                dn=""
                pw=""

                # bind anonymously
                con.simple_bind_s(dn, pw)
                # search by e-mail address

                filter = '(mail='+username+')'
                # find the uid
                attrs = ['uid']

                # perform the actual search

                company_search_result=con.search_s(ldap_basedn, ldap.SCOPE_SUBTREE, filter, attrs)
                dn=company_search_result[0][0]

                # perform the real authentication test
                con.simple_bind_s(dn, password)
==============================================================================

I put the code before:

==============================================================================
if ldap_mode == 'uid_r':
==============================================================================

I then changed my model so that instead of appending a new authentication method, I replaced the local method

==============================================================================
auth.settings.login_methods=[ldap_auth(mode='company',
    server='yp.company.com',
    base_dn='ou=yp,o=company.com')]
==============================================================================

** I will add a try to catch eventual errors and set it up so that the admin will have to approve the users.
Reply all
Reply to author
Forward
0 new messages