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
fix(housekeeping): validate grant mutations
This commit is contained in:
+1
-2
@@ -12,7 +12,6 @@ import java.sql.SQLException;
|
||||
|
||||
public class HousekeepingGiveCreditsEvent extends MessageHandler {
|
||||
private static final String ACTION_KEY = "user.give_credits";
|
||||
private static final int MAX_GRANT = 1_000_000_000;
|
||||
|
||||
@Override
|
||||
public int getRatelimit() {
|
||||
@@ -28,7 +27,7 @@ public class HousekeepingGiveCreditsEvent extends MessageHandler {
|
||||
int userId = this.packet.readInt();
|
||||
int amount = this.packet.readInt();
|
||||
|
||||
if (userId <= 0 || amount == 0 || amount < -MAX_GRANT || amount > MAX_GRANT) {
|
||||
if (userId <= 0 || !HousekeepingMutationGuard.isPositiveGrantAmount(amount)) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "housekeeping.error.invalid_input"));
|
||||
return;
|
||||
}
|
||||
|
||||
+6
-2
@@ -18,7 +18,6 @@ import java.sql.SQLException;
|
||||
*/
|
||||
public class HousekeepingGiveCurrencyEvent extends MessageHandler {
|
||||
private static final int CURRENCY_DUCKETS = 0;
|
||||
private static final int MAX_GRANT = 1_000_000_000;
|
||||
|
||||
@Override
|
||||
public int getRatelimit() {
|
||||
@@ -37,7 +36,7 @@ public class HousekeepingGiveCurrencyEvent extends MessageHandler {
|
||||
|
||||
String actionKey = "user.give_currency_" + currencyType;
|
||||
|
||||
if (userId <= 0 || amount == 0 || amount < -MAX_GRANT || amount > MAX_GRANT) {
|
||||
if (userId <= 0 || !HousekeepingMutationGuard.isCurrencyType(currencyType) || !HousekeepingMutationGuard.isPositiveGrantAmount(amount)) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(actionKey, false, 0, "housekeeping.error.invalid_input"));
|
||||
return;
|
||||
}
|
||||
@@ -47,6 +46,11 @@ public class HousekeepingGiveCurrencyEvent extends MessageHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HousekeepingMutationGuard.userExists(userId)) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(actionKey, false, 0, "housekeeping.error.user_not_found"));
|
||||
return;
|
||||
}
|
||||
|
||||
Habbo online = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId);
|
||||
|
||||
if (online != null) {
|
||||
|
||||
+10
@@ -45,6 +45,16 @@ public class HousekeepingGrantItemEvent extends MessageHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HousekeepingMutationGuard.userExists(userId)) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "housekeeping.error.user_not_found"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HousekeepingMutationGuard.itemExists(itemId)) {
|
||||
this.client.sendResponse(new HousekeepingActionResultComposer(ACTION_KEY, false, 0, "housekeeping.error.item_not_found"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (quantity > MAX_QUANTITY_PER_CALL) {
|
||||
quantity = MAX_QUANTITY_PER_CALL;
|
||||
}
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.eu.habbo.messages.incoming.housekeeping;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
final class HousekeepingMutationGuard {
|
||||
static final int MAX_GRANT = 1_000_000_000;
|
||||
|
||||
private HousekeepingMutationGuard() {
|
||||
}
|
||||
|
||||
static boolean isPositiveGrantAmount(int amount) {
|
||||
return amount > 0 && amount <= MAX_GRANT;
|
||||
}
|
||||
|
||||
static boolean isCurrencyType(int currencyType) {
|
||||
return currencyType >= 0;
|
||||
}
|
||||
|
||||
static boolean userExists(int userId) {
|
||||
if (userId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Emulator.getGameEnvironment().getHabboManager().getHabbo(userId) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try (Connection connection = Emulator.getDatabase().getDataSource().getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1")) {
|
||||
statement.setInt(1, userId);
|
||||
try (ResultSet set = statement.executeQuery()) {
|
||||
return set.next();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean itemExists(int itemId) {
|
||||
return itemId > 0 && Emulator.getGameEnvironment().getItemManager().getItem(itemId) != null;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.eu.habbo.messages.incoming.housekeeping;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class HousekeepingGrantMutationContractTest {
|
||||
private static final Path CREDITS_SOURCE = Path.of(
|
||||
"src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingGiveCreditsEvent.java");
|
||||
private static final Path CURRENCY_SOURCE = Path.of(
|
||||
"src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingGiveCurrencyEvent.java");
|
||||
private static final Path GRANT_ITEM_SOURCE = Path.of(
|
||||
"src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingGrantItemEvent.java");
|
||||
|
||||
@Test
|
||||
void housekeepingGrantsRejectNegativeOrOversizedAmountsServerSide() throws IOException {
|
||||
String credits = Files.readString(CREDITS_SOURCE);
|
||||
String currency = Files.readString(CURRENCY_SOURCE);
|
||||
|
||||
assertTrue(credits.contains("HousekeepingMutationGuard.isPositiveGrantAmount(amount)"),
|
||||
"credit grants must only accept positive bounded amounts");
|
||||
assertTrue(currency.contains("HousekeepingMutationGuard.isPositiveGrantAmount(amount)"),
|
||||
"currency grants must only accept positive bounded amounts");
|
||||
}
|
||||
|
||||
@Test
|
||||
void housekeepingCurrencyGrantsRejectInvalidTypesAndMissingUsers() throws IOException {
|
||||
String currency = Files.readString(CURRENCY_SOURCE);
|
||||
|
||||
assertTrue(currency.contains("HousekeepingMutationGuard.isCurrencyType(currencyType)"),
|
||||
"currency grants must reject negative currency types");
|
||||
assertTrue(currency.contains("HousekeepingMutationGuard.userExists(userId)"),
|
||||
"offline currency grants must not create orphan users_currency rows");
|
||||
}
|
||||
|
||||
@Test
|
||||
void housekeepingItemGrantsRequireRealUsersAndItemsBeforeInsert() throws IOException {
|
||||
String grantItem = Files.readString(GRANT_ITEM_SOURCE);
|
||||
|
||||
int userCheck = grantItem.indexOf("HousekeepingMutationGuard.userExists(userId)");
|
||||
int itemCheck = grantItem.indexOf("HousekeepingMutationGuard.itemExists(itemId)");
|
||||
int insert = grantItem.indexOf("INSERT INTO items");
|
||||
|
||||
assertTrue(userCheck >= 0, "item grants must check the target user exists");
|
||||
assertTrue(itemCheck >= 0, "item grants must check the item base exists");
|
||||
assertTrue(userCheck < insert, "target user must be validated before item insert");
|
||||
assertTrue(itemCheck < insert, "item base must be validated before item insert");
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.eu.habbo.messages.incoming.housekeeping;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class HousekeepingMutationGuardTest {
|
||||
@Test
|
||||
void positiveGrantAmountsMustBeStrictlyPositiveAndBounded() {
|
||||
assertFalse(HousekeepingMutationGuard.isPositiveGrantAmount(-1));
|
||||
assertFalse(HousekeepingMutationGuard.isPositiveGrantAmount(0));
|
||||
assertTrue(HousekeepingMutationGuard.isPositiveGrantAmount(1));
|
||||
assertTrue(HousekeepingMutationGuard.isPositiveGrantAmount(HousekeepingMutationGuard.MAX_GRANT));
|
||||
assertFalse(HousekeepingMutationGuard.isPositiveGrantAmount(HousekeepingMutationGuard.MAX_GRANT + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void currencyTypesCannotBeNegative() {
|
||||
assertFalse(HousekeepingMutationGuard.isCurrencyType(-1));
|
||||
assertTrue(HousekeepingMutationGuard.isCurrencyType(0));
|
||||
assertTrue(HousekeepingMutationGuard.isCurrencyType(101));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user