diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 2b06661d..34af96e2 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -100,6 +100,25 @@ class UiRequest: def resolveDomain(self, domain): return self.server.site_manager.resolveDomainCached(domain) + def hasCorsPermission(self, referer): + """Check if site from referer has CORS permission to read site in current request + + NOTE: this allows embedding WITHOUT prepending "cors-" (as it has already been used + for a long time e.g. on ZeroBlog++ based sites) as long as read permission has been + granted. + """ + target_path = self.env['PATH_INFO'] + if referer is None or target_path is None: + return False + s_parts = self.parsePath(referer) + t_parts = self.parsePath(target_path) + s_address = s_parts['address'] + t_address = t_parts['address'] + if not s_address or not t_address: + return False + s_site = self.server.sites[s_address] + return f'Cors:{t_address}' in s_site.settings['permissions'] + def isCrossOriginRequest(self): """Prevent detecting sites on this 0net instance @@ -129,7 +148,7 @@ class UiRequest: return False # Deny cross site requests - if not self.isSameOrigin(referer, url): + if not self.isSameOrigin(referer, url) and not self.hasCorsPermission(referer): return True return False @@ -731,7 +750,7 @@ class UiRequest: if "../" in path or "./" in path: raise SecurityError("Invalid path") - match = re.match(r"/(media/)?(?P
[A-Za-z0-9]+[A-Za-z0-9\._-]+)(?P/.*|$)", path) + match = re.match(r"(?P(http[s]{0,1}://(.*?))?)/(media/)?(?P
[A-Za-z0-9]+[A-Za-z0-9\._-]+)(?P/.*|$)", path) if match: path_parts = match.groupdict() addr = path_parts["address"] diff --git a/src/Ui/UiServer.py b/src/Ui/UiServer.py index 27727d4c..de90f8f1 100644 --- a/src/Ui/UiServer.py +++ b/src/Ui/UiServer.py @@ -162,7 +162,7 @@ class UiServer: return ui_request.route(path) except Exception as err: logging.debug(f"UiRequest @ site error: {Debug.formatException(err)}") - return ui_request.error500('Error while trying to server site data') + return ui_request.error500('Error while trying to serve site data') def startSiteServer(self): self.site_server = WSGIServer((self.ip, self.site_port), self.handleSiteRequest, log=self.log)