Added option to "lock" server using global password. Users won't be able to register.

This commit is contained in:
samo_lego 2020-02-17 18:51:23 +01:00
parent 7934c1242b
commit 322c3ad00b
7 changed files with 87 additions and 26 deletions

View File

@ -6,6 +6,8 @@ import net.fabricmc.fabric.api.event.server.ServerStopCallback;
import net.fabricmc.fabric.api.registry.CommandRegistry; import net.fabricmc.fabric.api.registry.CommandRegistry;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.samo_lego.simpleauth.commands.*; import org.samo_lego.simpleauth.commands.*;
@ -31,7 +33,6 @@ public class SimpleAuth implements DedicatedServerModInitializer {
// Mod config // Mod config
public static AuthConfig config; public static AuthConfig config;
@Override @Override
public void onInitializeServer() { public void onInitializeServer() {
// Info I guess :D // Info I guess :D
@ -76,4 +77,11 @@ public class SimpleAuth implements DedicatedServerModInitializer {
LOGGER.info("[SimpleAuth] Shutting down SimpleAuth."); LOGGER.info("[SimpleAuth] Shutting down SimpleAuth.");
db.close(); db.close();
} }
public static void authenticatePlayer(ServerPlayerEntity player, Text msg) {
SimpleAuth.deauthenticatedUsers.remove(player);
// Player no longer needs to be invisible and invulnerable
player.setInvulnerable(false);
player.setInvisible(false);
player.sendMessage(msg);
}
} }

View File

