Modularize authentication backends

This commit is contained in:
games647
2024-05-21 17:07:09 +02:00
parent 7a8e5a59d0
commit c7254034bb
27 changed files with 503 additions and 438 deletions

View File

@ -16,9 +16,11 @@
## Removed
Dropped some features listed below. Please contact us if you still need them
* Dropped Java support < 11
* 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

View File

@ -26,7 +26,7 @@
package com.github.games647.fastlogin.bukkit;
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.storage.StoredProfile;
import org.jetbrains.annotations.Nullable;

View File

@ -25,23 +25,21 @@
*/
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.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.ConnectionListener;
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.bukkit.hook.DelayedAuthHook;
import com.github.games647.fastlogin.core.CommonUtil;
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.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -71,18 +69,26 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
Duration.ofMinutes(1), -1
);
@Getter
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
private final Logger logger;
private boolean serverStarted;
private BungeeManager bungeeManager;
private final BukkitScheduler scheduler;
@Getter
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
@Getter
private FloodgateService floodgateService;
private GeyserService geyserService;
private PremiumPlaceholder premiumPlaceholder;
private AuthenticationBackend backend;
@Getter
private boolean initialized;
public FastLoginBukkit() {
this.logger = CommonUtil.initializeLoggerService(getLogger());
this.scheduler = new BukkitScheduler(this, logger);
@ -104,51 +110,42 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
setEnabled(false);
}
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeManager.isEnabled()) {
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 {
backend = initializeAuthenticationBackend();
if (backend == null) {
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
getServer().getScheduler().runTaskLater(this, new DelayedAuthHook(this), 5L);
backend.init(getServer().getPluginManager());
PluginManager pluginManager = getServer().getPluginManager();
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();
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
premiumPlaceholder = new PremiumPlaceholder(this);
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() {
@ -182,27 +179,15 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core.close();
}
if (bungeeManager != null) {
bungeeManager.cleanup();
if (backend != null) {
backend.stop();
}
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
try {
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;
}
/**
* Gets a thread-safe map about players which are connecting to the server are being checked to be premium (paid
* account)
@ -232,10 +217,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
loginSession.remove(id);
}
public Map<UUID, PremiumStatus> getPremiumPlayers() {
return premiumPlayers;
}
/**
* Fetches the premium status of an online player.
* {@snippet :
@ -263,24 +244,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
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
public Path getPluginFolder() {
return getDataFolder().toPath();
@ -313,12 +276,17 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
}
public FloodgateService getFloodgateService() {
return floodgateService;
public void setInitialized(boolean hookFound) {
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() {
return geyserService;
initialized = true;
}
@Override
@ -326,19 +294,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
if (floodgateService != null) {
return floodgateService;
}
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();
}
}
}

View File

@ -23,44 +23,15 @@
* 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;
package com.github.games647.fastlogin.bukkit.auth;
import com.github.games647.fastlogin.core.shared.LoginSource;
import protocolsupport.api.events.PlayerLoginStartEvent;
import org.bukkit.plugin.PluginManager;
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) {
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
+ '}';
}
void stop();
}

View File

@ -23,23 +23,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.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 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.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.Metadatable;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
/**
@ -56,14 +50,6 @@ public class ConnectionListener implements Listener {
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)
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
Player player = joinEvent.getPlayer();
@ -102,21 +88,13 @@ public class ConnectionListener implements Listener {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
plugin.getBungeeManager().markJoinEventFired(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
removeBlockedStatus(player);
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
plugin.getPremiumPlayers().remove(player.getUniqueId());
plugin.getBungeeManager().cleanup(player);
}
private void removeBlockedStatus(Metadatable player) {
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.FastLoginBukkit;

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.FastLoginBukkit;

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
package com.github.games647.fastlogin.bukkit.auth;
import java.net.InetAddress;

View File

@ -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();
}
}
}

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener;
package com.github.games647.fastlogin.bukkit.auth;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.github.games647.craftapi.model.skin.Textures;

View File

@ -23,10 +23,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.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.Hashing;
import com.google.common.io.Resources;
@ -58,8 +58,8 @@ import java.time.Instant;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Random;
import java.util.UUID;
import java.util.random.RandomGenerator;
/**
* Encryption and decryption minecraft util for connection between servers

View File

@ -23,14 +23,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.events.PacketEvent;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
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.listener.protocollib.packet.ClientPublicKey;
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;

View File

@ -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"));
}
}
}

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.ProtocolLibrary;
@ -42,7 +42,7 @@ import com.comphenix.protocol.wrappers.Converters;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
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.Action;
import com.mojang.datafixers.util.Either;

View File

@ -23,14 +23,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
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 org.bukkit.entity.Player;

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.WrappedSignedProperty;

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.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.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.InetUtils;
import com.github.games647.fastlogin.bukkit.listener.protocollib.packet.ClientPublicKey;
import com.github.games647.fastlogin.bukkit.auth.InetUtils;
import com.github.games647.fastlogin.bukkit.auth.protocollib.packet.ClientPublicKey;
import lombok.val;
import org.bukkit.entity.Player;

View File

@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib.packet;
package com.github.games647.fastlogin.bukkit.auth.protocollib.packet;
import lombok.Value;
import lombok.experimental.Accessors;

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -23,11 +23,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.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.hooks.AuthPlugin;
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
* the connection is in online mode.
*/
public class BungeeListener implements PluginMessageListener {
public class ProxyListener implements PluginMessageListener {
private final FastLoginBukkit plugin;
private final ProxyVerifier verifier;
public BungeeListener(FastLoginBukkit plugin) {
public ProxyListener(FastLoginBukkit plugin, ProxyVerifier verifier) {
this.plugin = plugin;
this.verifier = verifier;
}
@Override
@ -79,7 +81,7 @@ public class BungeeListener implements PluginMessageListener {
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
} else {
UUID sourceId = loginMessage.getProxyId();
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
if (verifier.isProxyAllowed(sourceId)) {
readMessage(targetPlayer, loginMessage);
} else {
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);
// 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);
if (result) {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);

View File

@ -23,22 +23,18 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.LoginActionMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageRecipient;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
@ -48,11 +44,9 @@ import java.util.Set;
import java.util.UUID;
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;
public class BungeeManager {
public class ProxyVerifier {
private static final String LEGACY_FILE_NAME = "proxy-whitelist.txt";
private static final String FILE_NAME = "allowed-proxies.txt";
@ -61,11 +55,10 @@ public class BungeeManager {
private Set<UUID> proxyIds;
private final FastLoginBukkit plugin;
private boolean enabled;
private final Collection<UUID> firedJoinEvents = new HashSet<>();
public BungeeManager(FastLoginBukkit plugin) {
public ProxyVerifier(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@ -84,90 +77,11 @@ public class BungeeManager {
}
}
public boolean isEnabled() {
return enabled;
}
public void initialize() {
enabled = detectProxy();
if (enabled) {
public void loadSecrets() {
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() {

View File

@ -23,15 +23,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* 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.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 org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -51,19 +45,7 @@ public class DelayedAuthHook implements Runnable {
@Override
public void run() {
boolean hookFound = 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();
}
plugin.setInitialized(isHookFound());
}
private boolean isHookFound() {

View File

@ -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);
}
}

View File

@ -25,8 +25,9 @@
*/
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.packet.ClientPublicKey;
import com.google.common.hash.Hashing;
import lombok.val;
import org.junit.jupiter.api.Test;

View File

@ -25,7 +25,7 @@
*/
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.gson.Gson;
import com.google.gson.JsonObject;

View File

@ -25,6 +25,7 @@
*/
package com.github.games647.fastlogin.bukkit.task;
import com.github.games647.fastlogin.bukkit.hook.DelayedAuthHook;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import lombok.val;
import org.bukkit.entity.Player;