From 0580d77ecba37ac032dde3e3d8d7b054ccc7fd74 Mon Sep 17 00:00:00 2001 From: Jeremy Stanley Date: Sun, 14 May 2017 16:42:55 +0000 Subject: [PATCH] Guard against KeyError on universe.contents index When accessing base level configuration elements from the main engine, check that they're actually in universe.contents before trying to retrieve their facets. Also use sane default fallbacks if they're undefined. --- mudpy/data.py | 6 +++-- mudpy/misc.py | 78 +++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/mudpy/data.py b/mudpy/data.py index d7de13a..2e22c7e 100644 --- a/mudpy/data.py +++ b/mudpy/data.py @@ -134,9 +134,11 @@ class DataFile: if "__control__" in self.data and "backup_count" in self.data[ "__control__"]: max_count = self.data["__control__"]["backup_count"] - else: + elif "mudpy.limit" in self.universe.contents: max_count = self.universe.contents["mudpy.limit"].get( - "backups") + "backups", 0) + else: + max_count = 0 if os.path.exists(self.filename) and max_count: backups = [] for candidate in os.listdir(os.path.dirname(self.filename)): diff --git a/mudpy/misc.py b/mudpy/misc.py index 3cb201c..2923feb 100644 --- a/mudpy/misc.py +++ b/mudpy/misc.py @@ -651,8 +651,8 @@ class User: if self.state is not "authenticated": log("User " + self.account.get("name") + " logged in.", 2) self.authenticated = True - if self.account.subkey in universe.contents["mudpy.limit"].get( - "admins"): + if ("mudpy.limit" in universe.contents and self.account.subkey in + universe.contents["mudpy.limit"].get("admins")): self.account.set("administrator", "True") def show_menu(self): @@ -974,9 +974,14 @@ def log(message, level=0): """Log a message.""" # a couple references we need - file_name = universe.contents["mudpy.log"].get("file") - max_log_lines = universe.contents["mudpy.log"].get("lines") - syslog_name = universe.contents["mudpy.log"].get("syslog") + if "mudpy.log" in universe.contents: + file_name = universe.contents["mudpy.log"].get("file", "") + max_log_lines = universe.contents["mudpy.log"].get("lines", 0) + syslog_name = universe.contents["mudpy.log"].get("syslog", "") + else: + file_name = "" + max_log_lines = 0 + syslog_name = "" timestamp = time.asctime()[4:19] # turn the message into a list of nonempty lines @@ -993,7 +998,8 @@ def log(message, level=0): file_descriptor.close() # send the timestamp and line to standard output - if universe.contents["mudpy.log"].get("stdout"): + if ("mudpy.log" in universe.contents and + universe.contents["mudpy.log"].get("stdout")): for line in lines: print(timestamp + " " + line) @@ -1710,6 +1716,12 @@ def handler_checking_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # does the hashed input equal the stored hash? if mudpy.password.verify(input_data, user.account.get("passhash")): @@ -1719,8 +1731,7 @@ def handler_checking_password(user): user.state = "main_utility" # if at first your hashes don't match, try, try again - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "incorrect" @@ -1738,6 +1749,12 @@ def handler_entering_new_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # make sure the password is strong--at least one upper, one lower and # one digit, seven or more characters in length if len(input_data) > 6 and len( @@ -1753,8 +1770,7 @@ def handler_entering_new_password(user): user.state = "verifying_new_password" # the password was weak, try again if you haven't tried too many times - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "weak" @@ -1773,6 +1789,12 @@ def handler_verifying_new_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # hash the input and match it to storage if mudpy.password.verify(input_data, user.account.get("passhash")): user.authenticate() @@ -1783,8 +1805,7 @@ def handler_verifying_new_password(user): # go back to entering the new password as long as you haven't tried # too many times - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "differs" user.state = "entering_new_password" @@ -1998,12 +2019,13 @@ def command_say(actor, parameters): if message: # match the punctuation used, if any, to an action - actions = universe.contents["mudpy.linguistic"].get( - "actions" - ) - default_punctuation = ( - universe.contents["mudpy.linguistic"].get( - "default_punctuation")) + if "mudpy.linguistic" in universe.contents: + actions = universe.contents["mudpy.linguistic"].get("actions", {}) + default_punctuation = (universe.contents["mudpy.linguistic"].get( + "default_punctuation", ".")) + else: + actions = {} + default_punctuation = "." action = "" # reverse sort punctuation options so the longest match wins @@ -2027,9 +2049,10 @@ def command_say(actor, parameters): message = message[0].lower() + message[1:] # iterate over all words in message, replacing typos - typos = universe.contents["mudpy.linguistic"].get( - "typos" - ) + if "mudpy.linguistic" in universe.contents: + typos = universe.contents["mudpy.linguistic"].get("typos", {}) + else: + typos = {} words = message.split() for index in range(len(words)): word = words[index] @@ -2313,7 +2336,8 @@ def daemonize(universe): """Fork and disassociate from everything.""" # only if this is what we're configured to do - if universe.contents["mudpy.process"].get("daemon"): + if "mudpy.process" in universe.contents and universe.contents[ + "mudpy.process"].get("daemon"): # log before we start forking around, so the terminal gets the message log("Disassociating from the controlling terminal.") @@ -2350,7 +2374,10 @@ def create_pidfile(universe): """Write a file containing the current process ID.""" pid = str(os.getpid()) log("Process ID: " + pid) - file_name = universe.contents["mudpy.process"].get("pidfile") + if "mudpy.process" in universe.contents: + file_name = universe.contents["mudpy.process"].get("pidfile", "") + else: + file_name = "" if file_name: if not os.path.isabs(file_name): file_name = os.path.join(universe.startdir, file_name) @@ -2362,7 +2389,10 @@ def create_pidfile(universe): def remove_pidfile(universe): """Remove the file containing the current process ID.""" - file_name = universe.contents["mudpy.process"].get("pidfile") + if "mudpy.process" in universe.contents: + file_name = universe.contents["mudpy.process"].get("pidfile", "") + else: + file_name = "" if file_name: if not os.path.isabs(file_name): file_name = os.path.join(universe.startdir, file_name) -- 2.11.0