Subject: [PATCH] Adding shell script execution on login
===================================================================
diff --git a/dist/config/authserver.properties b/dist/config/authserver.properties
--- a/dist/config/authserver.properties (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/dist/config/authserver.properties (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -95,6 +95,31 @@
# Minimum: 1800, or you get banned
TorRefreshRate = 5400
+
+# Execute a shell script when an account logs in into the loginserver.
+ExecuteShellScriptOnLogin = False
+
+# The shell script to be executed. Can be a .sh script path as well.
+# $IP is replaced with the IP address of the client.
+# $ACCOUNT is replaced with the account name of the user.
+ShellScriptOnLogin = sudo ipset -! add gs_whitelist $IP
+
+# The timeout in milliseconds, for the shell script to execute.
+# If the shell script does not execute in the given time, it will fail.
+ShellScriptOnLoginTimeout = 5000
+
+# Enable if you want to forcibly destroy the shell script after its execution or fail.
+# It is recommended to normally close the process, but if you experience issues with the process not exiting,
+# you can temporarily enable this, while you are working on solving the issue.
+ShellScriptDestroyForcibly = False
+
+# Log shell script output to the console for debugging purposes.
+ShellScriptLogging = False
+
+# If the shell script execution fails (err code different than 0 is received),
+# send "There is a system error. Please log in again later" error and close the client.
+PreventLoginOnShellScriptFail = False
+
Index: src/main/java/org/mmocore/authserver/Config.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/org/mmocore/authserver/Config.java b/src/main/java/org/mmocore/authserver/Config.java
--- a/src/main/java/org/mmocore/authserver/Config.java (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/src/main/java/org/mmocore/authserver/Config.java (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -76,6 +76,13 @@
public static boolean TOR_BANNED;
public static String TOR_BAN_LIST;
public static long TOR_REFRESH_RATE;
+
+ public static boolean EXECUTE_SHELL_SCRIPT_ON_LOGIN;
+ public static String SHELL_SCRIPT_ON_LOGIN;
+ public static long SHELL_SCRIPT_ON_LOGIN_TIMEOUT;
+ public static boolean SHELL_SCRIPT_DESTROY_FORCIBLY;
+ public static boolean SHELL_SCRIPT_LOGGING;
+ public static boolean PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL;
private static ScrambledKeyPair[] _keyPairs;
private static byte[][] _blowfishKeys;
@@ -261,6 +268,13 @@
TOR_BANNED = serverSettings.getProperty("TorBanned", false);
TOR_BAN_LIST = serverSettings.getProperty("TorBanList", "https://www.dan.me.uk/torlist/?exit");
TOR_REFRESH_RATE = Math.min(1800, serverSettings.getProperty("TorRefreshRate", 1800)) * 1000L; // 1800s minimum
+
+ EXECUTE_SHELL_SCRIPT_ON_LOGIN = serverSettings.getProperty("ExecuteShellScriptOnLogin", false);
+ SHELL_SCRIPT_ON_LOGIN = serverSettings.getProperty("ShellScriptOnLogin", "sudo ipset -! add gs_whitelist $IP");
+ SHELL_SCRIPT_ON_LOGIN_TIMEOUT = serverSettings.getProperty("ShellScriptOnLoginTimeout", 5000);
+ SHELL_SCRIPT_DESTROY_FORCIBLY = serverSettings.getProperty("ShellScriptDestroyForcibly", false);
+ SHELL_SCRIPT_LOGGING = serverSettings.getProperty("ShellScriptLogging", false);
+ PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL = serverSettings.getProperty("PreventLoginOnShellScriptFail", false);
GAME_SERVER_PING_DELAY = serverSettings.getProperty("GameServerPingDelay", 30) * 1000L;
GAME_SERVER_PING_RETRY = serverSettings.getProperty("GameServerPingRetry", 4);
Index: src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java b/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java
--- a/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java (revision dd4612b907357287d32b8ad77e657eba86253f2e)
+++ b/src/main/java/org/mmocore/authserver/network/l2/c2s/RequestAuthLogin.java (revision e2f6658a4434af74825cd3d27a0deea5b4813c7c)
@@ -18,7 +18,11 @@
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.time.LocalDateTime;
+import java.util.concurrent.TimeUnit;
/**
* Format: b[128]ddddddhc b[128]: the rsa encrypted block with the login an password
@@ -156,6 +160,68 @@
client.close(LoginFailReason.REASON_ATTEMPTED_RESTRICTED_IP);
return;
}
+
+ if (Config.EXECUTE_SHELL_SCRIPT_ON_LOGIN)
+ {
+ int errCode;
+ try
+ {
+ final Process exec = Runtime.getRuntime().exec(Config.SHELL_SCRIPT_ON_LOGIN.replace("$IP", String.valueOf(client.getIpAddress())).replace("$ACCOUNT", String.valueOf(account.getLogin())));
+ if (!exec.waitFor(Config.SHELL_SCRIPT_ON_LOGIN_TIMEOUT, TimeUnit.MILLISECONDS))
+ {
+ errCode = -1;
+ }
+
+ BufferedReader stdInput = null;
+ BufferedReader stdErr = null;
+ if (Config.SHELL_SCRIPT_LOGGING)
+ {
+ stdInput = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+ stdErr = new BufferedReader(new InputStreamReader(exec.getErrorStream()));
+ }
+
+ if (exec.isAlive())
+ {
+ if (Config.SHELL_SCRIPT_DESTROY_FORCIBLY)
+ {
+ exec.destroyForcibly();
+ }
+ else
+ {
+ exec.destroy();
+ }
+ }
+
+ if (Config.SHELL_SCRIPT_LOGGING)
+ {
+ _log.info("Shell script logging: Started");
+ if (stdInput != null)
+ {
+ stdInput.lines().forEach(line -> _log.info("Shell in: {}", line));
+ stdInput.close();
+ }
+
+ if (stdErr != null)
+ {
+ stdErr.lines().forEach(line -> _log.info("Shell err: {}", line));
+ stdErr.close();
+ }
+ }
+
+ errCode = exec.exitValue();
+ }
+ catch (NullPointerException | IOException | InterruptedException e)
+ {
+ _log.error("Failed to execute shell script on login for account: " + account + " with client: " + client, e);
+ errCode = -1;
+ }
+
+ if (Config.PREVENT_LOGIN_ON_SHELL_SCRIPT_FAIL && errCode != 0)
+ {
+ client.close(LoginFailReason.REASON_SYSTEM_ERROR);
+ return;
+ }
+ }
for (GameServer gs : GameServerManager.getInstance().getGameServers())
if (gs.getProtocol() >= 2 && gs.isAuthed())