mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-36: Define and enforce password policies.
This commit is contained in:
@@ -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.SharingProfilePermissionMapper;
|
||||||
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService;
|
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService;
|
||||||
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionSet;
|
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.ConnectionSharingService;
|
||||||
import org.apache.guacamole.auth.jdbc.sharing.HashSharedConnectionMap;
|
import org.apache.guacamole.auth.jdbc.sharing.HashSharedConnectionMap;
|
||||||
import org.apache.guacamole.auth.jdbc.sharing.SecureRandomShareKeyGenerator;
|
import org.apache.guacamole.auth.jdbc.sharing.SecureRandomShareKeyGenerator;
|
||||||
@@ -159,6 +160,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
|
|||||||
bind(ConnectionService.class);
|
bind(ConnectionService.class);
|
||||||
bind(GuacamoleTunnelService.class).to(RestrictedGuacamoleTunnelService.class);
|
bind(GuacamoleTunnelService.class).to(RestrictedGuacamoleTunnelService.class);
|
||||||
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
|
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
|
||||||
|
bind(PasswordPolicyService.class);
|
||||||
bind(SaltService.class).to(SecureRandomSaltService.class);
|
bind(SaltService.class).to(SecureRandomSaltService.class);
|
||||||
bind(SharedConnectionMap.class).to(HashSharedConnectionMap.class).in(Scopes.SINGLETON);
|
bind(SharedConnectionMap.class).to(HashSharedConnectionMap.class).in(Scopes.SINGLETON);
|
||||||
bind(ShareKeyGenerator.class).to(SecureRandomShareKeyGenerator.class).in(Scopes.SINGLETON);
|
bind(ShareKeyGenerator.class).to(SecureRandomShareKeyGenerator.class).in(Scopes.SINGLETON);
|
||||||
|
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc;
|
|||||||
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.environment.LocalEnvironment;
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JDBC-specific implementation of Environment that defines generic properties
|
* A JDBC-specific implementation of Environment that defines generic properties
|
||||||
@@ -128,4 +129,14 @@ public abstract class JDBCEnvironment extends LocalEnvironment {
|
|||||||
public abstract int getDefaultMaxGroupConnectionsPerUser()
|
public abstract int getDefaultMaxGroupConnectionsPerUser()
|
||||||
throws GuacamoleException;
|
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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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;
|
||||||
|
|
||||||
|
}
|
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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.ObjectPermissionModel;
|
||||||
import org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
import org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
||||||
import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
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.Field;
|
||||||
import org.apache.guacamole.form.PasswordField;
|
import org.apache.guacamole.form.PasswordField;
|
||||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
@@ -130,6 +131,12 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
@Inject
|
@Inject
|
||||||
private PasswordEncryptionService encryptionService;
|
private PasswordEncryptionService encryptionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for enforcing password complexity policies.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PasswordPolicyService passwordPolicyService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModeledDirectoryObjectMapper<UserModel> getObjectMapper() {
|
protected ModeledDirectoryObjectMapper<UserModel> getObjectMapper() {
|
||||||
return userMapper;
|
return userMapper;
|
||||||
@@ -199,6 +206,10 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
if (!existing.isEmpty())
|
if (!existing.isEmpty())
|
||||||
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
||||||
|
|
||||||
|
// Verify new password does not violate defined policies (if specified)
|
||||||
|
if (object.getPassword() != null)
|
||||||
|
passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -220,7 +231,11 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify new password does not violate defined policies (if specified)
|
||||||
|
if (object.getPassword() != null)
|
||||||
|
passwordPolicyService.verifyPassword(object.getIdentifier(), object.getPassword());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -412,6 +427,9 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
if (!newPassword.equals(confirmNewPassword))
|
if (!newPassword.equals(confirmNewPassword))
|
||||||
throw new GuacamoleClientException("LOGIN.ERROR_PASSWORD_MISMATCH");
|
throw new GuacamoleClientException("LOGIN.ERROR_PASSWORD_MISMATCH");
|
||||||
|
|
||||||
|
// Verify new password does not violate defined policies
|
||||||
|
passwordPolicyService.verifyPassword(username, newPassword);
|
||||||
|
|
||||||
// Change password and reset expiration flag
|
// Change password and reset expiration flag
|
||||||
userModel.setExpired(false);
|
userModel.setExpired(false);
|
||||||
user.setPassword(newPassword);
|
user.setPassword(newPassword);
|
||||||
|
@@ -54,6 +54,16 @@
|
|||||||
"INFO_SHARED_BY" : "Shared by {USERNAME}"
|
"INFO_SHARED_BY" : "Shared by {USERNAME}"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"PASSWORD_POLICY" : {
|
||||||
|
|
||||||
|
"ERROR_CONTAINS_USERNAME" : "Passwords may not contain the username.",
|
||||||
|
"ERROR_REQUIRES_DIGIT" : "Passwords must contain at least one digit.",
|
||||||
|
"ERROR_REQUIRES_MULTIPLE_CASE" : "Passwords must contain both uppercase and lowercase characters.",
|
||||||
|
"ERROR_REQUIRES_NON_ALNUM" : "Passwords must contain at least one symbol.",
|
||||||
|
"ERROR_TOO_SHORT" : "Passwords must be at least {LENGTH} {LENGTH, plural, one{character} other{characters}} long."
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
"USER_ATTRIBUTES" : {
|
"USER_ATTRIBUTES" : {
|
||||||
|
|
||||||
"FIELD_HEADER_DISABLED" : "Login disabled:",
|
"FIELD_HEADER_DISABLED" : "Login disabled:",
|
||||||
|
@@ -23,6 +23,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MySQL-specific implementation of JDBCEnvironment provides database
|
* A MySQL-specific implementation of JDBCEnvironment provides database
|
||||||
@@ -220,6 +221,11 @@ public class MySQLEnvironment extends JDBCEnvironment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordPolicy getPasswordPolicy() {
|
||||||
|
return new MySQLPasswordPolicy(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hostname of the MySQL server hosting the Guacamole
|
* Returns the hostname of the MySQL server hosting the Guacamole
|
||||||
* authentication tables. If unspecified, this will be "localhost".
|
* authentication tables. If unspecified, this will be "localhost".
|
||||||
|
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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.mysql;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
|
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PasswordPolicy implementation which reads the details of the policy from
|
||||||
|
* MySQL-specific properties in guacamole.properties.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class MySQLPasswordPolicy implements PasswordPolicy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies the minimum length required of all user
|
||||||
|
* passwords. By default, this will be zero.
|
||||||
|
*/
|
||||||
|
private static final IntegerGuacamoleProperty MIN_LENGTH =
|
||||||
|
new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-user-password-min-length"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one lowercase character and one uppercase character. By default,
|
||||||
|
* no such restriction is imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_MULTIPLE_CASE =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-user-password-require-multiple-case"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one numeric character (digit). By default, no such restriction is
|
||||||
|
* imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_DIGIT =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-user-password-require-digit"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one non-alphanumeric character (symbol). By default, no such
|
||||||
|
* restriction is imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_SYMBOL =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-user-password-require-symbol"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether users are prohibited from including
|
||||||
|
* their own username in their password. By default, no such restriction is
|
||||||
|
* imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty PROHIBIT_USERNAME =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-user-password-prohibit-username"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole server environment.
|
||||||
|
*/
|
||||||
|
private final JDBCEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new MySQLPasswordPolicy which reads the details of the policy
|
||||||
|
* from the properties exposed by the given environment.
|
||||||
|
*
|
||||||
|
* @param environment
|
||||||
|
* The environment from which password policy properties should be
|
||||||
|
* read.
|
||||||
|
*/
|
||||||
|
public MySQLPasswordPolicy(JDBCEnvironment environment) {
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinimumLength() throws GuacamoleException {
|
||||||
|
return environment.getProperty(MIN_LENGTH, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMultipleCaseRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_MULTIPLE_CASE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNumericRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_DIGIT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNonAlphanumericRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_SYMBOL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUsernameProhibited() throws GuacamoleException {
|
||||||
|
return environment.getProperty(PROHIBIT_USERNAME, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -23,6 +23,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PostgreSQL-specific implementation of JDBCEnvironment provides database
|
* A PostgreSQL-specific implementation of JDBCEnvironment provides database
|
||||||
@@ -219,6 +220,11 @@ public class PostgreSQLEnvironment extends JDBCEnvironment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordPolicy getPasswordPolicy() {
|
||||||
|
return new PostgreSQLPasswordPolicy(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hostname of the PostgreSQL server hosting the Guacamole
|
* Returns the hostname of the PostgreSQL server hosting the Guacamole
|
||||||
* authentication tables. If unspecified, this will be "localhost".
|
* authentication tables. If unspecified, this will be "localhost".
|
||||||
|
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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.postgresql;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
|
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
|
||||||
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
|
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PasswordPolicy implementation which reads the details of the policy from
|
||||||
|
* PostgreSQL-specific properties in guacamole.properties.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class PostgreSQLPasswordPolicy implements PasswordPolicy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies the minimum length required of all user
|
||||||
|
* passwords. By default, this will be zero.
|
||||||
|
*/
|
||||||
|
private static final IntegerGuacamoleProperty MIN_LENGTH =
|
||||||
|
new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-user-password-min-length"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one lowercase character and one uppercase character. By default,
|
||||||
|
* no such restriction is imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_MULTIPLE_CASE =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-user-password-require-multiple-case"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one numeric character (digit). By default, no such restriction is
|
||||||
|
* imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_DIGIT =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-user-password-require-digit"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether all user passwords must have at
|
||||||
|
* least one non-alphanumeric character (symbol). By default, no such
|
||||||
|
* restriction is imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty REQUIRE_SYMBOL =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-user-password-require-symbol"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property which specifies whether users are prohibited from including
|
||||||
|
* their own username in their password. By default, no such restriction is
|
||||||
|
* imposed.
|
||||||
|
*/
|
||||||
|
private static final BooleanGuacamoleProperty PROHIBIT_USERNAME =
|
||||||
|
new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-user-password-prohibit-username"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole server environment.
|
||||||
|
*/
|
||||||
|
private final JDBCEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new PostgreSQLPasswordPolicy which reads the details of the
|
||||||
|
* policy from the properties exposed by the given environment.
|
||||||
|
*
|
||||||
|
* @param environment
|
||||||
|
* The environment from which password policy properties should be
|
||||||
|
* read.
|
||||||
|
*/
|
||||||
|
public PostgreSQLPasswordPolicy(JDBCEnvironment environment) {
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinimumLength() throws GuacamoleException {
|
||||||
|
return environment.getProperty(MIN_LENGTH, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMultipleCaseRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_MULTIPLE_CASE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNumericRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_DIGIT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNonAlphanumericRequired() throws GuacamoleException {
|
||||||
|
return environment.getProperty(REQUIRE_SYMBOL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUsernameProhibited() throws GuacamoleException {
|
||||||
|
return environment.getProperty(PROHIBIT_USERNAME, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user