diff --git a/.gitignore b/.gitignore index eed13312..90f4ecf8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ target/ ### IntelliJ IDEA ### .idea +.DS_Store *.iws *.iml *.ipr diff --git a/config/application.properties b/config/application.properties index ae23c08c..70b54207 100644 --- a/config/application.properties +++ b/config/application.properties @@ -13,6 +13,7 @@ billing.server.port=8443 ## Please notice most games won't work with localhost or 127.0.0.1 #allnet.server.host=localhost #allnet.server.port=80 +allnet.server.check-keychip=false ## This is for some games that use shop name for in-game functions. ## Specify the place name here if you need it. By default it is empty. #allnet.server.place-name= diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java index f8eaec31..e8ba0b72 100644 --- a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java @@ -7,6 +7,8 @@ import icu.samnyan.aqua.sega.allnet.model.response.PowerOnResponse; import icu.samnyan.aqua.sega.allnet.model.response.PowerOnResponseV2; import icu.samnyan.aqua.sega.allnet.model.response.PowerOnResponseV3; import icu.samnyan.aqua.sega.allnet.util.Decoder; +import icu.samnyan.aqua.sega.allnet.util.KeychipChecker; +import icu.samnyan.aqua.sega.allnet.dao.keychip.KeyChipRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -40,10 +42,15 @@ public class AllNetController { private final String PLACE_NAME; private final boolean MAIMAI2_NO_HTTP; + private final boolean ALLNET_CHECK_KEYCHIP; + private final KeyChipRepository keychipRepository; + public AllNetController(@Value("${allnet.server.host:}") String HOST, @Value("${allnet.server.port:}") String PORT, @Value("${allnet.server.place-name:}") String PLACE_NAME, - @Value("${game.maimai2.splash-old-patch:false}") boolean MAIMAI2_NO_HTTP) { + @Value("${game.maimai2.splash-old-patch:false}") boolean MAIMAI2_NO_HTTP, + @Value("${allnet.server.check-keychip:false}") boolean ALLNET_CHECK_KEYCHIP, + KeyChipRepository keychipRepository) { this.HOST_OVERRIDE = HOST; this.PORT_OVERRIDE = PORT; this.MAIMAI2_NO_HTTP = MAIMAI2_NO_HTTP; @@ -51,6 +58,8 @@ public class AllNetController { // More better way to this is to use XML or yaml format as these treated as UTF-8 // but I rather use hack than breaking backward compatibility.. for now this.PLACE_NAME = new String(PLACE_NAME.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + this.ALLNET_CHECK_KEYCHIP = ALLNET_CHECK_KEYCHIP; + this.keychipRepository = keychipRepository; } @GetMapping("/") @@ -91,16 +100,21 @@ public class AllNetController { String localPort = Integer.toString(req.getLocalPort()); byte[] bytes = dataStream.readAllBytes(); Map reqMap = Decoder.decode(bytes); - + String serial = reqMap.getOrDefault("serial", ""); logger.info("Request: PowerOn, " + mapper.writeValueAsString(reqMap)); - // TODO: Verify KeyChip id - + // TODO: Verify KeyChip id ? + // Seems verified now + if (this.ALLNET_CHECK_KEYCHIP){ + KeychipChecker keychipChecker = new KeychipChecker(this.keychipRepository); + if (!keychipChecker.checkKeychip(serial)){ + return "{}"; + // This will cause an allnet auth bad on client side + // Which is just what we want + } + } String gameId = reqMap.getOrDefault("game_id", ""); String ver = reqMap.getOrDefault("ver", "1.0"); - String serial = reqMap.getOrDefault("serial", DEFAULT_KEYCHIP_ID); - if (serial.equals(DEFAULT_KEYCHIP_ID)) { - serial = UUID.randomUUID().toString(); - } + serial = UUID.randomUUID().toString(); String format_ver = reqMap.getOrDefault("format_ver", ""); PowerOnResponse resp; if (format_ver.startsWith("2")) { diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/dao/keychip/KeyChipRepository.java b/src/main/java/icu/samnyan/aqua/sega/allnet/dao/keychip/KeyChipRepository.java new file mode 100644 index 00000000..6b109268 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/dao/keychip/KeyChipRepository.java @@ -0,0 +1,14 @@ +package icu.samnyan.aqua.sega.allnet.dao.keychip; + +import icu.samnyan.aqua.sega.allnet.model.Keychip; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository("KeyChipRepository") +public interface KeyChipRepository extends JpaRepository { + @Query(value = "select 1 from allnet_keychips where keychip_id = ?1 limit 1", nativeQuery = true) + Optional findKeyChipExistence(String KeychipId); +} diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/model/Keychip.java b/src/main/java/icu/samnyan/aqua/sega/allnet/model/Keychip.java new file mode 100644 index 00000000..fe559bc7 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/model/Keychip.java @@ -0,0 +1,23 @@ +package icu.samnyan.aqua.sega.allnet.model; + +import javax.persistence.*; + +@Entity(name = "Keychip") +@Table(name = "allnet_keychips", uniqueConstraints = {@UniqueConstraint(columnNames = {"keychip_id"})}) + +public class Keychip { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + @Column(name = "id", nullable = false) + private Long id; + + private String keychip_id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/service/CheckKeychipService.java b/src/main/java/icu/samnyan/aqua/sega/allnet/service/CheckKeychipService.java new file mode 100644 index 00000000..0b6316e5 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/service/CheckKeychipService.java @@ -0,0 +1,28 @@ +package icu.samnyan.aqua.sega.allnet.service; + +import icu.samnyan.aqua.sega.allnet.dao.keychip.KeyChipRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.NoSuchElementException; +import java.util.Optional; + +@Service("CheckKeychipService") +public class CheckKeychipService { + private final KeyChipRepository keyChipRepository; + + @Autowired + public CheckKeychipService(KeyChipRepository keyChipRepository) { + this.keyChipRepository = keyChipRepository; + } + + public boolean checkKeyChipExistence(String keychipId){ + Optional findRes = keyChipRepository.findKeyChipExistence(keychipId); + try { + findRes.orElseThrow(); + return true; + }catch (NoSuchElementException e){ + return false; + } + } +} diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/util/KeychipChecker.java b/src/main/java/icu/samnyan/aqua/sega/allnet/util/KeychipChecker.java new file mode 100644 index 00000000..a32c4d63 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/util/KeychipChecker.java @@ -0,0 +1,18 @@ +package icu.samnyan.aqua.sega.allnet.util; + +import icu.samnyan.aqua.sega.allnet.dao.keychip.KeyChipRepository; +import icu.samnyan.aqua.sega.allnet.service.CheckKeychipService; + + +public class KeychipChecker { + private final CheckKeychipService checkKeychipService; + + public KeychipChecker(KeyChipRepository keyChipRepository) { + this.checkKeychipService = new CheckKeychipService(keyChipRepository); + } + + public boolean checkKeychip(String keychipId){ + return checkKeychipService.checkKeyChipExistence(keychipId); + } + +} diff --git a/src/main/resources/db/migration/mariadb/V241__add_allnet_keychip_table.sql b/src/main/resources/db/migration/mariadb/V241__add_allnet_keychip_table.sql new file mode 100644 index 00000000..dfab1d0a --- /dev/null +++ b/src/main/resources/db/migration/mariadb/V241__add_allnet_keychip_table.sql @@ -0,0 +1,8 @@ +create table allnet_keychips +( + id int(20) primary key AUTOINCREMENT not null, + keychip_id varchar(255) not null +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + collate = utf8mb4_unicode_ci; \ No newline at end of file diff --git a/src/main/resources/db/migration/mysql/V241__add_allnet_keychip_table.sql b/src/main/resources/db/migration/mysql/V241__add_allnet_keychip_table.sql new file mode 100644 index 00000000..dfab1d0a --- /dev/null +++ b/src/main/resources/db/migration/mysql/V241__add_allnet_keychip_table.sql @@ -0,0 +1,8 @@ +create table allnet_keychips +( + id int(20) primary key AUTOINCREMENT not null, + keychip_id varchar(255) not null +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + collate = utf8mb4_unicode_ci; \ No newline at end of file diff --git a/src/main/resources/db/migration/sqlite/V241__add_allnet_keychip_table.sql b/src/main/resources/db/migration/sqlite/V241__add_allnet_keychip_table.sql new file mode 100644 index 00000000..8c714640 --- /dev/null +++ b/src/main/resources/db/migration/sqlite/V241__add_allnet_keychip_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE allnet_keychips +( + id INTEGER NOT NULL, + keychip_id VARCHAR(255), + PRIMARY KEY ( + id + ) +); \ No newline at end of file