-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add validation of format for 3pid and add validation of 3pid in admin api #7022
Changes from 7 commits
ea2a8de
a801e8d
4648933
59e4428
7c9da15
8ff3522
131255d
dbaf0a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add validation of format for 3pid. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add validation of 3pid in admin api ``PUT /_synapse/admin/v2/users/<user_id>``. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,6 +55,7 @@ class Codes(object): | |
THREEPID_IN_USE = "M_THREEPID_IN_USE" | ||
THREEPID_NOT_FOUND = "M_THREEPID_NOT_FOUND" | ||
THREEPID_DENIED = "M_THREEPID_DENIED" | ||
INVALID_THREEPID = "M_INVALID_THREEPID" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is unclear to me if this needs a spec change or not. @matrix-org/synapse-core any opinion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not find an spec for these errors. Only a documenttion https://github.com/matrix-org/matrix-doc/blob/master/specification/client_server_api.rst There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can see the list of error codes at https://matrix.org/docs/spec/client_server/r0.6.0#api-standards, this would need to get added as a separate one following the process at https://matrix.org/docs/spec/proposals |
||
INVALID_USERNAME = "M_INVALID_USERNAME" | ||
SERVER_NOT_TRUSTED = "M_SERVER_NOT_TRUSTED" | ||
CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ | |
historical_admin_path_patterns, | ||
) | ||
from synapse.types import UserID | ||
from synapse.util.threepids import check_3pid_allowed, check_3pid_valid_format | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
@@ -195,8 +196,35 @@ async def on_PUT(self, request, user_id): | |
# add new threepids to user | ||
current_time = self.hs.get_clock().time_msec() | ||
for threepid in body["threepids"]: | ||
# For emails, transform the address to lowercase. | ||
# We store all email addreses as lowercase in the DB. | ||
# (See add_threepid in synapse/handlers/auth.py) | ||
address = threepid["address"].lower() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noting that this seems related to #7021. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change needs to wait on the result of that conversation then. |
||
if not check_3pid_valid_format(threepid["medium"], address): | ||
raise SynapseError( | ||
400, | ||
"Third party identifier has not a valid format", | ||
Codes.INVALID_THREEPID, | ||
) | ||
|
||
if not check_3pid_allowed(self.hs, threepid["medium"], address): | ||
raise SynapseError( | ||
403, | ||
"Your email domain or account phone number is not authorized on this server", | ||
Codes.THREEPID_DENIED, | ||
) | ||
|
||
existing_user_id = await self.store.get_user_id_by_threepid( | ||
threepid["medium"], address | ||
) | ||
|
||
if existing_user_id is not None: | ||
raise SynapseError( | ||
400, "Threepid is already in use", Codes.THREEPID_IN_USE | ||
) | ||
|
||
await self.auth_handler.add_threepid( | ||
user_id, threepid["medium"], threepid["address"], current_time | ||
user_id, threepid["medium"], address, current_time | ||
) | ||
|
||
if "avatar_url" in body: | ||
|
@@ -271,8 +299,35 @@ async def on_PUT(self, request, user_id): | |
|
||
current_time = self.hs.get_clock().time_msec() | ||
for threepid in body["threepids"]: | ||
# For emails, transform the address to lowercase. | ||
# We store all email addreses as lowercase in the DB. | ||
# (See add_threepid in synapse/handlers/auth.py) | ||
address = threepid["address"].lower() | ||
if not check_3pid_valid_format(threepid["medium"], address): | ||
raise SynapseError( | ||
400, | ||
"Third party identifier has not a valid format", | ||
dklimpel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Codes.INVALID_THREEPID, | ||
) | ||
|
||
if not check_3pid_allowed(self.hs, threepid["medium"], address): | ||
raise SynapseError( | ||
403, | ||
"Your email domain or account phone number is not authorized on this server", | ||
Codes.THREEPID_DENIED, | ||
) | ||
|
||
existing_user_id = await self.store.get_user_id_by_threepid( | ||
threepid["medium"], address | ||
) | ||
|
||
if existing_user_id is not None: | ||
raise SynapseError( | ||
400, "Threepid is already in use", Codes.THREEPID_IN_USE | ||
) | ||
|
||
await self.auth_handler.add_threepid( | ||
user_id, threepid["medium"], threepid["address"], current_time | ||
user_id, threepid["medium"], address, current_time | ||
) | ||
|
||
if "avatar_url" in body: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,3 +48,25 @@ def check_3pid_allowed(hs, medium, address): | |
return True | ||
|
||
return False | ||
|
||
|
||
def check_3pid_valid_format(medium, address): | ||
"""Checks whether 3pid has a valid format | ||
|
||
Args: | ||
medium (str): 3pid medium - e.g. email, msisdn | ||
address (str): 3pid address to check (e.g. "wotan@matrix.org") | ||
dklimpel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Returns: | ||
bool: whether the email address has a valid format | ||
""" | ||
|
||
if medium == "email": | ||
regex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At a glance this looks like it'll hit most valid e-mails, but usually things like e-mails and domains are relatively hard to validate -- where did this regular expression come from? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Source of regex is: https://emailregex.com/
We can change the regex. That is the reason why the validation is a new function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not found a good regex for msidns. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main issue I see here is that this doesn't support international domain names (or Unicode in general, although I'm not sure if Unicode is valid in the local part of an email address). Taking a look at that site, it seems the Python regular expression is much simpler than some of the others, which I find concerning. Poking around a bit, some other solutions seem to suggest being generous since it is hard to know the form of an email without trying to actually validate it and use something like: |
||
if re.search(regex, address): | ||
return True | ||
else: | ||
return False | ||
dklimpel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
elif medium == "msisdn": | ||
return True | ||
else: | ||
return False | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a comment above this saying that any other medium is not understood and is thus invalid? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contrary to how towncrier is normally used, we've been putting in newsfragments just for the pull request number, so this file can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please delete this file.