From 54c98455cec03f5f57ce747ab8ef205809f0d983 Mon Sep 17 00:00:00 2001
From: Julian Rother <julianr@fsmpi.rwth-aachen.de>
Date: Wed, 4 Nov 2020 04:01:22 +0100
Subject: [PATCH] handle unsafe login name in forgot_password, closes #31

---
 tests/test_selfservice.py | 9 +++++++++
 uffd/ldap/ldap.py         | 2 +-
 uffd/selfservice/views.py | 5 ++++-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/tests/test_selfservice.py b/tests/test_selfservice.py
index 3c5800f9..789e30a5 100644
--- a/tests/test_selfservice.py
+++ b/tests/test_selfservice.py
@@ -176,6 +176,15 @@ class TestSelfservice(UffdTestCase):
 		self.assertFalse(hasattr(self.app, 'last_mail'))
 		self.assertEqual(len(PasswordToken.query.all()), 0)
 
+	# Regression test for #31
+	def test_forgot_password_invalid_user(self):
+		r = self.client.post(path=url_for('selfservice.forgot_password'),
+			data={'loginname': '=', 'mail': 'test@example.com'}, follow_redirects=True)
+		dump('forgot_password_submit_invalid_user', r)
+		self.assertEqual(r.status_code, 200)
+		self.assertFalse(hasattr(self.app, 'last_mail'))
+		self.assertEqual(len(PasswordToken.query.all()), 0)
+
 	def test_token_password(self):
 		user = User.from_ldap_dn('uid=testuser,ou=users,dc=example,dc=com')
 		oldpw = get_ldap_password()
diff --git a/uffd/ldap/ldap.py b/uffd/ldap/ldap.py
index 7e8f53d6..6e2f40dd 100644
--- a/uffd/ldap/ldap.py
+++ b/uffd/ldap/ldap.py
@@ -67,7 +67,7 @@ def uid_to_dn(uid):
 def loginname_to_dn(loginname):
 	if loginname_is_safe(loginname):
 		return 'uid={},{}'.format(loginname, current_app.config["LDAP_BASE_USER"])
-	raise Exception('unsafe login name')
+	raise ValueError('unsafe login name')
 
 def mail_to_dn(uid):
 	if mailname_is_safe(uid):
diff --git a/uffd/selfservice/views.py b/uffd/selfservice/views.py
index 9b1e8890..fae2c27d 100644
--- a/uffd/selfservice/views.py
+++ b/uffd/selfservice/views.py
@@ -67,7 +67,10 @@ def forgot_password():
 	reset_ratelimit.log(loginname+'/'+mail)
 	host_ratelimit.log()
 	flash("We sent a mail to this users mail address if you entered the correct mail and login name combination")
-	user = User.from_ldap_dn(loginname_to_dn(loginname))
+	try:
+		user = User.from_ldap_dn(loginname_to_dn(loginname))
+	except ValueError:
+		user = None
 	if user and user.mail == mail:
 		send_passwordreset(loginname)
 	return redirect(url_for('session.login'))
-- 
GitLab