Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -342,20 +342,24 @@ public void validateProfile( final Context context, final UserProfile profile )

if( !m_engine.getManager( AuthenticationManager.class ).isContainerAuthenticated() ) {
// passwords must match and can't be null

//this is the new password
final String password = profile.getPassword();
if( password == null ) {
session.addMessage( SESSION_MESSAGES, rb.getString( "security.error.blankpassword" ) );
} else {
final HttpServletRequest request = context.getHttpRequest();
//the existing password
final String password0 = ( request == null ) ? null : request.getParameter( "password0" );
//the new password confirmation
final String password2 = ( request == null ) ? null : request.getParameter( "password2" );
if( !password.equals( password2 ) ) {
session.addMessage( SESSION_MESSAGES, rb.getString( "security.error.passwordnomatch" ) );
}
if( !profile.isNew() && !getUserDatabase().validatePassword( profile.getLoginName(), password0 ) ) {
session.addMessage( SESSION_MESSAGES, rb.getString( "security.error.passwordnomatch" ) );
}
List<String> msg = PasswordComplexityVeriffier.validate(password2, context);
List<String> msg = PasswordComplexityVeriffier.validate(password2, password0, context);
for (String s : msg) {
session.addMessage( SESSION_MESSAGES, s );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private PasswordComplexityVeriffier() {
* @param context
* @return see above
*/
public static List<String> validate(String pwd, Context context) {
public static List<String> validate(String pwd, String previousPwd, Context context) {
Properties wikiProps = context.getEngine().getWikiProperties();
final ResourceBundle rb = ResourceBundle.getBundle(InternationalizationManager.CORE_BUNDLE, context.getWikiSession().getLocale());

Expand All @@ -55,6 +55,7 @@ public static List<String> validate(String pwd, Context context) {
int minDigits = Integer.parseInt(wikiProps.getProperty("jspwiki.credentials.minDigits", "1"));
int minSymbols = Integer.parseInt(wikiProps.getProperty("jspwiki.credentials.minSymbols", "1"));
int maxRepeats = Integer.parseInt(wikiProps.getProperty("jspwiki.credentials.repeatingCharacters", "1"));
int minChanged = Integer.parseInt(wikiProps.getProperty("jspwiki.credentials.minChanged", "0"));
//potential future enhancement, detect common patterns like keyboard walks, asdf, etc
//boolean allowCommonPatterns = "true".equalsIgnoreCase(wikiProps.getProperty("jspwiki.credentials.allowCommonPatterns", "false"));
//potential future enhancements, detect common numerical patterns, such as 1234 oe 4321
Expand All @@ -69,6 +70,7 @@ public static List<String> validate(String pwd, Context context) {
problems.add(MessageFormat.format(rb.getString("pwdcheck.tooshort"), minLength));
}
char[] cred = pwd.toCharArray();
int qtyChanged = 0;
int upper = 0;
int lower = 0;
int digits = 0;
Expand Down Expand Up @@ -108,6 +110,24 @@ public static List<String> validate(String pwd, Context context) {
}
}
}

//quantity of changed character test
if (minChanged > 0 && previousPwd != null) {
for (int i = 0; i < cred.length; i++) {
if ((i + 1) < previousPwd.length()) {
if (previousPwd.charAt(i) != cred[i]) {
qtyChanged++;
}
} else {
//i.e. the new pass is longer than the old one
break;
}

}
if (qtyChanged < minChanged) {
problems.add(MessageFormat.format(rb.getString("pwdcheck.minchanged"), minChanged));
}
}

if (repeatCheck) {
if (localrepeats > repeats) {
Expand Down
3 changes: 2 additions & 1 deletion jspwiki-main/src/main/resources/CoreResources.properties
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,5 @@ pwdcheck.minLower=Not enough lower case (a-z) characters, min={0}
pwdcheck.minDigits=Not enough digits (0-9), min={0}
pwdcheck.minOther=Not enough symbols or other characters, min={0}
pwdcheck.tooshort=Password too short, min={0}
pwdcheck.toolong=Password too long, max={0}
pwdcheck.toolong=Password too long, max={0}
pwdcheck.minchanged=Not enough characters changed, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,4 @@ pwdcheck.minDigits=Nicht gen\u00fcgend Ziffern (0-9), min={0}
pwdcheck.minOther=Nicht gen\u00fcgend Symbole oder andere Zeichen, min={0}
pwdcheck.tooshort=Passwort zu kurz, min={0}
pwdcheck.toolong=Passwort zu lang, max={0}
pwdcheck.minchanged=Nicht gen\u00fcgend Zeichen ge\u00e4ndert, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,4 @@ pwdcheck.minDigits=No hay suficientes d\u00edgitos (0-9), min={0}
pwdcheck.minOther=No hay suficientes s\u00edmbolos u otros caracteres, min={0}
pwdcheck.tooshort=Contrase\u00f1a demasiado corta, min={0}
pwdcheck.toolong=Contrase\u00f1a demasiado larga, m\u00e1ximo={0}
pwdcheck.minchanged=No se cambiaron suficientes caracteres, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,4 @@ pwdcheck.minDigits=Ei tarpeeksi numeroita (0-9), min={0}
pwdcheck.minOther=Ei tarpeeksi symboleja tai muita merkkej\u00e4, min={0}
pwdcheck.tooshort=Salasana liian lyhyt, min={0}
pwdcheck.toolong=Salasana liian pitk\u00e4, max={0}
pwdcheck.minchanged=Pas assez de caract\u00e8res modifi\u00e9s, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,4 @@ pwdcheck.minDigits=Nombre de chiffres insuffisant (0-9), min={0}
pwdcheck.minOther=Pas assez de symboles ou d'autres caract\u00e8res, min={0}
pwdcheck.tooshort=Mot de passe trop court, min={0}
pwdcheck.toolong=Mot de passe trop long, max={0}
pwdcheck.minchanged=Pas assez de caract\u00e8res modifi\u00e9s, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,4 @@ pwdcheck.minDigits=Cifre insufficienti (0-9), min={0}
pwdcheck.minOther=Simboli o altri caratteri non sufficienti, min={0}
pwdcheck.tooshort=Password troppo corta, min={0}
pwdcheck.toolong=Password troppo lunga, max={0}
pwdcheck.minchanged=Non sono stati modificati abbastanza caratteri, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,4 @@ pwdcheck.minDigits=Niet genoeg cijfers (0-9), min={0}
pwdcheck.minOther=Niet genoeg symbolen of andere tekens, min={0}
pwdcheck.tooshort=Wachtwoord te kort, min={0}
pwdcheck.toolong=Wachtwoord te lang, max={0}
pwdcheck.minchanged=Er zijn niet genoeg tekens gewijzigd, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,4 @@ pwdcheck.minDigits=D\u00edgitos insuficientes (0-9), m\u00ednimo={0}
pwdcheck.minOther=N\u00e3o h\u00e1 s\u00edmbolos ou outros caracteres suficientes, min={0}
pwdcheck.tooshort=Senha muito curta, min={0}
pwdcheck.toolong=Senha muito longa, m\u00e1ximo={0}
pwdcheck.minchanged=N\u00e3o foram alterados caracteres suficientes, min={0}
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,4 @@ pwdcheck.minDigits=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\
pwdcheck.minOther=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0437\u043d\u0430\u043a\u043e\u0432, min={0}
pwdcheck.tooshort=\u041f\u0430\u0440\u043e\u043b\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439, \u043c\u0438\u043d={0}
pwdcheck.toolong=\u041f\u0430\u0440\u043e\u043b\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043b\u0438\u043d\u043d\u044b\u0439, \u043c\u0430\u043a\u0441.={0}
pwdcheck.minchanged=\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e, \u043c\u0438\u043d={0}
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,4 @@ pwdcheck.minDigits=\u6570\u5b57\u4e0d\u8db3\uff080-9\uff09\uff0c\u6700\u5c0f\u50
pwdcheck.minOther=\u7b26\u53f7\u6216\u5176\u4ed6\u5b57\u7b26\u4e0d\u8db3\uff0c\u6700\u5c0f\u503c\u4e3a{0}
pwdcheck.tooshort=\u5bc6\u7801\u8fc7\u77ed\uff0c\u6700\u5c0f\u503c\u4e3a{0}
pwdcheck.toolong=\u5bc6\u7801\u8fc7\u957f\uff0c\u6700\u5927\u9650\u5236\u4e3a{0}
pwdcheck.minchanged=\u66f4\u6539\u7684\u5b57\u7b26\u6570\u4e0d\u8db3\uff0c\u6700\u5c0f\u503c\u4e3a0\u3002
3 changes: 2 additions & 1 deletion jspwiki-main/src/main/resources/ini/jspwiki.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,8 @@ jspwiki.credentials.minSymbols=1
# allow X repeating characters but no more. 1 is the default.
# i.e. 1 with "password" is ok but "passsword" is not
jspwiki.credentials.repeatingCharacters=1

# when changing a password, at least this number of characters must be different
jspwiki.credentials.minChanged=1

# Added in v3.0.0 Audit Logging alerting
# true to enable the audit logger, false otherwise
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public PasswordComplexityVeriffierTest() throws Exception {
// allow X repeating characters but no more. 1 is the default.
// i.e. 1 with "password" is ok but "passsword" is not
props.setProperty("jspwiki.credentials.repeatingCharacters", "1");
props.setProperty("jspwiki.credentials.minChanged", "1");
engine = TestEngine.build(props);
context = new WikiContext(engine,
new WikiPage(engine, "test"));
Expand All @@ -57,43 +58,54 @@ public PasswordComplexityVeriffierTest() throws Exception {
@Test
public void testValidate() {

List<String> result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,", context);
List<String> result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,",null, context);
Assertions.assertTrue(result.isEmpty(), StringUtils.join(result));

//too long
result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,1234", context);
result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,1234",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//no upper, digits symbols
result = PasswordComplexityVeriffier.validate("abcedefghi", context);
result = PasswordComplexityVeriffier.validate("abcedefghi",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//too short
result = PasswordComplexityVeriffier.validate("abc", context);
result = PasswordComplexityVeriffier.validate("abc",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//no lower, digits, symbols
result = PasswordComplexityVeriffier.validate("ABCEDEFGHI", context);
result = PasswordComplexityVeriffier.validate("ABCEDEFGHI",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//too many repeating
result = PasswordComplexityVeriffier.validate("a@CEDEFGHI222", context);
result = PasswordComplexityVeriffier.validate("a@CEDEFGHI222",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("a@CEDEFGHI222a", context);
result = PasswordComplexityVeriffier.validate("a@CEDEFGHI222a",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("aaa@CEDEFGHI2a", context);
result = PasswordComplexityVeriffier.validate("aaa@CEDEFGHI2a",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("aaa@CEbbbbGHI2a", context);
result = PasswordComplexityVeriffier.validate("aaa@CEbbbbGHI2a",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("a@CEbbGH4444", context);
result = PasswordComplexityVeriffier.validate("a@CEbbGH4444",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("aaaa@CEbbGH444", context);
result = PasswordComplexityVeriffier.validate("aaaa@CEbbGH444",null, context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//shorter to longer version
result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,","e,#Em1KG1!tez8EYm,", context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

//longer to shorter
result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi","e,#Em1KG1!tez8EYmi?", context);
Assertions.assertTrue(!result.isEmpty(), StringUtils.join(result));

result = PasswordComplexityVeriffier.validate("e,#Em1KG1!tez8EYmi?,","e,#Em1KG1!teAAEYmi?,", context);
Assertions.assertTrue(result.isEmpty(), StringUtils.join(result));
}

}
Loading