From 3744755a1ecf134d111b7cd3287496b06cce514f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 17 Aug 2016 15:19:47 -0700 Subject: [PATCH] GUACAMOLE-36: Define and enforce password policies. --- .../JDBCAuthenticationProviderModule.java | 2 + .../guacamole/auth/jdbc/JDBCEnvironment.java | 11 ++ .../PasswordContainsUsernameException.java | 42 +++++ .../PasswordMinimumLengthException.java | 52 ++++++ .../auth/jdbc/security/PasswordPolicy.java | 103 ++++++++++++ .../security/PasswordPolicyException.java | 86 ++++++++++ .../jdbc/security/PasswordPolicyService.java | 149 ++++++++++++++++++ .../PasswordRequiresDigitException.java | 43 +++++ ...PasswordRequiresMultipleCaseException.java | 43 +++++ .../PasswordRequiresSymbolException.java | 43 +++++ .../guacamole/auth/jdbc/user/UserService.java | 20 ++- .../src/main/resources/translations/en.json | 10 ++ .../auth/mysql/MySQLEnvironment.java | 6 + .../auth/mysql/MySQLPasswordPolicy.java | 142 +++++++++++++++++ .../postgresql/PostgreSQLEnvironment.java | 6 + .../postgresql/PostgreSQLPasswordPolicy.java | 142 +++++++++++++++++ 16 files changed, 899 insertions(+), 1 deletion(-) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordContainsUsernameException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordMinimumLengthException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicy.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyService.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresDigitException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresMultipleCaseException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresSymbolException.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/MySQLPasswordPolicy.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/PostgreSQLPasswordPolicy.java diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java index 6aa52afeb..e52ca5a1d 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java @@ -63,6 +63,7 @@ import org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper; import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper; import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService; import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionSet; +import org.apache.guacamole.auth.jdbc.security.PasswordPolicyService; import org.apache.guacamole.auth.jdbc.sharing.ConnectionSharingService; import org.apache.guacamole.auth.jdbc.sharing.HashSharedConnectionMap; import org.apache.guacamole.auth.jdbc.sharing.SecureRandomShareKeyGenerator; @@ -159,6 +160,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { bind(ConnectionService.class); bind(GuacamoleTunnelService.class).to(RestrictedGuacamoleTunnelService.class); bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class); + bind(PasswordPolicyService.class); bind(SaltService.class).to(SecureRandomSaltService.class); bind(SharedConnectionMap.class).to(HashSharedConnectionMap.class).in(Scopes.SINGLETON); bind(ShareKeyGenerator.class).to(SecureRandomShareKeyGenerator.class).in(Scopes.SINGLETON); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java index 7d014c4c8..c539ef5e1 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java @@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.environment.LocalEnvironment; +import org.apache.guacamole.auth.jdbc.security.PasswordPolicy; /** * A JDBC-specific implementation of Environment that defines generic properties @@ -128,4 +129,14 @@ public abstract class JDBCEnvironment extends LocalEnvironment { public abstract int getDefaultMaxGroupConnectionsPerUser() throws GuacamoleException; + /** + * Returns the policy which applies to newly-set passwords. Passwords which + * apply to Guacamole user accounts will be required to conform to this + * policy. + * + * @return + * The password policy which applies to Guacamole user accounts. + */ + public abstract PasswordPolicy getPasswordPolicy(); + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordContainsUsernameException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordContainsUsernameException.java new file mode 100644 index 000000000..f3e70d7d8 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordContainsUsernameException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +/** + * Thrown when an attempt is made to set a user's password to a string which + * contains their own username, in violation of the defined password policy. + * + * @author Michael Jumper + */ +public class PasswordContainsUsernameException extends PasswordPolicyException { + + /** + * Creates a new PasswordContainsUsernameException with the given + * human-readable message. The translatable message is already defined. + * + * @param message + * A human-readable message describing the password policy violation + * that occurred. + */ + public PasswordContainsUsernameException(String message) { + super(message, "PASSWORD_POLICY.ERROR_CONTAINS_USERNAME"); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordMinimumLengthException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordMinimumLengthException.java new file mode 100644 index 000000000..f6a9e4fef --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordMinimumLengthException.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +import java.util.Collections; +import org.apache.guacamole.language.TranslatableMessage; + +/** + * Thrown when an attempt is made to set a user's password to a string which is + * too short, in violation of the defined password policy. + * + * @author Michael Jumper + */ +public class PasswordMinimumLengthException extends PasswordPolicyException { + + /** + * Creates a new PasswordMinimumLengthException with the given + * human-readable message. The translatable message is already defined. + * + * @param message + * A human-readable message describing the password policy violation + * that occurred. + * + * @param length + * The minimum length that passwords must have to avoid violating + * policy, in characters. + */ + public PasswordMinimumLengthException(String message, int length) { + super(message, new TranslatableMessage( + "PASSWORD_POLICY.ERROR_TOO_SHORT", + Collections.singletonMap("LENGTH", length) + )); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicy.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicy.java new file mode 100644 index 000000000..8526bf633 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicy.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +import org.apache.guacamole.GuacamoleException; + +/** + * A set of restrictions which define the level of complexity required for + * the passwords of Guacamole user accounts. + * + * @author Michael Jumper + */ +public interface PasswordPolicy { + + /** + * Returns the minimum length of new passwords, in characters. Passwords + * which are shorter than this length cannot be used. + * + * @return + * The minimum number of characters required for new passwords. + * + * @throws GuacamoleException + * If the minimum password length cannot be parsed from + * guacamole.properties. + */ + int getMinimumLength() throws GuacamoleException; + + /** + * Returns whether both uppercase and lowercase characters must be present + * in new passwords. If true, passwords which do not have at least one + * uppercase letter and one lowercase letter cannot be used. + * + * @return + * true if both uppercase and lowercase characters must be present in + * new passwords, false otherwise. + * + * @throws GuacamoleException + * If the multiple case requirement cannot be parsed from + * guacamole.properties. + */ + boolean isMultipleCaseRequired() throws GuacamoleException; + + /** + * Returns whether numeric characters (digits) must be present in new + * passwords. If true, passwords which do not have at least one numeric + * character cannot be used. + * + * @return + * true if numeric characters must be present in new passwords, + * false otherwise. + * + * @throws GuacamoleException + * If the numeric character requirement cannot be parsed from + * guacamole.properties. + */ + boolean isNumericRequired() throws GuacamoleException; + + /** + * Returns whether non-alphanumeric characters (symbols) must be present in + * new passwords. If true, passwords which do not have at least one + * non-alphanumeric character cannot be used. + * + * @return + * true if non-alphanumeric characters must be present in new passwords, + * false otherwise. + * + * @throws GuacamoleException + * If the non-alphanumeric character requirement cannot be parsed from + * guacamole.properties. + */ + boolean isNonAlphanumericRequired() throws GuacamoleException; + + /** + * Returns whether new passwords must not contain the user's own username. + * + * @return + * true if new passwords must not contain the user's own username, + * false otherwise. + * + * @throws GuacamoleException + * If the username password restriction cannot be parsed from + * guacamole.properties. + */ + boolean isUsernameProhibited() throws GuacamoleException; + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyException.java new file mode 100644 index 000000000..b4b21b1ed --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyException.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +import org.apache.guacamole.GuacamoleClientException; +import org.apache.guacamole.language.Translatable; +import org.apache.guacamole.language.TranslatableMessage; + +/** + * Thrown when an attempt to change a user's password fails due to a violation + * of password complexity policies. + * + * @author Michael Jumper + */ +public class PasswordPolicyException extends GuacamoleClientException + implements Translatable { + + /** + * A translatable message which, after being passed through the translation + * system, describes the policy violation that occurred. + */ + private final TranslatableMessage translatableMessage; + + /** + * Creates a new PasswordPolicyException with the given human-readable + * message (which will not be passed through the translation system) and + * translation string key(which WILL be passed through the translation + * system), both of which should describe the policy violation that + * occurred. + * + * @param message + * A human-readable message describing the policy violation that + * occurred. + * + * @param translationKey + * The key of a translation string known to the translation system + * which describes the policy violation that occurred. + */ + public PasswordPolicyException(String message, String translationKey) { + super(message); + this.translatableMessage = new TranslatableMessage(translationKey); + } + + /** + * Creates a new PasswordPolicyException with the given human-readable + * message (which will not be passed through the translation system) and + * translatable message (which WILL be passed through the translation + * system), both of which should describe the policy violation that + * occurred. + * + * @param message + * A human-readable message describing the policy violation that + * occurred. + * + * @param translatableMessage + * A translatable message which, after being passed through the + * translation system, describes the policy violation that occurred. + */ + public PasswordPolicyException(String message, TranslatableMessage translatableMessage) { + super(message); + this.translatableMessage = translatableMessage; + } + + @Override + public TranslatableMessage getTranslatableMessage() { + return translatableMessage; + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyService.java new file mode 100644 index 000000000..8d3c0b652 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordPolicyService.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +import com.google.inject.Inject; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.jdbc.JDBCEnvironment; + +/** + * Service which verifies compliance with the password policy configured via + * guacamole.properties. + * + * @author Michael Jumper + */ +public class PasswordPolicyService { + + /** + * The Guacamole server environment. + */ + @Inject + private JDBCEnvironment environment; + + /** + * Regular expression which matches only if the string contains at least one + * lowercase character. + */ + private final Pattern CONTAINS_LOWERCASE = Pattern.compile("\\p{javaLowerCase}"); + + /** + * Regular expression which matches only if the string contains at least one + * uppercase character. + */ + private final Pattern CONTAINS_UPPERCASE = Pattern.compile("\\p{javaUpperCase}"); + + /** + * Regular expression which matches only if the string contains at least one + * numeric character. + */ + private final Pattern CONTAINS_DIGIT = Pattern.compile("\\p{Digit}"); + + /** + * Regular expression which matches only if the string contains at least one + * non-alphanumeric character. + */ + private final Pattern CONTAINS_NON_ALPHANUMERIC = + Pattern.compile("[^\\p{javaLowerCase}\\p{javaUpperCase}\\p{Digit}]"); + + /** + * Returns whether the given string matches all of the provided regular + * expressions. + * + * @param str + * The string to test against all provided regular expressions. + * + * @param patterns + * The regular expressions to match against the given string. + * + * @return + * true if the given string matches all provided regular expressions, + * false otherwise. + */ + private boolean matches(String str, Pattern... patterns) { + + // Check given string against all provided patterns + for (Pattern pattern : patterns) { + + // Fail overall test if any pattern fails to match + Matcher matcher = pattern.matcher(str); + if (!matcher.find()) + return false; + + } + + // All provided patterns matched + return true; + + } + + /** + * Verifies that the given new password complies with the password policy + * configured within guacamole.properties, throwing a GuacamoleException if + * the policy is violated in any way. + * + * @param username + * The username of the user whose password is being changed. + * + * @param password + * The proposed new password. + * + * @throws GuacamoleException + * If the password policy cannot be parsed, or if the proposed password + * violates the password policy. + */ + public void verifyPassword(String username, String password) + throws GuacamoleException { + + // Retrieve password policy from environment + PasswordPolicy policy = environment.getPasswordPolicy(); + + // Enforce minimum password length + if (password.length() < policy.getMinimumLength()) + throw new PasswordMinimumLengthException( + "Password does not meet minimum length requirements.", + policy.getMinimumLength()); + + // Disallow passwords containing the username + if (policy.isUsernameProhibited() && password.toLowerCase().contains(username.toLowerCase())) + throw new PasswordContainsUsernameException( + "Password must not contain username."); + + // Require both uppercase and lowercase characters + if (policy.isMultipleCaseRequired() && !matches(password, CONTAINS_LOWERCASE, CONTAINS_UPPERCASE)) + throw new PasswordRequiresMultipleCaseException( + "Password must contain both uppercase and lowercase."); + + // Require digits + if (policy.isNumericRequired() && !matches(password, CONTAINS_DIGIT)) + throw new PasswordRequiresDigitException( + "Passwords must contain at least one digit."); + + // Require non-alphanumeric symbols + if (policy.isNonAlphanumericRequired() && !matches(password, CONTAINS_NON_ALPHANUMERIC)) + throw new PasswordRequiresSymbolException( + "Passwords must contain at least one non-alphanumeric character."); + + // Password passes all defined restrictions + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresDigitException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresDigitException.java new file mode 100644 index 000000000..78e7561ae --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresDigitException.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +/** + * Thrown when an attempt is made to set a user's password to a string which + * contains no numeric characters (digits), in violation of the defined password + * policy. + * + * @author Michael Jumper + */ +public class PasswordRequiresDigitException extends PasswordPolicyException { + + /** + * Creates a new PasswordRequiresDigitException with the given + * human-readable message. The translatable message is already defined. + * + * @param message + * A human-readable message describing the password policy violation + * that occurred. + */ + public PasswordRequiresDigitException(String message) { + super(message, "PASSWORD_POLICY.ERROR_REQUIRES_DIGIT"); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresMultipleCaseException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresMultipleCaseException.java new file mode 100644 index 000000000..7911343f5 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresMultipleCaseException.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +/** + * Thrown when an attempt is made to set a user's password to a string which + * does not contain both uppercase and lowercase characters, in violation of the + * defined password policy. + * + * @author Michael Jumper + */ +public class PasswordRequiresMultipleCaseException extends PasswordPolicyException { + + /** + * Creates a new PasswordRequiresMultipleCaseException with the given + * human-readable message. The translatable message is already defined. + * + * @param message + * A human-readable message describing the password policy violation + * that occurred. + */ + public PasswordRequiresMultipleCaseException(String message) { + super(message, "PASSWORD_POLICY.ERROR_REQUIRES_MULTIPLE_CASE"); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresSymbolException.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresSymbolException.java new file mode 100644 index 000000000..f2116fbb7 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/security/PasswordRequiresSymbolException.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.security; + +/** + * Thrown when an attempt is made to set a user's password to a string which + * contains no non-alphanumeric characters (symbols), in violation of the + * defined password policy. + * + * @author Michael Jumper + */ +public class PasswordRequiresSymbolException extends PasswordPolicyException { + + /** + * Creates a new PasswordRequiresSymbolException with the given + * human-readable message. The translatable message is already defined. + * + * @param message + * A human-readable message describing the password policy violation + * that occurred. + */ + public PasswordRequiresSymbolException(String message) { + super(message, "PASSWORD_POLICY.ERROR_REQUIRES_NON_ALNUM"); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java index ad041c284..e131841cc 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java @@ -35,6 +35,7 @@ import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper; import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel; import org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper; import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService; +import org.apache.guacamole.auth.jdbc.security.PasswordPolicyService; import org.apache.guacamole.form.Field; import org.apache.guacamole.form.PasswordField; import org.apache.guacamole.net.auth.AuthenticatedUser; @@ -130,6 +131,12 @@ public class UserService extends ModeledDirectoryObjectService getObjectMapper() { return userMapper; @@ -199,6 +206,10 @@ public class UserService extends ModeledDirectoryObjectService