Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Limit device_id size to 512B #12454

Merged
merged 10 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/12454.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Limit max size of device_id to less than 8KB.
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
11 changes: 11 additions & 0 deletions synapse/rest/client/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import logging
import re
import sys
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -342,6 +343,16 @@ async def _complete_login(
user_id = canonical_uid

device_id = login_submission.get("device_id")

# Check that device_id is not greater than a reasonable 512B
device_id_size = sys.getsizeof(device_id)
if device_id_size > 512:
raise LoginError(
400,
"Device_id cannot be greater than 512B.",
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
errcode=Codes.INVALID_PARAM,
)

H-Shay marked this conversation as resolved.
Show resolved Hide resolved
initial_display_name = login_submission.get("initial_device_display_name")
(
device_id,
Expand Down
35 changes: 34 additions & 1 deletion tests/rest/client/test_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
# 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 sys
import time
import urllib.parse
from typing import Any, Dict, List, Optional, Union
Expand Down Expand Up @@ -384,6 +385,38 @@ def test_session_can_hard_logout_all_sessions_after_being_soft_logged_out(
channel = self.make_request(b"POST", "/logout/all", access_token=access_token)
self.assertEqual(channel.result["code"], b"200", channel.result)

def test_login_with_overly_large_device_id_fails(self) -> None:
self.register_user("mickey", "cheese")

# create a device_id larger than 512B
device_id = 1000**1000
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
self.assertGreater(sys.getsizeof(device_id), 512)

body = {
"type": "m.login.password",
"user": "mickey",
"password": "cheese",
"device_id": device_id,
}

# make a login request with the bad device_id
channel = self.make_request(
"POST",
"/_matrix/client/r0/login",
H-Shay marked this conversation as resolved.
Show resolved Hide resolved
json.dumps(body).encode("utf8"),
custom_headers=None,
)

# test that the login fails with the correct error code/message
self.assertEqual(channel.code, 400)
self.assertEqual(
channel.json_body,
{
"errcode": "M_INVALID_PARAM",
"error": "Device_id cannot be greater than 512B.",
},
)


@skip_unless(has_saml2 and HAS_OIDC, "Requires SAML2 and OIDC")
class MultiSSOTestCase(unittest.HomeserverTestCase):
Expand Down