From edddb2e9d4260687ab9c0b8dc67818c5814f7567 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 22:58:40 -0500 Subject: [PATCH 01/13] fix allnet request using the wrong function --- core/allnet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 3b371ce..7e5accd 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -151,7 +151,7 @@ class AllnetServlet: def handle_dlorder(self, request: Request): request_ip = request.getClientAddress().host try: - req = AllnetDownloadOrderRequest(self.allnet_req_to_dict(request.content.getvalue())) + req = AllnetDownloadOrderRequest(self.billing_req_to_dict(request.content.getvalue())) # Validate the request. Currently we only validate the fields we plan on using if not req.game_id or not req.ver or not req.token or not req.serial or not req.ip: @@ -243,7 +243,7 @@ class AllnetServlet: ret.append(tmp) - def allnet_req_to_dict(self, data: bytes): + def billing_req_to_dict(self, data: bytes): """ Parses an billing request string into a python dictionary """ @@ -258,7 +258,7 @@ class AllnetServlet: print(e) return None - def billing_req_to_dict(self, data: str) -> Optional[List[Dict[str, Any]]]: + def allnet_req_to_dict(self, data: str) -> Optional[List[Dict[str, Any]]]: """ Parses an allnet request string into a python dictionary """ From 9a43303880b507a5c518555d392ae7814aef6309 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:02:50 -0500 Subject: [PATCH 02/13] fix incorrect class being used --- core/allnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 7e5accd..9e69c0e 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -252,7 +252,7 @@ class AllnetServlet: unzipped = decomp.decompress(data) sections = unzipped.decode('ascii').split('\r\n') - return Utils.kvp_to_dict(sections) + return self.kvp_to_dict(sections) except Exception as e: print(e) @@ -267,7 +267,7 @@ class AllnetServlet: unzipped = zlib.decompress(zipped) sections = unzipped.decode('utf-8').split('\r\n') - return Utils.kvp_to_dict(sections) + return self.kvp_to_dict(sections) except Exception as e: print(e) From 655d9dc5308da72bca1d8bb4415583ecd5ec3199 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:12:40 -0500 Subject: [PATCH 03/13] simplified main dispatcher --- core/allnet.py | 6 +++--- core/mucha.py | 4 ++-- index.py | 36 +++++++++--------------------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 9e69c0e..de0d20c 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -92,7 +92,7 @@ class AllnetServlet: self.uri_registry[code] = (uri, host) self.logger.info(f"Allnet serving {len(self.uri_registry)} games on port {core_cfg.allnet.port}") - def handle_poweron(self, request: Request): + def handle_poweron(self, request: Request, _: Dict): request_ip = request.getClientAddress().host try: req = AllnetPowerOnRequest(self.allnet_req_to_dict(request.content.getvalue())) @@ -148,7 +148,7 @@ class AllnetServlet: return self.dict_to_http_form_string([vars(resp)]) - def handle_dlorder(self, request: Request): + def handle_dlorder(self, request: Request, _: Dict): request_ip = request.getClientAddress().host try: req = AllnetDownloadOrderRequest(self.billing_req_to_dict(request.content.getvalue())) @@ -168,7 +168,7 @@ class AllnetServlet: else: # TODO: Actual dlorder response return self.dict_to_http_form_string(vars(resp)) - def handle_billing_request(self, request: Request): + def handle_billing_request(self, request: Request, _: Dict): req_dict = self.billing_req_to_dict(request.content.getvalue()) request_ip = request.getClientAddress() if req_dict is None: diff --git a/core/mucha.py b/core/mucha.py index a861101..312d83f 100644 --- a/core/mucha.py +++ b/core/mucha.py @@ -28,7 +28,7 @@ class MuchaServlet: self.logger.setLevel(logging.INFO) coloredlogs.install(level=logging.INFO, logger=self.logger, fmt=log_fmt_str) - def handle_boardauth(self, request: Request) -> bytes: + def handle_boardauth(self, request: Request, _: Dict) -> bytes: req_dict = self.mucha_preprocess(request.content.getvalue()) if req_dict is None: self.logger.error(f"Error processing mucha request {request.content.getvalue()}") @@ -41,7 +41,7 @@ class MuchaServlet: return self.mucha_postprocess(vars(resp)) - def handle_updatecheck(self, request: Request) -> bytes: + def handle_updatecheck(self, request: Request, _: Dict) -> bytes: req_dict = self.mucha_preprocess(request.content.getvalue()) if req_dict is None: self.logger.error(f"Error processing mucha request {request.content.getvalue()}") diff --git a/index.py b/index.py index 7fae586..0049427 100644 --- a/index.py +++ b/index.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import argparse +from typing import Dict import yaml from os import path, mkdir, access, W_OK from core import * @@ -36,46 +37,27 @@ class HttpDispatcher(resource.Resource): if test is None: return b"" - controller = getattr(self, test["controller"], None) - if controller is None: - return b"" - - handler = getattr(controller, test["action"], None) - if handler is None: - return b"" - - url_vars = test - url_vars.pop("controller") - url_vars.pop("action") - - if len(url_vars) > 0: - ret = handler(request, url_vars) - else: - ret = handler(request) - - if type(ret) == str: - return ret.encode() - elif type(ret) == bytes: - return ret - else: - return b"" + return self.dispatch(test, request) def render_POST(self, request: Request) -> bytes: test = self.map_post.match(request.uri.decode()) if test is None: return b"" + + return self.dispatch(test, request) - controller = getattr(self, test["controller"], None) + def dispatch(self, matcher: Dict, request: Request) -> bytes: + controller = getattr(self, matcher["controller"], None) if controller is None: return b"" - handler = getattr(controller, test["action"], None) + handler = getattr(controller, matcher["action"], None) if handler is None: return b"" - url_vars = test + url_vars = matcher url_vars.pop("controller") - url_vars.pop("action") + url_vars.pop("action") ret = handler(request, url_vars) if type(ret) == str: From 68b9c64f7147d56839d3756bbd8f66413b905334 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:24:38 -0500 Subject: [PATCH 04/13] fix kvp_to_dict --- core/allnet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/allnet.py b/core/allnet.py index de0d20c..939e16e 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -230,7 +230,7 @@ class AllnetServlet: self.logger.debug(f"response {vars(resp)}") return resp_str.encode("utf-8") - def kvp_to_dict(self, *kvp: str) -> List[Dict[str, Any]]: + def kvp_to_dict(self, kvp: List[str]) -> List[Dict[str, Any]]: ret: List[Dict[str, Any]] = [] for x in kvp: items = x.split('&') From b09d2326c26db762cbdfd0499551c527ec9a602b Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:27:25 -0500 Subject: [PATCH 05/13] fix kvp_to_dict not returning --- core/allnet.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/allnet.py b/core/allnet.py index 939e16e..95de25b 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -242,6 +242,8 @@ class AllnetServlet: tmp[kvp[0]] = kvp[1] ret.append(tmp) + + return ret def billing_req_to_dict(self, data: bytes): """ From f42c2d7785fe0f0f5178e3d784b610533f45f0b6 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:31:52 -0500 Subject: [PATCH 06/13] fix allnet requests not processing --- core/allnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 95de25b..49b7828 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -95,7 +95,7 @@ class AllnetServlet: def handle_poweron(self, request: Request, _: Dict): request_ip = request.getClientAddress().host try: - req = AllnetPowerOnRequest(self.allnet_req_to_dict(request.content.getvalue())) + req = AllnetPowerOnRequest(self.allnet_req_to_dict(request.content.getvalue())[0]) # Validate the request. Currently we only validate the fields we plan on using if not req.game_id or not req.ver or not req.token or not req.serial or not req.ip: @@ -151,7 +151,7 @@ class AllnetServlet: def handle_dlorder(self, request: Request, _: Dict): request_ip = request.getClientAddress().host try: - req = AllnetDownloadOrderRequest(self.billing_req_to_dict(request.content.getvalue())) + req = AllnetDownloadOrderRequest(self.billing_req_to_dict(request.content.getvalue())[0]) # Validate the request. Currently we only validate the fields we plan on using if not req.game_id or not req.ver or not req.token or not req.serial or not req.ip: From a843e3d3ac1e67f66fc483272a77c939f40cba95 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:40:19 -0500 Subject: [PATCH 07/13] added token replacement --- core/allnet.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/allnet.py b/core/allnet.py index 49b7828..b528295 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -142,11 +142,15 @@ class AllnetServlet: req.region_name2 = arcade["city"] req.client_timezone = arcade["timezone"] if arcade["timezone"] is not None else "+0900" + int_ver = req.ver.replace(".", "") + req.uri = req.uri.replace("$v", int_ver) + req.host = req.host.replace("$v", int_ver) + msg = f"{req.serial} authenticated from {request_ip}: {req.game_id} v{req.ver}" self.data.base.log_event("allnet", "ALLNET_AUTH_SUCCESS", logging.INFO, msg) self.logger.info(msg) - return self.dict_to_http_form_string([vars(resp)]) + return self.dict_to_http_form_string([vars(resp)]).encode("utf-8") def handle_dlorder(self, request: Request, _: Dict): request_ip = request.getClientAddress().host From a3c689cd0931e01ae99f2b63b947a58dea85e383 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:42:27 -0500 Subject: [PATCH 08/13] fix using the request instead of the response --- core/allnet.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index b528295..9d59c2e 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -131,20 +131,20 @@ class AllnetServlet: if machine is not None: arcade = self.data.arcade.get_arcade(machine["arcade"]) - req.country = arcade["country"] if machine["country"] is None else machine["country"] - req.place_id = arcade["id"] - req.allnet_id = machine["id"] - req.name = arcade["name"] - req.nickname = arcade["nickname"] - req.region0 = arcade["region_id"] - req.region_name0 = arcade["country"] - req.region_name1 = arcade["state"] - req.region_name2 = arcade["city"] - req.client_timezone = arcade["timezone"] if arcade["timezone"] is not None else "+0900" + resp.country = arcade["country"] if machine["country"] is None else machine["country"] + resp.place_id = arcade["id"] + resp.allnet_id = machine["id"] + resp.name = arcade["name"] + resp.nickname = arcade["nickname"] + resp.region0 = arcade["region_id"] + resp.region_name0 = arcade["country"] + resp.region_name1 = arcade["state"] + resp.region_name2 = arcade["city"] + resp.client_timezone = arcade["timezone"] if arcade["timezone"] is not None else "+0900" int_ver = req.ver.replace(".", "") - req.uri = req.uri.replace("$v", int_ver) - req.host = req.host.replace("$v", int_ver) + resp.uri = resp.uri.replace("$v", int_ver) + resp.host = resp.host.replace("$v", int_ver) msg = f"{req.serial} authenticated from {request_ip}: {req.game_id} v{req.ver}" self.data.base.log_event("allnet", "ALLNET_AUTH_SUCCESS", logging.INFO, msg) @@ -227,7 +227,7 @@ class AllnetServlet: resp = BillingResponse(playlimit, playlimit_sig, nearfull, nearfull_sig) - resp_str = self.dict_to_http_form_string([vars(resp)]) + resp_str = self.dict_to_http_form_string([vars(resp)], True) if resp_str is None: self.logger.error(f"Failed to parse response {vars(resp)}") From ed479866cc8fbc6966f9e5c424a03fd6beffc65e Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sat, 18 Feb 2023 23:57:45 -0500 Subject: [PATCH 09/13] fix download order --- core/allnet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/allnet.py b/core/allnet.py index 9d59c2e..b32b7f7 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -155,7 +155,7 @@ class AllnetServlet: def handle_dlorder(self, request: Request, _: Dict): request_ip = request.getClientAddress().host try: - req = AllnetDownloadOrderRequest(self.billing_req_to_dict(request.content.getvalue())[0]) + req = AllnetDownloadOrderRequest(self.allnet_req_to_dict(request.content.getvalue())[0]) # Validate the request. Currently we only validate the fields we plan on using if not req.game_id or not req.ver or not req.token or not req.serial or not req.ip: From f5d9bd8003cb07ae3ad72188f8700951730b2c48 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 19 Feb 2023 00:01:39 -0500 Subject: [PATCH 10/13] fix copypasta code --- core/allnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index b32b7f7..9aea93e 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -158,8 +158,8 @@ class AllnetServlet: req = AllnetDownloadOrderRequest(self.allnet_req_to_dict(request.content.getvalue())[0]) # Validate the request. Currently we only validate the fields we plan on using - if not req.game_id or not req.ver or not req.token or not req.serial or not req.ip: - raise AllnetRequestException(f"Bad auth request params from {request_ip} - {vars(req)}") + if not req.game_id or not req.ver or not req.serial: + raise AllnetRequestException(f"Bad download request params from {request_ip} - {vars(req)}") except AllnetRequestException as e: self.logger.error(e) From d434bf084d95e76c90b45bd51a3a145abdcbc46b Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 19 Feb 2023 00:06:21 -0500 Subject: [PATCH 11/13] fix sending incorrect params to dict_to_http_form_string --- core/allnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 9aea93e..08f636a 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -167,10 +167,10 @@ class AllnetServlet: resp = AllnetDownloadOrderResponse() if not self.config.allnet.allow_online_updates: - return self.dict_to_http_form_string(vars(resp)) + return self.dict_to_http_form_string([vars(resp)]) else: # TODO: Actual dlorder response - return self.dict_to_http_form_string(vars(resp)) + return self.dict_to_http_form_string([vars(resp)]) def handle_billing_request(self, request: Request, _: Dict): req_dict = self.billing_req_to_dict(request.content.getvalue()) From a57d2cf71c04cc9b5efb943db1b44ea49b956ef4 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 19 Feb 2023 00:07:14 -0500 Subject: [PATCH 12/13] fix typo in aimedb --- core/aimedb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/aimedb.py b/core/aimedb.py index b8ce3b7..78ce350 100644 --- a/core/aimedb.py +++ b/core/aimedb.py @@ -164,7 +164,7 @@ class AimedbProtocol(Protocol): def handle_register(self, data: bytes) -> bytes: luid = data[0x20: 0x2a].hex() - if self.config.server.allow_registration: + if self.config.server.allow_user_registration: user_id = self.data.user.create_user() if user_id is None: From df4efa1fda20f0c2a64dbbbf188f57cdb09153ac Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Sun, 19 Feb 2023 00:10:42 -0500 Subject: [PATCH 13/13] replace print statements with error logging --- core/allnet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/allnet.py b/core/allnet.py index 08f636a..bd2ecce 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -261,7 +261,7 @@ class AllnetServlet: return self.kvp_to_dict(sections) except Exception as e: - print(e) + self.logger.error(e) return None def allnet_req_to_dict(self, data: str) -> Optional[List[Dict[str, Any]]]: @@ -276,7 +276,7 @@ class AllnetServlet: return self.kvp_to_dict(sections) except Exception as e: - print(e) + self.logger.error(e) return None def dict_to_http_form_string(self, data:List[Dict[str, Any]], crlf: bool = False, trailing_newline: bool = True) -> Optional[str]: @@ -303,7 +303,7 @@ class AllnetServlet: return urlencode except Exception as e: - print(e) + self.logger.error(e) return None class AllnetPowerOnRequest():