diff options
author | Dico200 <dico.karssiens@gmail.com> | 2015-04-17 00:10:21 +0200 |
---|---|---|
committer | Dico200 <dico.karssiens@gmail.com> | 2015-04-17 00:10:21 +0200 |
commit | 487375dd077e1c9a3b601699e209c3831a084065 (patch) | |
tree | cfe8a9fca7c3a9b3b98d155c48afed781ae710f5 /loginsecurity.py | |
parent | ab1087f210267b5f06bed7224ddc49db1518ac44 (diff) |
Added loginsecurity module
Added to make an easily adjustible version of LoginSecurity.
LoginSecurity does not (seem to) support name changes since it retrieves
the UUID used from a byte[] of "OfflinePlayer:<username>" which means
the UUID changes when a player changes their name. This should fix
/rmpass. It uses BCrypt. I'll test this on the dev server (hoping bcrypt
is installed)
Diffstat (limited to 'loginsecurity.py')
-rw-r--r-- | loginsecurity.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/loginsecurity.py b/loginsecurity.py new file mode 100644 index 0000000..6822ad9 --- /dev/null +++ b/loginsecurity.py @@ -0,0 +1,121 @@ +from helpers import * +from basecommands import simplecommand +import bcrypt +from time import time as now +import thread + + +wait_time = 60 #seconds +admin_perm = "utils.loginsecurity.admin" +min_pass_length = 6 + +run_kick_thread = True +blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent"] +passwords = open_json_file("loginpasswords", {}) + +#if passwords == None: (set default value to None ^^) +# Keep everyone from playing? (Insecure) + +withholdings = {} #pname : jointime + + +def save_passwords(): + save_json_file("loginpasswords", passwords) + + +def matches(password, user): + hashed = passwords.get(uid(user)) + return bcrypt.hashpw(password, hashed) == hashed + + +@simplecommand("login", + usage = "<password>", + description = "Logs you in if <password> matches your password.", + senderLimit = 0, + helpNoargs = True) +def login_command(sender, command, label, args): + password = " ".join(args) + if matches(password, sender): + del withholdings[sender.getName()] + return "&aLogged in successfully!" + return "&cInvalid password" + + +@simplecommand("register", + usage = "<password>", + description = "Registers you with <password>. Next time you join, log in with /login", + senderLimit = 0, + helpNoArgs = True) +def register_command(sender, command, label, args): + uuid = uid(sender) + if uuid in passwords: + return "&cYou are already registered!" + password = " ".join(args) + if len(password) < min_pass_length: + return "&cThe password has to be made up of at least 8 characters!" + hashed = bcrypt.hashpw(password, bcrypt.gensalt(16)) + passwords[uuid] = hashed + return "&cPassword set. Use /login <password> upon join." + + +@simplecommand("rmpass", + usage = "<password>", + description = "Removes your password if the password matches", + senderLimit = 0, + helpNoArgs = True) +def rmpass_command(sender, command, label, args): + password = " ".join(args) + if matches(password, sender): + del passwords[uuid(sender)] + return "&aPassword removed successfully. You will not be prompted anymore." + return "&cInvalid password" + + +@simplecommand("rmotherpass", + aliases = ["lacrmpass"], + usage = "<user>", + description = "Removes password of <user> and sends them a notification", + helpNoArgs = True) +def rmotherpass_command(sender, command, label, args): + user = server.getOfflinePlayer(args[0]) + if user: + del passwords[uid(user)] + runas(server.getConsoleSender(), colorify("mail send %s &cYour password was reset by a staff member. Use &o/register&c to set a new one.")) + return "&sPassword of %s reset successfully" % user.getName() + return "&cThat player could not be found" + + +@hook.event("player.PlayerJoinEvent", "highest") +def on_join(event): + user = event.getPlayer() + if get_id(user) in passwords: + withholdings[user.getName()] = now() + + +@hook.event("player.PlayerQuitEvent", "normal") +def on_quit(event): + del withholdings[event.getPlayer().getName()] + + +def kick_thread(): + wait_time_millis = wait_time * 1000 + while True: + if not run_kick_thread: + info("Exiting LoginSecurity kicking thread!") + thread.exit() + time.sleep(1) + moment = now() + for name, jointime in withholdings.iteritems(): + if moment - jointime > wait_time_millis: + server.getPlayer(name).kickPlayer(colorify("&cLogin timed out")) + + +thread.start_new_thread(kick_thread, ()) + +for blocked_event in blocked_events: + @hook.event(blocked_event, "low") + def on_blocked_event(event): + user = event.getPlayer() + if user.getName() in withholdings: + event.setCancelled(True) + msg(user, "&cYou have to log in first! Use /login <password>") |