| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  | __filename__ = "daemon_get_nodeinfo.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							|  |  |  | __version__ = "1.5.0" | 
					
						
							|  |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@libreserver.org" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2024-03-23 15:11:05 +00:00
										 |  |  | __module_group__ = "Core GET" | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import json | 
					
						
							|  |  |  | from httpcodes import http_400 | 
					
						
							|  |  |  | from httpcodes import http_404 | 
					
						
							|  |  |  | from httpcodes import http_503 | 
					
						
							|  |  |  | from httpcodes import write2 | 
					
						
							|  |  |  | from httpheaders import set_headers | 
					
						
							|  |  |  | from utils import convert_domains | 
					
						
							|  |  |  | from utils import get_instance_url | 
					
						
							|  |  |  | from utils import local_network_host | 
					
						
							|  |  |  | from siteactive import referer_is_active | 
					
						
							|  |  |  | from crawlers import update_known_crawlers | 
					
						
							|  |  |  | from blocking import broch_mode_is_active | 
					
						
							|  |  |  | from metadata import meta_data_node_info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_nodeinfo(self, ua_str: str, calling_domain: str, | 
					
						
							|  |  |  |                  referer_domain: str, | 
					
						
							|  |  |  |                  http_prefix: str, calling_site_timeout: int, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                  debug: bool, base_dir: str, | 
					
						
							|  |  |  |                  unit_test: bool, | 
					
						
							|  |  |  |                  domain_full: str, | 
					
						
							|  |  |  |                  path: str, | 
					
						
							|  |  |  |                  allow_local_network_access: bool, | 
					
						
							|  |  |  |                  sites_unavailable: [], | 
					
						
							|  |  |  |                  known_crawlers: [], | 
					
						
							|  |  |  |                  onion_domain: str, | 
					
						
							|  |  |  |                  i2p_domain: str, | 
					
						
							|  |  |  |                  project_version: str, | 
					
						
							|  |  |  |                  show_node_info_version: bool, | 
					
						
							|  |  |  |                  show_node_info_accounts: bool, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:18:02 +00:00
										 |  |  |                  registration: bool, domain: str, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:52:03 +00:00
										 |  |  |                  instance_description_short: str, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:18:02 +00:00
										 |  |  |                  instance_description: str) -> bool: | 
					
						
							| 
									
										
										
										
											2024-08-05 20:50:32 +00:00
										 |  |  |     """Supports nodeinfo version 2.x
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |     if path.startswith('/nodeinfo/1.0'): | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         http_400(self) | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2024-08-05 20:50:32 +00:00
										 |  |  |     if not path.startswith('/nodeinfo/2.') and \ | 
					
						
							|  |  |  |        not path.startswith('/.well-known/host-meta') and \ | 
					
						
							|  |  |  |        not path.startswith('/.well-known/nodeinfo') and \ | 
					
						
							|  |  |  |        not path.startswith('/.well-known/x-nodeinfo'): | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  |     if not referer_domain: | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |         if not debug and not unit_test: | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |             print('nodeinfo request has no referer domain ' + str(ua_str)) | 
					
						
							|  |  |  |             http_400(self) | 
					
						
							|  |  |  |             return True | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |     if referer_domain == domain_full: | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         print('nodeinfo request from self') | 
					
						
							|  |  |  |         http_400(self) | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     if self.server.nodeinfo_is_active: | 
					
						
							|  |  |  |         if not referer_domain: | 
					
						
							|  |  |  |             print('nodeinfo is busy during request without referer domain') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             print('nodeinfo is busy during request from ' + referer_domain) | 
					
						
							|  |  |  |         http_503(self) | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     self.server.nodeinfo_is_active = True | 
					
						
							|  |  |  |     # is this a real website making the call ? | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |     if not debug and not unit_test and referer_domain: | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         # Does calling_domain look like a domain? | 
					
						
							|  |  |  |         if ' ' in referer_domain or \ | 
					
						
							|  |  |  |            ';' in referer_domain or \ | 
					
						
							|  |  |  |            '.' not in referer_domain: | 
					
						
							|  |  |  |             print('nodeinfo referer domain does not look like a domain ' + | 
					
						
							|  |  |  |                   referer_domain) | 
					
						
							|  |  |  |             http_400(self) | 
					
						
							|  |  |  |             self.server.nodeinfo_is_active = False | 
					
						
							|  |  |  |             return True | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |         if not allow_local_network_access: | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |             if local_network_host(referer_domain): | 
					
						
							|  |  |  |                 print('nodeinfo referer domain is from the ' + | 
					
						
							|  |  |  |                       'local network ' + referer_domain) | 
					
						
							|  |  |  |                 http_400(self) | 
					
						
							|  |  |  |                 self.server.nodeinfo_is_active = False | 
					
						
							|  |  |  |                 return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not referer_is_active(http_prefix, | 
					
						
							|  |  |  |                                  referer_domain, ua_str, | 
					
						
							|  |  |  |                                  calling_site_timeout, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                                  sites_unavailable): | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |             print('nodeinfo referer url is not active ' + | 
					
						
							|  |  |  |                   referer_domain) | 
					
						
							|  |  |  |             http_400(self) | 
					
						
							|  |  |  |             self.server.nodeinfo_is_active = False | 
					
						
							|  |  |  |             return True | 
					
						
							| 
									
										
										
										
											2024-04-08 14:00:47 +00:00
										 |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |         print('DEBUG: nodeinfo ' + path) | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |     crawl_time = \ | 
					
						
							|  |  |  |         update_known_crawlers(ua_str, | 
					
						
							| 
									
										
										
										
											2024-04-08 09:15:15 +00:00
										 |  |  |                               base_dir, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                               known_crawlers, | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |                               self.server.last_known_crawler) | 
					
						
							|  |  |  |     if crawl_time is not None: | 
					
						
							|  |  |  |         self.server.last_known_crawler = crawl_time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # If we are in broch mode then don't show potentially | 
					
						
							|  |  |  |     # sensitive metadata. | 
					
						
							|  |  |  |     # For example, if this or allied instances are being attacked | 
					
						
							|  |  |  |     # then numbers of accounts may be changing as people | 
					
						
							|  |  |  |     # migrate, and that information may be useful to an adversary | 
					
						
							| 
									
										
										
										
											2024-04-08 09:15:15 +00:00
										 |  |  |     broch_mode = broch_mode_is_active(base_dir) | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |     node_info_version = project_version | 
					
						
							|  |  |  |     if not show_node_info_version or broch_mode: | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         node_info_version = '0.0.0' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if broch_mode: | 
					
						
							|  |  |  |         show_node_info_accounts = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     instance_url = get_instance_url(calling_domain, | 
					
						
							| 
									
										
										
										
											2024-04-08 14:00:47 +00:00
										 |  |  |                                     http_prefix, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                                     domain_full, | 
					
						
							|  |  |  |                                     onion_domain, | 
					
						
							|  |  |  |                                     i2p_domain) | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |     about_url = instance_url + '/about' | 
					
						
							|  |  |  |     terms_of_service_url = instance_url + '/terms' | 
					
						
							| 
									
										
										
										
											2024-04-08 09:15:15 +00:00
										 |  |  |     info = meta_data_node_info(base_dir, | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |                                about_url, terms_of_service_url, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                                registration, | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |                                node_info_version, | 
					
						
							| 
									
										
										
										
											2024-05-16 10:05:14 +00:00
										 |  |  |                                show_node_info_accounts, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:18:02 +00:00
										 |  |  |                                domain, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:52:03 +00:00
										 |  |  |                                instance_description_short, | 
					
						
							| 
									
										
										
										
											2024-06-04 18:18:02 +00:00
										 |  |  |                                instance_description) | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |     if info: | 
					
						
							|  |  |  |         msg_str = json.dumps(info) | 
					
						
							|  |  |  |         msg_str = convert_domains(calling_domain, referer_domain, | 
					
						
							|  |  |  |                                   msg_str, http_prefix, | 
					
						
							| 
									
										
										
										
											2024-04-11 16:29:29 +00:00
										 |  |  |                                   domain, | 
					
						
							|  |  |  |                                   onion_domain, | 
					
						
							|  |  |  |                                   i2p_domain) | 
					
						
							| 
									
										
										
										
											2024-03-02 15:34:08 +00:00
										 |  |  |         msg = msg_str.encode('utf-8') | 
					
						
							|  |  |  |         msglen = len(msg) | 
					
						
							|  |  |  |         protocol_str = \ | 
					
						
							|  |  |  |             'application/json; profile=' + \ | 
					
						
							|  |  |  |             '"http://nodeinfo.diaspora.software/ns/schema/2.1#"' | 
					
						
							|  |  |  |         set_headers(self, protocol_str, msglen, | 
					
						
							|  |  |  |                     None, calling_domain, True) | 
					
						
							|  |  |  |         write2(self, msg) | 
					
						
							|  |  |  |         if referer_domain: | 
					
						
							|  |  |  |             print('nodeinfo sent to ' + referer_domain) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             print('nodeinfo sent to unknown referer') | 
					
						
							|  |  |  |         self.server.nodeinfo_is_active = False | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     http_404(self, 5) | 
					
						
							|  |  |  |     self.server.nodeinfo_is_active = False | 
					
						
							|  |  |  |     return True |