diff --git a/CommonCore/SQL/src/de/steamwar/sql/AuditLog.java b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.java new file mode 100644 index 00000000..ffe093a0 --- /dev/null +++ b/CommonCore/SQL/src/de/steamwar/sql/AuditLog.java @@ -0,0 +1,125 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SqlTypeMapper; +import de.steamwar.sql.internal.Statement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; + +import java.sql.Timestamp; +import java.time.Instant; + +@AllArgsConstructor +public class AuditLog { + + static { + SqlTypeMapper.nameEnumMapper(AuditLog.Type.class); + } + + public static final String SERVER_NAME_VELOCITY = "Velocity"; + + private static final Table table = new Table<>(AuditLog.class); + + private static final Statement create = table.insertFields(true, "time", "serverName", "serverOwner", "actor", "actionType", "actionText"); + + @Getter + @Field + private final Timestamp time; + + @Getter + @Field + private final String serverName; + + @Field(nullable = true) + private final int serverOwner; + + @Field + private final int actor; + + @Getter + @Field + private final Type actionType; + + @Getter + @Field + private final String actionText; + + public enum Type { + JOIN, + LEAVE, + COMMAND, + SENSITIVE_COMMAND, + + CHAT, + GUI_OPEN, + GUI_CLOSE, + GUI_CLICK, + } + + private static void create(String serverName, SteamwarUser serverOwner, SteamwarUser actor, Type actionType, String text) { + create.insertGetKey(Timestamp.from(Instant.now()), serverName, serverOwner, actor, actionType, text); + } + + public static void createJoin(@NonNull String jointServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) { + create(jointServerName, serverOwner, joinedPlayer, Type.JOIN, ""); + } + + public static void createLeave(@NonNull String leftServerName, SteamwarUser serverOwner, @NonNull SteamwarUser joinedPlayer) { + create(leftServerName, serverOwner, joinedPlayer, Type.LEAVE, ""); + } + + public static void createCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) { + if (player == null) return; + create(serverName, serverOwner, player, Type.COMMAND, command); + } + + public static void createSensitiveCommand(@NonNull String serverName, SteamwarUser serverOwner, SteamwarUser player, @NonNull String command) { + if (player == null) return; + create(serverName, serverOwner, player, Type.SENSITIVE_COMMAND, command); + } + + public static void createChat(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser chatter, @NonNull String chat) { + create(serverName, serverOwner, chatter, Type.CHAT, chat); + } + + public static void createGuiOpen(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) { + create(serverName, serverOwner, player, Type.GUI_OPEN, guiName); + } + + public static void createGuiClick(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName, @NonNull String clickType, int slot, @NonNull String itemName) { + create(serverName, serverOwner, player, Type.GUI_CLICK, "Gui: " + guiName + "\nSlot: " + slot + "\nClickType: " + clickType + "\nItemName: " + itemName); + } + + public static void createGuiClose(@NonNull String serverName, SteamwarUser serverOwner, @NonNull SteamwarUser player, @NonNull String guiName) { + create(serverName, serverOwner, player, Type.GUI_CLOSE, guiName); + } + + public SteamwarUser getServerOwner() { + return SteamwarUser.get(serverOwner); + } + + public SteamwarUser getActor() { + return SteamwarUser.get(actor); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index d181ce02..11cac3fe 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -68,6 +68,11 @@ public class FightSystem extends JavaPlugin { Core.setInstance(this); TinyProtocol.init(); } + if (Config.SpectatePort != 0) { + Core.setServerName("Spectate"); + } else if (Config.ReplayID != 0) { + Core.setServerName("Replay"); + } message = new Message("de.steamwar.fightsystem.FightSystem", FightSystem.class.getClassLoader()); diff --git a/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java index 56af8fd7..6712e45a 100644 --- a/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java +++ b/LegacyBauSystem/src/de/steamwar/bausystem/BauSystem.java @@ -53,6 +53,7 @@ public class BauSystem extends JavaPlugin implements Listener { @Override public void onEnable() { + Core.setServerName("Dev"); plugin = this; Mapper.init(); diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem.java b/LobbySystem/src/de/steamwar/lobby/LobbySystem.java index 4d198d4b..900d0941 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem.java +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem.java @@ -19,6 +19,7 @@ package de.steamwar.lobby; +import de.steamwar.core.Core; import de.steamwar.entity.REntityServer; import de.steamwar.lobby.command.FlyCommand; import de.steamwar.lobby.command.HologramCommand; @@ -52,6 +53,7 @@ public class LobbySystem extends JavaPlugin { message = new Message("de.steamwar.lobby.LobbySystem", getClassLoader()); entityServer = new REntityServer(); debugEntityServer = new REntityServer(); + Core.setServerName("Lobby"); CustomMap.init(); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CaseInsensitiveCommandsListener.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CaseInsensitiveCommandsListener.java index a829308a..05eafdbb 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CaseInsensitiveCommandsListener.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CaseInsensitiveCommandsListener.java @@ -19,6 +19,10 @@ package de.steamwar.command; +import de.steamwar.core.Core; +import de.steamwar.providers.BauServerInfo; +import de.steamwar.sql.AuditLog; +import de.steamwar.sql.SteamwarUser; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -31,5 +35,6 @@ public class CaseInsensitiveCommandsListener implements Listener { String[] strings = event.getMessage().split(" "); strings[0] = strings[0].toLowerCase(); event.setMessage(String.join(" ", strings)); + AuditLog.createCommand(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(event.getPlayer().getUniqueId()), event.getMessage()); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java index c2086b0b..91c05851 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -33,6 +33,8 @@ import de.steamwar.network.handlers.ServerDataHandler; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.internal.Statement; +import lombok.Getter; +import lombok.Setter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.event.Listener; @@ -52,12 +54,17 @@ public class Core extends JavaPlugin { return Reflection.MAJOR_VERSION; } + @Getter + @Setter private static JavaPlugin instance; - public static JavaPlugin getInstance() { - return instance; - } - public static void setInstance(JavaPlugin instance) { - Core.instance = instance; + + @Getter + private static String serverName = ""; + + public static void setServerName(String serverName) { + if (serverName.isEmpty()) { + Core.serverName = serverName; + } } private ErrorHandler errorHandler; @@ -66,6 +73,7 @@ public class Core extends JavaPlugin { @Override public void onLoad() { setInstance(this); + serverName = System.getProperty("serverName", ""); } @Override diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java index 29b0ffd8..d3fd33a0 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/events/PlayerJoinedEvent.java @@ -19,6 +19,9 @@ package de.steamwar.core.events; +import de.steamwar.core.Core; +import de.steamwar.providers.BauServerInfo; +import de.steamwar.sql.AuditLog; import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.UserPerm; import de.steamwar.sql.internal.Statement; @@ -44,12 +47,14 @@ public class PlayerJoinedEvent implements Listener{ player.setDisplayName(prefix.getColorCode() + player.getName() + "§r"); event.setJoinMessage("§a§l» §r" + player.getDisplayName()); + AuditLog.createJoin(Core.getServerName(), BauServerInfo.getOwnerUser(), user); } - @EventHandler + @EventHandler(priority = EventPriority.LOWEST) private void onQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); event.setQuitMessage("§c§l« §r" + player.getDisplayName()); + AuditLog.createLeave(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId())); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWInventory.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWInventory.java index 001fae9f..1b4529d3 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWInventory.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWInventory.java @@ -20,7 +20,9 @@ package de.steamwar.inventory; import de.steamwar.core.Core; -import de.steamwar.core.TrickyTrialsWrapper; +import de.steamwar.providers.BauServerInfo; +import de.steamwar.sql.AuditLog; +import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -145,6 +147,7 @@ public class SWInventory implements Listener { Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); open = true; } + AuditLog.createGuiOpen(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()), title); } @EventHandler @@ -156,6 +159,7 @@ public class SWInventory implements Listener { e.setCancelled(true); Core.getInstance().getLogger().info("[SWINV] " + e.getWhoClicked().getName() + " " + e.getClick().name() + " clicked " + e.getRawSlot() + " on " + (e.getCurrentItem() != null ? e.getCurrentItem().getItemMeta().getDisplayName() : "[EMPTY]") + " in " + e.getView().getTitle()); callbacks.get(e.getRawSlot()).accept(e); + AuditLog.createGuiClick(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()), e.getView().getTitle(), e.getClick().name(), e.getRawSlot(), (e.getCurrentItem() != null ? e.getCurrentItem().getItemMeta().getDisplayName() : "[EMPTY]")); } } @@ -167,8 +171,10 @@ public class SWInventory implements Listener { InventoryClickEvent.getHandlerList().unregister(this); InventoryCloseEvent.getHandlerList().unregister(this); Core.getInstance().getLogger().info("[SWINV] " + player.getName() + " closed " + title); - if(callbacks.containsKey(-1)) + if(callbacks.containsKey(-1)) { callbacks.get(-1).accept(null); + } open = false; + AuditLog.createGuiClose(Core.getServerName(), BauServerInfo.getOwnerUser(), SteamwarUser.get(player.getUniqueId()), title); } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java index ddc7839e..309db835 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/providers/BauServerInfo.java @@ -19,6 +19,7 @@ package de.steamwar.providers; +import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; public class BauServerInfo { @@ -37,4 +38,9 @@ public class BauServerInfo { public static boolean isBauServer() { return bauOwner != null; } + + public static SteamwarUser getOwnerUser() { + if (bauOwner == null) return null; + return SteamwarUser.get(bauOwner); + } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index d295d62b..058771e7 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -276,6 +276,7 @@ public class ServerStarter { int port = portrange.freePort(); String serverName = serverNameProvider.apply(port); + arguments.put("serverName", serverName); if(node == null) { node = Node.getNode(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java index 17137bf5..dfdf5c7f 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java @@ -27,6 +27,8 @@ import com.velocitypowered.api.event.player.PlayerChatEvent; import com.velocitypowered.api.event.player.TabCompleteEvent; import com.velocitypowered.api.proxy.ConsoleCommandSource; import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ServerConnection; +import com.velocitypowered.api.proxy.server.ServerInfo; import de.steamwar.messages.Chatter; import de.steamwar.messages.ChatterGroup; import de.steamwar.messages.Message; @@ -80,17 +82,32 @@ public class ChatListener extends BasicListener { if(VelocityCore.getProxy().getCommandManager().hasCommand(cmd)) { CommandSource source = e.getCommandSource(); String name; - if(source instanceof Player player) + SteamwarUser user = null; + if (source instanceof Player player) { + user = SteamwarUser.get(player.getUniqueId()); name = player.getUsername(); - else if(source instanceof ConsoleCommandSource) + } else if (source instanceof ConsoleCommandSource) { + user = SteamwarUser.get(-1); name = "«CONSOLE»"; - else + } else { name = source.toString(); + } if (noLogCommands.contains(cmd)) { return; } + switch (cmd) { + case "msg": + case "r": + case "tc": + AuditLog.createSensitiveCommand(AuditLog.SERVER_NAME_VELOCITY, null, user, "/" + command); + break; + default: + AuditLog.createCommand(AuditLog.SERVER_NAME_VELOCITY, null, user, "/" + command); + break; + } + cmdLogger.log(Level.INFO, "%s -> executed command /%s".formatted(name, command)); } else if (e.getCommandSource() instanceof Player player) { // System.out.println("spoofChatInput " + e); @@ -106,8 +123,8 @@ public class ChatListener extends BasicListener { e.setResult(PlayerChatEvent.ChatResult.denied()); + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); if (message.contains("jndi:ldap")) { - SteamwarUser user = SteamwarUser.get(player.getUniqueId()); PunishmentCommand.ban(user, Punishment.PERMA_TIME, "Versuchte Exploit-Ausnutzung", SteamwarUser.get(-1), true); VelocityCore.getLogger().log(Level.SEVERE, "%s %s wurde automatisch wegen jndi:ldap gebannt.".formatted(user.getUserName(), user.getId())); return; @@ -117,13 +134,20 @@ public class ChatListener extends BasicListener { return; Subserver subserver = Subserver.getSubserver(player); + String serverName = AuditLog.SERVER_NAME_VELOCITY; if(Subserver.isArena(subserver) && subserver.getServer() == player.getCurrentServer().orElseThrow().getServerInfo()) { + serverName = subserver.getServer().getName(); localChat(Chatter.of(player), message); } else if (message.startsWith("+")) { + serverName = player.getCurrentServer() + .map(ServerConnection::getServerInfo) + .map(ServerInfo::getName) + .orElse(serverName); localChat(Chatter.of(player), message.substring(1)); } else { sendChat(Chatter.of(player), Chatter.globalChat(), "CHAT_GLOBAL", null, message); } + AuditLog.createChat(serverName, null, user, message); } private static boolean isMistypedCommand(Player player, String message) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/SessionManager.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/SessionManager.java index 7caeac14..248fd606 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/SessionManager.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/SessionManager.java @@ -22,6 +22,7 @@ package de.steamwar.velocitycore.listeners; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.PostLoginEvent; +import de.steamwar.sql.AuditLog; import de.steamwar.velocitycore.VelocityCore; import de.steamwar.sql.Session; import de.steamwar.sql.SteamwarUser; @@ -36,10 +37,12 @@ public class SessionManager extends BasicListener { @Subscribe public void onPostLogin(PostLoginEvent event){ sessions.put(event.getPlayer(), Timestamp.from(Instant.now())); + AuditLog.createJoin(AuditLog.SERVER_NAME_VELOCITY, null, SteamwarUser.get(event.getPlayer().getUniqueId())); } @Subscribe public void onDisconnect(DisconnectEvent e){ + AuditLog.createLeave(AuditLog.SERVER_NAME_VELOCITY, null, SteamwarUser.get(e.getPlayer().getUniqueId())); Timestamp timestamp = sessions.remove(e.getPlayer()); if(timestamp != null) { VelocityCore.schedule(() -> Session.insertSession(SteamwarUser.get(e.getPlayer().getUniqueId()).getId(), timestamp)).schedule();