diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java index 0ffc7edd1..883e58986 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java @@ -62,7 +62,6 @@ import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermis import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionSet; import org.glyptodon.guacamole.auth.jdbc.activeconnection.ActiveConnectionService; import org.glyptodon.guacamole.auth.jdbc.activeconnection.TrackedActiveConnection; -import org.glyptodon.guacamole.environment.Environment; import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.mybatis.guice.MyBatisModule; import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider; @@ -80,12 +79,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { /** * The environment of the Guacamole server. */ - private final Environment environment; - - /** - * The service to use to provide GuacamoleTunnels for each connection. - */ - private final GuacamoleTunnelService tunnelService; + private final JDBCEnvironment environment; /** * The AuthenticationProvider which is using this module to configure @@ -104,16 +98,11 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { * * @param environment * The environment to use to configure injected classes. - * - * @param tunnelService - * The tunnel service to use to provide tunnels sockets for connections. */ public JDBCAuthenticationProviderModule(AuthenticationProvider authProvider, - Environment environment, - GuacamoleTunnelService tunnelService) { + JDBCEnvironment environment) { this.authProvider = authProvider; this.environment = environment; - this.tunnelService = tunnelService; } @Override @@ -140,7 +129,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { bind(ActiveConnectionDirectory.class); bind(ActiveConnectionPermissionSet.class); bind(AuthenticationProvider.class).toInstance(authProvider); - bind(Environment.class).toInstance(environment); + bind(JDBCEnvironment.class).toInstance(environment); bind(ConnectionDirectory.class); bind(ConnectionGroupDirectory.class); bind(ConnectionGroupPermissionSet.class); @@ -169,9 +158,6 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { bind(UserPermissionService.class); bind(UserService.class); - // Bind provided tunnel service - bind(GuacamoleTunnelService.class).toInstance(tunnelService); - } } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCEnvironment.java new file mode 100644 index 000000000..f7a3a6fbe --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/JDBCEnvironment.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.auth.jdbc; + +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.environment.LocalEnvironment; + +/** + * A JDBC-specific implementation of Environment that defines generic properties + * intended for use within JDBC based authentication providers. + * + * @author James Muehlner + */ +public abstract class JDBCEnvironment extends LocalEnvironment { + + /** + * Constructs a new JDBCEnvironment using an underlying LocalEnviroment to + * read properties from the file system. + * + * @throws GuacamoleException + * If an error occurs while setting up the underlying LocalEnvironment. + */ + public JDBCEnvironment() throws GuacamoleException { + super(); + } + + /** + * Returns the default maximum number of concurrent connections to allow to + * any one connection, unless specified differently on an individual + * connection. Zero denotes unlimited. + * + * @return + * The default maximum allowable number of concurrent connections + * to any connection. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property. + */ + public abstract int getDefaultMaxConnections() throws GuacamoleException; + + /** + * Returns the default maximum number of concurrent connections to allow to + * any one connection group, unless specified differently on an individual + * connection group. Zero denotes unlimited. + * + * @return + * The default maximum allowable number of concurrent connections + * to any connection group. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property. + */ + public abstract int getDefaultMaxGroupConnections() + throws GuacamoleException; + + /** + * Returns the default maximum number of concurrent connections to allow to + * any one connection by an individual user, unless specified differently on + * an individual connection. Zero denotes unlimited. + * + * @return + * The default maximum allowable number of concurrent connections to + * any connection by an individual user. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property. + */ + public abstract int getDefaultMaxConnectionsPerUser() + throws GuacamoleException; + + /** + * Returns the default maximum number of concurrent connections to allow to + * any one connection group by an individual user, unless specified + * differently on an individual connection group. Zero denotes unlimited. + * + * @return + * The default maximum allowable number of concurrent connections to + * any connection group by an individual user. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property. + */ + public abstract int getDefaultMaxGroupConnectionsPerUser() + throws GuacamoleException; + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java index 94a5753d7..667be3329 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java @@ -45,6 +45,7 @@ import org.glyptodon.guacamole.auth.jdbc.connection.ParameterModel; import org.glyptodon.guacamole.auth.jdbc.user.UserModel; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleSecurityException; +import org.glyptodon.guacamole.auth.jdbc.JDBCEnvironment; import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionMapper; import org.glyptodon.guacamole.environment.Environment; import org.glyptodon.guacamole.net.GuacamoleSocket; @@ -72,7 +73,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS * The environment of the Guacamole server. */ @Inject - private Environment environment; + private JDBCEnvironment environment; /** * Mapper for accessing connections. diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ConfigurableGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ConfigurableGuacamoleTunnelService.java index 3b5e8b54d..0f9bf15f0 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ConfigurableGuacamoleTunnelService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/tunnel/ConfigurableGuacamoleTunnelService.java @@ -23,6 +23,7 @@ package org.glyptodon.guacamole.auth.jdbc.tunnel; import com.google.common.collect.ConcurrentHashMultiset; +import com.google.inject.Inject; import com.google.inject.Singleton; import java.util.Arrays; import java.util.Comparator; @@ -32,6 +33,7 @@ import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleResourceConflictException; +import org.glyptodon.guacamole.auth.jdbc.JDBCEnvironment; import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; @@ -46,6 +48,11 @@ import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; @Singleton public class ConfigurableGuacamoleTunnelService extends AbstractGuacamoleTunnelService { + + /** + * The configuration for the current JDBC environment. + */ + @Inject JDBCEnvironment jdbcEnvironment; /** * Set of all currently-active user/connection pairs (seats). @@ -67,66 +74,6 @@ public class ConfigurableGuacamoleTunnelService */ private final ConcurrentHashMultiset activeGroups = ConcurrentHashMultiset.create(); - /** - * The maximum number of connections allowed per connection by default, or - * zero if no default limit applies. - */ - private final int connectionDefaultMaxConnections; - - /** - * The maximum number of connections a user may have to any one connection - * by default, or zero if no default limit applies. - */ - private final int connectionDefaultMaxConnectionsPerUser; - - /** - * The maximum number of connections allowed per connection group by - * default, or zero if no default limit applies. - */ - private final int connectionGroupDefaultMaxConnections; - - /** - * The maximum number of connections a user may have to any one connection - * group by default, or zero if no default limit applies. - */ - private final int connectionGroupDefaultMaxConnectionsPerUser; - - /** - * Creates a new ConfigurableGuacamoleTunnelService which applies the given - * limitations when new connections are acquired. - * - * @param connectionDefaultMaxConnections - * The maximum number of connections allowed per connection by default, - * or zero if no default limit applies. - * - * @param connectionDefaultMaxConnectionsPerUser - * The maximum number of connections a user may have to any one - * connection by default, or zero if no default limit applies. - * - * @param connectionGroupDefaultMaxConnections - * The maximum number of connections allowed per connection group by - * default, or zero if no default limit applies. - * - * @param connectionGroupDefaultMaxConnectionsPerUser - * The maximum number of connections a user may have to any one - * connection group by default, or zero if no default limit applies. - */ - public ConfigurableGuacamoleTunnelService( - int connectionDefaultMaxConnections, - int connectionDefaultMaxConnectionsPerUser, - int connectionGroupDefaultMaxConnections, - int connectionGroupDefaultMaxConnectionsPerUser) { - - // Set default connection limits - this.connectionDefaultMaxConnections = connectionDefaultMaxConnections; - this.connectionDefaultMaxConnectionsPerUser = connectionDefaultMaxConnectionsPerUser; - - // Set default connection group limits - this.connectionGroupDefaultMaxConnections = connectionGroupDefaultMaxConnections; - this.connectionGroupDefaultMaxConnectionsPerUser = connectionGroupDefaultMaxConnectionsPerUser; - - } - /** * Attempts to add a single instance of the given value to the given * multiset without exceeding the specified maximum number of values. If @@ -203,12 +150,12 @@ public class ConfigurableGuacamoleTunnelService // Determine per-user limits on this connection Integer connectionMaxConnectionsPerUser = connection.getModel().getMaxConnectionsPerUser(); if (connectionMaxConnectionsPerUser == null) - connectionMaxConnectionsPerUser = connectionDefaultMaxConnectionsPerUser; + connectionMaxConnectionsPerUser = jdbcEnvironment.getDefaultMaxConnectionsPerUser(); // Determine overall limits on this connection Integer connectionMaxConnections = connection.getModel().getMaxConnections(); if (connectionMaxConnections == null) - connectionMaxConnections = connectionDefaultMaxConnections; + connectionMaxConnections = jdbcEnvironment.getDefaultMaxConnections(); // Attempt to aquire connection according to per-user limits Seat seat = new Seat(username, connection.getIdentifier()); @@ -255,12 +202,12 @@ public class ConfigurableGuacamoleTunnelService // Determine per-user limits on this connection group Integer connectionGroupMaxConnectionsPerUser = connectionGroup.getModel().getMaxConnectionsPerUser(); if (connectionGroupMaxConnectionsPerUser == null) - connectionGroupMaxConnectionsPerUser = connectionGroupDefaultMaxConnectionsPerUser; + connectionGroupMaxConnectionsPerUser = jdbcEnvironment.getDefaultMaxGroupConnectionsPerUser(); // Determine overall limits on this connection group Integer connectionGroupMaxConnections = connectionGroup.getModel().getMaxConnections(); if (connectionGroupMaxConnections == null) - connectionGroupMaxConnections = connectionGroupDefaultMaxConnections; + connectionGroupMaxConnections = jdbcEnvironment.getDefaultMaxGroupConnections(); // Attempt to aquire connection group according to per-user limits Seat seat = new Seat(username, connectionGroup.getIdentifier()); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java index ed4f60c87..303401b60 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java @@ -29,14 +29,8 @@ import org.glyptodon.guacamole.net.auth.AuthenticationProvider; import org.glyptodon.guacamole.net.auth.Credentials; import org.glyptodon.guacamole.net.auth.UserContext; import org.glyptodon.guacamole.auth.jdbc.JDBCAuthenticationProviderModule; -import org.glyptodon.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService; -import org.glyptodon.guacamole.auth.jdbc.tunnel.ConfigurableGuacamoleTunnelService; import org.glyptodon.guacamole.auth.jdbc.user.AuthenticationProviderService; -import org.glyptodon.guacamole.environment.Environment; -import org.glyptodon.guacamole.environment.LocalEnvironment; import org.glyptodon.guacamole.net.auth.AuthenticatedUser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Provides a MySQL based implementation of the AuthenticationProvider @@ -47,123 +41,12 @@ import org.slf4j.LoggerFactory; */ public class MySQLAuthenticationProvider implements AuthenticationProvider { - /** - * Logger for this class. - */ - private static final Logger logger = LoggerFactory.getLogger(MySQLAuthenticationProvider.class); - /** * Injector which will manage the object graph of this authentication * provider. */ private final Injector injector; - /** - * Returns the appropriate tunnel service given the Guacamole environment. - * The service is configured based on configuration options that dictate - * the default concurrent usage policy. - * - * @param environment - * The environment of the Guacamole server. - * - * @return - * A tunnel service implementation configured according to the - * concurrent usage policy options set in the Guacamole environment. - * - * @throws GuacamoleException - * If an error occurs while reading the configuration options. - */ - private GuacamoleTunnelService getTunnelService(Environment environment) - throws GuacamoleException { - - // Tunnel service default configuration - int connectionDefaultMaxConnections; - int connectionDefaultMaxConnectionsPerUser; - int connectionGroupDefaultMaxConnections; - int connectionGroupDefaultMaxConnectionsPerUser; - - // Read legacy concurrency-related properties - Boolean disallowSimultaneous = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS); - Boolean disallowDuplicate = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS); - - // Legacy "simultaneous" property dictates only the maximum number of - // connections per connection - if (disallowSimultaneous != null) { - - // Translate legacy property - if (disallowSimultaneous) { - connectionDefaultMaxConnections = 1; - connectionGroupDefaultMaxConnections = 0; - } - else { - connectionDefaultMaxConnections = 0; - connectionGroupDefaultMaxConnections = 0; - } - - // Warn of deprecation - logger.warn("The \"{}\" property is deprecated. Use \"{}\" and \"{}\" instead.", - MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS.getName(), - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS.getName(), - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName()); - - // Inform of new equivalent - logger.info("To achieve the same result of setting \"{}\" to \"{}\", set \"{}\" to \"{}\" and \"{}\" to \"{}\".", - MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS.getName(), disallowSimultaneous, - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS.getName(), connectionDefaultMaxConnections, - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName(), connectionGroupDefaultMaxConnections); - - } - - // If legacy property is not specified, use new property - else { - connectionDefaultMaxConnections = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS, 0); - connectionGroupDefaultMaxConnections = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS, 0); - } - - // Legacy "duplicate" property dictates whether connections and groups - // may be used concurrently only by different users - if (disallowDuplicate != null) { - - // Translate legacy property - if (disallowDuplicate) { - connectionDefaultMaxConnectionsPerUser = 1; - connectionGroupDefaultMaxConnectionsPerUser = 1; - } - else { - connectionDefaultMaxConnectionsPerUser = 0; - connectionGroupDefaultMaxConnectionsPerUser = 0; - } - - // Warn of deprecation - logger.warn("The \"{}\" property is deprecated. Use \"{}\" and \"{}\" instead.", - MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS.getName(), - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER.getName(), - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName()); - - // Inform of new equivalent - logger.info("To achieve the same result of setting \"{}\" to \"{}\", set \"{}\" to \"{}\" and \"{}\" to \"{}\".", - MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS.getName(), disallowDuplicate, - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER.getName(), connectionDefaultMaxConnectionsPerUser, - MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER.getName(), connectionGroupDefaultMaxConnectionsPerUser); - - } - - // If legacy property is not specified, use new property - else { - connectionDefaultMaxConnectionsPerUser = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER, 1); - connectionGroupDefaultMaxConnectionsPerUser = environment.getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER, 1); - } - - // Return service configured for specified default limits - return new ConfigurableGuacamoleTunnelService( - connectionDefaultMaxConnections, - connectionDefaultMaxConnectionsPerUser, - connectionGroupDefaultMaxConnections, - connectionGroupDefaultMaxConnectionsPerUser - ); - - } - /** * Creates a new MySQLAuthenticationProvider that reads and writes * authentication data to a MySQL database defined by properties in @@ -176,7 +59,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider { public MySQLAuthenticationProvider() throws GuacamoleException { // Get local environment - Environment environment = new LocalEnvironment(); + MySQLEnvironment environment = new MySQLEnvironment(); // Set up Guice injector. injector = Guice.createInjector( @@ -185,8 +68,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider { new MySQLAuthenticationProviderModule(environment), // Configure JDBC authentication core - new JDBCAuthenticationProviderModule(this, environment, - getTunnelService(environment)) + new JDBCAuthenticationProviderModule(this, environment) ); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProviderModule.java index e5af46928..a11c525db 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProviderModule.java @@ -27,7 +27,6 @@ import com.google.inject.Module; import com.google.inject.name.Names; import java.util.Properties; import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.environment.Environment; import org.mybatis.guice.datasource.helper.JdbcHelper; /** @@ -59,16 +58,16 @@ public class MySQLAuthenticationProviderModule implements Module { * If a required property is missing, or an error occurs while parsing * a property. */ - public MySQLAuthenticationProviderModule(Environment environment) + public MySQLAuthenticationProviderModule(MySQLEnvironment environment) throws GuacamoleException { // Set the MySQL-specific properties for MyBatis. myBatisProperties.setProperty("mybatis.environment.id", "guacamole"); - myBatisProperties.setProperty("JDBC.host", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_HOSTNAME)); - myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PORT))); - myBatisProperties.setProperty("JDBC.schema", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE)); - myBatisProperties.setProperty("JDBC.username", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME)); - myBatisProperties.setProperty("JDBC.password", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD)); + myBatisProperties.setProperty("JDBC.host", environment.getMySQLHostname()); + myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getMySQLPort())); + myBatisProperties.setProperty("JDBC.schema", environment.getMySQLDatabase()); + myBatisProperties.setProperty("JDBC.username", environment.getMySQLUsername()); + myBatisProperties.setProperty("JDBC.password", environment.getMySQLPassword()); myBatisProperties.setProperty("JDBC.autoCommit", "false"); myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true"); myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1"); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLEnvironment.java new file mode 100644 index 000000000..d058414e1 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLEnvironment.java @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package net.sourceforge.guacamole.net.auth.mysql; + +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.auth.jdbc.JDBCEnvironment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A MySQL-specific implementation of JDBCEnvironment provides database + * properties specifically for MySQL. + * + * @author James Muehlner + */ +public class MySQLEnvironment extends JDBCEnvironment { + + /** + * Logger for this class. + */ + private static final Logger logger = LoggerFactory.getLogger(MySQLEnvironment.class); + + /** + * Constructs a new MysqlEnvironment. + * + * @throws GuacamoleException + * If an error occurs while setting up the underlying JDBCEnvironment. + */ + public MySQLEnvironment() throws GuacamoleException { + super(); + } + + /** + * Log a warning about the usage of the deprecated + * MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS property, and the appropriate + * replacements for it. + * + * @param disallowSimultaneous + * Whether simultaneous connections have been disabled. + */ + private void warnOfSimultaneousPropertyDeprecation(boolean disallowSimultaneous) { + + // Warn of deprecation + logger.warn("The \"{}\" property is deprecated. Use \"{}\" and \"{}\" instead.", + MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS.getName(), + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS.getName(), + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName()); + + // Inform of new equivalent + logger.info("To achieve the same result of setting \"{}\" to \"{}\", set \"{}\" to \"{}\" and \"{}\" to \"{}\".", + MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS.getName(), disallowSimultaneous, + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS.getName(), disallowSimultaneous ? 1 : 0, + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName(), 0); + + } + + /** + * Log a warning about the usage of the deprecated + * MYSQL_DISALLOW_DUPLICATE_CONNECTIONS property, and the appropriate + * replacements for it. + * + * @param disallowDuplicate + * Whether duplicate connections have been disabled. + */ + private void warnOfDuplicatePropertyDeprecation(boolean disallowDuplicate) { + + // Warn of deprecation + logger.warn("The \"{}\" property is deprecated. Use \"{}\" and \"{}\" instead.", + MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS.getName(), + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER.getName(), + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS.getName()); + + // Inform of new equivalent + logger.info("To achieve the same result of setting \"{}\" to \"{}\", set \"{}\" to \"{}\" and \"{}\" to \"{}\".", + MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS.getName(), disallowDuplicate, + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER.getName(), disallowDuplicate ? 1 :0, + MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER.getName(), disallowDuplicate ? 1 :0); + + } + + @Override + public int getDefaultMaxConnections() throws GuacamoleException { + + // Tunnel service default configuration + int connectionDefaultMaxConnections; + + // Read legacy concurrency-related property + Boolean disallowSimultaneous = getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS); + + // Legacy "simultaneous" property dictates only the maximum number of + // connections per connection + if (disallowSimultaneous != null) { + + // Translate legacy property + if (disallowSimultaneous) { + connectionDefaultMaxConnections = 1; + } + else { + connectionDefaultMaxConnections = 0; + } + + // Warn that a different property should be used going forward + warnOfSimultaneousPropertyDeprecation(disallowSimultaneous); + + } + + // If legacy property is not specified, use new property + else { + connectionDefaultMaxConnections = getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS, 0); + } + + return connectionDefaultMaxConnections; + } + + @Override + public int getDefaultMaxGroupConnections() throws GuacamoleException { + + int connectionGroupDefaultMaxConnections; + + // Read legacy concurrency-related property + Boolean disallowSimultaneous = getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS); + + // Legacy "simultaneous" property dictates only the maximum number of + // connections per connection + if (disallowSimultaneous != null) { + + // Translate legacy property + connectionGroupDefaultMaxConnections = 0; + + // Warn that a different property should be used going forward + warnOfSimultaneousPropertyDeprecation(disallowSimultaneous); + + } + + // If legacy property is not specified, use new property + else { + connectionGroupDefaultMaxConnections = getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS, 0); + } + + return connectionGroupDefaultMaxConnections; + } + + @Override + public int getDefaultMaxConnectionsPerUser() throws GuacamoleException { + + int connectionDefaultMaxConnectionsPerUser; + + // Read legacy concurrency-related properties + Boolean disallowDuplicate = getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS); + + // Legacy "duplicate" property dictates whether connections and groups + // may be used concurrently only by different users + if (disallowDuplicate != null) { + + // Translate legacy property + if (disallowDuplicate) { + connectionDefaultMaxConnectionsPerUser = 1; + } + else { + connectionDefaultMaxConnectionsPerUser = 0; + } + + // Warn that a different property should be used going forward + warnOfDuplicatePropertyDeprecation(disallowDuplicate); + + } + + // If legacy property is not specified, use new property + else { + connectionDefaultMaxConnectionsPerUser = getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER, 1); + } + + return connectionDefaultMaxConnectionsPerUser; + } + + @Override + public int getDefaultMaxGroupConnectionsPerUser() throws GuacamoleException { + + int connectionGroupDefaultMaxConnectionsPerUser; + + // Read legacy concurrency-related property + Boolean disallowDuplicate = getProperty(MySQLGuacamoleProperties.MYSQL_DISALLOW_DUPLICATE_CONNECTIONS); + + // Legacy "duplicate" property dictates whether connections and groups + // may be used concurrently only by different users + if (disallowDuplicate != null) { + + // Translate legacy property + if (disallowDuplicate) { + connectionGroupDefaultMaxConnectionsPerUser = 1; + } + else { + connectionGroupDefaultMaxConnectionsPerUser = 0; + } + + // Warn that a different property should be used going forward + warnOfDuplicatePropertyDeprecation(disallowDuplicate); + + } + + // If legacy property is not specified, use new property + else { + connectionGroupDefaultMaxConnectionsPerUser = getProperty(MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER, 1); + } + + return connectionGroupDefaultMaxConnectionsPerUser; + + } + + /** + * Returns the hostname of the MySQL server hosting the Guacamole + * authentication tables. If unspecified, this will be "localhost". + * + * @return + * The URL of the MySQL server. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property value. + */ + public String getMySQLHostname() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_HOSTNAME, "localhost"); + } + + /** + * Returns the port number of the MySQL server hosting the Guacamole + * authentication tables. If unspecified, this will be the default MySQL + * port of 3306. + * + * @return + * The port number of the MySQL server. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property value. + */ + public int getMySQLPort() throws GuacamoleException { + return getProperty(MySQLGuacamoleProperties.MYSQL_PORT, 3306); + } + + /** + * Returns the name of the MySQL database containing the Guacamole + * authentication tables. + * + * @return + * The name of the MySQL database. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property value, or if the + * value was not set, as this property is required. + */ + public String getMySQLDatabase() throws GuacamoleException { + return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE); + } + + /** + * Returns the username that should be used when authenticating with the + * MySQL database containing the Guacamole authentication tables. + * + * @return + * The username for the MySQL database. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property value, or if the + * value was not set, as this property is required. + */ + public String getMySQLUsername() throws GuacamoleException { + return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME); + } + + /** + * Returns the password that should be used when authenticating with the + * MySQL database containing the Guacamole authentication tables. + * + * @return + * The password for the MySQL database. + * + * @throws GuacamoleException + * If an error occurs while retrieving the property value, or if the + * value was not set, as this property is required. + */ + public String getMySQLPassword() throws GuacamoleException { + return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleProperties.java index 369f2ef89..cb0c35bed 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleProperties.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLGuacamoleProperties.java @@ -28,6 +28,7 @@ import org.glyptodon.guacamole.properties.StringGuacamoleProperty; /** * Properties used by the MySQL Authentication plugin. + * * @author James Muehlner */ public class MySQLGuacamoleProperties { @@ -38,7 +39,8 @@ public class MySQLGuacamoleProperties { private MySQLGuacamoleProperties() {} /** - * The URL of the MySQL server hosting the guacamole authentication tables. + * The hostname of the MySQL server hosting the Guacamole authentication + * tables. */ public static final StringGuacamoleProperty MYSQL_HOSTNAME = new StringGuacamoleProperty() { @@ -48,7 +50,8 @@ public class MySQLGuacamoleProperties { }; /** - * The port of the MySQL server hosting the guacamole authentication tables. + * The port number of the MySQL server hosting the Guacamole authentication + * tables. */ public static final IntegerGuacamoleProperty MYSQL_PORT = new IntegerGuacamoleProperty() { @@ -58,7 +61,8 @@ public class MySQLGuacamoleProperties { }; /** - * The name of the MySQL database containing the guacamole authentication tables. + * The name of the MySQL database containing the Guacamole authentication + * tables. */ public static final StringGuacamoleProperty MYSQL_DATABASE = new StringGuacamoleProperty() { @@ -68,7 +72,8 @@ public class MySQLGuacamoleProperties { }; /** - * The username used to authenticate to the MySQL database containing the guacamole authentication tables. + * The username that should be used when authenticating with the MySQL + * database containing the Guacamole authentication tables. */ public static final StringGuacamoleProperty MYSQL_USERNAME = new StringGuacamoleProperty() { @@ -78,7 +83,8 @@ public class MySQLGuacamoleProperties { }; /** - * The password used to authenticate to the MySQL database containing the guacamole authentication tables. + * The password that should be used when authenticating with the MySQL + * database containing the Guacamole authentication tables. */ public static final StringGuacamoleProperty MYSQL_PASSWORD = new StringGuacamoleProperty() { @@ -88,7 +94,8 @@ public class MySQLGuacamoleProperties { }; /** - * Whether or not multiple users accessing the same connection at the same time should be disallowed. + * Whether or not multiple users accessing the same connection at the same + * time should be disallowed. */ public static final BooleanGuacamoleProperty MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS = new BooleanGuacamoleProperty() { @@ -98,7 +105,8 @@ public class MySQLGuacamoleProperties { }; /** - * Whether or not the same user accessing the same connection or connection group at the same time should be disallowed. + * Whether or not the same user accessing the same connection or connection + * group at the same time should be disallowed. */ public static final BooleanGuacamoleProperty MYSQL_DISALLOW_DUPLICATE_CONNECTIONS = new BooleanGuacamoleProperty() {