mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-24 03:05:17 +01:00
Merge branch 'master' of https://github.com/AuthMe/AuthMeReloaded into 792-add-registration-date-and-ip
This commit is contained in:
commit
58657f5d3f
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sun Sep 17 11:29:07 CEST 2017. See docs/hashmethods/hash_algorithms.tpl.md -->
|
<!-- File auto-generated on Thu Oct 19 21:41:21 CEST 2017. See docs/hashmethods/hash_algorithms.tpl.md -->
|
||||||
|
|
||||||
## Hash Algorithms
|
## Hash Algorithms
|
||||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||||
@ -10,11 +10,9 @@ Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Se
|
|||||||
BCRYPT | Recommended | 60 | | | Text | |
|
BCRYPT | Recommended | 60 | | | Text | |
|
||||||
BCRYPT2Y | Recommended | 60 | | | Text | 22 |
|
BCRYPT2Y | Recommended | 60 | | | Text | 22 |
|
||||||
CRAZYCRYPT1 | Do not use | 128 | | | Username | |
|
CRAZYCRYPT1 | Do not use | 128 | | | Username | |
|
||||||
DOUBLEMD5 | Deprecated | 32 | | | None | |
|
|
||||||
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
||||||
IPB4 | Does not work | 60 | | | Text | 22 | Y
|
IPB4 | Does not work | 60 | | | Text | 22 | Y
|
||||||
JOOMLA | Acceptable | 65 | | | Text | 32 |
|
JOOMLA | Acceptable | 65 | | | Text | 32 |
|
||||||
MD5 | Deprecated | 32 | | | None | |
|
|
||||||
MD5VB | Acceptable | 56 | | | Text | 16 |
|
MD5VB | Acceptable | 56 | | | Text | 16 |
|
||||||
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
||||||
PBKDF2 | Recommended | 165 | | | Text | 16 |
|
PBKDF2 | Recommended | 165 | | | Text | 16 |
|
||||||
@ -24,14 +22,11 @@ PHPFUSION | Do not use | 64 | Y | | | | Y
|
|||||||
ROYALAUTH | Do not use | 128 | | | None | |
|
ROYALAUTH | Do not use | 128 | | | None | |
|
||||||
SALTED2MD5 | Acceptable | 32 | | | Text | | Y
|
SALTED2MD5 | Acceptable | 32 | | | Text | | Y
|
||||||
SALTEDSHA512 | Recommended | 128 | | | | | Y
|
SALTEDSHA512 | Recommended | 128 | | | | | Y
|
||||||
SHA1 | Deprecated | 40 | | | None | |
|
|
||||||
SHA256 | Recommended | 86 | | | Text | 16 |
|
SHA256 | Recommended | 86 | | | Text | 16 |
|
||||||
SHA512 | Deprecated | 128 | | | None | |
|
SMF | Do not use | 40 | | | Username | | Y
|
||||||
SMF | Do not use | 40 | | | Username | |
|
|
||||||
TWO_FACTOR | Does not work | 16 | | | None | |
|
TWO_FACTOR | Does not work | 16 | | | None | |
|
||||||
WBB3 | Acceptable | 40 | | | Text | 40 | Y
|
WBB3 | Acceptable | 40 | | | Text | 40 | Y
|
||||||
WBB4 | Recommended | 60 | | | Text | 8 |
|
WBB4 | Recommended | 60 | | | Text | 8 |
|
||||||
WHIRLPOOL | Deprecated | 128 | | | None | |
|
|
||||||
WORDPRESS | Acceptable | 34 | | | Text | 9 |
|
WORDPRESS | Acceptable | 34 | | | Text | 9 |
|
||||||
XAUTH | Recommended | 140 | | | Text | 12 |
|
XAUTH | Recommended | 140 | | | Text | 12 |
|
||||||
XFBCRYPT | | 60 | | | | |
|
XFBCRYPT | | 60 | | | | |
|
||||||
@ -83,4 +78,4 @@ or bad.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
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
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Thu Oct 19 21:41:21 CEST 2017
|
||||||
|
4
pom.xml
4
pom.xml
@ -325,7 +325,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>23.0</version>
|
<version>23.2-jre</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
@ -360,7 +360,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.zaxxer</groupId>
|
<groupId>com.zaxxer</groupId>
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<version>2.7.1</version>
|
<version>2.7.2</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
@ -23,7 +23,6 @@ import fr.xephi.authme.listener.PlayerListener18;
|
|||||||
import fr.xephi.authme.listener.PlayerListener19;
|
import fr.xephi.authme.listener.PlayerListener19;
|
||||||
import fr.xephi.authme.listener.PlayerListener19Spigot;
|
import fr.xephi.authme.listener.PlayerListener19Spigot;
|
||||||
import fr.xephi.authme.listener.ServerListener;
|
import fr.xephi.authme.listener.ServerListener;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
|
||||||
import fr.xephi.authme.security.crypts.Sha256;
|
import fr.xephi.authme.security.crypts.Sha256;
|
||||||
import fr.xephi.authme.service.BackupService;
|
import fr.xephi.authme.service.BackupService;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
@ -268,13 +267,6 @@ public class AuthMe extends JavaPlugin {
|
|||||||
&& settings.getProperty(EmailSettings.SMTP_PORT) != 25) {
|
&& settings.getProperty(EmailSettings.SMTP_PORT) != 25) {
|
||||||
ConsoleLogger.warning("Note: You have set Email.useTls to false but this only affects mail over port 25");
|
ConsoleLogger.warning("Note: You have set Email.useTls to false but this only affects mail over port 25");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsalted hashes will be deprecated in 5.4 (see Github issue #1016)
|
|
||||||
HashAlgorithm hash = settings.getProperty(SecuritySettings.PASSWORD_HASH);
|
|
||||||
if (OnStartupTasks.isHashDeprecatedIn54(hash)) {
|
|
||||||
ConsoleLogger.warning("You are using an unsalted hash (" + hash + "). Support for this will be removed "
|
|
||||||
+ "in 5.4 -- do you still need it? Comment on https://github.com/AuthMe/AuthMeReloaded/issues/1016");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,7 @@ import java.util.Date;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The plugin's static logger.
|
* The plugin's static logger.
|
||||||
@ -168,7 +169,7 @@ public final class ConsoleLogger {
|
|||||||
* @param message the message
|
* @param message the message
|
||||||
* @param param1 parameter to replace in the message
|
* @param param1 parameter to replace in the message
|
||||||
*/
|
*/
|
||||||
public static void debug(String message, String param1) {
|
public static void debug(String message, Object param1) {
|
||||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||||
String debugMessage = "[DEBUG] " + message;
|
String debugMessage = "[DEBUG] " + message;
|
||||||
logger.log(Level.INFO, debugMessage, param1);
|
logger.log(Level.INFO, debugMessage, param1);
|
||||||
@ -184,24 +185,9 @@ public final class ConsoleLogger {
|
|||||||
* @param param2 second param to replace in message
|
* @param param2 second param to replace in message
|
||||||
*/
|
*/
|
||||||
// Avoids array creation if DEBUG level is disabled
|
// Avoids array creation if DEBUG level is disabled
|
||||||
public static void debug(String message, String param1, String param2) {
|
public static void debug(String message, Object param1, Object param2) {
|
||||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||||
debug(message, new String[]{param1, param2});
|
debug(message, new Object[]{param1, param2});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log the DEBUG message.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
* @param params the params to replace in the message
|
|
||||||
*/
|
|
||||||
// Equivalent to debug(String, Object...) but avoids conversions
|
|
||||||
public static void debug(String message, String... params) {
|
|
||||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
|
||||||
String debugMessage = "[DEBUG] " + message;
|
|
||||||
logger.log(Level.INFO, debugMessage, params);
|
|
||||||
writeLog(debugMessage + " {" + String.join(", ", params) + "}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +199,10 @@ public final class ConsoleLogger {
|
|||||||
*/
|
*/
|
||||||
public static void debug(String message, Object... params) {
|
public static void debug(String message, Object... params) {
|
||||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||||
debug(message, Arrays.stream(params).map(String::valueOf).toArray(String[]::new));
|
String debugMessage = "[DEBUG] " + message;
|
||||||
|
logger.log(Level.INFO, debugMessage, params);
|
||||||
|
writeLog(debugMessage + " {"
|
||||||
|
+ Arrays.stream(params).map(String::valueOf).collect(Collectors.joining(", ")) + "}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ public class MySQL implements DataSource {
|
|||||||
public boolean hasSession(String user) {
|
public boolean hasSession(String user) {
|
||||||
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
pst.setString(1, user);
|
pst.setString(1, user.toLowerCase());
|
||||||
try (ResultSet rs = pst.executeQuery()) {
|
try (ResultSet rs = pst.executeQuery()) {
|
||||||
return rs.next() && (rs.getInt(col.HAS_SESSION) == 1);
|
return rs.next() && (rs.getInt(col.HAS_SESSION) == 1);
|
||||||
}
|
}
|
||||||
|
@ -509,7 +509,7 @@ public class SQLite implements DataSource {
|
|||||||
public boolean hasSession(String user) {
|
public boolean hasSession(String user) {
|
||||||
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
|
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
pst.setString(1, user);
|
pst.setString(1, user.toLowerCase());
|
||||||
try (ResultSet rs = pst.executeQuery()) {
|
try (ResultSet rs = pst.executeQuery()) {
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
return rs.getInt(col.HAS_SESSION) == 1;
|
return rs.getInt(col.HAS_SESSION) == 1;
|
||||||
@ -526,7 +526,7 @@ public class SQLite implements DataSource {
|
|||||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
pst.setInt(1, 1);
|
pst.setInt(1, 1);
|
||||||
pst.setString(2, user);
|
pst.setString(2, user.toLowerCase());
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
logSqlException(ex);
|
logSqlException(ex);
|
||||||
@ -538,7 +538,7 @@ public class SQLite implements DataSource {
|
|||||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
pst.setInt(1, 0);
|
pst.setInt(1, 0);
|
||||||
pst.setString(2, user);
|
pst.setString(2, user.toLowerCase());
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
logSqlException(ex);
|
logSqlException(ex);
|
||||||
|
@ -7,9 +7,6 @@ import fr.xephi.authme.message.MessageKey;
|
|||||||
import fr.xephi.authme.message.Messages;
|
import fr.xephi.authme.message.Messages;
|
||||||
import fr.xephi.authme.output.ConsoleFilter;
|
import fr.xephi.authme.output.ConsoleFilter;
|
||||||
import fr.xephi.authme.output.Log4JFilter;
|
import fr.xephi.authme.output.Log4JFilter;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
|
||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
@ -103,23 +100,4 @@ public class OnStartupTasks {
|
|||||||
}
|
}
|
||||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the hash algorithm is deprecated and won't be able
|
|
||||||
* to be actively used anymore in 5.4.
|
|
||||||
*
|
|
||||||
* @param hash the hash algorithm to check
|
|
||||||
* @return true if the hash will be deprecated, false otherwise
|
|
||||||
* @see <a href="https://github.com/AuthMe/AuthMeReloaded/issues/1016">#1016</a>
|
|
||||||
*/
|
|
||||||
public static boolean isHashDeprecatedIn54(HashAlgorithm hash) {
|
|
||||||
if (hash.getClazz() == null || hash == HashAlgorithm.PLAINTEXT) {
|
|
||||||
// Exclude PLAINTEXT from this check because it already has a mandatory migration, which takes care of
|
|
||||||
// sending all the necessary messages and warnings.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Recommendation recommendation = hash.getClazz().getAnnotation(Recommendation.class);
|
|
||||||
return recommendation != null && recommendation.value() == Usage.DEPRECATED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,34 +10,34 @@ public enum HashAlgorithm {
|
|||||||
BCRYPT(fr.xephi.authme.security.crypts.BCrypt.class),
|
BCRYPT(fr.xephi.authme.security.crypts.BCrypt.class),
|
||||||
BCRYPT2Y(fr.xephi.authme.security.crypts.BCrypt2y.class),
|
BCRYPT2Y(fr.xephi.authme.security.crypts.BCrypt2y.class),
|
||||||
CRAZYCRYPT1(fr.xephi.authme.security.crypts.CrazyCrypt1.class),
|
CRAZYCRYPT1(fr.xephi.authme.security.crypts.CrazyCrypt1.class),
|
||||||
DOUBLEMD5(fr.xephi.authme.security.crypts.DoubleMd5.class),
|
|
||||||
IPB3(fr.xephi.authme.security.crypts.Ipb3.class),
|
IPB3(fr.xephi.authme.security.crypts.Ipb3.class),
|
||||||
IPB4(fr.xephi.authme.security.crypts.Ipb4.class),
|
IPB4(fr.xephi.authme.security.crypts.Ipb4.class),
|
||||||
JOOMLA(fr.xephi.authme.security.crypts.Joomla.class),
|
JOOMLA(fr.xephi.authme.security.crypts.Joomla.class),
|
||||||
MD5(fr.xephi.authme.security.crypts.Md5.class),
|
|
||||||
MD5VB(fr.xephi.authme.security.crypts.Md5vB.class),
|
MD5VB(fr.xephi.authme.security.crypts.Md5vB.class),
|
||||||
MYBB(fr.xephi.authme.security.crypts.MyBB.class),
|
MYBB(fr.xephi.authme.security.crypts.MyBB.class),
|
||||||
PBKDF2(fr.xephi.authme.security.crypts.Pbkdf2.class),
|
PBKDF2(fr.xephi.authme.security.crypts.Pbkdf2.class),
|
||||||
PBKDF2DJANGO(fr.xephi.authme.security.crypts.Pbkdf2Django.class),
|
PBKDF2DJANGO(fr.xephi.authme.security.crypts.Pbkdf2Django.class),
|
||||||
PHPBB(fr.xephi.authme.security.crypts.PhpBB.class),
|
PHPBB(fr.xephi.authme.security.crypts.PhpBB.class),
|
||||||
PHPFUSION(fr.xephi.authme.security.crypts.PhpFusion.class),
|
PHPFUSION(fr.xephi.authme.security.crypts.PhpFusion.class),
|
||||||
@Deprecated
|
|
||||||
PLAINTEXT(fr.xephi.authme.security.crypts.PlainText.class),
|
|
||||||
ROYALAUTH(fr.xephi.authme.security.crypts.RoyalAuth.class),
|
ROYALAUTH(fr.xephi.authme.security.crypts.RoyalAuth.class),
|
||||||
SALTED2MD5(fr.xephi.authme.security.crypts.Salted2Md5.class),
|
SALTED2MD5(fr.xephi.authme.security.crypts.Salted2Md5.class),
|
||||||
SALTEDSHA512(fr.xephi.authme.security.crypts.SaltedSha512.class),
|
SALTEDSHA512(fr.xephi.authme.security.crypts.SaltedSha512.class),
|
||||||
SHA1(fr.xephi.authme.security.crypts.Sha1.class),
|
|
||||||
SHA256(fr.xephi.authme.security.crypts.Sha256.class),
|
SHA256(fr.xephi.authme.security.crypts.Sha256.class),
|
||||||
SHA512(fr.xephi.authme.security.crypts.Sha512.class),
|
|
||||||
SMF(fr.xephi.authme.security.crypts.Smf.class),
|
SMF(fr.xephi.authme.security.crypts.Smf.class),
|
||||||
TWO_FACTOR(fr.xephi.authme.security.crypts.TwoFactor.class),
|
TWO_FACTOR(fr.xephi.authme.security.crypts.TwoFactor.class),
|
||||||
WBB3(fr.xephi.authme.security.crypts.Wbb3.class),
|
WBB3(fr.xephi.authme.security.crypts.Wbb3.class),
|
||||||
WBB4(fr.xephi.authme.security.crypts.Wbb4.class),
|
WBB4(fr.xephi.authme.security.crypts.Wbb4.class),
|
||||||
WHIRLPOOL(fr.xephi.authme.security.crypts.Whirlpool.class),
|
|
||||||
WORDPRESS(fr.xephi.authme.security.crypts.Wordpress.class),
|
WORDPRESS(fr.xephi.authme.security.crypts.Wordpress.class),
|
||||||
XAUTH(fr.xephi.authme.security.crypts.XAuth.class),
|
XAUTH(fr.xephi.authme.security.crypts.XAuth.class),
|
||||||
XFBCRYPT(fr.xephi.authme.security.crypts.XfBCrypt.class),
|
XFBCRYPT(fr.xephi.authme.security.crypts.XfBCrypt.class),
|
||||||
CUSTOM(null);
|
CUSTOM(null),
|
||||||
|
|
||||||
|
@Deprecated DOUBLEMD5(fr.xephi.authme.security.crypts.DoubleMd5.class),
|
||||||
|
@Deprecated MD5(fr.xephi.authme.security.crypts.Md5.class),
|
||||||
|
@Deprecated PLAINTEXT(fr.xephi.authme.security.crypts.PlainText.class),
|
||||||
|
@Deprecated SHA1(fr.xephi.authme.security.crypts.Sha1.class),
|
||||||
|
@Deprecated SHA512(fr.xephi.authme.security.crypts.Sha512.class),
|
||||||
|
@Deprecated WHIRLPOOL(fr.xephi.authme.security.crypts.Whirlpool.class);
|
||||||
|
|
||||||
private final Class<? extends EncryptionMethod> clazz;
|
private final Class<? extends EncryptionMethod> clazz;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
|||||||
|
|
||||||
import static fr.xephi.authme.security.HashUtils.md5;
|
import static fr.xephi.authme.security.HashUtils.md5;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Recommendation(Usage.DEPRECATED)
|
@Recommendation(Usage.DEPRECATED)
|
||||||
public class DoubleMd5 extends UnsaltedMethod {
|
public class DoubleMd5 extends UnsaltedMethod {
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import fr.xephi.authme.security.HashUtils;
|
|||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Recommendation(Usage.DEPRECATED)
|
@Recommendation(Usage.DEPRECATED)
|
||||||
public class Md5 extends UnsaltedMethod {
|
public class Md5 extends UnsaltedMethod {
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import fr.xephi.authme.security.HashUtils;
|
|||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Recommendation(Usage.DEPRECATED)
|
@Recommendation(Usage.DEPRECATED)
|
||||||
public class Sha1 extends UnsaltedMethod {
|
public class Sha1 extends UnsaltedMethod {
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import fr.xephi.authme.security.HashUtils;
|
|||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Recommendation(Usage.DEPRECATED)
|
@Recommendation(Usage.DEPRECATED)
|
||||||
public class Sha512 extends UnsaltedMethod {
|
public class Sha512 extends UnsaltedMethod {
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Recommendation(Usage.DEPRECATED)
|
@Recommendation(Usage.DEPRECATED)
|
||||||
public class Whirlpool extends UnsaltedMethod {
|
public class Whirlpool extends UnsaltedMethod {
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ package fr.xephi.authme.settings;
|
|||||||
import ch.jalu.configme.properties.Property;
|
import ch.jalu.configme.properties.Property;
|
||||||
import ch.jalu.configme.resource.PropertyResource;
|
import ch.jalu.configme.resource.PropertyResource;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ public class EnumSetProperty<E extends Enum<E>> extends Property<Set<E>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<E> getFromResource(PropertyResource resource) {
|
protected Set<E> getFromResource(PropertyResource resource) {
|
||||||
List<?> elements = resource.getList(getPath());
|
Object entry = resource.getObject(getPath());
|
||||||
if (elements != null) {
|
if (entry instanceof Collection<?>) {
|
||||||
return elements.stream()
|
return ((Collection<?>) entry).stream()
|
||||||
.map(val -> toEnum(String.valueOf(val)))
|
.map(val -> toEnum(String.valueOf(val)))
|
||||||
.filter(e -> e != null)
|
.filter(e -> e != null)
|
||||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
@ -10,6 +10,7 @@ import fr.xephi.authme.initialization.DataFolder;
|
|||||||
import fr.xephi.authme.output.LogLevel;
|
import fr.xephi.authme.output.LogLevel;
|
||||||
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
|
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
|
||||||
import fr.xephi.authme.process.register.RegistrationType;
|
import fr.xephi.authme.process.register.RegistrationType;
|
||||||
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
@ -20,6 +21,7 @@ import java.io.FileWriter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
|
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
|
||||||
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
|
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
|
||||||
@ -73,6 +75,7 @@ public class SettingsMigrationService extends PlainMigrationService {
|
|||||||
| hasSupportOldPasswordProperty(resource)
|
| hasSupportOldPasswordProperty(resource)
|
||||||
| convertToRegistrationType(resource)
|
| convertToRegistrationType(resource)
|
||||||
| mergeAndMovePermissionGroupSettings(resource)
|
| mergeAndMovePermissionGroupSettings(resource)
|
||||||
|
| moveDeprecatedHashAlgorithmIntoLegacySection(resource)
|
||||||
|| hasDeprecatedProperties(resource);
|
|| hasDeprecatedProperties(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +289,31 @@ public class SettingsMigrationService extends PlainMigrationService {
|
|||||||
return performedChanges;
|
return performedChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a deprecated hash is used, it is added to the legacy hashes option and the active hash
|
||||||
|
* is changed to SHA256.
|
||||||
|
*
|
||||||
|
* @param resource The property resource
|
||||||
|
* @return True if the configuration has changed, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean moveDeprecatedHashAlgorithmIntoLegacySection(PropertyResource resource) {
|
||||||
|
HashAlgorithm currentHash = SecuritySettings.PASSWORD_HASH.getValue(resource);
|
||||||
|
// Skip CUSTOM (has no class) and PLAINTEXT (is force-migrated later on in the startup process)
|
||||||
|
if (currentHash != HashAlgorithm.CUSTOM && currentHash != HashAlgorithm.PLAINTEXT) {
|
||||||
|
Class<?> encryptionClass = currentHash.getClazz();
|
||||||
|
if (encryptionClass.isAnnotationPresent(Deprecated.class)) {
|
||||||
|
resource.setValue(SecuritySettings.PASSWORD_HASH.getPath(), HashAlgorithm.SHA256);
|
||||||
|
Set<HashAlgorithm> legacyHashes = SecuritySettings.LEGACY_HASHES.getValue(resource);
|
||||||
|
legacyHashes.add(currentHash);
|
||||||
|
resource.setValue(SecuritySettings.LEGACY_HASHES.getPath(), legacyHashes);
|
||||||
|
ConsoleLogger.warning("The hash algorithm '" + currentHash
|
||||||
|
+ "' is no longer supported for active use. New hashes will be in SHA256.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for an old property path and moves it to a new path if it is present and the new path is not yet set.
|
* Checks for an old property path and moves it to a new path if it is present and the new path is not yet set.
|
||||||
*
|
*
|
||||||
|
@ -53,7 +53,7 @@ public final class SecuritySettings implements SettingsHolder {
|
|||||||
newProperty("settings.security.passwordMaxLength", 30);
|
newProperty("settings.security.passwordMaxLength", 30);
|
||||||
|
|
||||||
@Comment({
|
@Comment({
|
||||||
"Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512, WHIRLPOOL,",
|
"Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,",
|
||||||
"MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,",
|
"MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,",
|
||||||
"PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only). See full list at",
|
"PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only). See full list at",
|
||||||
"https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md"
|
"https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md"
|
||||||
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -142,25 +143,22 @@ public class ConsoleLoggerTest {
|
|||||||
ConsoleLogger.setLoggingOptions(newSettings(true, LogLevel.DEBUG));
|
ConsoleLogger.setLoggingOptions(newSettings(true, LogLevel.DEBUG));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ConsoleLogger.debug("Got {0} entries", "test");
|
ConsoleLogger.debug("Got {0} entries", 17);
|
||||||
ConsoleLogger.debug("Player `{0}` is in world `{1}`", "Bobby", "world");
|
ConsoleLogger.debug("Player `{0}` is in world `{1}`", "Bobby", new World("world"));
|
||||||
ConsoleLogger.debug("The {0} is {1} the {2}", "fox", "behind", "chicken");
|
|
||||||
ConsoleLogger.debug("{0} quick {1} jump over {2} lazy {3} (reason: {4})", 5, "foxes", 3, "dogs", null);
|
ConsoleLogger.debug("{0} quick {1} jump over {2} lazy {3} (reason: {4})", 5, "foxes", 3, "dogs", null);
|
||||||
ConsoleLogger.debug(() -> "Too little too late");
|
ConsoleLogger.debug(() -> "Too little too late");
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(logger).log(Level.INFO, "[DEBUG] Got {0} entries", "test");
|
verify(logger).log(Level.INFO, "[DEBUG] Got {0} entries", 17);
|
||||||
verify(logger).log(Level.INFO, "[DEBUG] Player `{0}` is in world `{1}`", new Object[]{"Bobby", "world"});
|
verify(logger).log(Level.INFO, "[DEBUG] Player `{0}` is in world `{1}`", new Object[]{"Bobby", new World("world")});
|
||||||
verify(logger).log(Level.INFO, "[DEBUG] The {0} is {1} the {2}", new Object[]{"fox", "behind", "chicken"});
|
|
||||||
verify(logger).log(Level.INFO, "[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4})",
|
verify(logger).log(Level.INFO, "[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4})",
|
||||||
new Object[]{"5", "foxes", "3", "dogs", "null"});
|
new Object[]{5, "foxes", 3, "dogs", null});
|
||||||
verify(logger).info("[DEBUG] Too little too late");
|
verify(logger).info("[DEBUG] Too little too late");
|
||||||
|
|
||||||
List<String> loggedLines = Files.readAllLines(logFile.toPath(), StandardCharsets.UTF_8);
|
List<String> loggedLines = Files.readAllLines(logFile.toPath(), StandardCharsets.UTF_8);
|
||||||
assertThat(loggedLines, contains(
|
assertThat(loggedLines, contains(
|
||||||
containsString("[DEBUG] Got {0} entries {test}"),
|
containsString("[DEBUG] Got {0} entries {17}"),
|
||||||
containsString("[DEBUG] Player `{0}` is in world `{1}` {Bobby, world}"),
|
containsString("[DEBUG] Player `{0}` is in world `{1}` {Bobby, w[world]}"),
|
||||||
containsString("[DEBUG] The {0} is {1} the {2} {fox, behind, chicken}"),
|
|
||||||
containsString("[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4}) {5, foxes, 3, dogs, null}"),
|
containsString("[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4}) {5, foxes, 3, dogs, null}"),
|
||||||
containsString("[DEBUG] Too little too late")));
|
containsString("[DEBUG] Too little too late")));
|
||||||
}
|
}
|
||||||
@ -176,4 +174,25 @@ public class ConsoleLoggerTest {
|
|||||||
given(settings.getProperty(PluginSettings.LOG_LEVEL)).willReturn(logLevel);
|
given(settings.getProperty(PluginSettings.LOG_LEVEL)).willReturn(logLevel);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class World {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
World(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "w[" + name + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other instanceof World) {
|
||||||
|
return Objects.equals(this.name, ((World) other).name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package fr.xephi.authme.initialization;
|
|
||||||
|
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for {@link OnStartupTasks}.
|
|
||||||
*/
|
|
||||||
public class OnStartupTasksTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shouldCheckIfHashIsDeprecatedIn54() {
|
|
||||||
// given / when / then
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.CUSTOM), equalTo(false));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.IPB3), equalTo(false));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.PLAINTEXT), equalTo(false));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.SHA256), equalTo(false));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.WORDPRESS), equalTo(false));
|
|
||||||
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.MD5), equalTo(true));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.SHA512), equalTo(true));
|
|
||||||
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.WHIRLPOOL), equalTo(true));
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,8 @@ import ch.jalu.injector.Injector;
|
|||||||
import ch.jalu.injector.InjectorBuilder;
|
import ch.jalu.injector.InjectorBuilder;
|
||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
@ -12,6 +14,8 @@ import org.junit.BeforeClass;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
@ -70,4 +74,29 @@ public class HashAlgorithmIntegrationTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldBeDeprecatedIfEncryptionClassIsDeprecated() throws NoSuchFieldException {
|
||||||
|
// given
|
||||||
|
List<String> failedEntries = new LinkedList<>();
|
||||||
|
|
||||||
|
// when
|
||||||
|
for (HashAlgorithm hashAlgorithm : HashAlgorithm.values()) {
|
||||||
|
if (hashAlgorithm != HashAlgorithm.CUSTOM) {
|
||||||
|
boolean isEnumDeprecated = HashAlgorithm.class.getDeclaredField(hashAlgorithm.name())
|
||||||
|
.isAnnotationPresent(Deprecated.class);
|
||||||
|
boolean isDeprecatedClass = hashAlgorithm.getClazz().isAnnotationPresent(Deprecated.class);
|
||||||
|
Recommendation recommendation = hashAlgorithm.getClazz().getAnnotation(Recommendation.class);
|
||||||
|
boolean hasDeprecatedUsage = recommendation != null && recommendation.value() == Usage.DEPRECATED;
|
||||||
|
if (isEnumDeprecated != isDeprecatedClass || isEnumDeprecated != hasDeprecatedUsage) {
|
||||||
|
failedEntries.add(hashAlgorithm + ": enum @Deprecated = " + isEnumDeprecated
|
||||||
|
+ ", @Deprecated class = " + isDeprecatedClass + ", usage Deprecated = " + hasDeprecatedUsage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
if (!failedEntries.isEmpty()) {
|
||||||
|
fail("Found inconsistencies:\n" + String.join("\n", failedEntries));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
|
import ch.jalu.configme.configurationdata.ConfigurationData;
|
||||||
|
import ch.jalu.configme.properties.Property;
|
||||||
import ch.jalu.configme.resource.PropertyResource;
|
import ch.jalu.configme.resource.PropertyResource;
|
||||||
import ch.jalu.configme.resource.YamlFileResource;
|
import ch.jalu.configme.resource.YamlFileResource;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import fr.xephi.authme.TestHelper;
|
import fr.xephi.authme.TestHelper;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
import fr.xephi.authme.output.LogLevel;
|
import fr.xephi.authme.output.LogLevel;
|
||||||
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
|
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
|
||||||
import fr.xephi.authme.process.register.RegistrationType;
|
import fr.xephi.authme.process.register.RegistrationType;
|
||||||
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@ -16,6 +20,8 @@ import org.junit.rules.TemporaryFolder;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static fr.xephi.authme.TestHelper.getJarFile;
|
import static fr.xephi.authme.TestHelper.getJarFile;
|
||||||
import static fr.xephi.authme.settings.properties.PluginSettings.ENABLE_PERMISSION_CHECK;
|
import static fr.xephi.authme.settings.properties.PluginSettings.ENABLE_PERMISSION_CHECK;
|
||||||
@ -28,6 +34,8 @@ import static fr.xephi.authme.settings.properties.RegistrationSettings.REGISTRAT
|
|||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_LOCATION_AFTER_LOGIN;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_LOCATION_AFTER_LOGIN;
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_ON_WORLDS;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_ON_WORLDS;
|
||||||
|
import static fr.xephi.authme.settings.properties.SecuritySettings.LEGACY_HASHES;
|
||||||
|
import static fr.xephi.authme.settings.properties.SecuritySettings.PASSWORD_HASH;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
@ -47,8 +55,9 @@ public class SettingsMigrationServiceTest {
|
|||||||
TestHelper.setupLogger();
|
TestHelper.setupLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When settings are loaded, test that migrations are applied and immediately available in memory. */
|
||||||
@Test
|
@Test
|
||||||
public void shouldPerformMigrations() throws IOException {
|
public void shouldPerformMigrationsInMemory() throws IOException {
|
||||||
// given
|
// given
|
||||||
File dataFolder = temporaryFolder.newFolder();
|
File dataFolder = temporaryFolder.newFolder();
|
||||||
File configFile = new File(dataFolder, "config.yml");
|
File configFile = new File(dataFolder, "config.yml");
|
||||||
@ -61,22 +70,31 @@ public class SettingsMigrationServiceTest {
|
|||||||
dataFolder, resource, migrationService, AuthMeSettingsRetriever.buildConfigurationData());
|
dataFolder, resource, migrationService, AuthMeSettingsRetriever.buildConfigurationData());
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(settings.getProperty(ALLOWED_NICKNAME_CHARACTERS), equalTo(ALLOWED_NICKNAME_CHARACTERS.getDefaultValue()));
|
verifyHasUpToDateSettings(settings, dataFolder);
|
||||||
assertThat(settings.getProperty(DELAY_JOIN_MESSAGE), equalTo(true));
|
}
|
||||||
assertThat(settings.getProperty(FORCE_SPAWN_LOCATION_AFTER_LOGIN), equalTo(true));
|
|
||||||
assertThat(settings.getProperty(FORCE_SPAWN_ON_WORLDS), contains("survival", "survival_nether", "creative"));
|
|
||||||
assertThat(settings.getProperty(LOG_LEVEL), equalTo(LogLevel.INFO));
|
|
||||||
assertThat(settings.getProperty(REGISTRATION_TYPE), equalTo(RegistrationType.EMAIL));
|
|
||||||
assertThat(settings.getProperty(REGISTER_SECOND_ARGUMENT), equalTo(RegisterSecondaryArgument.CONFIRMATION));
|
|
||||||
assertThat(settings.getProperty(ENABLE_PERMISSION_CHECK), equalTo(true));
|
|
||||||
assertThat(settings.getProperty(REGISTERED_GROUP), equalTo("unLoggedinGroup"));
|
|
||||||
assertThat(settings.getProperty(UNREGISTERED_GROUP), equalTo(""));
|
|
||||||
|
|
||||||
// Check migration of old setting to email.html
|
/*
|
||||||
assertThat(Files.readLines(new File(dataFolder, "email.html"), StandardCharsets.UTF_8),
|
* When settings are loaded, test that migrations are applied and persisted to disk,
|
||||||
contains("Dear <playername />, <br /><br /> This is your new AuthMe password for the server "
|
* i.e. when the settings are loaded again from the file, no migrations should be necessary.
|
||||||
+ "<br /><br /> <servername /> : <br /><br /> <generatedpass /><br /><image /><br />Do not forget to "
|
*/
|
||||||
+ "change password after login! <br /> /changepassword <generatedpass /> newPassword"));
|
@Test
|
||||||
|
public void shouldPerformMigrationsAndPersistToDisk() throws IOException {
|
||||||
|
// given
|
||||||
|
File dataFolder = temporaryFolder.newFolder();
|
||||||
|
File configFile = new File(dataFolder, "config.yml");
|
||||||
|
Files.copy(getJarFile(OLD_CONFIG_FILE), configFile);
|
||||||
|
PropertyResource resource = new YamlFileResource(configFile);
|
||||||
|
TestMigrationServiceExtension migrationService = new TestMigrationServiceExtension(dataFolder);
|
||||||
|
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||||
|
|
||||||
|
// when
|
||||||
|
new Settings(dataFolder, resource, migrationService, configurationData);
|
||||||
|
resource = new YamlFileResource(configFile);
|
||||||
|
Settings settings = new Settings(dataFolder, resource, migrationService, configurationData);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verifyHasUpToDateSettings(settings, dataFolder);
|
||||||
|
assertThat(migrationService.returnedValues, contains(true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -97,4 +115,40 @@ public class SettingsMigrationServiceTest {
|
|||||||
assertThat(migrationService.getOnRegisterCommands(), contains("me registers", "msg CONSOLE hi"));
|
assertThat(migrationService.getOnRegisterCommands(), contains("me registers", "msg CONSOLE hi"));
|
||||||
assertThat(migrationService.getOnRegisterConsoleCommands(), contains("sethome %p:regloc"));
|
assertThat(migrationService.getOnRegisterConsoleCommands(), contains("sethome %p:regloc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyHasUpToDateSettings(Settings settings, File dataFolder) throws IOException {
|
||||||
|
assertThat(settings.getProperty(ALLOWED_NICKNAME_CHARACTERS), equalTo(ALLOWED_NICKNAME_CHARACTERS.getDefaultValue()));
|
||||||
|
assertThat(settings.getProperty(DELAY_JOIN_MESSAGE), equalTo(true));
|
||||||
|
assertThat(settings.getProperty(FORCE_SPAWN_LOCATION_AFTER_LOGIN), equalTo(true));
|
||||||
|
assertThat(settings.getProperty(FORCE_SPAWN_ON_WORLDS), contains("survival", "survival_nether", "creative"));
|
||||||
|
assertThat(settings.getProperty(LOG_LEVEL), equalTo(LogLevel.INFO));
|
||||||
|
assertThat(settings.getProperty(REGISTRATION_TYPE), equalTo(RegistrationType.EMAIL));
|
||||||
|
assertThat(settings.getProperty(REGISTER_SECOND_ARGUMENT), equalTo(RegisterSecondaryArgument.CONFIRMATION));
|
||||||
|
assertThat(settings.getProperty(ENABLE_PERMISSION_CHECK), equalTo(true));
|
||||||
|
assertThat(settings.getProperty(REGISTERED_GROUP), equalTo("unLoggedinGroup"));
|
||||||
|
assertThat(settings.getProperty(UNREGISTERED_GROUP), equalTo(""));
|
||||||
|
assertThat(settings.getProperty(PASSWORD_HASH), equalTo(HashAlgorithm.SHA256));
|
||||||
|
assertThat(settings.getProperty(LEGACY_HASHES), contains(HashAlgorithm.PBKDF2, HashAlgorithm.WORDPRESS, HashAlgorithm.SHA512));
|
||||||
|
|
||||||
|
// Check migration of old setting to email.html
|
||||||
|
assertThat(Files.readLines(new File(dataFolder, "email.html"), StandardCharsets.UTF_8),
|
||||||
|
contains("Dear <playername />, <br /><br /> This is your new AuthMe password for the server "
|
||||||
|
+ "<br /><br /> <servername /> : <br /><br /> <generatedpass /><br /><image /><br />Do not forget to "
|
||||||
|
+ "change password after login! <br /> /changepassword <generatedpass /> newPassword"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestMigrationServiceExtension extends SettingsMigrationService {
|
||||||
|
private List<Boolean> returnedValues = new ArrayList<>();
|
||||||
|
|
||||||
|
TestMigrationServiceExtension(@DataFolder File pluginFolder) {
|
||||||
|
super(pluginFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean performMigrations(PropertyResource resource, List<Property<?>> properties) {
|
||||||
|
boolean result = super.performMigrations(resource, properties);
|
||||||
|
returnedValues.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,10 @@ settings:
|
|||||||
# PLAINTEXT ( unhashed password),
|
# PLAINTEXT ( unhashed password),
|
||||||
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
|
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
|
||||||
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
|
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
|
||||||
passwordHash: SHA256
|
passwordHash: SHA512
|
||||||
|
legacyHashes:
|
||||||
|
- PBKDF2
|
||||||
|
- WORDPRESS
|
||||||
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
|
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
|
||||||
doubleMD5SaltLength: 8
|
doubleMD5SaltLength: 8
|
||||||
# If password checking return false , do we need to check with all
|
# If password checking return false , do we need to check with all
|
||||||
|
Loading…
Reference in New Issue
Block a user