You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
Merge pull request #232 from simoleo89/fix/gameclients-inputs
fix(gameclients): bound login session inputs
This commit is contained in:
@@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class GameClient {
|
public class GameClient {
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ public class GameClient {
|
|||||||
private final LatencyTracker latencyTracker;
|
private final LatencyTracker latencyTracker;
|
||||||
|
|
||||||
private Habbo habbo;
|
private Habbo habbo;
|
||||||
|
private final AtomicBoolean disposed = new AtomicBoolean(false);
|
||||||
private boolean handshakeFinished;
|
private boolean handshakeFinished;
|
||||||
private String machineId = "";
|
private String machineId = "";
|
||||||
private String ssoTicket = "";
|
private String ssoTicket = "";
|
||||||
@@ -153,6 +155,10 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dispose(boolean allowSessionResume) {
|
public void dispose(boolean allowSessionResume) {
|
||||||
|
if (!this.disposed.compareAndSet(false, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.channel.close();
|
this.channel.close();
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -73,11 +73,11 @@ public class SecureLoginEvent extends MessageHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String sso = this.packet.readString().replace(" ", "");
|
String sso = SecureLoginInputGuard.normalizeSsoTicket(this.packet.readString());
|
||||||
|
|
||||||
if (Emulator.getPluginManager().fireEvent(new SSOAuthenticationEvent(sso)).isCancelled()) {
|
if (!SecureLoginInputGuard.isValidSsoTicket(sso)) {
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
||||||
LOGGER.info("SSO Authentication is cancelled by a plugin. Closed connection...");
|
LOGGER.debug("Client is trying to connect with an invalid SSO ticket! Closed connection...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.handshake;
|
||||||
|
|
||||||
|
final class SecureLoginInputGuard {
|
||||||
|
static final int MAX_SSO_TICKET_LENGTH = 512;
|
||||||
|
|
||||||
|
private SecureLoginInputGuard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static String normalizeSsoTicket(String ticket) {
|
||||||
|
if (ticket == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ticket.replace(" ", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isValidSsoTicket(String ticket) {
|
||||||
|
return ticket != null && !ticket.isEmpty() && ticket.length() <= MAX_SSO_TICKET_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.gameclients;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
class GameClientManagerContractTest {
|
class GameClientManagerContractTest {
|
||||||
|
|
||||||
@@ -19,4 +20,11 @@ class GameClientManagerContractTest {
|
|||||||
assertDoesNotThrow(() -> manager.disposeClient(null));
|
assertDoesNotThrow(() -> manager.disposeClient(null));
|
||||||
assertDoesNotThrow(() -> manager.forceDisposeClient(null));
|
assertDoesNotThrow(() -> manager.forceDisposeClient(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void gameClientDisposeIsExplicitlyIdempotent() throws Exception {
|
||||||
|
assertTrue(java.util.concurrent.atomic.AtomicBoolean.class.isAssignableFrom(
|
||||||
|
GameClient.class.getDeclaredField("disposed").getType()
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.handshake;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class SecureLoginInputGuardTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void normalizesNullAndSpacesBeforeAuthentication() {
|
||||||
|
assertEquals("", SecureLoginInputGuard.normalizeSsoTicket(null));
|
||||||
|
assertEquals("abc123", SecureLoginInputGuard.normalizeSsoTicket(" abc 123 "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsMissingOrOversizedTickets() {
|
||||||
|
assertFalse(SecureLoginInputGuard.isValidSsoTicket(""));
|
||||||
|
assertFalse(SecureLoginInputGuard.isValidSsoTicket("x".repeat(SecureLoginInputGuard.MAX_SSO_TICKET_LENGTH + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void acceptsTicketWithinBound() {
|
||||||
|
assertTrue(SecureLoginInputGuard.isValidSsoTicket("x".repeat(SecureLoginInputGuard.MAX_SSO_TICKET_LENGTH)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user