Skip to content
Snippets Groups Projects
Commit caed6e29 authored by Timothy Allen's avatar Timothy Allen
Browse files

Only trust .bind_user() with a non-empty password.

There are two reasons one migh call .bind_user(): you might want to
connect to an LDAP server and perform operations on that user's behalf,
or you might want to check whether a username and password pair are
valid. Unfortunately, if you give the password as an empty string, many
LDAP servers will grant you access as an anonymous user, regardless of
the username you ask for, so just because .bind_user() accepts
a username/password pair doesn't mean that's the correct password for
that user.

Therefore:

- I've added a warning to the bind_user() docstring.
- I've modified the `basic_auth_required()` decorator to guard against
  empty passwords.
- I've modified the various code examples to guard against empty
  passwords.
parent 42fc823d
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ def login(): ...@@ -18,7 +18,7 @@ def login():
user = request.form['user'] user = request.form['user']
passwd = request.form['passwd'] passwd = request.form['passwd']
test = ldap.bind_user(user, passwd) test = ldap.bind_user(user, passwd)
if test is None: if test is None or passwd == '':
return 'Invalid credentials' return 'Invalid credentials'
else: else:
session['user_id'] = request.form['user'] session['user_id'] = request.form['user']
......
...@@ -36,7 +36,7 @@ def login(): ...@@ -36,7 +36,7 @@ def login():
user = request.form['user'] user = request.form['user']
passwd = request.form['passwd'] passwd = request.form['passwd']
test = ldap.bind_user(user, passwd) test = ldap.bind_user(user, passwd)
if test is None: if test is None or passwd = '':
return 'Invalid credentials' return 'Invalid credentials'
else: else:
session['user_id'] = request.form['user'] session['user_id'] = request.form['user']
......
...@@ -123,6 +123,15 @@ class LDAP(object): ...@@ -123,6 +123,15 @@ class LDAP(object):
"""Attempts to bind a user to the LDAP server using the credentials """Attempts to bind a user to the LDAP server using the credentials
supplied. supplied.
.. note::
Many LDAP servers will grant anonymous access if ``password`` is
the empty string, causing this method to return :obj:`True` no
matter what username is given. If you want to use this method to
validate a username and password, rather than actually connecting
to the LDAP server as a particular user, make sure ``password`` is
not empty.
:param str username: The username to attempt to bind with. :param str username: The username to attempt to bind with.
:param str password: The password of the username we're attempting to :param str password: The password of the username we're attempting to
bind with. bind with.
...@@ -319,7 +328,11 @@ class LDAP(object): ...@@ -319,7 +328,11 @@ class LDAP(object):
req_username = request.authorization.username req_username = request.authorization.username
req_password = request.authorization.password req_password = request.authorization.password
if req_username is None or req_password is None: # Many LDAP servers will grant you anonymous access if you log in
# with an empty password, even if you supply a non-anonymous user
# ID, causing .bind_user() to return True. Therefore, only accept
# non-empty passwords.
if req_username in ['', None] or req_password in ['', None]:
current_app.logger.debug('Got a request without auth data') current_app.logger.debug('Got a request without auth data')
return make_auth_required_response() return make_auth_required_response()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment