diff --git a/conf/core/server.conf b/conf/core/server.conf index 246be9aa9285e4434803d3a71d18c24412922bf4..5cad243fd60827437ae35fc3a9ba06c05feb6a88 100644 --- a/conf/core/server.conf +++ b/conf/core/server.conf @@ -199,6 +199,18 @@ CHECK_ENTITY_ACL_ROLES_MODE=MUST # part of any Entity ACL. GLOBAL_ENTITY_PERMISSIONS_FILE=./conf/core/global_entity_permissions.xml +# -------------------------------------------------- +# User Account Settings +# -------------------------------------------------- + +# Requirements for user names. The default is POSIX compliant, see +# https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_426 +USER_NAME_VALID_REGEX=^[\\w\\.][\\w\\.-]*{1,32}$ +USER_NAME_INVALID_MESSAGE=User names must have a length from 1 to 32 characters. They must contain only latin letters a-z (upper case or lower case), number 0-9, dots (.), underscores (_), or hyphens (-). They must no start with a hyphen. + +PASSWORD_VALID_REGEX=^((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\\p{Punct}]).{8,128})$ +PASSWORD_INVALID_MESSAGE=blablabla + # -------------------------------------------------- # Extensions # -------------------------------------------------- diff --git a/src/main/java/org/caosdb/server/ServerProperties.java b/src/main/java/org/caosdb/server/ServerProperties.java index 34899f7551ccc8ac99e6f2246eeb154c37171e53..aa8fc43ead96dad56e739950f12ad7638e550bef 100644 --- a/src/main/java/org/caosdb/server/ServerProperties.java +++ b/src/main/java/org/caosdb/server/ServerProperties.java @@ -108,8 +108,6 @@ public class ServerProperties extends Properties { public static final String KEY_NEW_USER_DEFAULT_ACTIVITY = "NEW_USER_DEFAULT_ACTIVITY"; - public static final String KEY_PASSWORD_STRENGTH_REGEX = "PASSWORD_STRENGTH_REGEX"; - public static final String KEY_QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS = "QUERY_FILTER_ENTITIES_WITHOUT_RETRIEVE_PERMISSIONS"; @@ -141,6 +139,12 @@ public class ServerProperties extends Properties { public static final String KEY_PROJECT_REVISTION = "project.revision"; public static final String KEY_BUILD_TIMESTAMP = "build.timestamp"; + public static final String KEY_USER_NAME_VALID_REGEX = "USER_NAME_VALID_REGEX"; + public static final String KEY_USER_NAME_INVALID_MESSAGE = "USER_NAME_INVALID_MESSAGE"; + + public static final String KEY_PASSWORD_STRENGTH_REGEX = "PASSWORD_VALID_REGEX"; + public static final String KEY_PASSWORD_WEAK_MESSAGE = "PASSWORD_INVALID_MESSAGE"; + /** * Read the config files and initialize the server properties. * diff --git a/src/main/java/org/caosdb/server/resource/UserResource.java b/src/main/java/org/caosdb/server/resource/UserResource.java index 2c463e0e4bf7a640adc2a8368f74d798f69d0fd5..de07331e9637549285d71ca2fd910916cd13316a 100644 --- a/src/main/java/org/caosdb/server/resource/UserResource.java +++ b/src/main/java/org/caosdb/server/resource/UserResource.java @@ -128,10 +128,9 @@ public class UserResource extends AbstractCaosDBServerResource { return error(m, Status.CLIENT_ERROR_NOT_FOUND); } else if (m == ServerMessages.ENTITY_DOES_NOT_EXIST) { return error(m, Status.CLIENT_ERROR_CONFLICT); - } else if (m == ServerMessages.PASSWORD_TOO_WEAK) { - return error(m, Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY); + } else { + return error(m, Status.CLIENT_ERROR_BAD_REQUEST); } - throw m; } catch (final NumberFormatException e) { return error(ServerMessages.CANNOT_PARSE_INT_VALUE, Status.CLIENT_ERROR_BAD_REQUEST); } @@ -163,10 +162,9 @@ public class UserResource extends AbstractCaosDBServerResource { } catch (final Message m) { if (m == ServerMessages.ACCOUNT_NAME_NOT_UNIQUE) { return error(m, Status.CLIENT_ERROR_CONFLICT); - } else if (m == ServerMessages.PASSWORD_TOO_WEAK) { - return error(m, Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY); + } else { + return error(m, Status.CLIENT_ERROR_BAD_REQUEST); } - throw m; } final Document doc = new Document(); diff --git a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java index 09d59e8d84659037da66e11f7b4c0da556d8aa50..8abc2ede52375158c006d0108e9fea2523526006 100644 --- a/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java +++ b/src/main/java/org/caosdb/server/transaction/InsertUserTransaction.java @@ -24,6 +24,8 @@ package org.caosdb.server.transaction; import org.apache.shiro.SecurityUtils; +import org.caosdb.server.CaosDBServer; +import org.caosdb.server.ServerProperties; import org.caosdb.server.accessControl.ACMPermissions; import org.caosdb.server.accessControl.Principal; import org.caosdb.server.accessControl.UserSources; @@ -86,18 +88,13 @@ public class InsertUserTransaction extends AccessControlTransaction { } /* - * Names should have at least a length of 1, a maximum length of 32 and match - * ^[a-zA-Z_][a-zA-Z0-9_-]*$. + * Check requirements for user names (length, character set). Default config is POSIX compliant. */ private void checkUserName(String name) throws Message { - // Make this configurable? - final boolean length = name.length() >= 1 && name.length() <= 32; - final boolean match = - name.matches("^[\\p{Lower}\\p{Upper}_][\\p{Lower}\\p{Upper}\\p{Digit}_-]*$"); - - if (!(length && match)) { + String regex = CaosDBServer.getServerProperty(ServerProperties.KEY_USER_NAME_VALID_REGEX); + if (!name.matches(regex)) { throw ServerMessages.INVALID_USER_NAME( - "User names must have a length from 1 to 32 characters, begin with a latin letter a-z (upper case or lower case) or an underscore (_), and all other characters must be latin letters, arabic numbers, hyphens (-) or undescores (_)."); + CaosDBServer.getServerProperty(ServerProperties.KEY_USER_NAME_INVALID_MESSAGE)); } if (UserSources.isUserExisting(new Principal(this.user.realm, this.user.name))) { diff --git a/src/main/java/org/caosdb/server/utils/ServerMessages.java b/src/main/java/org/caosdb/server/utils/ServerMessages.java index 151f55face7edbfab793606474f183a65f0468be..0ec31162490900f93b497ebb33f0defb617d1114 100644 --- a/src/main/java/org/caosdb/server/utils/ServerMessages.java +++ b/src/main/java/org/caosdb/server/utils/ServerMessages.java @@ -337,7 +337,7 @@ public class ServerMessages { new Message( MessageType.Error, MessageCode.MESSAGE_CODE_UNKNOWN, - "This user name is yet in use. Please choose another one."); + "This user name is already in use. Please choose another one."); public static final Message ACCOUNT_HAS_BEEN_DELETED = new Message( @@ -399,11 +399,12 @@ public class ServerMessages { MessageCode.MESSAGE_CODE_UNKNOWN, "This email address is not RFC822 compliant."); - public static final Message PASSWORD_TOO_WEAK = - new Message( - MessageType.Error, - MessageCode.MESSAGE_CODE_UNKNOWN, - "This password is too weak. It should be longer than 8 characters and sufficiently random."); + public static final Message PASSWORD_TOO_WEAK(String policy) { + return new Message( + MessageType.Error, + MessageCode.MESSAGE_CODE_UNKNOWN, + "This password does not match the current policies for passwords: " + policy); + } public static final Message AFFILIATION_ERROR = new Message( diff --git a/src/main/java/org/caosdb/server/utils/Utils.java b/src/main/java/org/caosdb/server/utils/Utils.java index b21ba0f550e1f855ca21e26c1cfd04bb75107223..07a7e9618aa5b9e45f0086e837acfe1bf427173f 100644 --- a/src/main/java/org/caosdb/server/utils/Utils.java +++ b/src/main/java/org/caosdb/server/utils/Utils.java @@ -35,6 +35,8 @@ import java.text.DecimalFormat; import java.util.Scanner; import java.util.regex.Pattern; import org.apache.commons.codec.binary.Base32; +import org.caosdb.server.CaosDBServer; +import org.caosdb.server.ServerProperties; import org.caosdb.server.entity.Message; import org.jdom2.Document; import org.jdom2.Element; @@ -304,18 +306,15 @@ public class Utils { * @param password The password to be checked. */ public static void checkPasswordStrength(final String password) throws Message { - final boolean length = password.length() >= 8; - final boolean uppercase = password.matches(".*\\p{Upper}.*"); - final boolean lowercase = password.matches(".*\\p{Lower}.*"); - final boolean number = password.matches(".*\\p{Digit}.*"); - final boolean punct = password.matches(".*\\p{Punct}.*"); + String regex = CaosDBServer.getServerProperty(ServerProperties.KEY_PASSWORD_STRENGTH_REGEX); - if (!(length && uppercase && lowercase && number && punct)) { - throw ServerMessages.PASSWORD_TOO_WEAK; + if (password.equals("correcthorsebatterystaple")) { + throw ServerMessages.PASSWORD_TOO_WEAK("PWNED!"); } - if (password.equals("correcthorsebatterystaple")) { - throw ServerMessages.PASSWORD_TOO_WEAK; + if (!password.matches(regex)) { + throw ServerMessages.PASSWORD_TOO_WEAK( + CaosDBServer.getServerProperty(ServerProperties.KEY_PASSWORD_WEAK_MESSAGE)); } } }