forked from TuxCoding/FastLogin
Modularize authentication backends
This commit is contained in:
@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
|
Dropped some features listed below. Please contact us if you still need them
|
||||||
|
|
||||||
* Dropped Java support < 11
|
* Dropped Java support < 11
|
||||||
* Removed configuration option to add multiple outgoing IPv4 towards Mojang
|
* Removed configuration option to add multiple outgoing IPv4 towards Mojang
|
||||||
* Was this really used?
|
* Dropped support for ProtocolSupport seems to unsupported
|
||||||
|
|
||||||
[...] A lot of changes
|
[...] A lot of changes
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.craftapi.model.skin.SkinProperty;
|
import com.github.games647.craftapi.model.skin.SkinProperty;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -25,23 +25,21 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.github.games647.fastlogin.bukkit.auth.AuthenticationBackend;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.ConnectionListener;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.ProtocolAuthentication;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.proxy.ProxyAuthentication;
|
||||||
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
|
import com.github.games647.fastlogin.bukkit.hook.DelayedAuthHook;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener;
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener;
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
|
||||||
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
|
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -71,18 +69,26 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
Duration.ofMinutes(1), -1
|
Duration.ofMinutes(1), -1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
private boolean serverStarted;
|
|
||||||
private BungeeManager bungeeManager;
|
|
||||||
private final BukkitScheduler scheduler;
|
private final BukkitScheduler scheduler;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
|
||||||
|
|
||||||
|
@Getter
|
||||||
private FloodgateService floodgateService;
|
private FloodgateService floodgateService;
|
||||||
private GeyserService geyserService;
|
private GeyserService geyserService;
|
||||||
|
|
||||||
private PremiumPlaceholder premiumPlaceholder;
|
private PremiumPlaceholder premiumPlaceholder;
|
||||||
|
|
||||||
|
private AuthenticationBackend backend;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
public FastLoginBukkit() {
|
public FastLoginBukkit() {
|
||||||
this.logger = CommonUtil.initializeLoggerService(getLogger());
|
this.logger = CommonUtil.initializeLoggerService(getLogger());
|
||||||
this.scheduler = new BukkitScheduler(this, logger);
|
this.scheduler = new BukkitScheduler(this, logger);
|
||||||
@ -104,51 +110,42 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bungeeManager = new BungeeManager(this);
|
backend = initializeAuthenticationBackend();
|
||||||
bungeeManager.initialize();
|
if (backend == null) {
|
||||||
|
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
|
||||||
PluginManager pluginManager = getServer().getPluginManager();
|
setEnabled(false);
|
||||||
if (bungeeManager.isEnabled()) {
|
return;
|
||||||
markInitialized();
|
|
||||||
} else {
|
|
||||||
if (!core.setupDatabase()) {
|
|
||||||
setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AntiBotService antiBotService = core.getAntiBotService();
|
|
||||||
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
|
|
||||||
pluginManager.registerEvents(new ProtocolSupportListener(this, antiBotService), this);
|
|
||||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
|
||||||
ProtocolLibListener.register(this, antiBotService, core.getConfig().getBoolean("verifyClientKeys"));
|
|
||||||
|
|
||||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
|
||||||
if (!isPaper() && getConfig().getBoolean("forwardSkin")) {
|
|
||||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
|
|
||||||
setEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//delay dependency setup because we load the plugin very early where plugins are initialized yet
|
backend.init(getServer().getPluginManager());
|
||||||
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
|
PluginManager pluginManager = getServer().getPluginManager();
|
||||||
|
|
||||||
pluginManager.registerEvents(new ConnectionListener(this), this);
|
pluginManager.registerEvents(new ConnectionListener(this), this);
|
||||||
|
|
||||||
//if server is using paper - we need to add one more listener to correct the user cache usage
|
|
||||||
if (isPaper()) {
|
|
||||||
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
registerCommands();
|
registerCommands();
|
||||||
|
|
||||||
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
|
||||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||||
premiumPlaceholder.register();
|
premiumPlaceholder.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delay dependency setup because we load the plugin very early where plugins are initialized yet
|
||||||
|
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationBackend initializeAuthenticationBackend() {
|
||||||
|
AuthenticationBackend proxyVerifier = new ProxyAuthentication(this);
|
||||||
|
if (proxyVerifier.isAvailable()) {
|
||||||
|
return proxyVerifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
|
||||||
|
AuthenticationBackend protocolAuthentication = new ProtocolAuthentication(this);
|
||||||
|
if (protocolAuthentication.isAvailable()) {
|
||||||
|
return protocolAuthentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
@ -182,25 +179,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
core.close();
|
core.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bungeeManager != null) {
|
if (backend != null) {
|
||||||
bungeeManager.cleanup();
|
backend.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||||
try {
|
premiumPlaceholder.unregister();
|
||||||
premiumPlaceholder.unregister();
|
|
||||||
} catch (Exception | NoSuchMethodError exception) {
|
|
||||||
logger.error("Failed to unregister placeholder", exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
|
|
||||||
return core;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,10 +217,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
loginSession.remove(id);
|
loginSession.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<UUID, PremiumStatus> getPremiumPlayers() {
|
|
||||||
return premiumPlayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the premium status of an online player.
|
* Fetches the premium status of an online player.
|
||||||
* {@snippet :
|
* {@snippet :
|
||||||
@ -263,24 +244,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait before the server is fully started. This is workaround, because connections right on startup are not
|
|
||||||
* injected by ProtocolLib
|
|
||||||
*
|
|
||||||
* @return true if ProtocolLib can now intercept packets
|
|
||||||
*/
|
|
||||||
public boolean isServerFullyStarted() {
|
|
||||||
return serverStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markInitialized() {
|
|
||||||
this.serverStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BungeeManager getBungeeManager() {
|
|
||||||
return bungeeManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path getPluginFolder() {
|
public Path getPluginFolder() {
|
||||||
return getDataFolder().toPath();
|
return getDataFolder().toPath();
|
||||||
@ -313,12 +276,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FloodgateService getFloodgateService() {
|
public void setInitialized(boolean hookFound) {
|
||||||
return floodgateService;
|
if (backend instanceof ProxyAuthentication) {
|
||||||
}
|
logger.info("BungeeCord setting detected. No auth plugin is required");
|
||||||
|
} else if (!hookFound) {
|
||||||
|
logger.warn("No auth plugin were found by this plugin "
|
||||||
|
+ "(other plugins could hook into this after the initialization of this plugin)"
|
||||||
|
+ "and BungeeCord is deactivated. "
|
||||||
|
+ "Either one or both of the checks have to pass in order to use this plugin");
|
||||||
|
}
|
||||||
|
|
||||||
public GeyserService getGeyserService() {
|
initialized = true;
|
||||||
return geyserService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -326,19 +294,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
if (floodgateService != null) {
|
if (floodgateService != null) {
|
||||||
return floodgateService;
|
return floodgateService;
|
||||||
}
|
}
|
||||||
|
|
||||||
return geyserService;
|
return geyserService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPaper() {
|
|
||||||
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|
|
||||||
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Class<?>> isClassAvailable(String clazzName) {
|
|
||||||
try {
|
|
||||||
return Optional.of(Class.forName(clazzName));
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,44 +23,15 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
public interface AuthenticationBackend {
|
||||||
|
|
||||||
public class ProtocolLoginSource implements LoginSource {
|
boolean isAvailable();
|
||||||
|
|
||||||
private final PlayerLoginStartEvent loginStartEvent;
|
void init(PluginManager pluginManager);
|
||||||
|
|
||||||
public ProtocolLoginSource(PlayerLoginStartEvent loginStartEvent) {
|
void stop();
|
||||||
this.loginStartEvent = loginStartEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enableOnlinemode() {
|
|
||||||
loginStartEvent.setOnlineMode(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kick(String message) {
|
|
||||||
loginStartEvent.denyLogin(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress getAddress() {
|
|
||||||
return loginStartEvent.getConnection().getRawAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayerLoginStartEvent getLoginStartEvent() {
|
|
||||||
return loginStartEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getClass().getSimpleName() + '{'
|
|
||||||
+ "loginStartEvent=" + loginStartEvent
|
|
||||||
+ '}';
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,23 +23,17 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
|
|
||||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
|
||||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.metadata.Metadatable;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,14 +50,6 @@ public class ConnectionListener implements Listener {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
|
||||||
removeBlockedStatus(loginEvent.getPlayer());
|
|
||||||
if (loginEvent.getResult() == Result.ALLOWED && !plugin.isServerFullyStarted()) {
|
|
||||||
loginEvent.disallow(Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||||
Player player = joinEvent.getPlayer();
|
Player player = joinEvent.getPlayer();
|
||||||
@ -102,21 +88,13 @@ public class ConnectionListener implements Listener {
|
|||||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getBungeeManager().markJoinEventFired(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||||
Player player = quitEvent.getPlayer();
|
Player player = quitEvent.getPlayer();
|
||||||
|
|
||||||
removeBlockedStatus(player);
|
|
||||||
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
|
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
|
||||||
plugin.getPremiumPlayers().remove(player.getUniqueId());
|
plugin.getPremiumPlayers().remove(player.getUniqueId());
|
||||||
plugin.getBungeeManager().cleanup(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeBlockedStatus(Metadatable player) {
|
|
||||||
player.removeMetadata(plugin.getName(), plugin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.SkinApplyListener;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class LocalAuthentication implements AuthenticationBackend {
|
||||||
|
|
||||||
|
protected final FastLoginBukkit plugin;
|
||||||
|
|
||||||
|
protected LocalAuthentication(FastLoginBukkit plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(PluginManager pluginManager) {
|
||||||
|
if (!plugin.getCore().setupDatabase()) {
|
||||||
|
plugin.setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if server is using paper - we need to add one more listener to correct the user cache usage
|
||||||
|
if (isPaper()) {
|
||||||
|
pluginManager.registerEvents(new PaperCacheListener(this), this);
|
||||||
|
} else if (plugin.getConfig().getBoolean("forwardSkin")) {
|
||||||
|
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
||||||
|
pluginManager.registerEvents(new SkinApplyListener(plugin), plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPaper() {
|
||||||
|
return isClassAvailable("com.destroystokyo.paper.PaperConfig").isPresent()
|
||||||
|
|| isClassAvailable("io.papermc.paper.configuration.Configuration").isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Class<?>> isClassAvailable(String clazzName) {
|
||||||
|
try {
|
||||||
|
return Optional.of(Class.forName(clazzName));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth;
|
||||||
|
|
||||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||||
import com.github.games647.craftapi.model.skin.Textures;
|
import com.github.games647.craftapi.model.skin.Textures;
|
@ -23,10 +23,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.hash.Hasher;
|
import com.google.common.hash.Hasher;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
@ -58,8 +58,8 @@ import java.time.Instant;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Base64.Encoder;
|
import java.util.Base64.Encoder;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.random.RandomGenerator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encryption and decryption minecraft util for connection between servers
|
* Encryption and decryption minecraft util for connection between servers
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
|
||||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.LocalAuthentication;
|
||||||
|
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||||
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
public class ProtocolAuthentication extends LocalAuthentication implements Listener {
|
||||||
|
|
||||||
|
public ProtocolAuthentication(FastLoginBukkit plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return plugin.getServer().getPluginManager().isPluginEnabled("ProtocolLib");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(PluginManager pluginManager) {
|
||||||
|
pluginManager.registerEvents(this, plugin);
|
||||||
|
|
||||||
|
FastLoginCore<Player, CommandSender, FastLoginBukkit> core = plugin.getCore();
|
||||||
|
AntiBotService antiBotService = core.getAntiBotService();
|
||||||
|
ProtocolLibListener.register(plugin, antiBotService, core.getConfig().getBoolean("verifyClientKeys"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
ProtocolLibrary.getProtocolManager().getAsynchronousManager().unregisterAsyncHandlers(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
||||||
|
if (loginEvent.getResult() == PlayerLoginEvent.Result.ALLOWED && !plugin.isInitialized()) {
|
||||||
|
loginEvent.disallow(PlayerLoginEvent.Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
@ -42,7 +42,7 @@ import com.comphenix.protocol.wrappers.Converters;
|
|||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
@ -23,14 +23,14 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.ProtocolManager;
|
import com.comphenix.protocol.ProtocolManager;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSource;
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||||
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib;
|
||||||
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
@ -47,8 +47,8 @@ import com.github.games647.craftapi.model.skin.SkinProperty;
|
|||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.InetUtils;
|
import com.github.games647.fastlogin.bukkit.auth.InetUtils;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
@ -23,7 +23,7 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
|
package com.github.games647.fastlogin.bukkit.auth.protocollib.packet;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.AuthenticationBackend;
|
||||||
|
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||||
|
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
|
||||||
|
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
|
||||||
|
|
||||||
|
public class ProxyAuthentication implements AuthenticationBackend {
|
||||||
|
|
||||||
|
private final FastLoginBukkit plugin;
|
||||||
|
private ProxyVerifier verifier;
|
||||||
|
|
||||||
|
public ProxyAuthentication(FastLoginBukkit plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return detectProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(PluginManager pluginManager) {
|
||||||
|
verifier = new ProxyVerifier(plugin);
|
||||||
|
verifier.loadSecrets();
|
||||||
|
|
||||||
|
registerPluginChannels();
|
||||||
|
|
||||||
|
pluginManager.registerEvents(new ProxyConnectionListener(plugin, verifier), plugin);
|
||||||
|
|
||||||
|
plugin.getLog().info("Found enabled proxy configuration");
|
||||||
|
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerPluginChannels() {
|
||||||
|
Server server = Bukkit.getServer();
|
||||||
|
|
||||||
|
// check for incoming messages from the bungeecord version of this plugin
|
||||||
|
String groupId = plugin.getName();
|
||||||
|
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
|
||||||
|
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new ProxyListener(plugin, verifier));
|
||||||
|
|
||||||
|
// outgoing
|
||||||
|
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
|
||||||
|
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
|
||||||
|
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
|
||||||
|
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
if (verifier != null) {
|
||||||
|
verifier.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean detectProxy() {
|
||||||
|
try {
|
||||||
|
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
// leave stacktrace for class not found out
|
||||||
|
plugin.getLog().warn("Cannot check for BungeeCord support: {}", classNotFoundException.getMessage());
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||||
|
plugin.getLog().warn("Cannot check for BungeeCord support", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return isVelocityEnabled();
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
plugin.getLog().warn("Cannot check for Velocity support in Paper: {}", classNotFoundException.getMessage());
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
||||||
|
plugin.getLog().warn("Cannot check for Velocity support in Paper", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isProxySupported(String className, String fieldName)
|
||||||
|
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||||
|
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVelocityEnabled()
|
||||||
|
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
|
||||||
|
NoSuchMethodException, InvocationTargetException {
|
||||||
|
try {
|
||||||
|
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
|
||||||
|
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
|
||||||
|
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
|
||||||
|
|
||||||
|
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
|
||||||
|
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
|
||||||
|
|
||||||
|
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
// try again using the older Paper configuration, because the old class file still exists in newer versions
|
||||||
|
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2024 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.FloodgateAuthTask;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
|
||||||
|
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.metadata.Metadatable;
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
|
public class ProxyConnectionListener implements Listener {
|
||||||
|
|
||||||
|
private static final long DELAY_LOGIN = 20L / 2;
|
||||||
|
|
||||||
|
private final FastLoginBukkit plugin;
|
||||||
|
private final ProxyVerifier verifier;
|
||||||
|
|
||||||
|
public ProxyConnectionListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.verifier = verifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeBlockedStatus(Metadatable player) {
|
||||||
|
player.removeMetadata(plugin.getName(), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
|
||||||
|
removeBlockedStatus(loginEvent.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
|
||||||
|
Player player = joinEvent.getPlayer();
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||||
|
delayForceLogin(player);
|
||||||
|
// delay the login process to let auth plugins initialize the player
|
||||||
|
// Magic number however as there is no direct event from those plugins
|
||||||
|
}, DELAY_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delayForceLogin(Player player) {
|
||||||
|
// session exists so the player is ready for force login
|
||||||
|
// cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already
|
||||||
|
// having the login session from the login process
|
||||||
|
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
|
||||||
|
|
||||||
|
if (session == null) {
|
||||||
|
// Floodgate players usually don't have a session at this point
|
||||||
|
// exception: if force login by bungee message had been delayed
|
||||||
|
FloodgateService floodgateService = plugin.getFloodgateService();
|
||||||
|
if (floodgateService != null) {
|
||||||
|
FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
|
||||||
|
if (floodgatePlayer != null) {
|
||||||
|
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
|
||||||
|
plugin.getLog().info("No on-going login session for player: {} with ID {}. ", player, sessionId);
|
||||||
|
plugin.getLog().info("Setups using Minecraft proxies will start delayed "
|
||||||
|
+ "when the command from the proxy is received");
|
||||||
|
} else {
|
||||||
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifier.markJoinEventFired(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
|
||||||
|
Player player = quitEvent.getPlayer();
|
||||||
|
|
||||||
|
removeBlockedStatus(player);
|
||||||
|
verifier.cleanup(player);
|
||||||
|
}
|
||||||
|
}
|
@ -23,11 +23,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener;
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
|
import com.github.games647.fastlogin.bukkit.auth.ForceLoginTask;
|
||||||
import com.github.games647.fastlogin.core.PremiumStatus;
|
import com.github.games647.fastlogin.core.PremiumStatus;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
||||||
@ -47,12 +47,14 @@ import java.util.UUID;
|
|||||||
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
|
* This class also receives the plugin message from the bungeecord version of this plugin in order to get notified if
|
||||||
* the connection is in online mode.
|
* the connection is in online mode.
|
||||||
*/
|
*/
|
||||||
public class BungeeListener implements PluginMessageListener {
|
public class ProxyListener implements PluginMessageListener {
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
|
private final ProxyVerifier verifier;
|
||||||
|
|
||||||
public BungeeListener(FastLoginBukkit plugin) {
|
public ProxyListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.verifier = verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -79,7 +81,7 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
|
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
|
||||||
} else {
|
} else {
|
||||||
UUID sourceId = loginMessage.getProxyId();
|
UUID sourceId = loginMessage.getProxyId();
|
||||||
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
|
if (verifier.isProxyAllowed(sourceId)) {
|
||||||
readMessage(targetPlayer, loginMessage);
|
readMessage(targetPlayer, loginMessage);
|
||||||
} else {
|
} else {
|
||||||
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
|
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
|
||||||
@ -127,7 +129,7 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
plugin.putSession(player.spigot().getRawAddress(), session);
|
plugin.putSession(player.spigot().getRawAddress(), session);
|
||||||
|
|
||||||
// only start a new login task if the join event fired earlier. This event then didn't
|
// only start a new login task if the join event fired earlier. This event then didn't
|
||||||
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
|
boolean result = verifier.didJoinEventFired(player);
|
||||||
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
|
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
|
||||||
if (result) {
|
if (result) {
|
||||||
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
|
@ -23,22 +23,18 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit.auth.proxy;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
import com.github.games647.fastlogin.core.message.ChannelMessage;
|
||||||
import com.github.games647.fastlogin.core.message.LoginActionMessage;
|
|
||||||
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
import com.github.games647.fastlogin.core.message.NamespaceKey;
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -48,11 +44,9 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
|
|
||||||
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
|
|
||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
|
|
||||||
public class BungeeManager {
|
public class ProxyVerifier {
|
||||||
|
|
||||||
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
|
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
|
||||||
private static final String FILE_NAME = "allowed-proxies.txt";
|
private static final String FILE_NAME = "allowed-proxies.txt";
|
||||||
@ -61,11 +55,10 @@ public class BungeeManager {
|
|||||||
private Set<UUID> proxyIds;
|
private Set<UUID> proxyIds;
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
private final FastLoginBukkit plugin;
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
private final Collection<UUID> firedJoinEvents = new HashSet<>();
|
private final Collection<UUID> firedJoinEvents = new HashSet<>();
|
||||||
|
|
||||||
public BungeeManager(FastLoginBukkit plugin) {
|
public ProxyVerifier(FastLoginBukkit plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,92 +77,13 @@ public class BungeeManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public void loadSecrets() {
|
||||||
return enabled;
|
proxyIds = loadBungeeCordIds();
|
||||||
}
|
if (proxyIds.isEmpty()) {
|
||||||
|
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
|
||||||
public void initialize() {
|
|
||||||
enabled = detectProxy();
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
proxyIds = loadBungeeCordIds();
|
|
||||||
if (proxyIds.isEmpty()) {
|
|
||||||
plugin.getLog().info("No valid IDs found. Minecraft proxy support cannot work in the current state");
|
|
||||||
}
|
|
||||||
|
|
||||||
registerPluginChannels();
|
|
||||||
plugin.getLog().info("Found enabled proxy configuration");
|
|
||||||
plugin.getLog().info("Remember to follow the proxy guide to complete your setup");
|
|
||||||
} else {
|
|
||||||
plugin.getLog().warn("Disabling Minecraft proxy configuration. Assuming direct connections from now on.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isProxySupported(String className, String fieldName)
|
|
||||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
|
||||||
return Class.forName(className).getDeclaredField(fieldName).getBoolean(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isVelocityEnabled()
|
|
||||||
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException,
|
|
||||||
NoSuchMethodException, InvocationTargetException {
|
|
||||||
try {
|
|
||||||
Class<?> globalConfig = Class.forName("io.papermc.paper.configuration.GlobalConfiguration");
|
|
||||||
Object global = globalConfig.getDeclaredMethod("get").invoke(null);
|
|
||||||
Object proxiesConfiguration = global.getClass().getDeclaredField("proxies").get(global);
|
|
||||||
|
|
||||||
Field velocitySectionField = proxiesConfiguration.getClass().getDeclaredField("velocity");
|
|
||||||
Object velocityConfig = velocitySectionField.get(proxiesConfiguration);
|
|
||||||
|
|
||||||
return velocityConfig.getClass().getDeclaredField("enabled").getBoolean(velocityConfig);
|
|
||||||
} catch (ClassNotFoundException classNotFoundException) {
|
|
||||||
// try again using the older Paper configuration, because the old class file still exists in newer versions
|
|
||||||
if (isProxySupported("com.destroystokyo.paper.PaperConfig", "velocitySupport")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean detectProxy() {
|
|
||||||
try {
|
|
||||||
if (isProxySupported("org.spigotmc.SpigotConfig", "bungee")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException classNotFoundException) {
|
|
||||||
// leave stacktrace for class not found out
|
|
||||||
plugin.getLog().warn("Cannot check for BungeeCord support: {}", classNotFoundException.getMessage());
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
|
||||||
plugin.getLog().warn("Cannot check for BungeeCord support", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return isVelocityEnabled();
|
|
||||||
} catch (ClassNotFoundException classNotFoundException) {
|
|
||||||
plugin.getLog().warn("Cannot check for Velocity support in Paper: {}", classNotFoundException.getMessage());
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
|
||||||
plugin.getLog().warn("Cannot check for Velocity support in Paper", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerPluginChannels() {
|
|
||||||
Server server = Bukkit.getServer();
|
|
||||||
|
|
||||||
// check for incoming messages from the bungeecord version of this plugin
|
|
||||||
String groupId = plugin.getName();
|
|
||||||
String forceChannel = NamespaceKey.getCombined(groupId, LoginActionMessage.FORCE_CHANNEL);
|
|
||||||
server.getMessenger().registerIncomingPluginChannel(plugin, forceChannel, new BungeeListener(plugin));
|
|
||||||
|
|
||||||
// outgoing
|
|
||||||
String successChannel = new NamespaceKey(groupId, SUCCESS_CHANNEL).getCombinedName();
|
|
||||||
String changeChannel = new NamespaceKey(groupId, CHANGE_CHANNEL).getCombinedName();
|
|
||||||
server.getMessenger().registerOutgoingPluginChannel(plugin, successChannel);
|
|
||||||
server.getMessenger().registerOutgoingPluginChannel(plugin, changeChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<UUID> loadBungeeCordIds() {
|
private Set<UUID> loadBungeeCordIds() {
|
||||||
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
|
Path proxiesFile = plugin.getPluginFolder().resolve(FILE_NAME);
|
||||||
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
|
Path legacyFile = plugin.getPluginFolder().resolve(LEGACY_FILE_NAME);
|
@ -23,15 +23,9 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.hook;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||||
import com.github.games647.fastlogin.bukkit.hook.AuthMeHook;
|
|
||||||
import com.github.games647.fastlogin.bukkit.hook.CrazyLoginHook;
|
|
||||||
import com.github.games647.fastlogin.bukkit.hook.LogItHook;
|
|
||||||
import com.github.games647.fastlogin.bukkit.hook.LoginSecurityHook;
|
|
||||||
import com.github.games647.fastlogin.bukkit.hook.UltraAuthHook;
|
|
||||||
import com.github.games647.fastlogin.bukkit.hook.XAuthHook;
|
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -51,19 +45,7 @@ public class DelayedAuthHook implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean hookFound = isHookFound();
|
plugin.setInitialized(isHookFound());
|
||||||
if (plugin.getBungeeManager().isEnabled()) {
|
|
||||||
plugin.getLog().info("BungeeCord setting detected. No auth plugin is required");
|
|
||||||
} else if (!hookFound) {
|
|
||||||
plugin.getLog().warn("No auth plugin were found by this plugin "
|
|
||||||
+ "(other plugins could hook into this after the initialization of this plugin)"
|
|
||||||
+ "and BungeeCord is deactivated. "
|
|
||||||
+ "Either one or both of the checks have to pass in order to use this plugin");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hookFound) {
|
|
||||||
plugin.markInitialized();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHookFound() {
|
private boolean isHookFound() {
|
@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015-2024 games647 and contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
|
|
||||||
|
|
||||||
import com.github.games647.craftapi.UUIDAdapter;
|
|
||||||
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
|
|
||||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
|
||||||
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
|
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService;
|
|
||||||
import com.github.games647.fastlogin.core.antibot.AntiBotService.Action;
|
|
||||||
import com.github.games647.fastlogin.core.shared.JoinManagement;
|
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
|
||||||
import com.github.games647.fastlogin.core.storage.StoredProfile;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import protocolsupport.api.events.ConnectionCloseEvent;
|
|
||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
|
||||||
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class ProtocolSupportListener extends JoinManagement<Player, CommandSender, ProtocolLoginSource>
|
|
||||||
implements Listener {
|
|
||||||
|
|
||||||
private final FastLoginBukkit plugin;
|
|
||||||
private final AntiBotService antiBotService;
|
|
||||||
|
|
||||||
public ProtocolSupportListener(FastLoginBukkit plugin, AntiBotService antiBotService) {
|
|
||||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
|
|
||||||
|
|
||||||
this.plugin = plugin;
|
|
||||||
this.antiBotService = antiBotService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
|
|
||||||
if (loginStartEvent.isLoginDenied() || plugin.getCore().getAuthPluginHook() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String username = loginStartEvent.getConnection().getProfile().getName();
|
|
||||||
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
|
|
||||||
plugin.getLog().info("Incoming login request for {} from {}", username, address);
|
|
||||||
|
|
||||||
Action action = antiBotService.onIncomingConnection(address, username);
|
|
||||||
switch (action) {
|
|
||||||
case Ignore:
|
|
||||||
// just ignore
|
|
||||||
return;
|
|
||||||
case Block:
|
|
||||||
String message = plugin.getCore().getMessage("kick-antibot");
|
|
||||||
loginStartEvent.denyLogin(message);
|
|
||||||
break;
|
|
||||||
case Continue:
|
|
||||||
default:
|
|
||||||
//remove old data every time on a new login in order to keep the session only for one person
|
|
||||||
plugin.removeSession(address);
|
|
||||||
|
|
||||||
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
|
|
||||||
super.onLogin(username, source);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
|
|
||||||
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
|
|
||||||
plugin.removeSession(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
|
|
||||||
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
|
|
||||||
|
|
||||||
BukkitLoginSession session = plugin.getSession(address);
|
|
||||||
|
|
||||||
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
|
|
||||||
session.setVerifiedPremium(true);
|
|
||||||
|
|
||||||
if (!plugin.getConfig().getBoolean("premiumUuid")) {
|
|
||||||
String username = Optional.ofNullable(profileCompleteEvent.getForcedName())
|
|
||||||
.orElse(profileCompleteEvent.getConnection().getProfile().getName());
|
|
||||||
profileCompleteEvent.setForcedUUID(UUIDAdapter.generateOfflineId(username));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLoginSource source,
|
|
||||||
StoredProfile profile) {
|
|
||||||
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
|
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username,
|
|
||||||
boolean registered) {
|
|
||||||
source.enableOnlinemode();
|
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
|
||||||
plugin.getCore().addLoginAttempt(ip, username);
|
|
||||||
|
|
||||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
|
|
||||||
plugin.putSession(source.getAddress(), playerSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startCrackedSession(ProtocolLoginSource source, StoredProfile profile, String username) {
|
|
||||||
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
|
|
||||||
plugin.putSession(source.getAddress(), loginSession);
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,8 +25,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.protocollib.EncryptionUtil;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.SignatureTestData.SignatureData;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
|
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.bukkit.task;
|
package com.github.games647.fastlogin.bukkit.task;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.bukkit.hook.DelayedAuthHook;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
Reference in New Issue
Block a user