diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py index a9247ace..1534e872 100644 --- a/app/classes/web/ajax_handler.py +++ b/app/classes/web/ajax_handler.py @@ -12,12 +12,14 @@ import os import shutil import html import re +from app.classes.models.users import helper_users from app.classes.shared.console import console from app.classes.shared.main_models import Users, installer from app.classes.web.base_handler import BaseHandler from app.classes.shared.helpers import helper from app.classes.shared.server import ServerOutBuf +from app.classes.models.server_permissions import Enum_Permissions_Server logger = logging.getLogger(__name__) @@ -133,6 +135,20 @@ class AjaxHandler(BaseHandler): @tornado.web.authenticated def post(self, page): user_data = json.loads(self.get_secure_cookie("user_data")) + server_id = self.get_argument('id', None) + exec_user_id = user_data['user_id'] + exec_user = helper_users.get_user(exec_user_id) + permissions = { + 'Commands': Enum_Permissions_Server.Commands, + 'Terminal': Enum_Permissions_Server.Terminal, + 'Logs': Enum_Permissions_Server.Logs, + 'Schedule': Enum_Permissions_Server.Schedule, + 'Backup': Enum_Permissions_Server.Backup, + 'Files': Enum_Permissions_Server.Files, + 'Config': Enum_Permissions_Server.Config, + 'Players': Enum_Permissions_Server.Players, + } + user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) error = bleach.clean(self.get_argument('error', "WTF Error!")) page_data = { @@ -157,6 +173,10 @@ class AjaxHandler(BaseHandler): self.controller.management.add_to_audit_log(user_data['user_id'], "Sent command to {} terminal: {}".format(self.controller.servers.get_server_friendly_name(server_id), command), server_id, self.get_remote_ip()) elif page == "create_file": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return file_parent = helper.get_os_understandable_path(self.get_body_argument('file_parent', default=None, strip=True)) file_name = self.get_body_argument('file_name', default=None, strip=True) file_path = os.path.join(file_parent, file_name) @@ -176,6 +196,10 @@ class AjaxHandler(BaseHandler): file_object.close() elif page == "create_dir": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return dir_parent = helper.get_os_understandable_path(self.get_body_argument('dir_parent', default=None, strip=True)) dir_name = self.get_body_argument('dir_name', default=None, strip=True) dir_path = os.path.join(dir_parent, dir_name) @@ -193,6 +217,10 @@ class AjaxHandler(BaseHandler): os.mkdir(dir_path) elif page == "unzip_file": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return server_id = self.get_argument('id', None) path = helper.get_os_understandable_path(self.get_argument('path', None)) helper.unzipFile(path) @@ -200,6 +228,10 @@ class AjaxHandler(BaseHandler): return elif page == "kill": + if not permissions['Commands'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Commands") + return server_id = self.get_argument('id', None) svr = self.controller.get_server_obj(server_id) try: @@ -213,6 +245,10 @@ class AjaxHandler(BaseHandler): svr.agree_eula(user_data['user_id']) elif page == "restore_backup": + if not permissions['Backup'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Backups") + return server_id = bleach.clean(self.get_argument('id', None)) zip_name = bleach.clean(self.get_argument('zip_file', None)) svr_obj = self.controller.servers.get_server_obj(server_id) @@ -229,7 +265,51 @@ class AjaxHandler(BaseHandler): @tornado.web.authenticated def delete(self, page): + user_data = json.loads(self.get_secure_cookie("user_data")) + server_id = self.get_argument('id', None) + exec_user_id = user_data['user_id'] + exec_user = helper_users.get_user(exec_user_id) + permissions = { + 'Commands': Enum_Permissions_Server.Commands, + 'Terminal': Enum_Permissions_Server.Terminal, + 'Logs': Enum_Permissions_Server.Logs, + 'Schedule': Enum_Permissions_Server.Schedule, + 'Backup': Enum_Permissions_Server.Backup, + 'Files': Enum_Permissions_Server.Files, + 'Config': Enum_Permissions_Server.Config, + 'Players': Enum_Permissions_Server.Players, + } + user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) if page == "del_file": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return + file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True)) + server_id = self.get_argument('id', None) + + console.warning("delete {} for server {}".format(file_path, server_id)) + + if not self.check_server_id(server_id, 'del_file'): + return + else: server_id = bleach.clean(server_id) + + server_info = self.controller.servers.get_server_data_by_id(server_id) + if not (helper.in_path(helper.get_os_understandable_path(server_info['path']), file_path) \ + or helper.in_path(helper.get_os_understandable_path(server_info['backup_path']), file_path)) \ + or not helper.check_file_exists(os.path.abspath(file_path)): + logger.warning("Invalid path in del_file ajax call ({})".format(file_path)) + console.warning("Invalid path in del_file ajax call ({})".format(file_path)) + return + + # Delete the file + os.remove(file_path) + + if page == "del_backup": + if not permissions['Backup'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Backups") + return file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True)) server_id = self.get_argument('id', None) @@ -251,6 +331,10 @@ class AjaxHandler(BaseHandler): os.remove(file_path) elif page == "del_dir": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return dir_path = helper.get_os_understandable_path(self.get_body_argument('dir_path', default=None, strip=True)) server_id = self.get_argument('id', None) @@ -271,12 +355,20 @@ class AjaxHandler(BaseHandler): shutil.rmtree(dir_path) # Removes also when there are contents elif page == "delete_server": + if not permissions['Config'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Config") + return server_id = self.get_argument('id', None) logger.info( "Removing server from panel for server: {}".format(self.controller.servers.get_server_friendly_name(server_id))) self.controller.remove_server(server_id, False) elif page == "delete_server_files": + if not permissions['Config'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Config") + return server_id = self.get_argument('id', None) logger.info( "Removing server and all associated files for server: {}".format(self.controller.servers.get_server_friendly_name(server_id))) @@ -284,7 +376,26 @@ class AjaxHandler(BaseHandler): @tornado.web.authenticated def put(self, page): + user_data = json.loads(self.get_secure_cookie("user_data")) + server_id = self.get_argument('id', None) + exec_user_id = user_data['user_id'] + exec_user = helper_users.get_user(exec_user_id) + permissions = { + 'Commands': Enum_Permissions_Server.Commands, + 'Terminal': Enum_Permissions_Server.Terminal, + 'Logs': Enum_Permissions_Server.Logs, + 'Schedule': Enum_Permissions_Server.Schedule, + 'Backup': Enum_Permissions_Server.Backup, + 'Files': Enum_Permissions_Server.Files, + 'Config': Enum_Permissions_Server.Config, + 'Players': Enum_Permissions_Server.Players, + } + user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) if page == "save_file": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return file_contents = self.get_body_argument('file_contents', default=None, strip=True) file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True)) server_id = self.get_argument('id', None) @@ -303,6 +414,10 @@ class AjaxHandler(BaseHandler): file_object.write(file_contents) elif page == "rename_item": + if not permissions['Files'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Files") + return item_path = helper.get_os_understandable_path(self.get_body_argument('item_path', default=None, strip=True)) new_item_name = self.get_body_argument('new_item_name', default=None, strip=True) server_id = self.get_argument('id', None) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index ee58da19..924862fe 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -213,39 +213,45 @@ class PanelHandler(BaseHandler): 'Players': Enum_Permissions_Server.Players, } page_data['user_permissions'] = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) - user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) if subpage == 'term': if not page_data['permissions']['Terminal'] in page_data['user_permissions']: if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access to Terminal") + return if subpage == 'logs': if not page_data['permissions']['Logs'] in page_data['user_permissions']: if not exec_user['superuser']: - self.redirect("/panel/error?error=Unauthorized access to Logs") + self.redirect("/panel/error?error=Unauthorized access to Logs") + return if subpage == 'tasks': if not page_data['permissions']['Schedule'] in page_data['user_permissions']: if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access To Scheduled Tasks") + return + page_data[''] if subpage == 'config': if not page_data['permissions']['Config'] in page_data['user_permissions']: if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access Server Config") + return if subpage == 'files': if not page_data['permissions']['Files'] in page_data['user_permissions']: if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access Files") + return if subpage == "backup": if not page_data['permissions']['Backup'] in page_data['user_permissions']: if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access to Backups") + return server_info = self.controller.servers.get_server_data_by_id(server_id) page_data['backup_config'] = self.controller.management.get_backup_config(server_id) self.controller.refresh_server_settings(server_id) @@ -647,7 +653,18 @@ class PanelHandler(BaseHandler): exec_user_data = json.loads(self.get_secure_cookie("user_data")) exec_user_id = exec_user_data['user_id'] exec_user = self.controller.users.get_user_by_id(exec_user_id) - + server_id = self.get_argument('id', None) + permissions = { + 'Commands': Enum_Permissions_Server.Commands, + 'Terminal': Enum_Permissions_Server.Terminal, + 'Logs': Enum_Permissions_Server.Logs, + 'Schedule': Enum_Permissions_Server.Schedule, + 'Backup': Enum_Permissions_Server.Backup, + 'Files': Enum_Permissions_Server.Files, + 'Config': Enum_Permissions_Server.Config, + 'Players': Enum_Permissions_Server.Players, + } + user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id) exec_user_role = set() if exec_user['superuser'] == 1: defined_servers = self.controller.list_defined_servers() @@ -661,17 +678,26 @@ class PanelHandler(BaseHandler): exec_user_role.add(role['role_name']) if page == 'server_detail': + if not permissions['Config'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access to Config") + return server_id = self.get_argument('id', None) server_name = self.get_argument('server_name', None) - server_path = self.get_argument('server_path', None) - log_path = self.get_argument('log_path', None) - executable = self.get_argument('executable', None) - execution_command = self.get_argument('execution_command', None) + server_obj = self.controller.servers.get_server_obj(server_id) + if exec_user['superuser']: + server_path = self.get_argument('server_path', None) + log_path = self.get_argument('log_path', None) + executable = self.get_argument('executable', None) + execution_command = self.get_argument('execution_command', None) + server_ip = self.get_argument('server_ip', None) + server_port = self.get_argument('server_port', None) + executable_update_url = self.get_argument('executable_update_url', None) + else: + execution_command = server_obj.execution_command + executable = server_obj.executable stop_command = self.get_argument('stop_command', None) auto_start_delay = self.get_argument('auto_start_delay', '10') - server_ip = self.get_argument('server_ip', None) - server_port = self.get_argument('server_port', None) - executable_update_url = self.get_argument('executable_update_url', None) auto_start = int(float(self.get_argument('auto_start', '0'))) crash_detection = int(float(self.get_argument('crash_detection', '0'))) logs_delete_after = int(float(self.get_argument('logs_delete_after', '0'))) @@ -705,10 +731,19 @@ class PanelHandler(BaseHandler): if helper.validate_traversal(helper.get_servers_root_dir(), executable): server_obj.executable = executable server_obj.execution_command = execution_command - server_obj.stop_command = stop_command server_obj.server_ip = server_ip server_obj.server_port = server_port server_obj.executable_update_url = executable_update_url + else: + server_obj.path = server_obj.path + server_obj.log_path = server_obj.log_path + server_obj.executable = server_obj.executable + print(server_obj.execution_command) + server_obj.execution_command = server_obj.execution_command + server_obj.server_ip = server_obj.server_ip + server_obj.server_port = server_obj.server_port + server_obj.executable_update_url = server_obj.executable_update_url + server_obj.stop_command = stop_command server_obj.auto_start_delay = auto_start_delay server_obj.auto_start = auto_start server_obj.crash_detection = crash_detection @@ -727,15 +762,20 @@ class PanelHandler(BaseHandler): if page == "server_backup": logger.debug(self.request.arguments) server_id = self.get_argument('id', None) - backup_path = bleach.clean(self.get_argument('backup_path', None)) + server_obj = self.controller.servers.get_server_obj(server_id) + if exec_user['superuser']: + backup_path = bleach.clean(self.get_argument('backup_path', None)) + else: + backup_path = server_obj.backup_path max_backups = bleach.clean(self.get_argument('max_backups', None)) try: enabled = int(float(bleach.clean(self.get_argument('auto_enabled'), '0'))) except Exception as e: enabled = '0' - if not exec_user['superuser']: - self.redirect("/panel/error?error=Unauthorized access: not superuser") + if not permissions['Backup'] in user_perms: + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: User not authorized") return elif server_id is None: self.redirect("/panel/error?error=Invalid Server ID") diff --git a/app/frontend/templates/panel/server_backup.html b/app/frontend/templates/panel/server_backup.html index 11fb1acf..f44f892a 100644 --- a/app/frontend/templates/panel/server_backup.html +++ b/app/frontend/templates/panel/server_backup.html @@ -157,7 +157,7 @@ $.ajax({ type: "DELETE", headers: {'X-XSRFToken': token}, - url: '/ajax/del_file?server_id='+id, + url: '/ajax/del_backup?server_id='+id, data: { file_path: filename, id: id diff --git a/main.py b/main.py index 7d812ab4..48209794 100644 --- a/main.py +++ b/main.py @@ -144,9 +144,10 @@ if __name__ == '__main__': console.info("Checking Internet/Port Service. This may take a minute.") if not helper.check_internet(): - console.error("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.") + console.warning("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.") elif not helper.check_port(helper.get_setting('https_port')): - console.error("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port'))) + console.warning("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port'))) + console.help("If you are not forwarding ports from your public IP or your router does not support hairpin NAT you can safely disregard the previous message.") Crafty = MainPrompt(tasks_manager, migration_manager)