5
5
# Copyright (C) 2014-2015 Nginx, Inc.
6
6
# Copyright (C) 2018 LinuxServer.io
7
7
8
- import sys, os, signal, base64, ldap, argparse
8
+ import sys, os, signal, base64, ldap, ldap.filter, argparse
9
9
if sys.version_info.major == 2:
10
10
from Cookie import BaseCookie
11
11
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
@@ -101,7 +101,7 @@ def do_GET(self):
101
101
self.log_error(e)
102
102
return True
103
103
104
- ctx[' user' ] = user
104
+ ctx[' user' ] = ldap.filter.escape_filter_chars( user)
105
105
ctx[' pass' ] = passwd
106
106
107
107
# Continue request processing
@@ -172,6 +172,7 @@ class LDAPAuthHandler(AuthHandler):
172
172
' realm' : (' X-Ldap-Realm' , ' Restricted' ),
173
173
' url' : (' X-Ldap-URL' , None),
174
174
' starttls' : (' X-Ldap-Starttls' , ' false' ),
175
+ ' disable_referrals' : (' X-Ldap-DisableReferrals' , ' false' ),
175
176
' basedn' : (' X-Ldap-BaseDN' , None),
176
177
' template' : (' X-Ldap-Template' , ' (cn=%(username)s)' ),
177
178
' binddn' : (' X-Ldap-BindDN' , ' ' ),
@@ -233,9 +234,9 @@ def do_GET(self):
233
234
if ctx[' starttls' ] == ' true' :
234
235
ldap_obj.start_tls_s ()
235
236
236
- # See http ://www.python-ldap.org/faq.shtml
237
- # uncomment, if required
238
- # ldap_obj.set_option(ldap.OPT_REFERRALS, 0)
237
+ # See https ://www.python-ldap.org/en/latest/ faq.html
238
+ if ctx[ ' disable_referrals ' ] == ' true ' :
239
+ ldap_obj.set_option(ldap.OPT_REFERRALS, 0)
239
240
240
241
ctx[' action' ] = ' binding as search user'
241
242
ldap_obj.bind_s(ctx[' binddn' ], ctx[' bindpasswd' ], ldap.AUTH_SIMPLE)
@@ -252,13 +253,27 @@ def do_GET(self):
252
253
searchfilter, [' objectclass' ], 1)
253
254
254
255
ctx[' action' ] = ' verifying search query results'
255
- if len(results) < 1:
256
+
257
+ nres = len(results)
258
+
259
+ if nres < 1:
256
260
self.auth_failed(ctx, ' no objects found' )
257
261
return
258
262
259
- ctx[' action' ] = ' binding as an existing user'
260
- ldap_dn = results[0][0]
261
- ctx[' action' ] += ' "%s"' % ldap_dn
263
+ if nres > 1:
264
+ self.log_message(" note: filter match multiple objects: %d, using first" % nres)
265
+
266
+ user_entry = results[0]
267
+ ldap_dn = user_entry[0]
268
+
269
+ if ldap_dn == None:
270
+ self.auth_failed(ctx, ' matched object has no dn' )
271
+ return
272
+
273
+ self.log_message(' attempting to bind using dn "%s"' % (ldap_dn))
274
+
275
+ ctx[' action' ] = ' binding as an existing user "%s"' % ldap_dn
276
+
262
277
ldap_obj.bind_s(ldap_dn, ctx[' pass' ], ldap.AUTH_SIMPLE)
263
278
264
279
self.log_message(' Auth OK for user "%s"' % (ctx[' user' ]))
@@ -328,6 +343,7 @@ def exit_handler(signal, frame):
328
343
' realm' : (' X-Ldap-Realm' , args.realm),
329
344
' url' : (' X-Ldap-URL' , args.url),
330
345
' starttls' : (' X-Ldap-Starttls' , args.starttls),
346
+ ' disable_referrals' : (' X-Ldap-DisableReferrals' , args.disable_referrals),
331
347
' basedn' : (' X-Ldap-BaseDN' , args.basedn),
332
348
' template' : (' X-Ldap-Template' , args.filter),
333
349
' binddn' : (' X-Ldap-BindDN' , args.binddn),
0 commit comments