This commit is contained in:
sgdc3 2017-09-27 14:04:30 +02:00
commit 51a9c81f6b
15 changed files with 122 additions and 96 deletions

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sat Aug 12 13:49:42 CEST 2017. See docs/config/config.tpl.md -->
<!-- File auto-generated on Sun Sep 17 11:29:06 CEST 2017. See docs/config/config.tpl.md -->
## AuthMe Configuration
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
@ -156,7 +156,7 @@ settings:
AllowRestrictedUser: false
# The restricted user feature will kick players listed below
# if they don't match the defined IP address. Names are case-insensitive.
# Ip addresses support regex expressions (regex:127\.0\.0\..*)
# You can use * as wildcard (127.0.0.*), or regex with a "regex:" prefix regex:127\.0\.0\..*
# Example:
# AllowedRestrictedUser:
# - playername;127.0.0.1
@ -374,7 +374,7 @@ Protection:
# Apply the protection also to registered usernames
enableProtectionRegistered: true
# Countries allowed to join the server and register. For country codes, see
# https://dev.bukkit.org/projects/authme-reloaded/pages/countries-codes
# http://dev.maxmind.com/geoip/legacy/codes/iso3166/
# PLEASE USE QUOTES!
countries:
- 'US'
@ -458,7 +458,7 @@ Security:
# This prevents an attacker from abusing AuthMe's email feature.
cooldown: 60
privacy:
# The maill shown using /email show will be partially hidden
# The mail shown using /email show will be partially hidden
# E.g. (if enabled)
# original email: my.email@example.com
# hidden email: my.***@***mple.com
@ -540,4 +540,4 @@ To change settings on a running server, save your changes to config.yml and use
---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Aug 12 13:49:42 CEST 2017
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Sep 17 11:29:06 CEST 2017

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sat Mar 25 00:15:27 CET 2017. See docs/hashmethods/hash_algorithms.tpl.md -->
<!-- File auto-generated on Sun Sep 17 11:29:07 CEST 2017. See docs/hashmethods/hash_algorithms.tpl.md -->
## Hash Algorithms
AuthMe supports the following hash algorithms for storing your passwords safely.
@ -48,6 +48,7 @@ You can change the hashing algorithm in the config.yml: under `security`, locate
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
- Deprecated: Cannot be used anymore actively or in the near future.
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
- Does not work: The algorithm does not work properly; do not use.
@ -82,4 +83,4 @@ or bad.
---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Mar 25 00:15:27 CET 2017
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Sep 17 11:29:07 CEST 2017

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Fri Aug 11 22:32:14 CEST 2017. See docs/translations/translations.tpl.md -->
<!-- File auto-generated on Sun Sep 17 11:29:08 CEST 2017. See docs/translations/translations.tpl.md -->
# AuthMe Translations
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
@ -11,7 +11,7 @@ Code | Language | Translated | &nbsp;
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
@ -41,4 +41,4 @@ Code | Language | Translated | &nbsp;
---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Aug 11 22:32:14 CEST 2017
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Sep 17 11:29:08 CEST 2017

View File

