Merge the Bukkit and BungeeCord version together to a universal plugin

This commit is contained in:
games647
2015-11-14 20:03:24 +01:00
parent c3f8e59a9a
commit f8c10d6890
30 changed files with 377 additions and 354 deletions

2
.gitignore vendored
View File

@ -39,4 +39,4 @@ hs_err_pid*
gradle-app.setting gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar !gradle-wrapper.jar

View File

@ -1,3 +1,7 @@
######0.3.1
* Improved BungeeCord security
#####0.3 #####0.3
* Added BungeeCord support * Added BungeeCord support

View File

@ -3,7 +3,7 @@
[![Build Status](https://travis-ci.org/games647/FastLogin.svg?branch=master)](https://travis-ci.org/games647/FastLogin) [![Build Status](https://travis-ci.org/games647/FastLogin.svg?branch=master)](https://travis-ci.org/games647/FastLogin)
Checks if a minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins). Checks if a minecraft player has a paid account (premium). If so, they can skip offline authentication (auth plugins).
So they don't need to enter passwords. This is also called auto login. So they don't need to enter passwords. This is also called auto login (auto-login).
###Features: ###Features:
* Detect paid accounts from others * Detect paid accounts from others
@ -12,8 +12,9 @@ So they don't need to enter passwords. This is also called auto login.
* Experimental Cauldron support * Experimental Cauldron support
* BungeeCord support * BungeeCord support
* No client modifications needed * No client modifications needed
* Good performance by async non blocking operations * Good performance by using async non blocking operations
* Free * Free
* Open source
*** ***
@ -118,8 +119,10 @@ by buying the username.
####Does the plugin have BungeeCord support? ####Does the plugin have BungeeCord support?
Yes it has. Just activate ipForward in your BungeeCord config and place the plugin in the plugins folder of Yes it has. Just activate ipForward in your BungeeCord config and place the plugin in the plugins folder of
Bukkit/Spigot and BungeeCord. This plugin will automatically detect if BungeeCord is running and so handle checks Bukkit/Spigot and BungeeCord. Then you have fill your BungeeCord Id (from the Stats-Option in the BungeeCord config)
there. into the whitelist file of your Bukkit/Spigot server. For security reasons, don't post this Id on Forums.
This plugin will automatically detect if BungeeCord is running and handle premium checks on BungeeCord.
####Could premium players have a premium UUID and Skin? ####Could premium players have a premium UUID and Skin?
Something like that is possible, but is not yet implemented. Something like that is possible, but is not yet implemented.

116
bukkit/pom.xml Normal file
View File

@ -0,0 +1,116 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin.bukkit</artifactId>
<packaging>jar</packaging>
<name>FastLoginBukkit</name>
<repositories>
<!--Bukkit-Server-API -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!--ProtocolLib-->
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
</repository>
<!--Authme Reloaded-->
<repository>
<id>xephi-repo</id>
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
</repository>
<!--xAuth-->
<repository>
<id>luricos.de-repo</id>
<url>http://repo.luricos.de/bukkit-plugins/</url>
</repository>
</repositories>
<dependencies>
<!--Server API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<!--Login Plugins-->
<dependency>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId>
<version>2.6</version>
<optional>true</optional>
<!--These artifacts produce conflicts on downloading-->
<exclusions>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
<exclusion>
<groupId>net.ess3</groupId>
<artifactId>EssentialsGroupManager</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--No maven repository :(-->
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyCore</artifactId>
<version>10.7.7</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath>
</dependency>
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyLogin</artifactId>
<version>7.23</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath>
</dependency>
<!--Maven repo down :(-->
<dependency>
<groupId>me.lenis0012.ls</groupId>
<artifactId>LoginSecurity</artifactId>
<version>2.0.10</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin; package com.github.games647.fastlogin.bukkit;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;

View File

@ -1,14 +1,14 @@
package com.github.games647.fastlogin; package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.listener.BukkitJoinListener;
import com.github.games647.fastlogin.bukkit.listener.StartPacketListener;
import com.github.games647.fastlogin.bukkit.listener.BungeeCordListener;
import com.github.games647.fastlogin.bukkit.listener.EncryptionPacketListener;
import com.github.games647.fastlogin.bukkit.listener.HandshakePacketListener;
import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.utility.SafeCacheBuilder; import com.comphenix.protocol.utility.SafeCacheBuilder;
import com.github.games647.fastlogin.hooks.AuthPlugin; import com.github.games647.fastlogin.bukkit.hooks.AuthPlugin;
import com.github.games647.fastlogin.listener.BukkitJoinListener;
import com.github.games647.fastlogin.listener.BungeeCordListener;
import com.github.games647.fastlogin.listener.EncryptionPacketListener;
import com.github.games647.fastlogin.listener.HandshakePacketListener;
import com.github.games647.fastlogin.listener.StartPacketListener;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -29,7 +29,7 @@ import org.bukkit.plugin.java.JavaPlugin;
/** /**
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication. * This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
*/ */
public class FastLogin extends JavaPlugin { public class FastLoginBukkit extends JavaPlugin {
//http connection, read timeout and user agent for a connection to mojang api servers //http connection, read timeout and user agent for a connection to mojang api servers
private static final int TIMEOUT = 1 * 1000; private static final int TIMEOUT = 1 * 1000;
@ -86,7 +86,8 @@ public class FastLogin extends JavaPlugin {
getCommand("premium").setExecutor(new PremiumCommand(this)); getCommand("premium").setExecutor(new PremiumCommand(this));
//check for incoming messages from the bungeecord version of this plugin //check for incoming messages from the bungeecord version of this plugin
getServer().getMessenger().registerIncomingPluginChannel(this, this.getName(), new BungeeCordListener(this)); getServer().getMessenger().registerIncomingPluginChannel(this, getName(), new BungeeCordListener(this));
getServer().getMessenger().registerOutgoingPluginChannel(this, getName());
} }
@Override @Override
@ -95,6 +96,11 @@ public class FastLogin extends JavaPlugin {
session.clear(); session.clear();
enabledPremium.clear(); enabledPremium.clear();
bungeeCordUsers.clear(); bungeeCordUsers.clear();
//remove old blacklists
for (Player player : getServer().getOnlinePlayers()) {
player.removeMetadata(getName(), this);
}
} }
/** /**

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin; package com.github.games647.fastlogin.bukkit;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;

View File

@ -1,5 +1,7 @@
package com.github.games647.fastlogin; package com.github.games647.fastlogin.bukkit;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -13,9 +15,9 @@ import org.bukkit.entity.Player;
*/ */
public class PremiumCommand implements CommandExecutor { public class PremiumCommand implements CommandExecutor {
private final FastLogin plugin; private final FastLoginBukkit plugin;
public PremiumCommand(FastLogin plugin) { public PremiumCommand(FastLoginBukkit plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
@ -31,9 +33,17 @@ public class PremiumCommand implements CommandExecutor {
String playerName = sender.getName(); String playerName = sender.getName();
plugin.getEnabledPremium().add(playerName); plugin.getEnabledPremium().add(playerName);
sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players"); sender.sendMessage(ChatColor.DARK_GREEN + "Added to the list of premium players");
notifiyBungeeCord((Player) sender);
return true; return true;
} }
return true; return true;
} }
private void notifiyBungeeCord(Player target) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
dataOutput.writeUTF("ACTIVE");
target.sendPluginMessage(plugin, plugin.getName(), dataOutput.toByteArray());
}
} }

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks; package com.github.games647.fastlogin.bukkit.hooks;
import fr.xephi.authme.api.NewAPI; import fr.xephi.authme.api.NewAPI;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks; package com.github.games647.fastlogin.bukkit.hooks;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks; package com.github.games647.fastlogin.bukkit.hooks;
import de.st_ddt.crazylogin.CrazyLogin; import de.st_ddt.crazylogin.CrazyLogin;
import de.st_ddt.crazylogin.data.LoginPlayerData; import de.st_ddt.crazylogin.data.LoginPlayerData;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks; package com.github.games647.fastlogin.bukkit.hooks;
import com.lenis0012.bukkit.ls.LoginSecurity; import com.lenis0012.bukkit.ls.LoginSecurity;

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.hooks; package com.github.games647.fastlogin.bukkit.hooks;
import de.luricos.bukkit.xAuth.xAuth; import de.luricos.bukkit.xAuth.xAuth;
import de.luricos.bukkit.xAuth.xAuthPlayer; import de.luricos.bukkit.xAuth.xAuthPlayer;

View File

@ -0,0 +1,66 @@
package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import com.github.games647.fastlogin.bukkit.hooks.AuthPlugin;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.FixedMetadataValue;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully.
* So the plugin can skip authentication.
*/
public class BukkitJoinListener implements Listener {
private static final long DELAY_LOGIN = 1 * 20L / 2;
protected final FastLoginBukkit plugin;
protected final AuthPlugin authPlugin;
public BukkitJoinListener(FastLoginBukkit plugin, AuthPlugin authPlugin) {
this.plugin = plugin;
this.authPlugin = authPlugin;
}
@EventHandler(ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
final Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
String address = player.getAddress().toString();
//removing the session because we now use it
PlayerSession session = plugin.getSessions().remove(address);
if (player.isOnline()) {
//blacklist this target player for BungeeCord Id brute force attacks
player.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
//check if it's the same player as we checked before
if (session != null && player.getName().equals(session.getUsername()) && session.isVerified()) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
}
}
}
//Wait before auth plugin and we received a message from BungeeCord initializes the player
}, DELAY_LOGIN);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
final Player player = quitEvent.getPlayer();
//prevent memory leaks
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@ -1,7 +1,7 @@
package com.github.games647.fastlogin.listener; package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.FastLogin; import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.PlayerSession; import com.github.games647.fastlogin.bukkit.PlayerSession;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
@ -13,23 +13,24 @@ import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.messaging.PluginMessageListener; import org.bukkit.plugin.messaging.PluginMessageListener;
/** /**
* Responsible for receiving messages from a BungeeCord instance. * Responsible for receiving messages from a BungeeCord instance.
* *
* This class also receives the plugin message from the bungeecord version of this plugin in order to * This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
* get notified if the connection is in online mode. * the connection is in online mode.
*/ */
public class BungeeCordListener implements PluginMessageListener { public class BungeeCordListener implements PluginMessageListener {
private static final String FILE_NAME = "proxy-whitelist.txt"; private static final String FILE_NAME = "proxy-whitelist.txt";
private final FastLogin plugin; private final FastLoginBukkit plugin;
//null if whitelist is empty so bungeecord support is disabled //null if whitelist is empty so bungeecord support is disabled
private final UUID proxyId; private final UUID proxyId;
public BungeeCordListener(FastLogin plugin) { public BungeeCordListener(FastLoginBukkit plugin) {
this.plugin = plugin; this.plugin = plugin;
this.proxyId = loadBungeeCordId(); this.proxyId = loadBungeeCordId();
} }
@ -44,23 +45,30 @@ public class BungeeCordListener implements PluginMessageListener {
String subchannel = dataInput.readUTF(); String subchannel = dataInput.readUTF();
plugin.getLogger().log(Level.FINEST, "Received plugin message for subchannel {0} from {1}" plugin.getLogger().log(Level.FINEST, "Received plugin message for subchannel {0} from {1}"
, new Object[]{subchannel, player}); , new Object[]{subchannel, player});
if ("Checked".equalsIgnoreCase(subchannel)) { if ("CHECKED".equalsIgnoreCase(subchannel)) {
//bungeecord UUID //make sure the proxy is allowed to transfer data to us
long mostSignificantBits = dataInput.readLong(); String playerName = dataInput.readUTF();
long leastSignificantBits = dataInput.readLong();
UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits); //check if the player is still online or disconnected
//fails too if no proxy id is specified in the whitelist file Player checkedPlayer = plugin.getServer().getPlayerExact(playerName);
if (sourceId.equals(proxyId)) { if (checkedPlayer != null && checkedPlayer.isOnline()
//make sure the proxy is allowed to transfer data to us //fail if target player is blacklisted because already authed or wrong bungeecord id
String playerName = dataInput.readUTF(); && !checkedPlayer.hasMetadata(plugin.getName())) {
//check if the player is still online or disconnected //bungeecord UUID
Player checkedPlayer = plugin.getServer().getPlayerExact(playerName); long mostSignificantBits = dataInput.readLong();
if (checkedPlayer != null && checkedPlayer.isOnline()) { long leastSignificantBits = dataInput.readLong();
UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits);
//fail if BungeeCord support is disabled (id = null)
if (sourceId.equals(proxyId)) {
PlayerSession playerSession = new PlayerSession(playerName, null, null); PlayerSession playerSession = new PlayerSession(playerName, null, null);
playerSession.setVerified(true); playerSession.setVerified(true);
//put it only if the user doesn't has a session open //put it only if the user doesn't has a session open
//so that the player have to send the bungeecord packet and cannot skip the verification then //so that the player have to send the bungeecord packet and cannot skip the verification then
plugin.getSessions().putIfAbsent(checkedPlayer.getAddress().toString(), playerSession); plugin.getSessions().putIfAbsent(checkedPlayer.getAddress().toString(), playerSession);
} else {
//blacklist target for the current login
checkedPlayer.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
} }
} }
} }

View File

@ -1,4 +1,4 @@
package com.github.games647.fastlogin.listener; package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.ProtocolManager;
@ -9,9 +9,9 @@ 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.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.EncryptionUtil; import com.github.games647.fastlogin.bukkit.EncryptionUtil;
import com.github.games647.fastlogin.FastLogin; import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.PlayerSession; import com.github.games647.fastlogin.bukkit.PlayerSession;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -54,9 +54,9 @@ public class EncryptionPacketListener extends PacketAdapter {
private final ProtocolManager protocolManager; private final ProtocolManager protocolManager;
//hides the inherit Plugin plugin field, but we need this type //hides the inherit Plugin plugin field, but we need this type
private final FastLogin plugin; private final FastLoginBukkit plugin;
public EncryptionPacketListener(FastLogin plugin, ProtocolManager protocolManger) { public EncryptionPacketListener(FastLoginBukkit plugin, ProtocolManager protocolManger) {
//run async in order to not block the server, because we make api calls to Mojang //run async in order to not block the server, because we make api calls to Mojang
super(params(plugin, PacketType.Login.Client.ENCRYPTION_BEGIN).optionAsync()); super(params(plugin, PacketType.Login.Client.ENCRYPTION_BEGIN).optionAsync());

View File

@ -1,10 +1,10 @@
package com.github.games647.fastlogin.listener; package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.FastLogin; import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.util.logging.Level; import java.util.logging.Level;
@ -27,9 +27,9 @@ import java.util.logging.Level;
public class HandshakePacketListener extends PacketAdapter { public class HandshakePacketListener extends PacketAdapter {
//hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin //hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin
private final FastLogin plugin; private final FastLoginBukkit plugin;
public HandshakePacketListener(FastLogin plugin) { public HandshakePacketListener(FastLoginBukkit plugin) {
//run async in order to not block the server, because we are making api calls to Mojang //run async in order to not block the server, because we are making api calls to Mojang
super(params(plugin, PacketType.Handshake.Client.SET_PROTOCOL).optionAsync()); super(params(plugin, PacketType.Handshake.Client.SET_PROTOCOL).optionAsync());

View File

@ -1,12 +1,12 @@
package com.github.games647.fastlogin.listener; package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.FastLogin; import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.PlayerSession; import com.github.games647.fastlogin.bukkit.PlayerSession;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -40,14 +40,14 @@ public class StartPacketListener extends PacketAdapter {
private final ProtocolManager protocolManager; private final ProtocolManager protocolManager;
//hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin //hides the inherit Plugin plugin field, but we need a more detailed type than just Plugin
private final FastLogin plugin; private final FastLoginBukkit plugin;
//just create a new once on plugin enable. This used for verify token generation //just create a new once on plugin enable. This used for verify token generation
private final Random random = new Random(); private final Random random = new Random();
//compile the pattern on plugin enable //compile the pattern on plugin enable
private final Pattern playernameMatcher = Pattern.compile(VALID_PLAYERNAME); private final Pattern playernameMatcher = Pattern.compile(VALID_PLAYERNAME);
public StartPacketListener(FastLogin plugin, ProtocolManager protocolManger) { public StartPacketListener(FastLoginBukkit plugin, ProtocolManager protocolManger) {
//run async in order to not block the server, because we are making api calls to Mojang //run async in order to not block the server, because we are making api calls to Mojang
super(params(plugin, PacketType.Login.Client.START).optionAsync()); super(params(plugin, PacketType.Login.Client.START).optionAsync());

View File

@ -1,6 +1,6 @@
# project informations for Bukkit in order to register our plugin with all it components # project informations for Bukkit in order to register our plugin with all it components
# ${project.name} are variables from Maven (pom.xml) which will be replaced after the build # ${-} are variables from Maven (pom.xml) which will be replaced after the build
name: ${project.name} name: ${project.parent.name}
version: ${project.version} version: ${project.version}
main: ${project.groupId}.${project.artifactId}.${project.name} main: ${project.groupId}.${project.artifactId}.${project.name}
@ -21,13 +21,13 @@ softdepend:
- LoginSecurity - LoginSecurity
commands: commands:
${project.artifactId}.: ${project.parent.name}:
description: 'Label the invoker or the player specified as premium' description: 'Label the invoker or the player specified as premium'
aliases: [prem, premium, loginfast] aliases: [prem, premium, loginfast]
usage: /<command> [player] usage: /<command> [player]
permission: ${project.artifactId}.command.premium permission: ${project.artifactId}.command.premium
permissions: permissions:
${project.artifactId}.command.premium: ${project.parent.name}.command.premium:
description: 'Label themselves as premium using a command' description: 'Label themselves as premium using a command'
default: true default: true

View File

@ -2,82 +2,19 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.github.games647</groupId> <parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<!--This have to be in lowercase because it's used by plugin.yml--> <!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastloginbungee</artifactId> <artifactId>fastlogin.bungee</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>FastLogin</name> <!--Represents the main plugin-->
<version>0.1</version> <name>FastLoginBungee</name>
<inceptionYear>2015</inceptionYear>
<url>https://github.com/games647/FastLogin</url>
<description>
Automatically logins premium (paid accounts) player on a offline mode server
</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--Possibility to deploy directly to the plugins folder-->
<outputDir>${basedir}/target</outputDir>
</properties>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/games647/FastLogin/issues</url>
</issueManagement>
<scm>
<url>https://github.com/games647/FastLogin</url>
<connection>scm:git:git://github.com/games647/FastLogin.git</connection>
<developerConnection>scm:git:ssh://git@github.com:games647/FastLogin.git</developerConnection>
</scm>
<build>
<defaultGoal>install</defaultGoal>
<!--Just use the project name to replace an old version of the plugin if the user does only copy-paste-->
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
<!--false means actual true http://jira.codehaus.org/browse/MCOMPILER-209-->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${outputDir}</outputDirectory>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<!--Replace variables-->
<filtering>true</filtering>
</resource>
<!--Add the license to jar in order to see it in the final jar-->
<resource>
<directory>${basedir}</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
</resources>
</build>
<repositories> <repositories>
<!-- BungeeCord --> <!-- BungeeCord -->

View File

@ -1,4 +1,4 @@
package com.github.games647.fastloginbungee; package com.github.games647.fastlogin.bungee;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -10,7 +10,7 @@ import net.md_5.bungee.api.plugin.Plugin;
* BungeeCord version of FastLogin. This plugin keeps track * BungeeCord version of FastLogin. This plugin keeps track
* on online mode connections. * on online mode connections.
*/ */
public class FastLogin extends Plugin { public class FastLoginBungee extends Plugin {
private final Set<String> enabledPremium = Sets.newConcurrentHashSet(); private final Set<String> enabledPremium = Sets.newConcurrentHashSet();
@ -19,8 +19,8 @@ public class FastLogin extends Plugin {
//events //events
getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this)); getProxy().getPluginManager().registerListener(this, new PlayerConnectionListener(this));
//commands //this is required to listen to messages from the server
getProxy().getPluginManager().registerCommand(this, new PremiumCommand(this)); getProxy().registerChannel(getDescription().getName());
} }
/** /**

View File

@ -1,5 +1,6 @@
package com.github.games647.fastloginbungee; package com.github.games647.fastlogin.bungee;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
@ -21,9 +22,9 @@ import net.md_5.bungee.event.EventHandler;
*/ */
public class PlayerConnectionListener implements Listener { public class PlayerConnectionListener implements Listener {
private final FastLogin plugin; private final FastLoginBungee plugin;
public PlayerConnectionListener(FastLogin plugin) { public PlayerConnectionListener(FastLoginBungee plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
@ -50,16 +51,16 @@ public class PlayerConnectionListener implements Listener {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput(); ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
//subchannel name //subchannel name
dataOutput.writeUTF("Checked"); dataOutput.writeUTF("CHECKED");
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
dataOutput.writeUTF(player.getName());
//proxy identifier to check if it's a acceptable proxy //proxy identifier to check if it's a acceptable proxy
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid()); UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
dataOutput.writeLong(proxyId.getMostSignificantBits()); dataOutput.writeLong(proxyId.getMostSignificantBits());
dataOutput.writeLong(proxyId.getLeastSignificantBits()); dataOutput.writeLong(proxyId.getLeastSignificantBits());
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
dataOutput.writeUTF(player.getName());
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray()); server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
} }
} }
@ -74,5 +75,16 @@ public class PlayerConnectionListener implements Listener {
//the client shouldn't be able to read the messages in order to know something about server internal states //the client shouldn't be able to read the messages in order to know something about server internal states
//moreover the client shouldn't be able fake a running premium check by sending the result message //moreover the client shouldn't be able fake a running premium check by sending the result message
pluginMessageEvent.setCancelled(true); pluginMessageEvent.setCancelled(true);
//check if the message is sent from the server
if (Server.class.isAssignableFrom(pluginMessageEvent.getSender().getClass())) {
byte[] data = pluginMessageEvent.getData();
ByteArrayDataInput dataInput = ByteStreams.newDataInput(data);
String subchannel = dataInput.readUTF();
if ("ACTIVE".equals(subchannel)) {
ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
plugin.getEnabledPremium().add(forPlayer.getName());
}
}
} }
} }

View File

@ -1,38 +0,0 @@
package com.github.games647.fastloginbungee;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
/**
* Let players activate the fastlogin method on a BungeeCord instance.
*/
public class PremiumCommand extends Command {
private final FastLogin plugin;
public PremiumCommand(FastLogin plugin) {
super(plugin.getDescription().getName()
, plugin.getDescription().getName() + ".command." + "premium"
, "prem" , "premium", "loginfast");
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!(sender instanceof ProxiedPlayer)) {
sender.sendMessage(new ComponentBuilder("Only player can invoke this command")
.color(ChatColor.DARK_RED)
.create());
return;
}
plugin.getEnabledPremium().add(sender.getName());
sender.sendMessage(new ComponentBuilder("Added to the list of premium players")
.color(ChatColor.DARK_GREEN)
.create());
}
}

View File

@ -1,8 +1,8 @@
# project informations for BungeeCord # project informations for BungeeCord
# This file will be prioritised over plugin.yml which can be also used for Bungee # This file will be prioritised over plugin.yml which can be also used for Bungee
# This make it easy to combine BungeeCord and Bukkit support in one plugin # This make it easy to combine BungeeCord and Bukkit support in one plugin
name: ${project.name} name: ${project.parent.name}
# ${...} will be automatically replaced by Maven # ${-} will be automatically replaced by Maven
main: ${project.groupId}.${project.artifactId}.${project.name} main: ${project.groupId}.${project.artifactId}.${project.name}
version: ${project.version} version: ${project.version}

127
pom.xml
View File

@ -4,23 +4,27 @@
<groupId>com.github.games647</groupId> <groupId>com.github.games647</groupId>
<!--This have to be in lowercase because it's used by plugin.yml--> <!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin</artifactId> <artifactId>fastlogin-parent</artifactId>
<packaging>jar</packaging> <packaging>pom</packaging>
<name>FastLogin</name> <name>FastLogin</name>
<version>0.3</version> <version>0.3</version>
<inceptionYear>2015</inceptionYear> <inceptionYear>2015</inceptionYear>
<url>https://github.com/games647/FastLogin</url> <url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
<description> <description>
Automatically logins premium (paid accounts) player on a offline mode server Automatically logins premium (paid accounts) player on a offline mode server
</description> </description>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--Possibility to deploy directly to the plugins folder-->
<outputDir>${basedir}/target</outputDir>
</properties> </properties>
<modules>
<module>bukkit</module>
<module>bungee</module>
<module>universal</module>
</modules>
<issueManagement> <issueManagement>
<system>GitHub</system> <system>GitHub</system>
<url>https://github.com/games647/FastLogin/issues</url> <url>https://github.com/games647/FastLogin/issues</url>
@ -41,7 +45,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version> <version>3.3</version>
<configuration> <configuration>
<source>1.7</source> <source>1.7</source>
<target>1.7</target> <target>1.7</target>
@ -51,15 +55,6 @@
<useIncrementalCompilation>false</useIncrementalCompilation> <useIncrementalCompilation>false</useIncrementalCompilation>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${outputDir}</outputDirectory>
</configuration>
</plugin>
</plugins> </plugins>
<resources> <resources>
@ -71,110 +66,12 @@
<!--Add the license to jar in order to see it in the final jar--> <!--Add the license to jar in order to see it in the final jar-->
<resource> <resource>
<directory>${basedir}</directory> <!--Parent folder-->
<directory>${basedir}/..</directory>
<includes> <includes>
<include>LICENSE</include> <include>LICENSE</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>
</build> </build>
<repositories>
<!--Bukkit-Server-API -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!--ProtocolLib-->
<repository>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
</repository>
<!--Authme Reloaded-->
<repository>
<id>xephi-repo</id>
<url>http://ci.xephi.fr/plugin/repository/everything/</url>
</repository>
<!--xAuth-->
<repository>
<id>luricos.de-repo</id>
<url>http://repo.luricos.de/bukkit-plugins/</url>
</repository>
</repositories>
<dependencies>
<!--Server API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<!--Login Plugins-->
<dependency>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId>
<version>2.6</version>
<optional>true</optional>
<!--These artifacts produce conflicts on downloading-->
<exclusions>
<exclusion>
<groupId>net.gravitydevelopment.updater</groupId>
<artifactId>updater</artifactId>
</exclusion>
<exclusion>
<groupId>net.ess3</groupId>
<artifactId>EssentialsGroupManager</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--No maven repository :(-->
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyCore</artifactId>
<version>10.7.7</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyCore v10.7.7.jar</systemPath>
</dependency>
<dependency>
<groupId>de.st_ddt.crazy</groupId>
<artifactId>CrazyLogin</artifactId>
<version>7.23</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CrazyLogin v7.23.2.jar</systemPath>
</dependency>
<!--Maven repo down :(-->
<dependency>
<groupId>me.lenis0012.ls</groupId>
<artifactId>LoginSecurity</artifactId>
<version>2.0.10</version>
<optional>true</optional>
<scope>system</scope>
<systemPath>${project.basedir}/lib/LoginSecurity v2.0.10.jar</systemPath>
</dependency>
</dependencies>
</project> </project>

View File

@ -1,53 +0,0 @@
package com.github.games647.fastlogin.listener;
import com.github.games647.fastlogin.FastLogin;
import com.github.games647.fastlogin.PlayerSession;
import com.github.games647.fastlogin.hooks.AuthPlugin;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
* plugin can skip authentication.
*/
public class BukkitJoinListener implements Listener {
private static final long DELAY_LOGIN = 2 * 20L;
protected final FastLogin plugin;
protected final AuthPlugin authPlugin;
public BukkitJoinListener(FastLogin plugin, AuthPlugin authPlugin) {
this.plugin = plugin;
this.authPlugin = authPlugin;
}
@EventHandler(ignoreCancelled = true)
public void onJoin(PlayerJoinEvent joinEvent) {
final Player player = joinEvent.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
String address = player.getAddress().toString();
//removing the session because we now use it
PlayerSession session = plugin.getSessions().remove(address);
//check if it's the same player as we checked before
if (player.isOnline() && session != null
&& player.getName().equals(session.getUsername()) && session.isVerified()) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
}
}
//Wait before auth plugin and we received a message from BungeeCord initializes the player
}, DELAY_LOGIN);
}
}

55
universal/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin-parent</artifactId>
<version>0.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>fastlogin-universal</artifactId>
<packaging>jar</packaging>
<name>FastLoginUniversal</name>
<build>
<defaultGoal>package</defaultGoal>
<finalName>${project.parent.name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>fastlogin.bukkit</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>fastlogin.bungee</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>