@ -24,6 +24,7 @@ public class AuthCommand {
private static Text userdataDeleted = new LiteralText(SimpleAuth.config.lang.userdataDeleted); private static Text userdataDeleted = new LiteralText(SimpleAuth.config.lang.userdataDeleted);
private static Text userdataUpdated = new LiteralText(SimpleAuth.config.lang.userdataUpdated); private static Text userdataUpdated = new LiteralText(SimpleAuth.config.lang.userdataUpdated);
private static Text configurationReloaded = new LiteralText(SimpleAuth.config.lang.configurationReloaded); private static Text configurationReloaded = new LiteralText(SimpleAuth.config.lang.configurationReloaded);
private static Text globalPasswordSet = new LiteralText(SimpleAuth.config.lang.globalPasswordSet);
public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) { public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) {
// Registering the "/auth" command // Registering the "/auth" command
@ -32,6 +33,14 @@ public class AuthCommand {
.then(literal("reload") .then(literal("reload")
.executes( ctx -> reloadConfig(ctx.getSource())) .executes( ctx -> reloadConfig(ctx.getSource()))
) )
.then(literal("setGlobalPassword")
.then(argument("password", word())
.executes( ctx -> setGlobalPassword(
ctx.getSource(),
getString(ctx, "password")
))
)
)
.then(literal("update") .then(literal("update")
.then(literal("byUuid") .then(literal("byUuid")
.then(argument("uuid", word()) .then(argument("uuid", word())
@ -80,6 +89,20 @@ public class AuthCommand {
) )
); );
} }
private static int setGlobalPassword(ServerCommandSource source, String pass) {
// Getting the player who send the command
Entity sender = source.getEntity();
// Writing the global pass to config
SimpleAuth.config.main.globalPassword = AuthHelper.hashPass(pass.toCharArray());
SimpleAuth.config.save(new File("./mods/SimpleAuth/config.json"));
if(sender != null)
sender.sendMessage(globalPasswordSet);
else
LOGGER.info(globalPasswordSet);
return 1;
}
// Method called for checking the password // Method called for checking the password
private static int updatePass(ServerCommandSource source, String uuid, String username, String pass) { private static int updatePass(ServerCommandSource source, String uuid, String username, String pass) {

View File

@ -18,7 +18,7 @@ public class LoginCommand {
private static Text enterPassword = new LiteralText(SimpleAuth.config.lang.enterPassword); private static Text enterPassword = new LiteralText(SimpleAuth.config.lang.enterPassword);
private static Text wrongPassword = new LiteralText(SimpleAuth.config.lang.wrongPassword); private static Text wrongPassword = new LiteralText(SimpleAuth.config.lang.wrongPassword);
private static Text alreadyAuthenticated = new LiteralText(SimpleAuth.config.lang.alreadyAuthenticated); private static Text alreadyAuthenticated = new LiteralText(SimpleAuth.config.lang.alreadyAuthenticated);
private static Text loginTriesExceeded = new LiteralText("§4Too many login tries."); //private static Text loginTriesExceeded = new LiteralText("§4Too many login tries.");
private static Text successfullyAuthenticated = new LiteralText(SimpleAuth.config.lang.successfullyAuthenticated); private static Text successfullyAuthenticated = new LiteralText(SimpleAuth.config.lang.successfullyAuthenticated);
public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) { public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) {
@ -37,16 +37,16 @@ public class LoginCommand {
private static int login(ServerCommandSource source, String pass) throws CommandSyntaxException { private static int login(ServerCommandSource source, String pass) throws CommandSyntaxException {
// Getting the player who send the command // Getting the player who send the command
ServerPlayerEntity player = source.getPlayer(); ServerPlayerEntity player = source.getPlayer();
if(SimpleAuth.isAuthenticated(player)) { if(SimpleAuth.config.main.enableGlobalPassword && AuthHelper.checkPass("globalPass", pass.toCharArray())) {
SimpleAuth.authenticatePlayer(player, successfullyAuthenticated);
return 1;
}
else if(SimpleAuth.isAuthenticated(player)) {
player.sendMessage(alreadyAuthenticated); player.sendMessage(alreadyAuthenticated);
return 0; return 0;
} }
else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray())) { else if (AuthHelper.checkPass(player.getUuidAsString(), pass.toCharArray())) {
SimpleAuth.deauthenticatedUsers.remove(player); SimpleAuth.authenticatePlayer(player, successfullyAuthenticated);
// Player no longer needs to be invisible and invulnerable
player.setInvulnerable(false);
player.setInvisible(false);
player.sendMessage(successfullyAuthenticated);
return 1; return 1;
} }
player.networkHandler.disconnect(wrongPassword); player.networkHandler.disconnect(wrongPassword);

View File

@ -7,6 +7,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.samo_lego.simpleauth.SimpleAuth; import org.samo_lego.simpleauth.SimpleAuth;
import org.samo_lego.simpleauth.utils.AuthConfig;
import org.samo_lego.simpleauth.utils.AuthHelper; import org.samo_lego.simpleauth.utils.AuthHelper;
import static com.mojang.brigadier.arguments.StringArgumentType.getString; import static com.mojang.brigadier.arguments.StringArgumentType.getString;
@ -21,6 +22,7 @@ public class RegisterCommand {
private static Text alreadyRegistered = new LiteralText(SimpleAuth.config.lang.alreadyRegistered); private static Text alreadyRegistered = new LiteralText(SimpleAuth.config.lang.alreadyRegistered);
private static Text registerSuccess = new LiteralText(SimpleAuth.config.lang.registerSuccess); private static Text registerSuccess = new LiteralText(SimpleAuth.config.lang.registerSuccess);
private static Text matchPass = new LiteralText( SimpleAuth.config.lang.matchPassword); private static Text matchPass = new LiteralText( SimpleAuth.config.lang.matchPassword);
private static Text globalPasswordRequired = new LiteralText( SimpleAuth.config.lang.globalPasswordRequired);
public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) { public static void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher) {
@ -39,18 +41,18 @@ public class RegisterCommand {
// Method called for hashing the password & writing to DB // Method called for hashing the password & writing to DB
private static int register(ServerCommandSource source, String pass1, String pass2) throws CommandSyntaxException { private static int register(ServerCommandSource source, String pass1, String pass2) throws CommandSyntaxException {
ServerPlayerEntity player = source.getPlayer(); ServerPlayerEntity player = source.getPlayer();
if(SimpleAuth.isAuthenticated(player)) { if(SimpleAuth.config.main.enableGlobalPassword) {
player.sendMessage(globalPasswordRequired);
return 0;
}
else if(SimpleAuth.isAuthenticated(player)) {
player.sendMessage(alreadyAuthenticated); player.sendMessage(alreadyAuthenticated);
return 0; return 0;
} }
else if(pass1.equals(pass2)) { else if(pass1.equals(pass2)) {
String hash = AuthHelper.hashPass(pass1.toCharArray()); String hash = AuthHelper.hashPass(pass1.toCharArray());
if (SimpleAuth.db.registerUser(player.getUuidAsString(), source.getName(), hash)) { if (SimpleAuth.db.registerUser(player.getUuidAsString(), source.getName(), hash)) {
SimpleAuth.deauthenticatedUsers.remove(player); SimpleAuth.authenticatePlayer(player, registerSuccess);
// Player no longer needs to be invisible and invulnerable
player.setInvulnerable(false);
player.setInvisible(false);
player.sendMessage(registerSuccess);
return 1; return 1;
} }
player.sendMessage(alreadyRegistered); player.sendMessage(alreadyRegistered);

View File

@ -2,6 +2,7 @@ package org.samo_lego.simpleauth.event;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.packet.ChatMessageC2SPacket; import net.minecraft.server.network.packet.ChatMessageC2SPacket;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
@ -24,6 +25,9 @@ public class AuthEventHandler {
// Player joining the server // Player joining the server
public static void onPlayerJoin(ServerPlayerEntity player) { public static void onPlayerJoin(ServerPlayerEntity player) {
SimpleAuth.deauthenticatedUsers.add(player); SimpleAuth.deauthenticatedUsers.add(player);
CompoundTag tag = new CompoundTag();
tag.putInt("loginTries", 0);
player.writeCustomDataToTag(tag);
// Player not authenticated // Player not authenticated
// If clause actually not needed, since we add player to deauthenticated hashset above // If clause actually not needed, since we add player to deauthenticated hashset above
if (!SimpleAuth.isAuthenticated(player)) { if (!SimpleAuth.isAuthenticated(player)) {

View File

@ -52,6 +52,13 @@ public class AuthConfig {
public boolean playerInvisible = true; public boolean playerInvisible = true;
// Time after which player will be kicked if not authenticated - in seconds // Time after which player will be kicked if not authenticated - in seconds
public int delay = 60; public int delay = 60;
// Disables registering and forces logging in with global password
public boolean enableGlobalPassword = false;
/* If above is true, the global password can be set with command:
`/auth setGlobalPassword <pass>`
Password will be hashed and saved.
*/
public String globalPassword = null;
} }
public static class LangConfig { public static class LangConfig {
public String enterPassword = "§6You need to enter your password!"; public String enterPassword = "§6You need to enter your password!";
@ -59,6 +66,8 @@ public class AuthConfig {
public String wrongPassword = "§4Wrong password!"; public String wrongPassword = "§4Wrong password!";
public String matchPassword = "§6Passwords must match!"; public String matchPassword = "§6Passwords must match!";
public String passwordUpdated = "§4Your password was updated successfully!"; public String passwordUpdated = "§4Your password was updated successfully!";
public String globalPasswordRequired = "§4Use /login <global password> to authenticate!";
public String globalPasswordSet = "§aGlobal password was successfully set!";
public String notAuthenticated = "§cYou are not authenticated!\n§6Try with /login or /register."; public String notAuthenticated = "§cYou are not authenticated!\n§6Try with /login or /register.";
public String alreadyAuthenticated = "§4You are already authenticated."; public String alreadyAuthenticated = "§4You are already authenticated.";
public String successfullyAuthenticated = "§aYou are now authenticated."; public String successfullyAuthenticated = "§aYou are now authenticated.";
@ -94,7 +103,7 @@ public class AuthConfig {
return config; return config;
} }
private void save(File file) { public void save(File file) {
try (FileWriter writer = new FileWriter(file)) { try (FileWriter writer = new FileWriter(file)) {
gson.toJson(this, writer); gson.toJson(this, writer);
} catch (IOException e) { } catch (IOException e) {

View File

@ -13,12 +13,26 @@ public class AuthHelper {
private static Argon2 argon2 = Argon2Factory.create(); private static Argon2 argon2 = Argon2Factory.create();
public static boolean checkPass(String uuid, char[] pass) { public static boolean checkPass(String uuid, char[] pass) {
if(uuid.equals("globalPass") && SimpleAuth.config.main.enableGlobalPassword) {
// We have global password enabled
try {
return argon2.verify(SimpleAuth.config.main.globalPassword, pass);
}
catch (Error e) {
LOGGER.error("[SimpleAuth] Argon2 error: " + e);
return false;
} finally {
// Wipe confidential data
argon2.wipeArray(pass);
}
}
else {
try { try {
// Hashed password from DB // Hashed password from DB
String hashed = SimpleAuth.db.getPassword(uuid); String hashed = SimpleAuth.db.getPassword(uuid);
// Verify password // Verify password
return argon2.verify(hashed, pass); return argon2.verify(hashed, pass);
} catch(Error e) { } catch (Error e) {
LOGGER.error("[SimpleAuth] error: " + e); LOGGER.error("[SimpleAuth] error: " + e);
return false; return false;
} finally { } finally {
@ -26,6 +40,7 @@ public class AuthHelper {
argon2.wipeArray(pass); argon2.wipeArray(pass);
} }
} }
}
// Hashing the password with the Argon2 power // Hashing the password with the Argon2 power
public static String hashPass(char[] pass) { public static String hashPass(char[] pass) {
try { try {