From c6e090dc9801bdaf7db9866ec85086dc687d223f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 9 Jan 2023 22:05:58 +0000 Subject: [PATCH] Add protocol handler --- daemon.py | 29 +++++++++++++++++++++++++++-- webfinger.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index bd68c5960..e22994ccf 100644 --- a/daemon.py +++ b/daemon.py @@ -30,6 +30,7 @@ from session import set_session_for_sender from webfinger import webfinger_meta from webfinger import webfinger_node_info from webfinger import webfinger_lookup +from webfinger import wellknown_protocol_handler from webfinger import webfinger_update from mastoapiv1 import masto_api_v1_response from metadata import meta_data_node_info @@ -1686,7 +1687,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.security_txt_is_active = False return True - def _webfinger(self, calling_domain: str, referer_domain: str) -> bool: + def _webfinger(self, calling_domain: str, referer_domain: str, + cookie: str) -> bool: if not self.path.startswith('/.well-known'): return False if self.server.debug: @@ -1723,6 +1725,29 @@ class PubServer(BaseHTTPRequestHandler): self.path.startswith('/friendi'): self._404() return True + # protocol handler. See https://fedi-to.github.io/protocol-handler.html + if self.path.startswith('/.well-known/protocol-handler'): + if referer_domain.endswidth('.onion'): + protocol_url = \ + wellknown_protocol_handler(self.path, + self.server.base_dir, 'http', + self.server.onion_domain) + elif referer_domain.endswidth('.i2p'): + protocol_url = \ + wellknown_protocol_handler(self.path, self.server.base_dir, + 'http', self.server.i2p_domain) + else: + protocol_url = \ + wellknown_protocol_handler(self.path, self.server.base_dir, + self.server.http_prefix, + self.server.domain_full) + if protocol_url: + self._redirect_headers(protocol_url, cookie, + calling_domain) + else: + self._404() + return True + # nodeinfo if self.path.startswith('/.well-known/nodeinfo') or \ self.path.startswith('/.well-known/x-nodeinfo'): if calling_domain.endswith('.onion') and \ @@ -18386,7 +18411,7 @@ class PubServer(BaseHTTPRequestHandler): return # get webfinger endpoint for a person - if self._webfinger(calling_domain, referer_domain): + if self._webfinger(calling_domain, referer_domain, cookie): fitness_performance(getreq_start_time, self.server.fitness, '_GET', 'webfinger called', self.server.debug) diff --git a/webfinger.py b/webfinger.py index 7235ed909..39f758018 100644 --- a/webfinger.py +++ b/webfinger.py @@ -252,6 +252,36 @@ def webfinger_meta(http_prefix: str, domain_full: str) -> str: return meta_str +def wellknown_protocol_handler(path: str, base_dir: str, + http_prefix: str, domain_full: str) -> {}: + """See https://fedi-to.github.io/protocol-handler.html + """ + if not path.startswith('/.well-known/protocol-handler?'): + return None + + if 'target=' in path: + target = path.split('target=')[1] + if ';' in target: + target = target.split(';')[0] + if not target: + return None + if not target.startswith('web+epicyon:'): + return None + handle = target.split(':', 1)[1].strip() + if handle.startswith('@'): + handle = handle[1:] + if '@' in handle: + nickname = handle.split('@')[0] + domain = handle.split('@')[1] + else: + nickname = handle + domain = domain_full + # not an open redirect + if domain == domain_full: + return http_prefix + '://' + domain_full + '/users/' + nickname + return None + + def webfinger_lookup(path: str, base_dir: str, domain: str, onion_domain: str, i2p_domain: str, port: int, debug: bool) -> {}: