add password hashing and commands
This commit is contained in:
parent
1b61f085e3
commit
ec0a1aa5c3
9 changed files with 148 additions and 19 deletions
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
|||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.security.KeyPair;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -854,7 +855,7 @@ public final class Server implements IThreadListener {
|
|||
if(tag != null)
|
||||
conn.readTags(tag);
|
||||
if(Config.authenticate) {
|
||||
if(conn.getPassword() == null && conn.getPubkey() == null) {
|
||||
if(conn.getPasswordHash() == null && conn.getPubkey() == null) {
|
||||
if(tag != null)
|
||||
return loginKey != null ? "Falscher Pubkey" : "Falsches Passwort";
|
||||
if(!Config.register)
|
||||
|
@ -870,11 +871,12 @@ public final class Server implements IThreadListener {
|
|||
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.setPassword(loginPass);
|
||||
conn.setPasswordHash(EncryptUtil.hashPassword(loginPass));
|
||||
Log.NETWORK.info(loginUser + " registrierte sich mit Passwort");
|
||||
}
|
||||
}
|
||||
else if(conn.getPubkey() != null ? !conn.getPubkey().equals(loginKey) : !conn.getPassword().equals(loginPass)) {
|
||||
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 {
|
||||
|
|
|
@ -25,6 +25,7 @@ import server.command.commands.CommandOfflinetp;
|
|||
import server.command.commands.CommandPasswd;
|
||||
import server.command.commands.CommandPlayers;
|
||||
import server.command.commands.CommandPotion;
|
||||
import server.command.commands.CommandPubkey;
|
||||
import server.command.commands.CommandRegister;
|
||||
import server.command.commands.CommandRemove;
|
||||
import server.command.commands.CommandRevoke;
|
||||
|
@ -280,6 +281,7 @@ public class CommandEnvironment {
|
|||
this.registerExecutable(new CommandMessage());
|
||||
this.registerExecutable(new CommandShutdown());
|
||||
this.registerExecutable(new CommandPasswd());
|
||||
this.registerExecutable(new CommandPubkey());
|
||||
this.registerExecutable(new CommandPlayers());
|
||||
this.registerExecutable(new CommandSave());
|
||||
this.registerExecutable(new CommandRegister());
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package server.command.commands;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import common.color.TextColor;
|
||||
import common.init.Config;
|
||||
import common.network.IPlayer;
|
||||
import common.util.EncryptUtil;
|
||||
import server.command.Command;
|
||||
import server.command.CommandEnvironment;
|
||||
import server.command.Executor;
|
||||
|
@ -25,6 +28,10 @@ public class CommandPasswd extends Command {
|
|||
throw new RunException("Bei Verwendung als Spieler darf kein Passwort angegeben werden");
|
||||
if(player.getAdmin() && player != exec)
|
||||
throw new RunException("%s ist ein Admin", player.getUser());
|
||||
if(player.getPubkey() != null && player == exec)
|
||||
throw new RunException("Es darf kein Pubkey vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
|
||||
if(player.getPasswordHash() == null && player == exec)
|
||||
throw new RunException("Es muss ein Passwort vorhanden sein, um diesen Befehl an sich selbst anzuwenden");
|
||||
((Player)exec).displayForm(new Form() {
|
||||
private Field checkField;
|
||||
private Field passwordField;
|
||||
|
@ -42,11 +49,11 @@ public class CommandPasswd extends Command {
|
|||
|
||||
protected void accept() {
|
||||
Player plr = env.getServer().getPlayer(player.getUser());
|
||||
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && 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");
|
||||
return;
|
||||
}
|
||||
if(this.checkField != null && !this.checkField.get().equals(plr.getPassword())) {
|
||||
if(this.checkField != null && !MessageDigest.isEqual(EncryptUtil.hashPassword(this.checkField.get(), plr.getPasswordHash().second()), plr.getPasswordHash().first())) {
|
||||
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
|
||||
return;
|
||||
}
|
||||
|
@ -54,7 +61,8 @@ public class CommandPasswd extends Command {
|
|||
exec.logConsole(TextColor.RED + "Passwörter stimmen nicht überein");
|
||||
return;
|
||||
}
|
||||
plr.setPassword(this.passwordField.get());
|
||||
plr.setPasswordHash(EncryptUtil.hashPassword(this.passwordField.get()));
|
||||
plr.setPubkey(null);
|
||||
exec.logConsole(TextColor.GREEN + "Passwort" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
|
||||
}
|
||||
});
|
||||
|
@ -62,7 +70,10 @@ public class CommandPasswd extends Command {
|
|||
else if(exec.isConsole()) {
|
||||
if(password == null)
|
||||
throw new RunException("Bei Verwendung in der Konsole muss ein Passwort angegeben werden");
|
||||
player.setPassword(password);
|
||||
if(password.length() < 8)
|
||||
throw new RunException("Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich");
|
||||
player.setPasswordHash(EncryptUtil.hashPassword(password));
|
||||
player.setPubkey(null);
|
||||
exec.logConsole(TextColor.GREEN + "Passwort für %s gesetzt", player.getUser());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package server.command.commands;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
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.util.Form;
|
||||
|
||||
public class CommandPubkey extends Command {
|
||||
public CommandPubkey() {
|
||||
super("pubkey");
|
||||
|
||||
this.addPlayer("player", true);
|
||||
this.setParamsOptional();
|
||||
this.addString("keySpec", false);
|
||||
this.addString("keyData", false);
|
||||
this.addString("keyHash", false);
|
||||
this.addString("keyName", false);
|
||||
}
|
||||
|
||||
public void exec(CommandEnvironment env, Executor exec, Player player, String keySpec, String keyData, String keyHash, String keyName) {
|
||||
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");
|
||||
if(player.getAdmin() && player != exec)
|
||||
throw new RunException("%s ist ein Admin", player.getUser());
|
||||
((Player)exec).displayForm(new Form() {
|
||||
private Field checkField;
|
||||
private Field keyField;
|
||||
|
||||
protected void init() {
|
||||
this.checkField = player.getPasswordHash() == null || player != exec ? null : this.addPassword("Aktuelles Passwort", 0, IPlayer.MAX_PASS_LENGTH, "");
|
||||
this.keyField = this.addField("Neuer Pubkey", 1, 960, "");
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return "Schlüssel für " + player.getUser() + " ändern";
|
||||
}
|
||||
|
||||
protected void accept() {
|
||||
Player plr = env.getServer().getPlayer(player.getUser());
|
||||
if(!((Player)exec).isAdmin() || plr == null || (plr.isAdmin() && plr != exec)) {
|
||||
exec.logConsole(TextColor.DRED + "Ein Fehler ist aufgetreten");
|
||||
return;
|
||||
}
|
||||
if(this.checkField != null && plr.getPasswordHash() != null && !MessageDigest.isEqual(EncryptUtil.hashPassword(this.checkField.get(), plr.getPasswordHash().second()), plr.getPasswordHash().first())) {
|
||||
exec.logConsole(TextColor.RED + "Falsches Passwort eingegeben");
|
||||
return;
|
||||
}
|
||||
Pair<PublicKey, String> key;
|
||||
try {
|
||||
key = EncryptUtil.parseArmoredPubkey(this.keyField.get());
|
||||
}
|
||||
catch(IllegalArgumentException e) {
|
||||
exec.logConsole(TextColor.RED + "Ungültiger Schlüssel");
|
||||
return;
|
||||
}
|
||||
plr.setPasswordHash(null);
|
||||
plr.setPubkey(key.first());
|
||||
exec.logConsole(TextColor.GREEN + "Schlüssel" + (plr != exec ? " für %s" : "") + " gesetzt", plr.getUser());
|
||||
}
|
||||
});
|
||||
}
|
||||
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");
|
||||
}
|
||||
player.setPasswordHash(null);
|
||||
player.setPubkey(key.first());
|
||||
exec.logConsole(TextColor.GREEN + "Schlüssel für %s gesetzt", player.getUser());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,6 +115,7 @@ import common.util.EncryptUtil;
|
|||
import common.util.ExtMath;
|
||||
import common.util.Facing;
|
||||
import common.util.IntHashMap;
|
||||
import common.util.Pair;
|
||||
import common.util.PortalType;
|
||||
import common.util.Position;
|
||||
import common.util.Vec3i;
|
||||
|
@ -172,7 +173,7 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
|||
private boolean admin;
|
||||
private int ping;
|
||||
private boolean deleted;
|
||||
private String password;
|
||||
private Pair<byte[], byte[]> password;
|
||||
private PublicKey pubkey;
|
||||
private boolean profiling;
|
||||
|
||||
|
@ -343,11 +344,11 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
|||
return this.isAdmin();
|
||||
}
|
||||
|
||||
public void setPassword(String pass) {
|
||||
this.password = pass;
|
||||
public void setPasswordHash(Pair<byte[], byte[]> hash) {
|
||||
this.password = hash;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
public Pair<byte[], byte[]> getPasswordHash() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
|
@ -628,8 +629,8 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
|||
|
||||
public void readTags(TagObject tag) {
|
||||
this.admin = tag.getBool("admin");
|
||||
if(tag.hasString("password"))
|
||||
this.password = tag.getString("password");
|
||||
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");
|
||||
|
@ -644,8 +645,10 @@ public class Player extends NetHandler implements ICrafting, Executor, IPlayer
|
|||
public void writeTags(TagObject tag) {
|
||||
if(this.admin)
|
||||
tag.setBool("admin", this.admin);
|
||||
if(this.password != null)
|
||||
tag.setString("password", this.password);
|
||||
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()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue