Send the correct kick packet to the client in order to show the reason

This commit is contained in:
games647
2015-10-01 19:35:41 +02:00
parent d573b11d77
commit 987518e0f4
7 changed files with 50 additions and 16 deletions

View File

@ -1,11 +1,19 @@
# FastLogin # FastLogin
Checks if a minecraft player has a valid premium (paid account). If so, they can skip offline authentification. Checks if a minecraft player has a valid premium (paid account). If so, they can skip offline authentication.
Requirements: ###Commands:
* /premium Marks the invoker as paid account
* /premium [playername] Mark player specified as a paid account
###Premissions:
* fastlogin.command.premium
* fastlogin.command.premium.others
###Requirements:
* [ProtocolLib](http://www.spigotmc.org/resources/protocollib.1997/) * [ProtocolLib](http://www.spigotmc.org/resources/protocollib.1997/)
* Bukkit 1.8.8 * Tested Bukkit 1.8.8 (could also work with other versions)
* Java 8 or above * Java 7 or above
* An auth plugin. Supported Plugins: * An auth plugin. Supported Plugins:
* [AuthMe](http://dev.bukkit.org/bukkit-plugins/authme-reloaded/) * [AuthMe](http://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
* [xAuth](http://dev.bukkit.org/bukkit-plugins/xauth/) * [xAuth](http://dev.bukkit.org/bukkit-plugins/xauth/)

View File

@ -8,7 +8,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<name>FastLogin</name> <name>FastLogin</name>
<version>0.2.2</version> <version>0.2.3</version>
<inceptionYear>2015</inceptionYear> <inceptionYear>2015</inceptionYear>
<url>https://github.com/games647/FastLogin</url> <url>https://github.com/games647/FastLogin</url>
<description> <description>
@ -127,12 +127,14 @@
<groupId>fr.xephi</groupId> <groupId>fr.xephi</groupId>
<artifactId>authme</artifactId> <artifactId>authme</artifactId>
<version>5.0-SNAPSHOT</version> <version>5.0-SNAPSHOT</version>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.luricos.bukkit</groupId> <groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId> <artifactId>xAuth</artifactId>
<version>2.6</version> <version>2.6</version>
<optional>true</optional>
<!--These artifacts produce conflicts on downloading--> <!--These artifacts produce conflicts on downloading-->
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -146,10 +148,12 @@
</exclusions> </exclusions>
</dependency> </dependency>
<!--No maven repository :(-->
<dependency> <dependency>
<groupId>de.st_ddt.crazy</groupId> <groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyCore</artifactId> <artifactId>CrazyCore</artifactId>
<version>10.7.7</version> <version>10.7.7</version>
<optional>true</optional>
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath> <systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath>
</dependency> </dependency>
@ -158,14 +162,17 @@
<groupId>de.st_ddt.crazy</groupId> <groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyLogin</artifactId> <artifactId>CrazyLogin</artifactId>
<version>7.23</version> <version>7.23</version>
<optional>true</optional>
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath> <systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath>
</dependency> </dependency>
<!--Maven repo down :(-->
<dependency> <dependency>
<groupId>me.lenis0012.ls</groupId> <groupId>me.lenis0012.ls</groupId>
<artifactId>LoginSecurity</artifactId> <artifactId>LoginSecurity</artifactId>
<version>2.0.10</version> <version>2.0.10</version>
<optional>true</optional>
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath> <systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath>
</dependency> </dependency>

View File

@ -149,7 +149,7 @@ public class FastLogin extends JavaPlugin {
} }
if (authPluginHook == null) { if (authPluginHook == null) {
//run this check for exceptions and not found plugins //run this check for exceptions (errors) and not found plugins
getLogger().warning("No support offline Auth plugin found. "); getLogger().warning("No support offline Auth plugin found. ");
getLogger().warning("Disabling this plugin..."); getLogger().warning("Disabling this plugin...");

View File

@ -7,6 +7,7 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory; import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.Encryption; import com.github.games647.fastlogin.Encryption;
import com.github.games647.fastlogin.FastLogin; import com.github.games647.fastlogin.FastLogin;
@ -137,14 +138,29 @@ public class EncryptionPacketListener extends PacketAdapter {
packetEvent.setCancelled(true); packetEvent.setCancelled(true);
} }
private void disconnect(PacketEvent packetEvent, String kickMessage, Level logLevel, String logMessage private void disconnect(PacketEvent packetEvent, String kickReason, Level logLevel, String logMessage
, Object... arguments) { , Object... arguments) {
plugin.getLogger().log(logLevel, logMessage, arguments); plugin.getLogger().log(logLevel, logMessage, arguments);
packetEvent.getPlayer().kickPlayer(kickMessage); kickPlayer(packetEvent.getPlayer(), kickReason);
//cancel the event in order to prevent the server receiving an invalid packet //cancel the event in order to prevent the server receiving an invalid packet
packetEvent.setCancelled(true); packetEvent.setCancelled(true);
} }
private void kickPlayer(Player player, String reason) {
PacketContainer kickPacket = protocolManager.createPacket(PacketType.Login.Server.DISCONNECT);
kickPacket.getChatComponents().write(0, WrappedChatComponent.fromText(reason));
try {
//send kick packet at login state
//the normal event.getPlayer.kickPlayer(String) method does only work at play state
protocolManager.sendServerPacket(player, kickPacket);
//tell the server that we want to close the connection
player.kickPlayer("Disconnect");
} catch (InvocationTargetException ex) {
plugin.getLogger().log(Level.SEVERE, "Error sending kickpacket", ex);
}
}
private Object getNetworkManager(Player player) private Object getNetworkManager(Player player)
throws SecurityException, IllegalAccessException, NoSuchFieldException { throws SecurityException, IllegalAccessException, NoSuchFieldException {
Object injector = TemporaryPlayerFactory.getInjectorFromPlayer(player); Object injector = TemporaryPlayerFactory.getInjectorFromPlayer(player);
@ -178,8 +194,8 @@ public class EncryptionPacketListener extends PacketAdapter {
//catch not only ioexceptions also parse and NPE on unexpected json format //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 if session is valid", ex);
} }
//this connection doesn't need to be closed. So can make use of keep alive in java
//this connection doesn't need to be closed. So can make use of keep alive in java
return false; return false;
} }
@ -191,11 +207,12 @@ public class EncryptionPacketListener extends PacketAdapter {
WrappedGameProfile fakeProfile = WrappedGameProfile.fromOfflinePlayer(Bukkit.getOfflinePlayer(username)); WrappedGameProfile fakeProfile = WrappedGameProfile.fromOfflinePlayer(Bukkit.getOfflinePlayer(username));
startPacket.getGameProfiles().write(0, fakeProfile); startPacket.getGameProfiles().write(0, fakeProfile);
try { try {
//we don't want to handle our own packets so ignore filters
protocolManager.recieveClientPacket(from, startPacket, false); protocolManager.recieveClientPacket(from, startPacket, false);
} catch (InvocationTargetException | IllegalAccessException ex) { } catch (InvocationTargetException | IllegalAccessException ex) {
plugin.getLogger().log(Level.WARNING, "Failed to fake a new start packet", ex); plugin.getLogger().log(Level.WARNING, "Failed to fake a new start packet", ex);
//cancel the event in order to prevent the server receiving an invalid packet //cancel the event in order to prevent the server receiving an invalid packet
from.kickPlayer("Error occurred"); kickPlayer(from, "Error occured");
} }
} }
} }

View File

@ -32,11 +32,13 @@ public class PlayerListener implements Listener {
//check if it's the same player as we checked before //check if it's the same player as we checked before
if (session != null && session.getUsername().equals(player.getName()) if (session != null && session.getUsername().equals(player.getName())
&& session.isVerified()) { && session.isVerified()) {
//java 8
// Bukkit.getScheduler().runTaskLater(plugin, () -> { // Bukkit.getScheduler().runTaskLater(plugin, () -> {
// if (player.isOnline()) { // if (player.isOnline()) {
// plugin.getLogger().log(Level.FINER, "Logging player {0} in", player.getName()); // plugin.getLogger().log(Level.FINER, "Logging player {0} in", player.getName());
// authPlugin.forceLogin(player); // authPlugin.forceLogin(player);
// } // }
//java 7+
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() { Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override @Override
@ -47,7 +49,7 @@ public class PlayerListener implements Listener {
} }
} }
//Wait before auth plugin initializes the player //Wait before auth plugin initializes the player
}, 1 * 20L); }, 2 * 20L);
} }
} }
} }

