diff options
| author | 2025-04-29 03:57:03 +0200 | |
|---|---|---|
| committer | 2025-04-29 03:57:03 +0200 | |
| commit | 75f9d1cc69872d4b8dbcd13145447ae1c6c2879a (patch) | |
| tree | a6d0231b88dde4025ed5ca292b2b5328e2a720f2 /deluge/ui | |
| parent | 354b8c521e7951f7f332efd62257aebb48d44437 (diff) | |
Adding upstream version 2.2.0.upstream/2.2.0
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'deluge/ui')
| -rw-r--r-- | deluge/ui/gtk3/new_release_dialog.py | 2 | ||||
| -rw-r--r-- | deluge/ui/web/auth.py | 10 | ||||
| -rw-r--r-- | deluge/ui/web/js/deluge-all/AboutWindow.js | 2 | ||||
| -rw-r--r-- | deluge/ui/web/server.py | 40 |
4 files changed, 41 insertions, 13 deletions
diff --git a/deluge/ui/gtk3/new_release_dialog.py b/deluge/ui/gtk3/new_release_dialog.py index a635bd2..7246994 100644 --- a/deluge/ui/gtk3/new_release_dialog.py +++ b/deluge/ui/gtk3/new_release_dialog.py @@ -61,7 +61,7 @@ class NewReleaseDialog: self.dialog.show() def _on_button_goto_downloads(self, widget): - deluge.common.open_url_in_browser('http://deluge-torrent.org') + deluge.common.open_url_in_browser('https://deluge-torrent.org') self.config['show_new_releases'] = not self.chk_not_show_dialog.get_active() self.dialog.destroy() diff --git a/deluge/ui/web/auth.py b/deluge/ui/web/auth.py index eacbbf5..a0c3a91 100644 --- a/deluge/ui/web/auth.py +++ b/deluge/ui/web/auth.py @@ -100,9 +100,9 @@ class Auth(JSONComponent): checksum = str(make_checksum(session_id)) request.addCookie( - b'_session_id', + '_session_id', session_id + checksum, - path=request.base + b'json', + path=request.base, expires=expires_str, ) @@ -160,10 +160,10 @@ class Auth(JSONComponent): _session_id = request.getCookie(b'_session_id') request.addCookie( - b'_session_id', + '_session_id', _session_id, - path=request.base + b'json', - expires=expires_str.encode('utf8'), + path=request.base, + expires=expires_str, ) if method: diff --git a/deluge/ui/web/js/deluge-all/AboutWindow.js b/deluge/ui/web/js/deluge-all/AboutWindow.js index cfae7a8..4ab6599 100644 --- a/deluge/ui/web/js/deluge-all/AboutWindow.js +++ b/deluge/ui/web/js/deluge-all/AboutWindow.js @@ -99,7 +99,7 @@ Deluge.about.AboutWindow = Ext.extend(Ext.Window, { { xtype: 'label', style: 'padding-top: 10px; font-size: 10px;', - text: _('Copyright 2007-2018 Deluge Team'), + text: _('Copyright 2007-2025 Deluge Team'), }, { xtype: 'label', diff --git a/deluge/ui/web/server.py b/deluge/ui/web/server.py index 5aba8aa..e93d4f6 100644 --- a/deluge/ui/web/server.py +++ b/deluge/ui/web/server.py @@ -20,8 +20,9 @@ from twisted.web import http, resource, server, static from twisted.web.resource import EncodingResourceWrapper from deluge import common, component, configmanager -from deluge.common import is_ipv6 +from deluge.common import AUTH_LEVEL_DEFAULT, is_ipv6 from deluge.crypto_utils import check_ssl_keys, get_context_factory +from deluge.error import NotAuthorizedError from deluge.i18n import set_language, setup_translation from deluge.ui.tracker_icons import TrackerIcons from deluge.ui.web.auth import Auth @@ -182,8 +183,9 @@ class Tracker(resource.Resource): except KeyError: self.tracker_icons = TrackerIcons() - def getChild(self, path, request): # NOQA: N802 - request.tracker_name = path + def getChild(self, path: bytes, request): # NOQA: N802 + # Ensure tracker name only to prevent path traversal. + request.tracker_name = os.path.basename(path.decode()) return self def on_got_icon(self, icon, request): @@ -200,8 +202,22 @@ class Tracker(resource.Resource): request.finish() def render(self, request): - d = self.tracker_icons.fetch(request.tracker_name.decode()) - d.addCallback(self.on_got_icon, request) + tracker_icon = self.tracker_icons.get(request.tracker_name) + if tracker_icon: + self.on_got_icon(tracker_icon, request) + return server.NOT_DONE_YET + + # Tracker endpoint is secured to avoid exploits when downloading icons. + try: + component.get('Auth').check_request(request, level=AUTH_LEVEL_DEFAULT) + except NotAuthorizedError: + log.warning('Auth required to download tracker icon.') + request.setResponseCode(http.UNAUTHORIZED) + request.finish() + else: + self.tracker_icons.fetch(request.tracker_name).addCallback( + self.on_got_icon, request + ) return server.NOT_DONE_YET @@ -211,7 +227,9 @@ class Flag(resource.Resource): return self def render(self, request): - flag = request.country.decode().lower() + '.png' + country = request.country.decode().lower() + # Ensure filename only, to prevent path traversal. + flag = os.path.basename(f'{country}.png') path = ('ui', 'data', 'pixmaps', 'flags', flag) filename = common.resource_filename('deluge', os.path.join(*path)) if os.path.exists(filename): @@ -433,8 +451,18 @@ class ScriptResource(resource.Resource, component.Component): filepath = filepath[0] path = filepath + lookup_path[len(pattern) :] + path = os.path.abspath(path) + + if not os.path.commonpath([path, filepath]) == filepath: + log.warning( + 'Script path %s traverses out of common dir %s', + path, + filepath, + ) + continue if not os.path.isfile(path): + log.warning('Unable to serve script which does not exist: %s', path) continue log.debug('Serving path: %s', path) |
