add encryption and enforce authentication
This commit is contained in:
parent
2ea3267e3a
commit
8d4b4b3619
16 changed files with 452 additions and 73 deletions
|
@ -6,6 +6,9 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
@ -67,6 +70,7 @@ import common.packet.SPacketTimeUpdate;
|
|||
import common.packet.SPacketWorld;
|
||||
import common.potion.PotionEffect;
|
||||
import common.util.BlockPos;
|
||||
import common.util.EncryptUtil;
|
||||
import common.util.ExtMath;
|
||||
import common.util.LazyLoadBase;
|
||||
import common.util.PortalType;
|
||||
|
@ -118,6 +122,7 @@ public final class Server implements IThreadListener {
|
|||
private final List<Dimension> unload = Lists.<Dimension>newArrayList();
|
||||
private final Map<String, Position> warps = Maps.<String, Position>newTreeMap();
|
||||
private final CommandEnvironment scriptEnv = new CommandEnvironment(this);
|
||||
private final KeyPair keyPair;
|
||||
private final boolean debug;
|
||||
|
||||
private WorldServer space;
|
||||
|
@ -238,6 +243,7 @@ public final class Server implements IThreadListener {
|
|||
}
|
||||
}
|
||||
}, "viewDistance");
|
||||
this.keyPair = EncryptUtil.generateKeyPair();
|
||||
}
|
||||
|
||||
public CommandEnvironment getScriptEnvironment() {
|
||||
|
@ -811,24 +817,22 @@ public final class Server implements IThreadListener {
|
|||
conn.readFromNBT(tag);
|
||||
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(/* !connection.isLocalChannel() && */ Config.auth) {
|
||||
if(conn.getPassword() == null) {
|
||||
if(!Config.register)
|
||||
return "Anmeldung neuer Accounts ist auf diesem Server deaktiviert (Whitelisted)";
|
||||
if(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.setPassword(loginPass);
|
||||
Log.JNI.info(loginUser + " registrierte sich mit Passwort");
|
||||
}
|
||||
else if(!conn.getPassword().equals(loginPass)) {
|
||||
return "Falsches Passwort";
|
||||
}
|
||||
else {
|
||||
Log.JNI.info(loginUser + " loggte sich mit Passwort ein");
|
||||
}
|
||||
}
|
||||
if(conn.getPassword() == null) {
|
||||
if(!Config.register)
|
||||
return "Anmeldung neuer Accounts ist auf diesem Server deaktiviert (Whitelisted)";
|
||||
if(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.setPassword(loginPass);
|
||||
Log.JNI.info(loginUser + " registrierte sich mit Passwort");
|
||||
}
|
||||
else if(!conn.getPassword().equals(loginPass)) {
|
||||
return "Falsches Passwort";
|
||||
}
|
||||
else {
|
||||
Log.JNI.info(loginUser + " loggte sich mit Passwort ein");
|
||||
}
|
||||
if(Config.compression >= 0) {
|
||||
connection.sendPacket(new RPacketEnableCompression(Config.compression), new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
|
@ -1300,4 +1304,12 @@ public final class Server implements IThreadListener {
|
|||
public void logConsole(String message) {
|
||||
Log.CONSOLE.info(message);
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
return this.keyPair.getPublic();
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey() {
|
||||
return this.keyPair.getPrivate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package server.network;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import common.color.TextColor;
|
||||
import common.init.Config;
|
||||
import common.log.Log;
|
||||
|
@ -7,23 +13,29 @@ import common.network.ILoginHandler;
|
|||
import common.network.IPlayer;
|
||||
import common.network.NetConnection;
|
||||
import common.network.NetHandler;
|
||||
import common.packet.LPacketLogin;
|
||||
import common.packet.LPacketPasswordResponse;
|
||||
import common.packet.LPacketStartEncrypt;
|
||||
import common.packet.RPacketDisconnect;
|
||||
import common.packet.RPacketRequestEncrypt;
|
||||
import server.Server;
|
||||
|
||||
public class LoginHandler extends NetHandler implements ILoginHandler
|
||||
{
|
||||
private static enum LoginState {
|
||||
PASSWORD, READY_TO_ACCEPT, ACCEPTED;
|
||||
INIT, ENCRYPT, PASSWORD, AUTHENTICATED, ACCEPTED;
|
||||
}
|
||||
|
||||
private static final SecureRandom TOKEN_RNG = new SecureRandom();
|
||||
|
||||
private final Server server;
|
||||
public final NetConnection netManager;
|
||||
|
||||
private LoginState state = LoginState.PASSWORD;
|
||||
private LoginState state = LoginState.INIT;
|
||||
private int timer;
|
||||
private String loginUser;
|
||||
private String loginPass;
|
||||
private byte[] loginToken;
|
||||
|
||||
public LoginHandler(Server server, NetConnection netManager)
|
||||
{
|
||||
|
@ -58,7 +70,7 @@ public class LoginHandler extends NetHandler implements ILoginHandler
|
|||
|
||||
public void update()
|
||||
{
|
||||
if(this.state == LoginState.READY_TO_ACCEPT)
|
||||
if(this.state == LoginState.AUTHENTICATED)
|
||||
this.tryAcceptPlayer();
|
||||
// else if (this.currentLoginState == LoginState.DELAY_ACCEPT)
|
||||
// {
|
||||
|
@ -93,15 +105,25 @@ public class LoginHandler extends NetHandler implements ILoginHandler
|
|||
this.state = LoginState.ACCEPTED;
|
||||
}
|
||||
|
||||
// public void processLoginStart(LPacketLoginStart packetIn)
|
||||
// {
|
||||
// if(this.state != LoginState.HELLO)
|
||||
// throw new IllegalStateException("Unerwartetes Start-Paket");
|
||||
// if(!this.netManager.isLocalChannel()) {
|
||||
// this.state = LoginState.PASSWORD;
|
||||
// this.netManager.sendPacket(new RPacketPasswordRequest()); // !Config.password.isEmpty(), Config.auth
|
||||
// }
|
||||
// }
|
||||
public void processLogin(LPacketLogin packet) {
|
||||
if(this.state != LoginState.INIT)
|
||||
throw new IllegalStateException("Unerwartetes Login-Paket");
|
||||
this.state = LoginState.ENCRYPT;
|
||||
this.loginToken = new byte[4];
|
||||
TOKEN_RNG.nextBytes(this.loginToken);
|
||||
this.netManager.sendPacket(new RPacketRequestEncrypt(this.server.getPublicKey(), this.loginToken));
|
||||
}
|
||||
|
||||
public void processEncryption(LPacketStartEncrypt packet) {
|
||||
if(this.state != LoginState.ENCRYPT)
|
||||
throw new IllegalStateException("Unerwartetes Verschlüsselungs-Paket");
|
||||
PrivateKey pkey = this.server.getPrivateKey();
|
||||
if(!Arrays.equals(this.loginToken, packet.getToken(pkey)))
|
||||
throw new IllegalStateException("Fehlerhaftes Token");
|
||||
SecretKey key = packet.getKey(pkey);
|
||||
this.netManager.startEncryption(key);
|
||||
this.state = LoginState.PASSWORD;
|
||||
}
|
||||
|
||||
public void processPasswordResponse(LPacketPasswordResponse packetIn) {
|
||||
if(this.state != LoginState.PASSWORD)
|
||||
|
@ -116,6 +138,6 @@ public class LoginHandler extends NetHandler implements ILoginHandler
|
|||
this.closeConnection("Falsches Zugangspasswort");
|
||||
return;
|
||||
}
|
||||
this.state = LoginState.READY_TO_ACCEPT;
|
||||
this.state = LoginState.AUTHENTICATED;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue