forked from TuxCoding/FastLogin
Fix NPE for skin apply in ProtocolLib mode (Related #182)
This commit is contained in:
@ -62,6 +62,7 @@ public class BukkitLoginSession extends LoginSession {
|
||||
return ArrayUtils.clone(verifyToken);
|
||||
}
|
||||
|
||||
//todo: this should be optional for players without a skin at all
|
||||
public synchronized SkinProperties getSkinProperty() {
|
||||
return skinProperty;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
|
||||
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
|
||||
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.JoinListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.LoginSkinApplyListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||
import com.github.games647.fastlogin.bukkit.tasks.DelayedAuthHook;
|
||||
@ -70,7 +70,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
//check for incoming messages from the bungeecord version of this plugin
|
||||
getServer().getMessenger().registerIncomingPluginChannel(this, getName(), new BungeeListener(this));
|
||||
getServer().getMessenger().registerOutgoingPluginChannel(this, getName());
|
||||
//register listeners on success
|
||||
} else {
|
||||
if (!core.setupDatabase()) {
|
||||
setEnabled(false);
|
||||
@ -81,11 +80,10 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
getServer().getPluginManager().registerEvents(new ProtocolSupportListener(this), this);
|
||||
} else if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
||||
//they will be created with a static builder, because otherwise it will throw a
|
||||
//java.lang.NoClassDefFoundError: com/comphenix/protocol/events/PacketListener if ProtocolSupport was
|
||||
//only found
|
||||
//NoClassDefFoundError: com/comphenix/protocol/events/PacketListener if only ProtocolSupport was found
|
||||
ProtocolLibListener.register(this);
|
||||
|
||||
getServer().getPluginManager().registerEvents(new LoginSkinApplyListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new SkinApplyListener(this), this);
|
||||
} else {
|
||||
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
|
||||
}
|
||||
|
@ -7,10 +7,12 @@ import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||
import com.google.common.net.HostAndPort;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -36,7 +38,8 @@ public class MojangApiBukkit extends MojangApiConnector {
|
||||
|
||||
HttpURLConnection conn = getConnection(url);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
//validate parsing
|
||||
//http://wiki.vg/Protocol_Encryption#Server
|
||||
VerificationReply verification = gson.fromJson(reader, VerificationReply.class);
|
||||
@ -50,7 +53,7 @@ public class MojangApiBukkit extends MojangApiConnector {
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} catch (IOException ex) {
|
||||
//catch not only io-exceptions also parse and NPE on unexpected json format
|
||||
logger.warn("Failed to verify session", ex);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class CrackedCommand implements CommandExecutor {
|
||||
plugin.getCore().sendLocaleMessage("remove-premium", sender);
|
||||
|
||||
profile.setPremium(false);
|
||||
profile.setUUID(null);
|
||||
profile.setUuid(null);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
plugin.getCore().getStorage().save(profile);
|
||||
});
|
||||
|
@ -14,6 +14,7 @@ import java.net.InetSocketAddress;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
|
||||
@ -93,6 +94,6 @@ public class ProtocolLibLoginSource implements LoginSource {
|
||||
}
|
||||
|
||||
public byte[] getVerifyToken() {
|
||||
return verifyToken;
|
||||
return ArrayUtils.clone(verifyToken);
|
||||
}
|
||||
}
|
||||
|
@ -19,15 +19,14 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
|
||||
public class LoginSkinApplyListener implements Listener {
|
||||
public class SkinApplyListener implements Listener {
|
||||
|
||||
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
|
||||
|
||||
private static final MethodAccessor GET_PROPERTIES = Accessors.getMethodAccessor(GAME_PROFILE, "getProperties");
|
||||
|
||||
private final FastLoginBukkit plugin;
|
||||
|
||||
public LoginSkinApplyListener(FastLoginBukkit plugin) {
|
||||
public SkinApplyListener(FastLoginBukkit plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@ -46,7 +45,10 @@ public class LoginSkinApplyListener implements Listener {
|
||||
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
|
||||
if (session.getUsername().equals(player.getName())) {
|
||||
SkinProperties skinProperty = session.getSkinProperty();
|
||||
applySkin(player, skinProperty.getValue(), skinProperty.getSignature());
|
||||
if (skinProperty != null) {
|
||||
applySkin(player, skinProperty.getValue(), skinProperty.getSignature());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -56,13 +58,13 @@ public class LoginSkinApplyListener implements Listener {
|
||||
private void applySkin(Player player, String skinData, String signature) {
|
||||
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player);
|
||||
if (skinData != null && signature != null) {
|
||||
WrappedSignedProperty skin = WrappedSignedProperty.fromValues("textures", skinData, signature);
|
||||
WrappedSignedProperty skin = WrappedSignedProperty.fromValues(SkinProperties.TEXTURE_KEY, skinData, signature);
|
||||
try {
|
||||
gameProfile.getProperties().put("textures", skin);
|
||||
gameProfile.getProperties().put(SkinProperties.TEXTURE_KEY, skin);
|
||||
} catch (ClassCastException castException) {
|
||||
Object map = GET_PROPERTIES.invoke(gameProfile.getHandle());
|
||||
try {
|
||||
MethodUtils.invokeMethod(map, "put", new Object[]{"textures", skin.getHandle()});
|
||||
MethodUtils.invokeMethod(map, "put", new Object[]{SkinProperties.TEXTURE_KEY, skin.getHandle()});
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
|
||||
plugin.getLog().error("Error setting premium skin", ex);
|
||||
}
|
@ -41,7 +41,7 @@ public class VerifyResponseTask implements Runnable {
|
||||
this.plugin = plugin;
|
||||
this.packetEvent = packetEvent;
|
||||
this.player = player;
|
||||
this.sharedSecret = sharedSecret;
|
||||
this.sharedSecret = Arrays.copyOf(sharedSecret, sharedSecret.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.PlayerProfile;
|
||||
import com.github.games647.fastlogin.core.mojang.SkinProperties;
|
||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@ -46,7 +47,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
||||
BukkitLoginSession session = plugin.getLoginSessions().get(address.toString());
|
||||
|
||||
//skin was resolved -> premium player
|
||||
if (propertiesResolveEvent.hasProperty("textures") && session != null) {
|
||||
if (propertiesResolveEvent.hasProperty(SkinProperties.TEXTURE_KEY) && session != null) {
|
||||
session.setVerified(true);
|
||||
}
|
||||
}
|
||||
|
@ -18,15 +18,17 @@ import org.bukkit.metadata.FixedMetadataValue;
|
||||
public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
|
||||
|
||||
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player) {
|
||||
super(core, player);
|
||||
super(core, player, getSession(core.getPlugin(), player));
|
||||
}
|
||||
|
||||
private static BukkitLoginSession getSession(FastLoginBukkit plugin, Player player) {
|
||||
//remove the bungeecord identifier if there is ones
|
||||
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
|
||||
return plugin.getLoginSessions().remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//remove the bungeecord identifier if there is ones
|
||||
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
|
||||
session = core.getPlugin().getLoginSessions().remove(id);
|
||||
|
||||
//blacklist this target player for BungeeCord Id brute force attacks
|
||||
FastLoginBukkit plugin = core.getPlugin();
|
||||
player.setMetadata(core.getPlugin().getName(), new FixedMetadataValue(plugin, true));
|
||||
|
@ -69,7 +69,7 @@ public class ConnectListener implements Listener {
|
||||
session.setUuid(connection.getUniqueId());
|
||||
|
||||
PlayerProfile playerProfile = session.getProfile();
|
||||
playerProfile.setUUID(connection.getUniqueId());
|
||||
playerProfile.setUuid(connection.getUniqueId());
|
||||
|
||||
//bungeecord will do this automatically so override it on disabled option
|
||||
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
||||
|
@ -44,7 +44,7 @@ public class AsyncToggleMessage implements Runnable {
|
||||
}
|
||||
|
||||
playerProfile.setPremium(false);
|
||||
playerProfile.setUUID(null);
|
||||
playerProfile.setUuid(null);
|
||||
core.getStorage().save(playerProfile);
|
||||
sendMessage("remove-premium");
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import com.google.common.io.ByteStreams;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
|
||||
@ -22,15 +21,13 @@ public class ForceLoginTask
|
||||
|
||||
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core,
|
||||
ProxiedPlayer player, Server server) {
|
||||
super(core, player);
|
||||
super(core, player, core.getPlugin().getSession().get(player.getPendingConnection()));
|
||||
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PendingConnection pendingConnection = player.getPendingConnection();
|
||||
session = core.getPlugin().getSession().get(pendingConnection);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class AuthStorage {
|
||||
|
||||
public void save(PlayerProfile playerProfile) {
|
||||
try (Connection con = dataSource.getConnection()) {
|
||||
UUID uuid = playerProfile.getUUID();
|
||||
UUID uuid = playerProfile.getUuid();
|
||||
|
||||
if (playerProfile.getUserId() == -1) {
|
||||
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
|
||||
|
@ -44,11 +44,11 @@ public class PlayerProfile {
|
||||
}
|
||||
|
||||
//todo: this should be optional
|
||||
public synchronized UUID getUUID() {
|
||||
public synchronized UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public synchronized void setUUID(UUID uuid) {
|
||||
public synchronized void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,9 @@ public class MojangApiConnector {
|
||||
|
||||
private Instant lastRateLimit = Instant.now().minus(10, ChronoUnit.MINUTES);
|
||||
|
||||
protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||
protected final Logger logger;
|
||||
protected final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||
|
||||
public MojangApiConnector(Logger logger, Collection<String> localAddresses, int rateLimit
|
||||
, Iterable<HostAndPort> proxies) {
|
||||
|
@ -2,6 +2,8 @@ package com.github.games647.fastlogin.core.mojang;
|
||||
|
||||
public class SkinProperties {
|
||||
|
||||
public static final String TEXTURE_KEY = "textures";
|
||||
|
||||
private final String name = "textures";
|
||||
|
||||
private String value;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.github.games647.fastlogin.core.mojang;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VerificationReply {
|
||||
@ -17,6 +18,6 @@ public class VerificationReply {
|
||||
}
|
||||
|
||||
public SkinProperties[] getProperties() {
|
||||
return properties;
|
||||
return Arrays.copyOf(properties, properties.length);
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
|
||||
protected final FastLoginCore<P, C, T> core;
|
||||
protected final P player;
|
||||
protected final L session;
|
||||
|
||||
protected L session;
|
||||
|
||||
public ForceLoginManagement(FastLoginCore<P, C, T> core, P player) {
|
||||
public ForceLoginManagement(FastLoginCore<P, C, T> core, P player, L session) {
|
||||
this.core = core;
|
||||
this.player = player;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,7 +49,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
if (success) {
|
||||
//update only on success to prevent corrupt data
|
||||
if (playerProfile != null) {
|
||||
playerProfile.setUUID(session.getUuid());
|
||||
playerProfile.setUuid(session.getUuid());
|
||||
playerProfile.setPremium(true);
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
@ -59,7 +59,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
||||
}
|
||||
} else if (playerProfile != null) {
|
||||
//cracked player
|
||||
playerProfile.setUUID(null);
|
||||
playerProfile.setUuid(null);
|
||||
playerProfile.setPremium(false);
|
||||
storage.save(playerProfile);
|
||||
}
|
||||
|
Reference in New Issue
Block a user