Ok!

:)

Richard


On Wed, Aug 7, 2013 at 10:10 AM, Massimo Di Pierro <
[email protected]> wrote:

> Please send me a patch when you test it. ;-)
>
> On Wednesday, 7 August 2013 07:51:58 UTC-5, Richard wrote:
>
>> No change... Auth seems to delegate entirely the validation on username
>> input field in case ldap_auth is used as authentication method.
>>
>> I guess this simple refactor (not tested) could do the tricks at least
>> for Active directory :
>>
>>                 if not IS_EMAIL()(username)[1]:
>>                     domain = []
>>                     for x in ldap_basedn.split(','):
>>                         if "DC=" in x.upper():
>>                             domain.append(x.split('=')[-1]**)
>>                     identifier = "%s@%s" % (username, '.'.join(domain))
>>                 else: return ERROR...
>>                 username_bare = username.split("@")[0]
>>
>> Richard
>>
>>
>>
>> On Wed, Aug 7, 2013 at 8:42 AM, Richard Vézina <[email protected]>wrote:
>>
>>> Hello,
>>>
>>> I was about to post this (I think I answer your question) :
>>>
>>> Hello,
>>>
>>> I think I found a flaw in the interaction between Auth and LDAP contrib
>>> (web2py 2.4.7).
>>>
>>> If I set LDAP as unique authentification method
>>> (auth.settings.login_methods = LDAP) as written in the book, web2py should
>>> leaves LDAP to create user... The things is web2py Auth seems to create
>>> user even if it LDAP that is responsible of doing it. I mean, I carefully
>>> read the code of LDAP and the only way it could create a new user is if
>>> manage_groups=True by calling do_manage_groups() since the other place
>>> where LDAP is instert new user it set email, first_name and last_name. In
>>> my case, if user use email instead of username (that should not be email,
>>> but I can't enforce this with the custom IS_NOT_EMAIL() validator I wrote)
>>> for login a new user get inserted like this : first_name = email (or the
>>> content of username input that is an email), username = email and
>>> registration_id = email. As far as I can see the only way LDAP could
>>> produce this result is if the do_manage_groups method is called, but it
>>> can't be call if manage_groups is set to False. So, the only remaining
>>> possibility is that Auth is creating the new user because it recieve a bad
>>> signal from LDAP.
>>>
>>> I make a couples tests and found that the insert new user base on the
>>> credentials of already existing user that log with it email instead of it
>>> username occure at line 2147-2148. So I guess Auth recieve a True flag from
>>> LDAP mean the user exist in directory, since web2py can't match a existing
>>> user base on the wrong username (email) it insert a new user with wrong
>>> setting.
>>>
>>> The origin of this is multifold. First, I think it could be prevent if
>>> there was a IS_NOT_EMAIL() validator on the username field, for some reason
>>> I can't get it to work properly with LDAP because of the way LDAP is
>>> working the validator seems to be skipped, and the username is first check
>>> against directory. Maybe using IS_NOT_EMAIL() inside ldap_auth contrib
>>> could solve this issue. Other possible origin is the way ldap_auth is
>>> written. I mean it seems that for saving a variable "username" is
>>> re-used... I think that the issue is coming from line 8 of code extract
>>> below :
>>>
>>>             if ldap_mode == 'ad':
>>>                 # Microsoft Active Directory
>>>                 if '@' not in username:
>>>                     domain = []
>>>                     for x in ldap_basedn.split(','):
>>>                         if "DC=" in x.upper():
>>>                             domain.append(x.split('=')[-1]**)
>>>                     username = "%s@%s" % (username, '.'.join(domain))
>>>                 username_bare = username.split("@")[0]
>>>                 con.set_option(ldap.OPT_**PROTOCOL_VERSION, 3)
>>>                 # In cases where ForestDnsZones and DomainDnsZones are
>>> found,
>>>                 # result will look like the following:
>>>                 # 
>>> ['ldap://ForestDnsZones.**domain.com/DC=ForestDnsZones<http://ForestDnsZones.domain.com/DC=ForestDnsZones>
>>> ,
>>>                 #    DC=domain,DC=com']
>>>                 if ldap_binddn:
>>>                     # need to search directory with an admin account 1st
>>>                     con.simple_bind_s(ldap_binddn, ldap_bindpw)
>>>                 else:
>>>                     # credentials should be in the form of
>>> [email protected]
>>>                     con.simple_bind_s(username, password)
>>>                 # this will throw an index error if the account is not
>>> found
>>>                 # in the ldap_basedn
>>>                 requested_attrs = ['sAMAccountName']
>>>                 if manage_user:
>>>                     requested_attrs.extend([user_**firstname_attrib,
>>>                                            user_lastname_attrib,
>>>                                            user_mail_attrib])
>>>                 result = con.search_ext_s(
>>>                     ldap_basedn, ldap.SCOPE_SUBTREE,
>>>                     "(&(sAMAccountName=%s)(%s))" % (
>>>                                 ldap.filter.escape_filter_**
>>> chars(username_bare),
>>>                                 filterstr),
>>>                     requested_attrs)[0][1]
>>>                 if not isinstance(result, dict):
>>>                     # result should be a dict in the form
>>>                     # {'sAMAccountName': [username_bare]}
>>>                     logger.warning('User [%s] not found!' % username)
>>>                     return False
>>>                 if ldap_binddn:
>>>                     # We know the user exists & is in the correct OU
>>>                     # so now we just check the password
>>>                     con.simple_bind_s(username, password)
>>>                 username = username_bare
>>>
>>> This peace of code is pretty unreliable : It start by re-creating a
>>> email and store it in username vars if username it recieves from web2py is
>>> not a email before derive a username_bare from the altered username var and
>>> at the end it finally set username = username_bare... Why all this just to
>>> avoid create a var?!
>>>
>>> I propose to refator this using creating a new ID or identifier var to
>>> store connection "identifier" var instead reusing the username for that.
>>> Then it will require to determine if the IS_NOT_EMAIL() should go at Auth
>>> level or ldap_auth. I don't know so much LDAP in general and even less the
>>> different implementation, so I don't know if some implementation use email
>>> as an identifier or not. Since, the Auth class as mechanism to create
>>> missing user I don't no if it intentional to allow the creation of user
>>> with email as username or not... So, maybe it a option in to use
>>> IS_NOT_EMAIL() on username field in this case it will require that
>>> IS_NOT_EMAIL be at level of Auth. Maybe, I didn't be able to make work my
>>> custom validator because of the order of validator (I had set multiple
>>> validator on username), I will try to set only IS_NOT_EMAIL and report here
>>> if it solve the problem I have with LDAP authentication.
>>>
>>> Thanks
>>>
>>> Richard
>>>
>>>
>>>
>>> On Wed, Aug 7, 2013 at 7:22 AM, Massimo Di Pierro <[email protected]
>>> > wrote:
>>>
>>>> How would you change this?
>>>>
>>>>
>>>> On Monday, 5 August 2013 15:42:39 UTC-5, Richard wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> Is there a way to prevent user to log with there email? I set LDAP
>>>>> authentication, I create a username field on custom auth_user model and 
>>>>> set
>>>>> auth.define_tables(username=**Tr**ue)
>>>>>
>>>>> But I notice that I can still login with [email protected]. In this
>>>>> case, ldap_auth create a new user with first_name and username =
>>>>> [email protected]
>>>>>
>>>>> So, I think there is a flaw here in ldap_auth :
>>>>>
>>>>> if ldap_mode == 'ad':
>>>>>                 # Microsoft Active Directory
>>>>>                 if '@' not in username:
>>>>>                     domain = []
>>>>>                     for x in ldap_basedn.split(','):
>>>>>                         if "DC=" in x.upper():
>>>>>                             domain.append(x.split('=')[-1]****)
>>>>>                     username = "%s@%s" % (username, '.'.join(domain))
>>>>>                 username_bare = username.split("@")[0]
>>>>>
>>>>> Since it seems to recreate email as username...
>>>>>
>>>>> Thanks
>>>>>
>>>>> Richard
>>>>>
>>>>  --
>>>>
>>>> ---
>>>> You received this message because you are subscribed to the Google
>>>> Groups "web2py-users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to web2py+un...@**googlegroups.com.
>>>>
>>>> For more options, visit 
>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>> .
>>>>
>>>>
>>>>
>>>
>>>
>>  --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "web2py-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to