complete login system for now, misc fixes

This commit is contained in:
Sen 2025-05-31 00:23:35 +02:00
parent 06a14ae645
commit a6c2695ccb
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
26 changed files with 460 additions and 210 deletions

View file

@ -15,7 +15,6 @@ import common.net.util.concurrent.Future;
import common.net.util.concurrent.GenericFutureListener; import common.net.util.concurrent.GenericFutureListener;
import common.network.IClientLoginHandler; import common.network.IClientLoginHandler;
import common.network.NetConnection; import common.network.NetConnection;
import common.network.NetHandler;
import common.network.PacketRegistry; import common.network.PacketRegistry;
import common.packet.LPacketChallenge; import common.packet.LPacketChallenge;
import common.packet.LPacketPassword; import common.packet.LPacketPassword;
@ -31,7 +30,7 @@ import common.packet.RPacketResponse;
import common.packet.RPacketServerConfig; import common.packet.RPacketServerConfig;
import common.util.EncryptUtil; import common.util.EncryptUtil;
public class ClientLoginHandler extends NetHandler implements IClientLoginHandler { public class ClientLoginHandler implements IClientLoginHandler {
private static enum LoginState { private static enum LoginState {
HANDSHAKE, CONFIRMING, CHALLENGE, ENCRYPTED, PROVING, AUTHENTICATING, DONE; HANDSHAKE, CONFIRMING, CHALLENGE, ENCRYPTED, PROVING, AUTHENTICATING, DONE;
} }

View file

@ -144,7 +144,7 @@ import common.world.Explosion;
import common.world.Weather; import common.world.Weather;
import common.world.World; import common.world.World;
public class ClientPlayer extends NetHandler implements IClientPlayer public class ClientPlayer implements IClientPlayer
{ {
/** /**
* The NetworkManager instance used to communicate with the server (used only by handlePlayerPosLook to update * The NetworkManager instance used to communicate with the server (used only by handlePlayerPosLook to update

View file

@ -8,7 +8,7 @@ import common.packet.RPacketRequestEncrypt;
import common.packet.RPacketResponse; import common.packet.RPacketResponse;
import common.packet.RPacketServerConfig; import common.packet.RPacketServerConfig;
public interface IClientLoginHandler { public interface IClientLoginHandler extends NetHandler {
void handleDisconnect(RPacketDisconnect packet); void handleDisconnect(RPacketDisconnect packet);
void handleLoginSuccess(RPacketLoginSuccess packet); void handleLoginSuccess(RPacketLoginSuccess packet);
void handleEnableCompression(RPacketEnableCompression packet); void handleEnableCompression(RPacketEnableCompression packet);

View file

@ -72,7 +72,7 @@ import common.tileentity.IInteractionObject;
import common.util.BlockPos; import common.util.BlockPos;
import common.world.World; import common.world.World;
public interface IClientPlayer { public interface IClientPlayer extends NetHandler {
void playSound(Sound sound); void playSound(Sound sound);
boolean isRenderViewEntity(Entity entity); boolean isRenderViewEntity(Entity entity);
void updatePlayerMoveState(); void updatePlayerMoveState();

View file

@ -2,6 +2,6 @@ package common.network;
import common.packet.HPacketHandshake; import common.packet.HPacketHandshake;
public interface IHandshakeHandler { public interface IHandshakeHandler extends NetHandler {
void processHandshake(HPacketHandshake packet); void processHandshake(HPacketHandshake packet);
} }

View file

@ -6,7 +6,7 @@ import common.packet.LPacketPubkey;
import common.packet.LPacketResponse; import common.packet.LPacketResponse;
import common.packet.LPacketStartEncrypt; import common.packet.LPacketStartEncrypt;
public interface ILoginHandler { public interface ILoginHandler extends NetHandler {
void processEncryption(LPacketStartEncrypt packet); void processEncryption(LPacketStartEncrypt packet);
void processPassword(LPacketPassword packet); void processPassword(LPacketPassword packet);
void processPubkey(LPacketPubkey packet); void processPubkey(LPacketPubkey packet);

View file

@ -31,7 +31,7 @@ import common.util.CharValidator;
import common.util.ChunkPos; import common.util.ChunkPos;
import common.util.PortalType; import common.util.PortalType;
public interface IPlayer { public interface IPlayer extends NetHandler {
public static class UserValidator implements CharValidator { public static class UserValidator implements CharValidator {
public boolean valid(char ch) { public boolean valid(char ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-'; return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-';

View file

@ -1,9 +1,9 @@
package common.network; package common.network;
public abstract class NetHandler { public interface NetHandler {
private static final ThreadQuickExitException EXIT = new ThreadQuickExitException();
public static final class ThreadQuickExitException extends RuntimeException { public static final class ThreadQuickExitException extends RuntimeException {
private static final ThreadQuickExitException EXIT = new ThreadQuickExitException();
private ThreadQuickExitException() { private ThreadQuickExitException() {
this.setStackTrace(new StackTraceElement[0]); this.setStackTrace(new StackTraceElement[0]);
} }
@ -14,9 +14,9 @@ public abstract class NetHandler {
} }
} }
public abstract void onDisconnect(String reason); void onDisconnect(String reason);
public void update() { default void update() {
} }
public static <T> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener) throws ThreadQuickExitException { public static <T> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener) throws ThreadQuickExitException {
@ -26,13 +26,13 @@ public abstract class NetHandler {
packet.processPacket(handler); packet.processPacket(handler);
} }
}); });
throw EXIT; throw ThreadQuickExitException.EXIT;
} }
} }
public static <T> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener, Object check) throws ThreadQuickExitException { public static <T> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener, Object check) throws ThreadQuickExitException {
if(check == null && listener.isMainThread()) if(check == null && listener.isMainThread())
throw EXIT; throw ThreadQuickExitException.EXIT;
checkThread(packet, handler, listener); checkThread(packet, handler, listener);
} }
} }

View file

@ -7,12 +7,12 @@ import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.InetAddress; import java.net.InetAddress;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
@ -99,6 +99,7 @@ import server.command.Executor;
import server.command.FixedExecutor; import server.command.FixedExecutor;
import server.network.HandshakeHandler; import server.network.HandshakeHandler;
import server.network.Player; import server.network.Player;
import server.network.User;
import server.world.Converter; import server.world.Converter;
import server.world.Region; import server.world.Region;
import server.world.WorldServer; import server.world.WorldServer;
@ -113,7 +114,8 @@ public final class Server implements IThreadListener {
private final Thread serverThread = Thread.currentThread(); private final Thread serverThread = Thread.currentThread();
private final List<NetConnection> clients = Collections.<NetConnection>synchronizedList(Lists.<NetConnection>newArrayList()); private final List<NetConnection> clients = Collections.<NetConnection>synchronizedList(Lists.<NetConnection>newArrayList());
private final List<Player> players = Lists.<Player>newArrayList(); private final List<Player> players = Lists.<Player>newArrayList();
private final Map<String, Player> usermap = Maps.<String, Player>newHashMap(); private final Map<String, Player> online = Maps.<String, Player>newHashMap();
private final Map<String, User> users = Maps.newTreeMap();
private final Queue<FutureTask<?>> queue = new ArrayDeque<FutureTask<?>>(); private final Queue<FutureTask<?>> queue = new ArrayDeque<FutureTask<?>>();
private final long[] tickTimes = new long[100]; private final long[] tickTimes = new long[100];
private final Map<Integer, WorldServer> dimensions = Maps.newTreeMap(); private final Map<Integer, WorldServer> dimensions = Maps.newTreeMap();
@ -277,20 +279,19 @@ public final class Server implements IThreadListener {
return this.scriptEnv; return this.scriptEnv;
} }
public String[] getUsers() { public List<String> getPlayerFilenames() {
String[] list = this.debug ? null : new File("players").list(); String[] list = this.debug ? null : new File("players").list();
if(list == null) { if(list == null)
list = new String[0]; return Lists.newArrayList();
} List<String> names = Lists.newArrayList();
for(int i = 0; i < list.length; ++i) { for(int i = 0; i < list.length; ++i) {
if(list[i].endsWith(".cdt")) { if(list[i].endsWith(".cdt")) {
list[i] = list[i].substring(0, list[i].length() - 4); String name = list[i].substring(0, list[i].length() - 4);
// Player player = this.getPlayer(list[i]); if(IPlayer.isValidUser(name))
// if(player != null) names.add(name);
// list[i] = player.getUser();
} }
} }
return list; return names;
} }
public void saveWorldInfo() { public void saveWorldInfo() {
@ -469,6 +470,7 @@ public final class Server implements IThreadListener {
Log.SYSTEM.info("Generiere neues Schlüsselpaar"); Log.SYSTEM.info("Generiere neues Schlüsselpaar");
this.keyPair = EncryptUtil.createKeypair(); this.keyPair = EncryptUtil.createKeypair();
} }
User.loadDatabase(this.users);
// if(dtime == -1L) // { // if(dtime == -1L) // {
// dtime = World.START_TIME; // dtime = World.START_TIME;
//// Config.set("spawnDim", "1", null); //// Config.set("spawnDim", "1", null);
@ -772,7 +774,7 @@ public final class Server implements IThreadListener {
this.timePassed = this.ticksTodo = this.ticksDone = 0L; this.timePassed = this.ticksTodo = this.ticksDone = 0L;
} }
public List<String> getAllUsernames() { public List<String> getAllPlayerNames() {
List<String> list = new ArrayList<String>(this.players.size()); List<String> list = new ArrayList<String>(this.players.size());
for(int z = 0; z < this.players.size(); z++) { for(int z = 0; z < this.players.size(); z++) {
list.add(this.players.get(z).getUser()); list.add(this.players.get(z).getUser());
@ -780,12 +782,24 @@ public final class Server implements IThreadListener {
return list; return list;
} }
public List<String> getAllUserNames() {
return Lists.newArrayList(this.users.keySet());
}
public List<Player> getPlayers() { public List<Player> getPlayers() {
return this.players; return this.players;
} }
public Collection<User> getUsers() {
return this.users.values();
}
public Player getPlayer(String user) { public Player getPlayer(String user) {
return this.usermap.get(user); return this.online.get(user);
}
public User getUser(String user) {
return this.users.get(user);
} }
private <V> ListenableFuture<V> callFromMainThread(Callable<V> callable) { private <V> ListenableFuture<V> callFromMainThread(Callable<V> callable) {
@ -848,43 +862,16 @@ public final class Server implements IThreadListener {
radius > 0 ? (-180.0f + world.rand.floatv() * 360.0f) : Config.spawnYaw, radius > 0 ? (-180.0f + world.rand.floatv() * 360.0f) : Config.spawnYaw,
radius > 0 ? 0.0f : Config.spawnPitch, world.dimension.getDimensionId()); radius > 0 ? 0.0f : Config.spawnPitch, world.dimension.getDimensionId());
} }
public void addUser(User user) {
this.users.put(user.getUser(), user);
}
public String addPlayer(NetConnection connection, String loginUser, String loginPass, PublicKey loginKey) { public void addPlayer(NetConnection connection, String loginUser) {
TagObject tag = this.readPlayer(loginUser); TagObject tag = this.readPlayer(loginUser);
Player conn = new Player(this, connection, loginUser); Player conn = new Player(this, connection, loginUser);
if(tag != null) if(tag != null)
conn.readTags(tag); conn.readTags(tag);
if(Config.authenticate) {
if(conn.getPasswordHash() == null && conn.getPubkey() == null) {
if(tag != null)
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
if(!Config.register)
return "Anmeldung neuer Accounts ist auf diesem Server deaktiviert (Whitelisted)";
if(Config.playerLimit > 0 && this.players.size() >= Config.playerLimit)
return String.format("Der Server ist voll (%d/%d)!", this.players.size(), Config.playerLimit);
if(loginKey != null) {
conn.setPubkey(loginKey);
Log.NETWORK.info(loginUser + " registrierte sich mit Pubkey");
}
else {
if(loginPass == null || loginPass.length() == 0)
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens " + Config.minPassLength + " Zeichen)";
if(loginPass.length() < Config.minPassLength)
return "Passwort ist zu kurz, mindestens " + Config.minPassLength + " Zeichen";
conn.setPasswordHash(EncryptUtil.hashPassword(loginPass));
Log.NETWORK.info(loginUser + " registrierte sich mit Passwort");
}
}
else if(conn.getPubkey() != null ? !conn.getPubkey().equals(loginKey) :
(loginPass == null || !MessageDigest.isEqual(EncryptUtil.hashPassword(loginPass, conn.getPasswordHash().second()), conn.getPasswordHash().first()))) {
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
}
else {
Log.NETWORK.info(loginUser + " loggte sich mit " + (loginKey != null ? "Pubkey" : "Passwort") + " ein");
}
}
if(Config.playerLimit > 0 && this.players.size() >= Config.playerLimit && !conn.isAdmin())
return String.format("Der Server ist voll (%d/%d)!", this.players.size(), Config.playerLimit);
if(Config.compression >= 0) { if(Config.compression >= 0) {
connection.sendPacket(new RPacketEnableCompression(Config.compression), new ChannelFutureListener() { connection.sendPacket(new RPacketEnableCompression(Config.compression), new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception { public void operationComplete(ChannelFuture future) throws Exception {
@ -895,7 +882,11 @@ public final class Server implements IThreadListener {
connection.sendPacket(new RPacketLoginSuccess(this.debug)); connection.sendPacket(new RPacketLoginSuccess(this.debug));
connection.setNetHandler(conn); connection.setNetHandler(conn);
this.players.add(conn); this.players.add(conn);
this.usermap.put(loginUser, conn); User user = this.users.remove(loginUser);
if(user != null)
conn.copyFrom(user);
this.users.put(loginUser, conn);
this.online.put(loginUser, conn);
tag = conn.readCharacter(); tag = conn.readCharacter();
WorldServer world = tag == null ? this.space : this.getWorld(tag.getInt("Dimension")); WorldServer world = tag == null ? this.space : this.getWorld(tag.getInt("Dimension"));
@ -936,7 +927,6 @@ public final class Server implements IThreadListener {
conn.sendPacket(new SPacketPlayerAbilities(player)); conn.sendPacket(new SPacketPlayerAbilities(player));
conn.addSelfToInternalCraftingInventory(); conn.addSelfToInternalCraftingInventory();
conn.onConnect(); conn.onConnect();
return null;
} }
public void removePlayer(Player conn) { public void removePlayer(Player conn) {
@ -947,7 +937,10 @@ public final class Server implements IThreadListener {
world.removeEntity(player); world.removeEntity(player);
world.removePlayer(player); world.removePlayer(player);
this.players.remove(conn); this.players.remove(conn);
this.usermap.remove(conn.getUser()); this.online.remove(conn.getUser());
User user = new User(conn.getUser());
user.copyFrom(conn);
this.users.put(conn.getUser(), user);
this.sendPacket(new SPacketPlayerListItem(true, conn)); this.sendPacket(new SPacketPlayerListItem(true, conn));
} }
@ -1215,7 +1208,7 @@ public final class Server implements IThreadListener {
for(Player conn : this.players) { for(Player conn : this.players) {
this.writePlayer(conn); this.writePlayer(conn);
} }
// this.saveUsers(); User.saveDatabase(this.users);
} }
private void updateTimeAndWeatherForPlayer(Player conn, WorldServer world) { private void updateTimeAndWeatherForPlayer(Player conn, WorldServer world) {

View file

@ -175,6 +175,10 @@ public abstract class Command implements Executable {
return this.addParameter(shortName, new TagParser(name, null)); return this.addParameter(shortName, new TagParser(name, null));
} }
protected Command addUser(String name, boolean defaulted) {
return this.addParameter(new UserParser(name, defaulted));
}
protected Command addPlayer(String name, boolean defaulted) { protected Command addPlayer(String name, boolean defaulted) {
return this.addParameter(new PlayerParser(name, defaulted)); return this.addParameter(new PlayerParser(name, defaulted));
} }

View file

@ -27,6 +27,7 @@ import server.command.commands.CommandPlayers;
import server.command.commands.CommandPotion; import server.command.commands.CommandPotion;
import server.command.commands.CommandPubkey; import server.command.commands.CommandPubkey;
import server.command.commands.CommandRegister; import server.command.commands.CommandRegister;
import server.command.commands.CommandRegkey;
import server.command.commands.CommandRemove; import server.command.commands.CommandRemove;
import server.command.commands.CommandRevoke; import server.command.commands.CommandRevoke;
import server.command.commands.CommandSave; import server.command.commands.CommandSave;
@ -36,6 +37,7 @@ import server.command.commands.CommandSpawn;
import server.command.commands.CommandTele; import server.command.commands.CommandTele;
import server.command.commands.CommandTime; import server.command.commands.CommandTime;
import server.command.commands.CommandTp; import server.command.commands.CommandTp;
import server.command.commands.CommandUsers;
import server.command.commands.CommandWarp; import server.command.commands.CommandWarp;
import server.command.commands.CommandWeather; import server.command.commands.CommandWeather;
import server.command.commands.CommandWorld; import server.command.commands.CommandWorld;
@ -283,8 +285,10 @@ public class CommandEnvironment {
this.registerExecutable(new CommandPasswd()); this.registerExecutable(new CommandPasswd());
this.registerExecutable(new CommandPubkey()); this.registerExecutable(new CommandPubkey());
this.registerExecutable(new CommandPlayers()); this.registerExecutable(new CommandPlayers());
this.registerExecutable(new CommandUsers());
this.registerExecutable(new CommandSave()); this.registerExecutable(new CommandSave());
this.registerExecutable(new CommandRegister()); this.registerExecutable(new CommandRegister());
this.registerExecutable(new CommandRegkey());
this.registerExecutable(new CommandFind()); this.registerExecutable(new CommandFind());
this.registerExecutable(new CommandBlock()); this.registerExecutable(new CommandBlock());
this.registerExecutable(new CommandSeed()); this.registerExecutable(new CommandSeed());

View file

@ -24,7 +24,7 @@ public class PlayerParser extends CompletingParser {
} }
public Collection<String> getCompletions(CommandEnvironment env) { public Collection<String> getCompletions(CommandEnvironment env) {
return env.getServer().getAllUsernames(); return env.getServer().getAllPlayerNames();
} }
public Class<?> getTypeClass(boolean required) { public Class<?> getTypeClass(boolean required) {

View file

@ -0,0 +1,34 @@
package server.command;
import java.util.Collection;
import server.network.Player;
import server.network.User;
public class UserParser extends CompletingParser {
protected final boolean useSender;
public UserParser(String name, boolean useSender) {
super(name);
this.useSender = useSender;
}
public Object parse(CommandEnvironment env, String input) {
User user = env.getServer().getUser(input);
if(user == null)
throw new RunException("Nutzer '%s' wurde nicht gefunden", input);
return user;
}
public Object getDefault(CommandEnvironment env) {
return this.useSender && env.getExecutor().isPlayer() ? (Player)env.getExecutor() : null;
}
public Collection<String> getCompletions(CommandEnvironment env) {
return env.getServer().getAllUserNames();
}
public Class<?> getTypeClass(boolean required) {
return User.class;
}
}

View file

@ -5,21 +5,23 @@ import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.network.Player; import server.network.Player;
import server.network.User;
public class CommandAdmin extends Command { public class CommandAdmin extends Command {
public CommandAdmin() { public CommandAdmin() {
super("admin"); super("admin");
this.addPlayer("player", false); this.addUser("user", false);
} }
public void exec(CommandEnvironment env, Executor exec, Player player) { public void exec(CommandEnvironment env, Executor exec, User user) {
if(player == exec) if(user == exec)
throw new RunException("Du kannst nicht deinen eigenen Admin-Status erneut setzen"); throw new RunException("Du kannst nicht deinen eigenen Admin-Status erneut setzen");
else if(player.getAdmin()) else if(user.isAdmin())
throw new RunException("%s ist bereits ein Admin", player.getUser()); throw new RunException("%s ist bereits ein Admin", user.getUser());
player.setAdmin(true); user.setAdmin(true);
player.logConsole("Du hast Administatorrechte von %s bekommen", exec.getExecId()); if(user.isOnline())
exec.logConsole("%s ist jetzt ein Admin", player.getUser()); ((Player)user).logConsole("Du hast Administatorrechte von %s bekommen", exec.getExecId());
exec.logConsole("%s ist jetzt ein Admin", user.getUser());
} }
} }

View file

@ -18,7 +18,7 @@ public class CommandKick extends Command {
public void exec(CommandEnvironment env, Executor exec, Player player, String message) { public void exec(CommandEnvironment env, Executor exec, Player player, String message) {
if(player == exec) if(player == exec)
throw new RunException("Du kannst nicht dich nicht selbst vom Server werfen"); throw new RunException("Du kannst nicht dich nicht selbst vom Server werfen");
else if(player.getAdmin()) else if(player.isAdmin())
throw new RunException("%s ist ein Admin", player.getUser()); throw new RunException("%s ist ein Admin", player.getUser());
player.disconnect(message); player.disconnect(message);
exec.logConsole("%s wurde vom Server geworfen", player.getUser()); exec.logConsole("%s wurde vom Server geworfen", player.getUser());

View file

@ -3,7 +3,6 @@ package server.command.commands;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import common.collect.Lists;
import common.entity.Entity; import common.entity.Entity;
import common.init.UniverseRegistry; import common.init.UniverseRegistry;
import common.util.Position; import common.util.Position;
@ -20,7 +19,7 @@ public class CommandOfflinetp extends Command {
this.addString("user", false, new StringCompleter() { this.addString("user", false, new StringCompleter() {
public Collection<String> complete(CommandEnvironment env) { public Collection<String> complete(CommandEnvironment env) {
return Lists.newArrayList(env.getServer().getUsers()); return env.getServer().getPlayerFilenames();
} }
}); });

View file

@ -11,26 +11,27 @@ import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.network.Player; import server.network.Player;
import server.network.User;
import server.util.Form; import server.util.Form;
public class CommandPasswd extends Command { public class CommandPasswd extends Command {
public CommandPasswd() { public CommandPasswd() {
super("passwd"); super("passwd");
this.addPlayer("player", true); this.addUser("user", true);
this.setParamsOptional(); this.setParamsOptional();
this.addString("password", false); this.addString("password", false);
} }
public void exec(CommandEnvironment env, Executor exec, Player player, String password) { public void exec(CommandEnvironment env, Executor exec, User user, String password) {
if(exec.isPlayer()) { if(exec.isPlayer()) {
if(password != null) if(password != null)
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden"); throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
if(player.getAdmin() && player != exec) if(user.isAdmin() && user != exec)
throw new RunException("%s ist ein Admin", player.getUser()); throw new RunException("%s ist ein Admin", user.getUser());
if(player.getPubkey() != null && player == exec) if(user.getPubkey() != null && user == exec)
throw new RunException("Es darf kein Pubkey vorhanden sein, um diesen Befehl an sich selbst anzuwenden"); throw new RunException("Es darf kein Pubkey vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
if(player.getPasswordHash() == null && player == exec) if(user.getPasswordHash() == null && user == exec)
throw new RunException("Es muss ein Passwort vorhanden sein, um diesen Befehl an sich selbst anzuwenden"); throw new RunException("Es muss ein Passwort vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
((Player)exec).displayForm(new Form() { ((Player)exec).displayForm(new Form() {
private Field checkField; private Field checkField;
@ -38,17 +39,17 @@ public class CommandPasswd extends Command {
private Field confirmField; private Field confirmField;
protected void init() { protected void init() {
this.checkField = player != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, ""); this.checkField = user != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
this.passwordField = this.addPassword("Neues Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, ""); this.passwordField = this.addPassword("Neues Passwort", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
this.confirmField = this.addPassword("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, ""); this.confirmField = this.addPassword("Passwort bestätigen", Config.minPassLength, IPlayer.MAX_PASS_LENGTH, "");
} }
public String getTitle() { public String getTitle() {
return "Passwort für " + player.getUser() + " ändern"; return "Passwort für " + user.getUser() + " ändern";
} }
protected void accept() { protected void accept() {
Player plr = env.getServer().getPlayer(player.getUser()); User plr = env.getServer().getUser(user.getUser());
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec) || (plr.getPasswordHash() == null && plr == exec) || (plr.getPubkey() != null && plr == exec)) { if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec) || (plr.getPasswordHash() == null && plr == exec) || (plr.getPubkey() != null && plr == exec)) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten"); exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return; return;
@ -72,9 +73,9 @@ public class CommandPasswd extends Command {
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden"); throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
if(password.length() < 8) if(password.length() < 8)
throw new RunException("Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich"); throw new RunException("Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich");
player.setPasswordHash(EncryptUtil.hashPassword(password)); user.setPasswordHash(EncryptUtil.hashPassword(password));
player.setPubkey(null); user.setPubkey(null);
exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", player.getUser()); exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", user.getUser());
} }
} }
} }

View file

@ -12,13 +12,14 @@ import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.network.Player; import server.network.Player;
import server.network.User;
import server.util.Form; import server.util.Form;
public class CommandPubkey extends Command { public class CommandPubkey extends Command {
public CommandPubkey() { public CommandPubkey() {
super("pubkey"); super("pubkey");
this.addPlayer("player", true); this.addUser("user", true);
this.setParamsOptional(); this.setParamsOptional();
this.addString("keySpec", false); this.addString("keySpec", false);
this.addString("keyData", false); this.addString("keyData", false);
@ -26,27 +27,27 @@ public class CommandPubkey extends Command {
this.addString("keyName", false); this.addString("keyName", false);
} }
public void exec(CommandEnvironment env, Executor exec, Player player, String keySpec, String keyData, String keyHash, String keyName) { public void exec(CommandEnvironment env, Executor exec, User user, String keySpec, String keyData, String keyHash, String keyName) {
if(exec.isPlayer()) { if(exec.isPlayer()) {
if(keySpec != null || keyData != null || keyHash != null || keyName != null) if(keySpec != null || keyData != null || keyHash != null || keyName != null)
throw new RunException("Bei Verwendung als Spieler darf kein Schlüssel angegeben werden"); throw new RunException("Bei Verwendung als Spieler darf kein Schlüssel angegeben werden");
if(player.getAdmin() && player != exec) if(user.isAdmin() && user != exec)
throw new RunException("%s ist ein Admin", player.getUser()); throw new RunException("%s ist ein Admin", user.getUser());
((Player)exec).displayForm(new Form() { ((Player)exec).displayForm(new Form() {
private Field checkField; private Field checkField;
private Field keyField; private Field keyField;
protected void init() { protected void init() {
this.checkField = player.getPasswordHash() == null || player != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, ""); this.checkField = user.getPasswordHash() == null || user != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
this.keyField = this.addField("Neuer Pubkey", 1, 960, ""); this.keyField = this.addField("Neuer Pubkey", 1, 960, "");
} }
public String getTitle() { public String getTitle() {
return "Schlüssel für " + player.getUser() + " ändern"; return "Schlüssel für " + user.getUser() + " ändern";
} }
protected void accept() { protected void accept() {
Player plr = env.getServer().getPlayer(player.getUser()); User plr = env.getServer().getUser(user.getUser());
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) { if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten"); exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return; return;
@ -79,9 +80,9 @@ public class CommandPubkey extends Command {
catch(IllegalArgumentException e) { catch(IllegalArgumentException e) {
throw new RunException(e, "Ungültiger Schlüssel"); throw new RunException(e, "Ungültiger Schlüssel");
} }
player.setPasswordHash(null); user.setPasswordHash(null);
player.setPubkey(key.first()); user.setPubkey(key.first());
exec.logConsole(TextColor.GREEN + "Schlüssel für %s gesetzt", player.getUser()); exec.logConsole(TextColor.GREEN + "Schlüssel für %s gesetzt", user.getUser());
} }
} }
} }

View file

@ -3,12 +3,13 @@ package server.command.commands;
import common.color.TextColor; import common.color.TextColor;
import common.init.Config; import common.init.Config;
import common.network.IPlayer; import common.network.IPlayer;
import common.tags.TagObject; import common.util.EncryptUtil;
import server.command.Command; import server.command.Command;
import server.command.CommandEnvironment; import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.network.Player; import server.network.Player;
import server.network.User;
import server.util.Form; import server.util.Form;
public class CommandRegister extends Command { public class CommandRegister extends Command {
@ -22,12 +23,10 @@ public class CommandRegister extends Command {
} }
public void exec(CommandEnvironment env, Executor exec, String username, String password, boolean admin) { public void exec(CommandEnvironment env, Executor exec, String username, String password, boolean admin) {
Player player = env.getServer().getPlayer(username); if(env.getServer().getUser(username) != null)
if(player != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits online");
TagObject tag = env.getServer().loadPlayerData(username);
if(tag != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits registriert"); throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits registriert");
if(env.getServer().loadPlayerData(username) != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen hat bereits Spielerdaten, ist aber nicht registriert");
if(exec.isPlayer()) { if(exec.isPlayer()) {
if(password != null) if(password != null)
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden"); throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
@ -45,7 +44,7 @@ public class CommandRegister extends Command {
} }
protected void accept() { protected void accept() {
if(!((Player)exec).isAdmin() || env.getServer().getPlayer(username) != null || env.getServer().loadPlayerData(username) != null) { if(!((Player)exec).isAdmin() || env.getServer().getUser(username) != null || env.getServer().loadPlayerData(username) != null) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten"); exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return; return;
} }
@ -53,9 +52,10 @@ public class CommandRegister extends Command {
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein"); exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
return; return;
} }
TagObject user = new TagObject(); User user = new User(username);
user.setString("password", this.passwordField.get()); user.setPasswordHash(EncryptUtil.hashPassword(this.passwordField.get()));
env.getServer().writePlayerData(username, user); user.setAdmin(admin);
env.getServer().addUser(user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username); exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
} }
}); });
@ -63,9 +63,12 @@ public class CommandRegister extends Command {
else if(exec.isConsole()) { else if(exec.isConsole()) {
if(password == null) if(password == null)
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden"); throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
TagObject user = new TagObject(); if(password.length() < 8)
user.setString("password", password); throw new RunException("Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich");
env.getServer().writePlayerData(username, user); User user = new User(username);
user.setPasswordHash(EncryptUtil.hashPassword(password));
user.setAdmin(admin);
env.getServer().addUser(user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username); exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
} }
} }

View file

@ -0,0 +1,87 @@
package server.command.commands;
import java.security.PublicKey;
import common.color.TextColor;
import common.network.IPlayer;
import common.util.EncryptUtil;
import common.util.Pair;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.command.RunException;
import server.network.Player;
import server.network.User;
import server.util.Form;
public class CommandRegkey extends Command {
public CommandRegkey() {
super("regkey");
this.addString("username", false, null, IPlayer.MAX_USER_LENGTH, IPlayer.VALID_USER);
this.setParamsOptional();
this.addString("keySpec", false);
this.addString("keyData", false);
this.addString("keyHash", false);
this.addString("keyName", false);
this.addFlag("admin", 'a');
}
public void exec(CommandEnvironment env, Executor exec, String username, String keySpec, String keyData, String keyHash, String keyName, boolean admin) {
if(env.getServer().getUser(username) != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen ist bereits registriert");
if(env.getServer().loadPlayerData(username) != null)
throw new RunException("Ein Spieler mit diesem Nutzernamen hat bereits Spielerdaten, ist aber nicht registriert");
if(exec.isPlayer()) {
if(keySpec != null || keyData != null || keyHash != null || keyName != null)
throw new RunException("Bei Verwendung als Spieler darf kein Schlüssel angegeben werden");
((Player)exec).displayForm(new Form() {
private Field keyField;
protected void init() {
this.keyField = this.addField("Pubkey", 1, 960, "");
}
public String getTitle() {
return "Spieler " + username + " registrieren";
}
protected void accept() {
if(!((Player)exec).isAdmin() || env.getServer().getUser(username) != null || env.getServer().loadPlayerData(username) != null) {
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
return;
}
Pair<PublicKey, String> key;
try {
key = EncryptUtil.parseArmoredPubkey(this.keyField.get());
}
catch(IllegalArgumentException e) {
exec.logConsole(TextColor.RED + "Ungültiger Schlüssel");
return;
}
User user = new User(username);
user.setPubkey(key.first());
user.setAdmin(admin);
env.getServer().addUser(user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
}
});
}
else if(exec.isConsole()) {
if(keySpec == null || keyData == null || keyHash == null)
throw new RunException("Bei Verwendung in der Konsole muss ein Schlüssel angegeben werden");
Pair<PublicKey, String> key;
try {
key = EncryptUtil.parseArmoredPubkey(keySpec + " " + keyData + " " + keyHash + (keyName == null ? null : " " + keyName));
}
catch(IllegalArgumentException e) {
throw new RunException(e, "Ungültiger Schlüssel");
}
User user = new User(username);
user.setPubkey(key.first());
user.setAdmin(admin);
env.getServer().addUser(user);
exec.logConsole(TextColor.GREEN + "Spieler %s registriert", username);
}
}
}

View file

@ -5,23 +5,25 @@ import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.network.Player; import server.network.Player;
import server.network.User;
public class CommandRevoke extends Command { public class CommandRevoke extends Command {
public CommandRevoke() { public CommandRevoke() {
super("revoke"); super("revoke");
this.addPlayer("player", false); this.addUser("user", false);
} }
public void exec(CommandEnvironment env, Executor exec, Player player) { public void exec(CommandEnvironment env, Executor exec, User user) {
if(!exec.isConsole()) if(!exec.isConsole())
throw new RunException("Dieser Befehl kann nur der Konsole ausgeführt werden"); throw new RunException("Dieser Befehl kann nur der Konsole ausgeführt werden");
// else if(player == exec) // else if(player == exec)
// throw new RunException("Du kannst nicht deinen eigenen Admin-Status entfernen"); // throw new RunException("Du kannst nicht deinen eigenen Admin-Status entfernen");
else if(!player.getAdmin()) else if(!user.isAdmin())
throw new RunException("%s ist kein Admin", player.getUser()); throw new RunException("%s ist kein Admin", user.getUser());
player.setAdmin(false); user.setAdmin(false);
player.logConsole("Der Host hat deine Administatorrechte entfernt"); if(user.isOnline())
exec.logConsole("%s ist jetzt kein Admin mehr", player.getUser()); ((Player)user).logConsole("Der Host hat deine Administatorrechte entfernt");
exec.logConsole("%s ist jetzt kein Admin mehr", user.getUser());
} }
} }

View file

@ -0,0 +1,26 @@
package server.command.commands;
import java.util.Collection;
import common.color.TextColor;
import server.command.Command;
import server.command.CommandEnvironment;
import server.command.Executor;
import server.network.User;
public class CommandUsers extends Command {
public CommandUsers() {
super("users");
}
public void exec(CommandEnvironment env, Executor exec) {
Collection<User> users = env.getServer().getUsers();
if(users.isEmpty()) {
exec.logConsole(TextColor.DGRAY + "Es sind keine Spieler registriert");
return;
}
exec.logConsole(TextColor.GREEN + "Es " + (users.size() == 1 ? "ist" : "sind") + " " + TextColor.YELLOW + "%d" + TextColor.GREEN + " Spieler registriert", users.size());
for(User user : users) {
exec.logConsole("%s%s" + TextColor.GRAY + ": %s" + TextColor.GRAY + ", %s", user.isAdmin() ? TextColor.RED : TextColor.NEON, user.getUser(), user.isOnline() ? TextColor.DGREEN + "Online" : TextColor.DGRAY + "Offline", user.getPubkey() != null ? TextColor.YELLOW + "Pubkey" : (user.getPasswordHash() != null ? TextColor.MAGENTA + "Passwort" : TextColor.BLACK + "Kein Login"));
}
}
}

View file

@ -2,14 +2,13 @@ package server.network;
import common.network.IHandshakeHandler; import common.network.IHandshakeHandler;
import common.network.NetConnection; import common.network.NetConnection;
import common.network.NetHandler;
import common.network.PacketRegistry; import common.network.PacketRegistry;
import common.packet.HPacketHandshake; import common.packet.HPacketHandshake;
import common.packet.RPacketDisconnect; import common.packet.RPacketDisconnect;
import common.util.Util; import common.util.Util;
import server.Server; import server.Server;
public class HandshakeHandler extends NetHandler implements IHandshakeHandler public class HandshakeHandler implements IHandshakeHandler
{ {
private final Server server; private final Server server;
private final NetConnection networkManager; private final NetConnection networkManager;

View file

@ -1,5 +1,6 @@
package server.network; package server.network;
import java.security.MessageDigest;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -15,7 +16,6 @@ import common.net.util.concurrent.GenericFutureListener;
import common.network.ILoginHandler; import common.network.ILoginHandler;
import common.network.IPlayer; import common.network.IPlayer;
import common.network.NetConnection; import common.network.NetConnection;
import common.network.NetHandler;
import common.packet.LPacketChallenge; import common.packet.LPacketChallenge;
import common.packet.LPacketPassword; import common.packet.LPacketPassword;
import common.packet.LPacketPubkey; import common.packet.LPacketPubkey;
@ -26,9 +26,10 @@ import common.packet.RPacketDisconnect;
import common.packet.RPacketRequestEncrypt; import common.packet.RPacketRequestEncrypt;
import common.packet.RPacketResponse; import common.packet.RPacketResponse;
import common.packet.RPacketServerConfig; import common.packet.RPacketServerConfig;
import common.util.EncryptUtil;
import server.Server; import server.Server;
public class LoginHandler extends NetHandler implements ILoginHandler public class LoginHandler implements ILoginHandler
{ {
private static enum LoginState { private static enum LoginState {
INIT, ENCRYPT, PROOF, PASSWORD, CHALLENGE, AUTHENTICATED, ACCEPTED; INIT, ENCRYPT, PROOF, PASSWORD, CHALLENGE, AUTHENTICATED, ACCEPTED;
@ -80,38 +81,57 @@ public class LoginHandler extends NetHandler implements ILoginHandler
public void update() public void update()
{ {
if(this.state == LoginState.AUTHENTICATED) if(this.state == LoginState.AUTHENTICATED)
this.tryAcceptPlayer(); this.tryAdvance();
// else if (this.currentLoginState == LoginState.DELAY_ACCEPT)
// {
// if (this.server.getPlayer(this.loginUser) == null)
// {
// this.currentLoginState = LoginState.ACCEPTED;
// this.server.addPlayer(this.networkManager, this.loginUser);
// }
// }
if(this.timer++ == 600) if(this.timer++ == 600)
this.closeConnection("Anmeldung dauerte zu lange"); this.closeConnection("Anmeldung dauerte zu lange");
} }
private void tryAcceptPlayer() private void tryAdvance() {
{ String kick = this.checkPlayer();
if(this.server.getPlayer(this.loginUser) != null) { if(kick != null) {
this.closeConnection("Nutzername '" + this.loginUser + "' ist bereits vergeben.");
return;
}
// if (this.server.getPlayer(this.loginUser) != null)
// {
// this.closeConnection("Nutzername '" + this.loginUser + "' ist bereits vergeben.");
// return;
//// this.currentLoginState = LoginState.DELAY_ACCEPT;
//// player.netHandler.kick("Du hast dich von einen anderen Ort verbunden");
// }
// this.networkManager.sendPacket(new RPacketLoginSuccess());
String kick = this.server.addPlayer(this.netManager, this.loginUser, this.loginPass, this.loginKey);
if(kick != null)
this.closeConnection(kick); this.closeConnection(kick);
else return;
this.state = LoginState.ACCEPTED; }
this.server.addPlayer(this.netManager, this.loginUser);
this.state = LoginState.ACCEPTED;
}
private String checkPlayer() {
if(this.server.getPlayer(this.loginUser) != null)
return "Nutzername '" + this.loginUser + "' ist bereits vergeben";
User user = this.server.getUser(this.loginUser);
if(Config.authenticate) {
if(user == null) {
if(!Config.register)
return "Anmeldung neuer Accounts ist auf diesem Server deaktiviert (Whitelisted)";
if(Config.playerLimit > 0 && this.server.getPlayers().size() >= Config.playerLimit)
return String.format("Der Server ist voll (%d/%d)!", this.server.getPlayers().size(), Config.playerLimit);
if(this.loginKey != null) {
this.server.addUser(user = new User(this.loginUser));
user.setPubkey(this.loginKey);
Log.NETWORK.info(this.loginUser + " registrierte sich mit Pubkey");
}
else {
if(this.loginPass == null || this.loginPass.length() == 0)
return "Ein neues Passwort ist erforderlich um diesen Server zu betreten (mindestens " + Config.minPassLength + " Zeichen)";
if(this.loginPass.length() < Config.minPassLength)
return "Passwort ist zu kurz, mindestens " + Config.minPassLength + " Zeichen";
this.server.addUser(user = new User(this.loginUser));
user.setPasswordHash(EncryptUtil.hashPassword(this.loginPass));
Log.NETWORK.info(this.loginUser + " registrierte sich mit Passwort");
}
}
else if((user.getPasswordHash() == null && user.getPubkey() == null) || (user.getPubkey() != null ? !user.getPubkey().equals(this.loginKey) :
(this.loginPass == null || !MessageDigest.isEqual(EncryptUtil.hashPassword(this.loginPass, user.getPasswordHash().second()), user.getPasswordHash().first())))) {
return this.loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
}
else {
Log.NETWORK.info(this.loginUser + " loggte sich mit " + (this.loginKey != null ? "Pubkey" : "Passwort") + " ein");
}
}
if(Config.playerLimit > 0 && this.server.getPlayers().size() >= Config.playerLimit && (user == null || !user.isAdmin()))
return String.format("Der Server ist voll (%d/%d)!", this.server.getPlayers().size(), Config.playerLimit);
return null;
} }
public void sendLoginPacket() { public void sendLoginPacket() {

View file

@ -1,6 +1,5 @@
package server.network; package server.network;
import java.security.PublicKey;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@ -111,11 +110,9 @@ import common.tileentity.TileEntitySign;
import common.util.BlockPos; import common.util.BlockPos;
import common.util.BoundingBox; import common.util.BoundingBox;
import common.util.ChunkPos; import common.util.ChunkPos;
import common.util.EncryptUtil;
import common.util.ExtMath; import common.util.ExtMath;
import common.util.Facing; import common.util.Facing;
import common.util.IntHashMap; import common.util.IntHashMap;
import common.util.Pair;
import common.util.PortalType; import common.util.PortalType;
import common.util.Position; import common.util.Position;
import common.util.Vec3i; import common.util.Vec3i;
@ -138,7 +135,7 @@ import server.world.ChunkServer;
import server.world.Region; import server.world.Region;
import server.world.WorldServer; import server.world.WorldServer;
public class Player extends NetHandler implements ICrafting, Executor, IPlayer public class Player extends User implements ICrafting, Executor, IPlayer
{ {
private static enum EditAction { private static enum EditAction {
SELECT("Auswahlmodus"), COPYPASTE("Kopiermodus"), TRANSFORM("Drehmodus"); SELECT("Auswahlmodus"), COPYPASTE("Kopiermodus"), TRANSFORM("Drehmodus");
@ -152,7 +149,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
private final NetConnection connection; private final NetConnection connection;
private final Server server; private final Server server;
private final String user;
private final IntHashMap<Short> transactions = new IntHashMap(); private final IntHashMap<Short> transactions = new IntHashMap();
private final List<TagObject> characters = Lists.newArrayList(); private final List<TagObject> characters = Lists.newArrayList();
@ -170,11 +166,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
private boolean charEditor = true; private boolean charEditor = true;
private Form form; private Form form;
private boolean admin;
private int ping; private int ping;
private boolean deleted;
private Pair<byte[], byte[]> password;
private PublicKey pubkey;
private boolean profiling; private boolean profiling;
private int selectionDim = Integer.MIN_VALUE; private int selectionDim = Integer.MIN_VALUE;
@ -217,7 +209,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public Player(Server server, NetConnection connection, String user) public Player(Server server, NetConnection connection, String user)
{ {
this.user = user; super(user);
this.server = server; this.server = server;
this.connection = connection; this.connection = connection;
// this.local = connection.isLocalChannel(); // this.local = connection.isLocalChannel();
@ -255,7 +247,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
this.pingKey = (int)this.lastPingTime; this.pingKey = (int)this.lastPingTime;
this.sendPacket(new SPacketKeepAlive(this.pingKey)); this.sendPacket(new SPacketKeepAlive(this.pingKey));
} }
if(this.admin && this.profiling) if(this.isAdmin() && this.profiling)
this.sendPacket(new SPacketServerTick((int)this.server.getLastTick())); this.sendPacket(new SPacketServerTick((int)this.server.getLastTick()));
if(this.respawnTimer > 0) { if(this.respawnTimer > 0) {
if(--this.respawnTimer == 0) { if(--this.respawnTimer == 0) {
@ -264,6 +256,10 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
} }
} }
public boolean isOnline() {
return true;
}
public void displayLoading(String message) { public void displayLoading(String message) {
this.sendPacket(new SPacketLoading(message)); this.sendPacket(new SPacketLoading(message));
} }
@ -323,10 +319,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public EntityNPC getEntity() { public EntityNPC getEntity() {
return this.entity; return this.entity;
} }
public String getUser() {
return this.user;
}
// public boolean isLocal() { // public boolean isLocal() {
// return this.local; // return this.local;
@ -335,30 +327,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public int getLatency() { public int getLatency() {
return this.ping; return this.ping;
} }
public boolean isAdmin() {
return this.admin; // || this.local;
}
public boolean getAdmin() {
return this.isAdmin();
}
public void setPasswordHash(Pair<byte[], byte[]> hash) {
this.password = hash;
}
public Pair<byte[], byte[]> getPasswordHash() {
return this.password;
}
public void setPubkey(PublicKey key) {
this.pubkey = key;
}
public PublicKey getPubkey() {
return this.pubkey;
}
@ -628,11 +596,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public void readTags(TagObject tag) { public void readTags(TagObject tag) {
this.admin = tag.getBool("admin");
if(tag.hasByteArray("passwordHash") && tag.hasByteArray("passwordSalt"))
this.password = new Pair<byte[], byte[]>(tag.getByteArray("passwordHash"), tag.getByteArray("passwordSalt"));
if(tag.hasByteArray("pubkey"))
this.pubkey = EncryptUtil.decodePublicKey(tag.getByteArray("pubkey"));
this.selected = tag.getInt("selected"); this.selected = tag.getInt("selected");
List<TagObject> list = tag.getList("characters"); List<TagObject> list = tag.getList("characters");
for(int z = 0; z < list.size(); z++) { for(int z = 0; z < list.size(); z++) {
@ -643,14 +606,6 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
} }
public void writeTags(TagObject tag) { public void writeTags(TagObject tag) {
if(this.admin)
tag.setBool("admin", this.admin);
if(this.password != null) {
tag.setByteArray("passwordHash", this.password.first());
tag.setByteArray("passwordSalt", this.password.second());
}
if(this.pubkey != null)
tag.setByteArray("pubkey", this.pubkey.getEncoded());
if(!this.characters.isEmpty()) { if(!this.characters.isEmpty()) {
tag.setInt("selected", this.selected); tag.setInt("selected", this.selected);
List<TagObject> list = Lists.newArrayList(); List<TagObject> list = Lists.newArrayList();
@ -1621,7 +1576,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public void disconnect(String message) public void disconnect(String message)
{ {
Log.NETWORK.info("Trenne %s: %s", this.user, message); Log.NETWORK.info("Trenne %s: %s", this.getUser(), message);
this.connection.sendPacket(new SPacketDisconnect(message), new GenericFutureListener < Future <? super Void >> () this.connection.sendPacket(new SPacketDisconnect(message), new GenericFutureListener < Future <? super Void >> ()
{ {
public void operationComplete(Future <? super Void > p_operationComplete_1_) throws Exception public void operationComplete(Future <? super Void > p_operationComplete_1_) throws Exception
@ -1641,8 +1596,8 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
public void onDisconnect(String reason) public void onDisconnect(String reason)
{ {
Log.NETWORK.info(this.user + " wurde getrennt: " + TextColor.stripCodes(reason)); Log.NETWORK.info(this.getUser() + " wurde getrennt: " + TextColor.stripCodes(reason));
this.server.sendPacket(new SPacketMessage(String.format("%s hat das Spiel verlassen", this.user), Type.FEED)); this.server.sendPacket(new SPacketMessage(String.format("%s hat das Spiel verlassen", this.getUser()), Type.FEED));
this.server.removePlayer(this); this.server.removePlayer(this);
} }
@ -1666,7 +1621,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
chars.add(this.getCharacterInfo(tag)); chars.add(this.getCharacterInfo(tag));
} }
this.sendPacket(new SPacketCharacterList(this.selected, chars)); this.sendPacket(new SPacketCharacterList(this.selected, chars));
this.server.sendPacket(new SPacketMessage(String.format("%s hat das Spiel betreten", this.user), Type.FEED)); this.server.sendPacket(new SPacketMessage(String.format("%s hat das Spiel betreten", this.getUser()), Type.FEED));
} }
public void sendPacket(final Packet packet) public void sendPacket(final Packet packet)
@ -1779,7 +1734,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
} }
public void setAdmin(boolean admin) { public void setAdmin(boolean admin) {
this.admin = admin; super.setAdmin(admin);
if(!this.isAdmin() && this.entity != null && this.entity.noclip) { if(!this.isAdmin() && this.entity != null && this.entity.noclip) {
this.entity.noclip = false; this.entity.noclip = false;
this.entity.flying &= this.entity.hasEffect(Potion.FLYING) || this.entity.canNaturallyFly(); this.entity.flying &= this.entity.hasEffect(Potion.FLYING) || this.entity.canNaturallyFly();
@ -1956,11 +1911,11 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
} }
public String getExecId() { public String getExecId() {
return this.user; return this.getUser();
} }
public String getExecName() { public String getExecName() {
return this.entity != null ? this.entity.getCommandName() : this.user; return this.entity != null ? this.entity.getCommandName() : this.getUser();
} }
public Position getExecPos() { public Position getExecPos() {
@ -2893,12 +2848,12 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
break; break;
case START_PROFILING: case START_PROFILING:
if(this.admin) if(this.isAdmin())
this.profiling = true; this.profiling = true;
break; break;
case STOP_PROFILING: case STOP_PROFILING:
if(this.admin) if(this.isAdmin())
this.profiling = false; this.profiling = false;
break; break;

View file

@ -0,0 +1,121 @@
package server.network;
import java.io.File;
import java.security.PublicKey;
import java.util.Map;
import common.log.Log;
import common.network.IPlayer;
import common.tags.TagObject;
import common.util.EncryptUtil;
import common.util.Pair;
public class User {
private final String user;
private boolean admin;
private Pair<byte[], byte[]> password;
private PublicKey pubkey;
public User(String user) {
this.user = user;
}
public boolean isOnline() {
return false;
}
public String getUser() {
return this.user;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public boolean isAdmin() {
return this.admin;
}
public void setPasswordHash(Pair<byte[], byte[]> hash) {
this.password = hash;
}
public Pair<byte[], byte[]> getPasswordHash() {
return this.password;
}
public void setPubkey(PublicKey key) {
this.pubkey = key;
}
public PublicKey getPubkey() {
return this.pubkey;
}
public void copyFrom(User user) {
this.admin = user.admin;
this.password = user.password;
this.pubkey = user.pubkey;
}
public void readUserTags(TagObject tag) {
this.admin = tag.getBool("admin");
if(tag.hasByteArray("passwordHash") && tag.hasByteArray("passwordSalt"))
this.password = new Pair<byte[], byte[]>(tag.getByteArray("passwordHash"), tag.getByteArray("passwordSalt"));
if(tag.hasByteArray("pubkey"))
this.pubkey = EncryptUtil.decodePublicKey(tag.getByteArray("pubkey"));
}
public void writeUserTags(TagObject tag) {
if(this.admin)
tag.setBool("admin", this.admin);
if(this.password != null) {
tag.setByteArray("passwordHash", this.password.first());
tag.setByteArray("passwordSalt", this.password.second());
}
if(this.pubkey != null)
tag.setByteArray("pubkey", this.pubkey.getEncoded());
}
public static void saveDatabase(Map<String, User> map) {
TagObject tag = new TagObject();
for(User user : map.values()) {
TagObject data = new TagObject();
user.writeUserTags(data);
tag.setObject(user.getUser(), data);
}
File nfile = new File("users.cdt.tmp");
File lfile = new File("users.cdt");
try {
TagObject.writeGZip(tag, nfile);
if(lfile.exists())
lfile.delete();
nfile.renameTo(lfile);
}
catch(Exception e) {
Log.IO.error(e, "Fehler beim Schreiben von " + nfile);
}
}
public static void loadDatabase(Map<String, User> map) {
File file = new File("users.cdt");
if(!file.exists())
file = new File("users.cdt.tmp");
if(file.exists()) {
try {
TagObject tag = TagObject.readGZip(file);
for(String key : tag.keySet()) {
if(IPlayer.isValidUser(key) && tag.hasObject(key)) {
User user = new User(key);
user.readUserTags(tag.getObject(key));
map.put(key, user);
}
}
}
catch(Exception e) {
Log.IO.error(e, "Fehler beim Lesen von " + file);
map.clear();
}
}
}
}