registration: Require an explicit realm on PreregistrationUser.

This completes the last commit's work to fix CVE-2017-0910, applying
to any invite links already created before the fix was deployed.  With
this change, all new-user registrations must match an explicit realm
in the PreregistrationUser row, except when creating a new realm.

[greg: rewrote commit message]
This commit is contained in:
Vishnu Ks 2017-11-08 22:02:50 +00:00 committed by Greg Price
parent 985768b2fd
commit d4ee3023b2
5 changed files with 28 additions and 8 deletions

View File

@ -4,12 +4,10 @@
<div class="pitch"> <div class="pitch">
<hr/> <hr/>
<p class="lead">Whoops. The confirmation link has expired.</p> <p class="lead">Whoops. The confirmation link has expired or been deactivated.</p>
<p> <p>
If you're not sure how to generate a new one, shoot us a line at Please contact your organization administrator for a new one.
<a href="mailto:{{ support_email }}">{{ support_email }}</a>
and we'll get this resolved shortly.
</p> </p>
</div> </div>

View File

@ -540,7 +540,7 @@ class GitHubAuthBackendTest(ZulipTestCase):
def test_github_backend_new_user(self) -> None: def test_github_backend_new_user(self) -> None:
rf = RequestFactory() rf = RequestFactory()
request = rf.get('/complete') request = rf.get('/complete', HTTP_HOST=self.user_profile.realm.host)
request.session = {} request.session = {}
request.user = self.user_profile request.user = self.user_profile
self.backend.strategy.request = request self.backend.strategy.request = request

View File

@ -52,7 +52,7 @@ class EmailChangeTestCase(ZulipTestCase):
type=Confirmation.EMAIL_CHANGE) type=Confirmation.EMAIL_CHANGE)
url = confirmation_url(key, user_profile.realm.host, Confirmation.EMAIL_CHANGE) url = confirmation_url(key, user_profile.realm.host, Confirmation.EMAIL_CHANGE)
response = self.client_get(url) response = self.client_get(url)
self.assert_in_success_response(["Whoops. The confirmation link has expired."], response) self.assert_in_success_response(["The confirmation link has expired or been deactivated."], response)
def test_confirm_email_change(self) -> None: def test_confirm_email_change(self) -> None:
user_profile = self.example_user('hamlet') user_profile = self.example_user('hamlet')

View File

@ -1040,7 +1040,7 @@ class MultiuseInviteTest(ZulipTestCase):
result = self.client_post(invite_link, {'email': email}) result = self.client_post(invite_link, {'email': email})
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
self.assert_in_response("Whoops. The confirmation link has expired.", result) self.assert_in_response("The confirmation link has expired or been deactivated.", result)
def test_invalid_multiuse_link(self) -> None: def test_invalid_multiuse_link(self) -> None:
email = self.nonreg_email('newuser') email = self.nonreg_email('newuser')
@ -1707,6 +1707,26 @@ class UserSignUpTest(ZulipTestCase):
'from_confirmation': '1'}, subdomain="zephyr") 'from_confirmation': '1'}, subdomain="zephyr")
self.assert_in_success_response(["We couldn't find your confirmation link"], result) self.assert_in_success_response(["We couldn't find your confirmation link"], result)
def test_failed_signup_due_to_empty_realm_in_prereg_user(self) -> None:
"""
Largely to test a transitional state, where we started requiring the
realm in PreregistrationUser (if realm_creation is False), and wanted
to make sure we had properly disabled any existing confirmation links that
didn't have the realm set.
"""
email = "newuser@zulip.com"
password = "password"
self.client_post('/accounts/home/', {'email': email})
PreregistrationUser.objects.update(realm=None)
result = self.client_post(
'/accounts/register/',
{'password': password,
'key': find_key_by_email(email),
'terms': True,
'full_name': "New User",
'from_confirmation': '1'})
self.assert_in_success_response(["The confirmation link has expired or been deactivated."], result)
def test_failed_signup_due_to_restricted_domain(self) -> None: def test_failed_signup_due_to_restricted_domain(self) -> None:
realm = get_realm('zulip') realm = get_realm('zulip')
realm.invite_required = False realm.invite_required = False

View File

@ -64,7 +64,9 @@ def accounts_register(request):
realm = None realm = None
else: else:
realm = get_realm(get_subdomain(request)) realm = get_realm(get_subdomain(request))
if prereg_user.realm is not None and prereg_user.realm != realm: if prereg_user.realm is None:
return render(request, 'confirmation/link_expired.html')
if prereg_user.realm != realm:
return render(request, 'confirmation/link_does_not_exist.html') return render(request, 'confirmation/link_does_not_exist.html')
if realm and not email_allowed_for_realm(email, realm): if realm and not email_allowed_for_realm(email, realm):