mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2026-01-30 10:02:14 +01:00
Fixed NPE on invalid sessions + Improved security for premium logins
This commit is contained in:
@@ -7,15 +7,30 @@ package com.github.games647.fastlogin;
|
||||
*/
|
||||
public class PlayerSession {
|
||||
|
||||
private final byte[] verifyToken;
|
||||
private final String username;
|
||||
private final String serverId;
|
||||
private final byte[] verifyToken;
|
||||
private boolean verified;
|
||||
|
||||
public PlayerSession(byte[] verifyToken, String username) {
|
||||
public PlayerSession(String username, String serverId, byte[] verifyToken) {
|
||||
this.username = username;
|
||||
this.serverId = serverId;
|
||||
this.verifyToken = verifyToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random generated server id. This makes sure the request
|
||||
* sent from the client is just for this server.
|
||||
*
|
||||
* See this for details
|
||||
* http://www.sk89q.com/2011/09/minecraft-name-spoofing-exploit/
|
||||
*
|
||||
* @return random generated server id
|
||||
*/
|
||||
public String getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the verify token the server sent to the client.
|
||||
*
|
||||
|
||||
@@ -34,17 +34,6 @@ public class PremiumCommand implements CommandExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sender.hasPermission(plugin.getName() + ".command." + command.getName() + ".others")) {
|
||||
String playerName = args[0];
|
||||
//todo check if valid username
|
||||
plugin.getEnabledPremium().add(playerName);
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Added "
|
||||
+ ChatColor.DARK_BLUE + ChatColor.BOLD + playerName
|
||||
+ ChatColor.RESET + ChatColor.DARK_GREEN + " to the list of premium players");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Not enough permissions");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,9 +100,13 @@ public class EncryptionPacketListener extends PacketAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
//this makes sure the request from the client is for us
|
||||
//this might be relevant http://www.sk89q.com/2011/09/minecraft-name-spoofing-exploit/
|
||||
String generatedId = session.getServerId();
|
||||
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L193
|
||||
//generate the server id based on client and server data
|
||||
byte[] serverIdHash = EncryptionUtil.getServerIdHash("", plugin.getServerKey().getPublic(), loginKey);
|
||||
byte[] serverIdHash = EncryptionUtil.getServerIdHash(generatedId, plugin.getServerKey().getPublic(), loginKey);
|
||||
String serverId = (new BigInteger(serverIdHash)).toString(16);
|
||||
|
||||
String username = session.getUsername();
|
||||
@@ -206,7 +210,7 @@ public class EncryptionPacketListener extends PacketAdapter {
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
if (!"null".equals(line)) {
|
||||
if (line != null && !line.equals("null")) {
|
||||
//validate parsing
|
||||
//http://wiki.vg/Protocol_Encryption#Server
|
||||
JSONObject userData = (JSONObject) JSONValue.parseWithException(line);
|
||||
@@ -222,7 +226,7 @@ public class EncryptionPacketListener extends PacketAdapter {
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//catch not only ioexceptions also parse and NPE on unexpected json format
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to verify if session is valid", ex);
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to verify session", ex);
|
||||
}
|
||||
|
||||
//this connection doesn't need to be closed. So can make use of keep alive in java
|
||||
|
||||
@@ -119,6 +119,10 @@ public class StartPacketListener extends PacketAdapter {
|
||||
*/
|
||||
PacketContainer newPacket = protocolManager.createPacket(PacketType.Login.Server.ENCRYPTION_BEGIN, true);
|
||||
|
||||
//randomized server id to make sure the request is for our server
|
||||
//this could be relevant http://www.sk89q.com/2011/09/minecraft-name-spoofing-exploit/
|
||||
String serverId = Long.toString(random.nextLong(), 16);
|
||||
newPacket.getStrings().write(0, serverId);
|
||||
newPacket.getSpecificModifier(PublicKey.class).write(0, plugin.getServerKey().getPublic());
|
||||
//generate a random token which should be the same when we receive it from the client
|
||||
byte[] verifyToken = new byte[VERIFY_TOKEN_LENGTH];
|
||||
@@ -129,7 +133,7 @@ public class StartPacketListener extends PacketAdapter {
|
||||
protocolManager.sendServerPacket(player, newPacket);
|
||||
|
||||
//cancel only if the player has a paid account otherwise login as normal offline player
|
||||
plugin.getSessions().put(sessionKey, new PlayerSession(verifyToken, username));
|
||||
plugin.getSessions().put(sessionKey, new PlayerSession(username, serverId, verifyToken));
|
||||
packetEvent.setCancelled(true);
|
||||
} catch (InvocationTargetException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Cannot send encryption packet. Falling back to normal login", ex);
|
||||
|
||||
Reference in New Issue
Block a user