@ -22,8 +22,6 @@ import fr.xephi.authme.listener.PlayerListener16;
import fr.xephi.authme.listener.PlayerListener18;
import fr.xephi.authme.listener.PlayerListener19;
import fr.xephi.authme.listener.ServerListener;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PermissionsSystemType;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.Sha256;
import fr.xephi.authme.service.BackupService;
@ -67,7 +65,6 @@ public class AuthMe extends JavaPlugin {
// Private instances
private CommandHandler commandHandler;
private PermissionsManager permsMan;
private Settings settings;
private DataSource database;
private BukkitService bukkitService;
@ -118,7 +115,7 @@ public class AuthMe extends JavaPlugin {
/**
* Method used to obtain the v2 plugin's api instance
* @deprecated Will be removed in 5.4, use {@link fr.xephi.authme.api.v3.AuthMeApi} instead
* @deprecated Will be removed in 5.5, use {@link fr.xephi.authme.api.v3.AuthMeApi} instead
*
* @return The plugin's api instance
*/
@ -248,7 +245,6 @@ public class AuthMe extends JavaPlugin {
*/
void instantiateServices(Injector injector) {
database = injector.getSingleton(DataSource.class);
permsMan = injector.getSingleton(PermissionsManager.class);
bukkitService = injector.getSingleton(BukkitService.class);
commandHandler = injector.getSingleton(CommandHandler.class);
backupService = injector.getSingleton(BackupService.class);

View File

@ -27,7 +27,7 @@ import java.util.List;
* NewAPI authmeApi = NewAPI.getInstance();
* </code>
*
* @deprecated Will be removed in 5.4! Use {@link fr.xephi.authme.api.v3.AuthMeApi} instead.
* @deprecated Will be removed in 5.5! Use {@link fr.xephi.authme.api.v3.AuthMeApi} instead.
*/
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
@Deprecated

View File

@ -50,6 +50,7 @@ class HasPermissionChecker implements DebugSection {
if (arguments.size() < 2) {
sender.sendMessage("Check if a player has permission:");
sender.sendMessage("Example: /authme debug perm bobby my.perm.node");
sender.sendMessage("Permission system type used: " + permissionsManager.getPermissionSystem());
return;
}

View File

@ -53,8 +53,10 @@ public class OnStartupTasks {
public static void sendMetrics(AuthMe plugin, Settings settings) {
final Metrics metrics = new Metrics(plugin);
metrics.addCustomChart(new Metrics.SimplePie("messages_language", () -> settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)));
metrics.addCustomChart(new Metrics.SimplePie("database_backend", () -> settings.getProperty(DatabaseSettings.BACKEND).toString()));
metrics.addCustomChart(new Metrics.SimplePie("messages_language",
() -> settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)));
metrics.addCustomChart(new Metrics.SimplePie("database_backend",
() -> settings.getProperty(DatabaseSettings.BACKEND).toString()));
}
/**

View File

@ -64,16 +64,16 @@ public class OnJoinVerifier implements Reloadable {
/**
* Checks if Antibot is enabled.
*
* @param player the player
* @param name the player name
* @param isAuthAvailable whether or not the player is registered
* @throws FailedVerificationException if the verification fails
*/
public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException {
if (isAuthAvailable || permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
public void checkAntibot(String name, boolean isAuthAvailable) throws FailedVerificationException {
if (isAuthAvailable || permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)) {
return;
}
if (antiBotService.shouldKick()) {
antiBotService.addPlayerKick(player.getName());
antiBotService.addPlayerKick(name);
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
}
}
@ -148,14 +148,13 @@ public class OnJoinVerifier implements Reloadable {
/**
* Checks that the casing in the username corresponds to the one in the database, if so configured.
*
* @param player the player to verify
* @param connectingName the player name to verify
* @param auth the auth object associated with the player
* @throws FailedVerificationException if the verification fails
*/
public void checkNameCasing(Player player, PlayerAuth auth) throws FailedVerificationException {
public void checkNameCasing(String connectingName, PlayerAuth auth) throws FailedVerificationException {
if (auth != null && settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)) {
String realName = auth.getRealName(); // might be null or "Player"
String connectingName = player.getName();
if (StringUtils.isEmpty(realName) || "Player".equals(realName)) {
dataSource.updateRealName(connectingName.toLowerCase(), connectingName);
@ -168,15 +167,15 @@ public class OnJoinVerifier implements Reloadable {
/**
* Checks that the player's country is admitted.
*
* @param player the player
* @param name the player name
* @param address the player address
* @param isAuthAvailable whether or not the user is registered
* @throws FailedVerificationException if the verification fails
*/
public void checkPlayerCountry(Player player, String address, boolean isAuthAvailable) throws FailedVerificationException {
public void checkPlayerCountry(String name, String address, boolean isAuthAvailable) throws FailedVerificationException {
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)
&& !permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_COUNTRY_CHECK)
&& !permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_COUNTRY_CHECK)
&& !validationService.isCountryAdmitted(address)) {
throw new FailedVerificationException(MessageKey.COUNTRY_BANNED_ERROR);
}

View File

@ -12,6 +12,7 @@ import fr.xephi.authme.service.TeleportationService;
import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
@ -26,6 +27,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
@ -77,6 +79,8 @@ public class PlayerListener implements Listener {
@Inject
private JoinMessageService joinMessageService;
private boolean isAsyncPlayerPreLoginEventCalled = false;
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
String cmd = event.getMessage().split(" ")[0].toLowerCase();
@ -190,19 +194,54 @@ public class PlayerListener implements Listener {
management.performJoin(player);
}
private void runOnJoinChecks(String name, String ip) throws FailedVerificationException {
// Fast stuff
onJoinVerifier.checkSingleSession(name);
onJoinVerifier.checkIsValidName(name);
// Get the auth later as this may cause the single session check to fail
// Slow stuff
final PlayerAuth auth = dataSource.getAuth(name);
final boolean isAuthAvailable = auth != null;
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
onJoinVerifier.checkNameCasing(name, auth);
onJoinVerifier.checkPlayerCountry(name, ip, isAuthAvailable);
}
// Note #831: AsyncPlayerPreLoginEvent is not fired by all servers in offline mode
// e.g. CraftBukkit does not fire it. So we need to run crucial things with PlayerLoginEvent.
// Single session feature can be implemented for Spigot and CraftBukkit by canceling a kick
// event caused by "logged in from another location". The nicer way, but only for Spigot, would be
// to check in the AsyncPlayerPreLoginEvent. To support all servers, we use the less nice way.
@EventHandler(priority = EventPriority.HIGHEST)
public void onAsyncPlayerPreLoginEvent(AsyncPlayerPreLoginEvent event) {
isAsyncPlayerPreLoginEventCalled = true;
final String name = event.getName();
if (validationService.isUnrestricted(name)) {
return;
}
try {
runOnJoinChecks(name, event.getAddress().getHostAddress());
} catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
}
}
@EventHandler(priority = EventPriority.LOW)
public void onPlayerLogin(PlayerLoginEvent event) {
final Player player = event.getPlayer();
final String name = player.getName();
if (validationService.isUnrestricted(name)) {
return;
}
if (onJoinVerifier.refusePlayerForFullServer(event)) {
return;
}
@ -210,26 +249,16 @@ public class PlayerListener implements Listener {
return;
}
try {
// Fast stuff
onJoinVerifier.checkSingleSession(name);
onJoinVerifier.checkIsValidName(name);
// Get the auth later as this may cause the single session check to fail
// Slow stuff
final PlayerAuth auth = dataSource.getAuth(name);
final boolean isAuthAvailable = auth != null;
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkPlayerCountry(player, event.getAddress().getHostAddress(), isAuthAvailable);
} catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
return;
}
teleportationService.teleportOnJoin(player);
if(!isAsyncPlayerPreLoginEventCalled) {
try {
runOnJoinChecks(name, event.getAddress().getHostAddress());
} catch (FailedVerificationException e) {
event.setKickMessage(m.retrieveSingle(e.getReason(), e.getArgs()));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)

View File

@ -78,7 +78,7 @@ public final class RestrictionSettings implements SettingsHolder {
@Comment({
"The restricted user feature will kick players listed below",
"if they don't match the defined IP address. Names are case-insensitive.",
"Ip addresses support regex expressions (regex:127\\.0\\.0\\..*)",
"You can use * as wildcard (127.0.0.*), or regex with a \"regex:\" prefix regex:127\\.0\\.0\\..*",
"Example:",
" AllowedRestrictedUser:",
" - playername;127.0.0.1",

View File

@ -133,7 +133,7 @@ public final class SecuritySettings implements SettingsHolder {
newProperty("Security.emailRecovery.cooldown", 60);
@Comment({
"The maill shown using /email show will be partially hidden",
"The mail shown using /email show will be partially hidden",
"E.g. (if enabled)",
" original email: my.email@example.com",
" hidden email: my.***@***mple.com"

View File

@ -31,7 +31,7 @@ public final class ListenerConsistencyTest {
"PlayerListener#onPlayerJoin", "PlayerListener#onPlayerLogin",
"PlayerListener#onPlayerQuit", "ServerListener#onPluginDisable",
"ServerListener#onServerPing", "ServerListener#onPluginEnable",
"PlayerListener#onJoinMessage");
"PlayerListener#onJoinMessage", "PlayerListener#onAsyncPlayerPreLoginEvent");
@BeforeClass
public static void collectListenerClasses() {

View File

@ -248,12 +248,12 @@ public class OnJoinVerifierTest {
@Test
public void shouldAllowProperlyCasedName() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Bobby");
String name = "Bobby";
PlayerAuth auth = PlayerAuth.builder().name("bobby").realName("Bobby").build();
given(settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)).willReturn(true);
// when
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
// then
verifyZeroInteractions(dataSource);
@ -262,7 +262,7 @@ public class OnJoinVerifierTest {
@Test
public void shouldRejectNameWithWrongCasing() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Tester");
String name = "Tester";
PlayerAuth auth = PlayerAuth.builder().name("tester").realName("testeR").build();
given(settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)).willReturn(true);
@ -270,19 +270,19 @@ public class OnJoinVerifierTest {
expectValidationExceptionWith(MessageKey.INVALID_NAME_CASE, "testeR", "Tester");
// when / then
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
verifyZeroInteractions(dataSource);
}
@Test
public void shouldUpdateMissingRealName() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Authme");
String name = "Authme";
PlayerAuth auth = PlayerAuth.builder().name("authme").realName("").build();
given(settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)).willReturn(true);
// when
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
// then
verify(dataSource).updateRealName("authme", "Authme");
@ -291,12 +291,12 @@ public class OnJoinVerifierTest {
@Test
public void shouldUpdateDefaultRealName() throws FailedVerificationException {
// given
Player player = newPlayerWithName("SOMEONE");
String name = "SOMEONE";
PlayerAuth auth = PlayerAuth.builder().name("someone").realName("Player").build();
given(settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)).willReturn(true);
// when
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
// then
verify(dataSource).updateRealName("someone", "SOMEONE");
@ -305,12 +305,12 @@ public class OnJoinVerifierTest {
@Test
public void shouldAcceptCasingMismatchForDisabledSetting() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Test");
String name = "Test";
PlayerAuth auth = PlayerAuth.builder().name("test").realName("TEST").build();
given(settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE)).willReturn(false);
// when
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
// then
verifyZeroInteractions(dataSource);
@ -319,11 +319,11 @@ public class OnJoinVerifierTest {
@Test
public void shouldAcceptNameForUnregisteredAccount() throws FailedVerificationException {
// given
Player player = newPlayerWithName("MyPlayer");
String name = "MyPlayer";
PlayerAuth auth = null;
// when
onJoinVerifier.checkNameCasing(player, auth);
onJoinVerifier.checkNameCasing(name, auth);
// then
verifyZeroInteractions(dataSource);
@ -347,7 +347,9 @@ public class OnJoinVerifierTest {
public void shouldRejectNameAlreadyOnline() throws FailedVerificationException {
// given
String name = "Charlie";
Player onlinePlayer = newPlayerWithName("charlie");
Player onlinePlayer = mock(Player.class);
given(bukkitService.getPlayerExact("Charlie")).willReturn(onlinePlayer);
given(settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)).willReturn(true);
@ -374,27 +376,27 @@ public class OnJoinVerifierTest {
@Test
public void shouldAllowUser() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Bobby");
String name = "Bobby";
boolean isAuthAvailable = false;
given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
given(antiBotService.shouldKick()).willReturn(false);
// when
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
// then
verify(permissionsManager).hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT);
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
verify(antiBotService).shouldKick();
}
@Test
public void shouldAllowUserWithAuth() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Lacey");
String name = "Lacey";
boolean isAuthAvailable = true;
// when
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
// then
verifyZeroInteractions(permissionsManager, antiBotService);
@ -403,32 +405,32 @@ public class OnJoinVerifierTest {
@Test
public void shouldAllowUserWithBypassPermission() throws FailedVerificationException {
// given
Player player = newPlayerWithName("Steward");
String name = "Steward";
boolean isAuthAvailable = false;
given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(true);
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(true);
// when
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
// then
verify(permissionsManager).hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT);
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
verifyZeroInteractions(antiBotService);
}
@Test
public void shouldKickUserForFailedAntibotCheck() throws FailedVerificationException {
// given
Player player = newPlayerWithName("D3");
String name = "D3";
boolean isAuthAvailable = false;
given(permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
given(antiBotService.shouldKick()).willReturn(true);
// when / then
try {
onJoinVerifier.checkAntibot(player, isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
fail("Expected exception to be thrown");
} catch (FailedVerificationException e) {
verify(permissionsManager).hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT);
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
verify(antiBotService).shouldKick();
}
@ -439,18 +441,18 @@ public class OnJoinVerifierTest {
*/
@Test
public void shouldNotCheckCountry() throws FailedVerificationException {
Player player = newPlayerWithName("david");
String name = "david";
String ip = "127.0.0.1";
// protection setting disabled
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(false);
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(true);
onJoinVerifier.checkPlayerCountry(player, ip, false);
onJoinVerifier.checkPlayerCountry(name, ip, false);
verifyZeroInteractions(validationService);
// protection for registered players disabled
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(false);
onJoinVerifier.checkPlayerCountry(player, ip, true);
onJoinVerifier.checkPlayerCountry(name, ip, true);
verifyZeroInteractions(validationService);
}
@ -458,12 +460,12 @@ public class OnJoinVerifierTest {
public void shouldCheckAndAcceptUnregisteredPlayerCountry() throws FailedVerificationException {
// given
String ip = "192.168.0.1";
Player player = newPlayerWithName("lucas");
String name = "lucas";
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
given(validationService.isCountryAdmitted(ip)).willReturn(true);
// when
onJoinVerifier.checkPlayerCountry(player, ip, false);
onJoinVerifier.checkPlayerCountry(name, ip, false);
// then
verify(validationService).isCountryAdmitted(ip);
@ -473,13 +475,13 @@ public class OnJoinVerifierTest {
public void shouldCheckAndAcceptRegisteredPlayerCountry() throws FailedVerificationException {
// given
String ip = "192.168.10.24";
Player player = newPlayerWithName("gabriel");
String name = "gabriel";
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(true);
given(validationService.isCountryAdmitted(ip)).willReturn(true);
// when
onJoinVerifier.checkPlayerCountry(player, ip, true);
onJoinVerifier.checkPlayerCountry(name, ip, true);
// then
verify(validationService).isCountryAdmitted(ip);
@ -489,7 +491,7 @@ public class OnJoinVerifierTest {
public void shouldThrowForBannedCountry() throws FailedVerificationException {
// given
String ip = "192.168.40.0";
Player player = newPlayerWithName("bob");
String name = "bob";
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
given(validationService.isCountryAdmitted(ip)).willReturn(false);
@ -497,13 +499,7 @@ public class OnJoinVerifierTest {
expectValidationExceptionWith(MessageKey.COUNTRY_BANNED_ERROR);
// when
onJoinVerifier.checkPlayerCountry(player, ip, false);
}
private static Player newPlayerWithName(String name) {
Player player = mock(Player.class);
given(player.getName()).willReturn(name);
return player;
onJoinVerifier.checkPlayerCountry(name, ip, false);
}
@SuppressWarnings({ "unchecked", "rawtypes" })

View File

@ -575,10 +575,10 @@ public class PlayerListenerTest {
verify(onJoinVerifier).refusePlayerForFullServer(event);
verify(onJoinVerifier).checkSingleSession(name);
verify(onJoinVerifier).checkIsValidName(name);
verify(onJoinVerifier).checkAntibot(player, true);
verify(onJoinVerifier).checkAntibot(name, true);
verify(onJoinVerifier).checkKickNonRegistered(true);
verify(onJoinVerifier).checkNameCasing(player, auth);
verify(onJoinVerifier).checkPlayerCountry(player, ip, true);
verify(onJoinVerifier).checkNameCasing(name, auth);
verify(onJoinVerifier).checkPlayerCountry(name, ip, true);
verify(teleportationService).teleportOnJoin(player);
verifyNoModifyingCalls(event);
}
@ -588,7 +588,8 @@ public class PlayerListenerTest {
// given
String name = "inval!dName";
Player player = mockPlayerWithName(name);
PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", null));
TestHelper.mockPlayerIp(player, "33.32.33.33");
PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", player.getAddress().getAddress()));
given(validationService.isUnrestricted(name)).willReturn(false);
given(onJoinVerifier.refusePlayerForFullServer(event)).willReturn(false);
FailedVerificationException exception = new FailedVerificationException(

View File

@ -22,6 +22,7 @@ You can change the hashing algorithm in the config.yml: under `security`, locate
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
- Deprecated: Cannot be used anymore actively or in the near future.
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
- Does not work: The algorithm does not work properly; do not use.