@@ -273,6 +273,10 @@ class LdapAuth(BaseAuth):
273273
274274 _ldap_uri = None
275275 _ldap_basedn = None
276+ _ldap_binddn_fmt = None
277+ _ldap_search = None
278+ _ldap_rw_group = None
279+ _ldap_ro_group = None
276280 _ldap_conn = None
277281 _authenticated = None
278282
@@ -303,6 +307,10 @@ def __init__(self, name, username, password, authoritative_source, auth_options=
303307 BaseAuth .__init__ (self , username , password , authoritative_source , name , auth_options )
304308 self ._ldap_uri = self ._cfg .get ('auth.backends.' + self .auth_backend , 'uri' )
305309 self ._ldap_basedn = self ._cfg .get ('auth.backends.' + self .auth_backend , 'basedn' )
310+ self ._ldap_binddn_fmt = self ._cfg .get ('auth.backends.' + self .auth_backend , 'binddn_fmt' )
311+ self ._ldap_search = self ._cfg .get ('auth.backends.' + self .auth_backend , 'search' )
312+ self ._ldap_ro_group = self ._cfg .get ('auth.backends.' + self .auth_backend , 'ro_group' )
313+ self ._ldap_rw_group = self ._cfg .get ('auth.backends.' + self .auth_backend , 'rw_group' )
306314
307315 self ._logger .debug ('Creating LdapAuth instance' )
308316
@@ -323,7 +331,7 @@ def authenticate(self):
323331 return self ._authenticated
324332
325333 try :
326- self ._ldap_conn .simple_bind_s ('uid=' + self .username + ',' + self ._ldap_basedn , self .password )
334+ self ._ldap_conn .simple_bind_s (self ._ldap_binddn_fmt . format ( ldap . dn . escape_dn_chars ( self .username )) , self .password )
327335 except ldap .SERVER_DOWN as exc :
328336 raise AuthError ('Could not connect to LDAP server' )
329337 except (ldap .INVALID_CREDENTIALS , ldap .INVALID_DN_SYNTAX ,
@@ -336,17 +344,45 @@ def authenticate(self):
336344
337345 # auth succeeded
338346 self .authenticated_as = self .username
339- self ._authenticated = True
340347 self .trusted = False
341348 self .readonly = False
342349
343350 try :
344- res = self ._ldap_conn .search_s (self ._ldap_basedn , ldap .SCOPE_SUBTREE , 'uid=' + self .username , ['cn' ])
351+ res = self ._ldap_conn .search_s (self ._ldap_basedn , ldap .SCOPE_SUBTREE , self ._ldap_search . format ( ldap . dn . escape_dn_chars ( self . username )) , ['cn' , 'memberOf ' ])
345352 self .full_name = res [0 ][1 ]['cn' ][0 ]
346- except :
353+ # check for ro_group membership if ro_group is configured
354+ if self ._ldap_ro_group :
355+ if self ._ldap_ro_group in res [0 ][1 ]['memberOf' ]:
356+ self .readonly = True
357+ # check for rw_group membership if rw_group is configured
358+ if self ._ldap_rw_group :
359+ if self ._ldap_rw_group in res [0 ][1 ]['memberOf' ]:
360+ self .readonly = False
361+ else :
362+ # if ro_group is configured, and the user is a member of
363+ # neither the ro_group nor the rw_group, fail authentication.
364+ if self ._ldap_ro_group :
365+ if self ._ldap_ro_group not in res [0 ][1 ]['memberOf' ]:
366+ self ._authenticated = False
367+ return self ._authenticated
368+ else :
369+ self .readonly = True
370+
371+ except (ldap .NO_SUCH_OBJECT ,ldap .OPERATIONS_ERROR ,ldap .FILTER_ERROR ,ldap .INVALID_DN_SYNTAX ,ldap .SERVER_DOWN ) as exc :
372+ raise AuthError (exc )
373+ except KeyError :
374+ raise AuthError ('LDAP attribute missing' )
375+ except IndexError :
347376 self .full_name = ''
377+ # authentication fails if either ro_group or rw_group are configured
378+ # and the user is not found.
379+ if self ._ldap_rw_group or self ._ldap_ro_group :
380+ self ._authenticated = False
381+ return self ._authenticated
348382
349- self ._logger .debug ('successfully authenticated as %s, username %s' % (self .authenticated_as , self .username ))
383+ self ._authenticated = True
384+
385+ self ._logger .debug ('successfully authenticated as %s, username %s, full_name %s, readonly %s' % (self .authenticated_as , self .username , self .full_name , str (self .readonly )))
350386 return self ._authenticated
351387
352388
0 commit comments