View File

@ -75,7 +75,7 @@ public class StartPacketListener extends PacketAdapter {
plugin.getLogger().log(Level.FINER, "Player {0} with {1} connecting to the server" plugin.getLogger().log(Level.FINER, "Player {0} with {1} connecting to the server"
, new Object[]{sessionKey, username}); , new Object[]{sessionKey, username});
//do premium login process //do premium login process
if (isPremium(username)) { if (plugin.getEnabledPremium().contains(username) && isPremium(username)) {
//minecraft server implementation //minecraft server implementation
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161 //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
sentEncryptionRequest(sessionKey, username, player, packetEvent); sentEncryptionRequest(sessionKey, username, player, packetEvent);
@ -84,7 +84,7 @@ public class StartPacketListener extends PacketAdapter {
private boolean isPremium(String playerName) { private boolean isPremium(String playerName) {
//check if it's a valid playername and the user activated fast logins //check if it's a valid playername and the user activated fast logins
if (playernameMatcher.matcher(playerName).matches() && plugin.getEnabledPremium().contains(playerName)) { if (playernameMatcher.matcher(playerName).matches()) {
//only make a API call if the name is valid existing mojang account //only make a API call if the name is valid existing mojang account
try { try {
HttpURLConnection connection = plugin.getConnection(UUID_LINK + playerName); HttpURLConnection connection = plugin.getConnection(UUID_LINK + playerName);
@ -119,7 +119,7 @@ public class StartPacketListener extends PacketAdapter {
random.nextBytes(verifyToken); random.nextBytes(verifyToken);
newPacket.getByteArrays().write(0, verifyToken); newPacket.getByteArrays().write(0, verifyToken);
protocolManager.sendServerPacket(player, newPacket, false); protocolManager.sendServerPacket(player, newPacket);
//cancel only if the player has a paid account otherwise login as normal offline player //cancel only if the player has a paid account otherwise login as normal offline player
packetEvent.setCancelled(true); packetEvent.setCancelled(true);

View File

@ -19,9 +19,9 @@ softdepend:
- LoginSecurity - LoginSecurity
commands: commands:
premium: ${project.artifactId}.:
description: 'Marks the invoker or the player specified as premium' description: 'Marks the invoker or the player specified as premium'
aliases: [prem, fastlogin, loginfast] aliases: [prem, premium, loginfast]
usage: /<command> [player] usage: /<command> [player]
permission: ${project.artifactId}.command.premium permission: ${project.artifactId}.command.premium