This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a config option for validating 'next_link' parameters against a d…
…omain whitelist (#8275) This is a config option ported over from DINUM's Sydent: matrix-org/sydent#285 They've switched to validating 3PIDs via Synapse rather than Sydent, and would like to retain this functionality. This original purpose for this change is phishing prevention. This solution could also potentially be replaced by a similar one to matrix-org/synapse#8004, but across all `*/submit_token` endpoint. This option may still be useful to enterprise even with that safeguard in place though, if they want to be absolutely sure that their employees don't follow links to other domains.
- Loading branch information
1 parent
fedb89a
commit ff91a45
Showing
5 changed files
with
218 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add a config option to specify a whitelist of domains that a user can be redirected to after validating their email or phone number. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,11 +14,11 @@ | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import json | ||
import os | ||
import re | ||
from email.parser import Parser | ||
from typing import Optional | ||
|
||
import pkg_resources | ||
|
||
|
@@ -29,6 +29,7 @@ | |
from synapse.rest.client.v2_alpha import account, register | ||
|
||
from tests import unittest | ||
from tests.unittest import override_config | ||
|
||
|
||
class PasswordResetTestCase(unittest.HomeserverTestCase): | ||
|
@@ -668,16 +669,104 @@ def test_no_valid_token(self): | |
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) | ||
self.assertFalse(channel.json_body["threepids"]) | ||
|
||
def _request_token(self, email, client_secret): | ||
@override_config({"next_link_domain_whitelist": None}) | ||
def test_next_link(self): | ||
"""Tests a valid next_link parameter value with no whitelist (good case)""" | ||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="https://example.com/a/good/site", | ||
expect_code=200, | ||
) | ||
|
||
@override_config({"next_link_domain_whitelist": None}) | ||
def test_next_link_exotic_protocol(self): | ||
"""Tests using a esoteric protocol as a next_link parameter value. | ||
Someone may be hosting a client on IPFS etc. | ||
""" | ||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="some-protocol://abcdefghijklmopqrstuvwxyz", | ||
expect_code=200, | ||
) | ||
|
||
@override_config({"next_link_domain_whitelist": None}) | ||
def test_next_link_file_uri(self): | ||
"""Tests next_link parameters cannot be file URI""" | ||
# Attempt to use a next_link value that points to the local disk | ||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="file:///host/path", | ||
expect_code=400, | ||
) | ||
|
||
@override_config({"next_link_domain_whitelist": ["example.com", "example.org"]}) | ||
def test_next_link_domain_whitelist(self): | ||
"""Tests next_link parameters must fit the whitelist if provided""" | ||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="https://example.com/some/good/page", | ||
expect_code=200, | ||
) | ||
|
||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="https://example.org/some/also/good/page", | ||
expect_code=200, | ||
) | ||
|
||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="https://bad.example.org/some/bad/page", | ||
expect_code=400, | ||
) | ||
|
||
@override_config({"next_link_domain_whitelist": []}) | ||
def test_empty_next_link_domain_whitelist(self): | ||
"""Tests an empty next_lint_domain_whitelist value, meaning next_link is essentially | ||
disallowed | ||
""" | ||
self._request_token( | ||
"[email protected]", | ||
"some_secret", | ||
next_link="https://example.com/a/page", | ||
expect_code=400, | ||
) | ||
|
||
def _request_token( | ||
self, | ||
email: str, | ||
client_secret: str, | ||
next_link: Optional[str] = None, | ||
expect_code: int = 200, | ||
) -> str: | ||
"""Request a validation token to add an email address to a user's account | ||
Args: | ||
email: The email address to validate | ||
client_secret: A secret string | ||
next_link: A link to redirect the user to after validation | ||
expect_code: Expected return code of the call | ||
Returns: | ||
The ID of the new threepid validation session | ||
""" | ||
body = {"client_secret": client_secret, "email": email, "send_attempt": 1} | ||
if next_link: | ||
body["next_link"] = next_link | ||
|
||
request, channel = self.make_request( | ||
"POST", | ||
b"account/3pid/email/requestToken", | ||
{"client_secret": client_secret, "email": email, "send_attempt": 1}, | ||
"POST", b"account/3pid/email/requestToken", body, | ||
) | ||
self.render(request) | ||
self.assertEquals(200, channel.code, channel.result) | ||
self.assertEquals(expect_code, channel.code, channel.result) | ||
|
||
return channel.json_body["sid"] | ||
return channel.json_body.get("sid") | ||
|
||
def _request_token_invalid_email( | ||
self, email, expected_errcode, expected_error, client_secret="foobar", | ||
|