GUAC-1101: Split JDBC and MySQL code into separate projects.

This commit is contained in:
Michael Jumper
2015-02-27 18:43:51 -08:00
parent bcb603a4b8
commit 2d175f8792
66 changed files with 144 additions and 100 deletions

View File

@@ -0,0 +1,2 @@
target/
*~

View File

@@ -0,0 +1,19 @@
Copyright (C) 2013 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.

View File

@@ -0,0 +1,85 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamole-auth-jdbc</artifactId>
<packaging>jar</packaging>
<version>0.9.5</version>
<name>guacamole-auth-jdbc</name>
<url>http://guac-dev.org/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!-- Written for 1.6 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Guacamole Java API -->
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>0.9.4</version>
<scope>provided</scope>
</dependency>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.glyptodon.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>0.9.5</version>
<scope>provided</scope>
</dependency>
<!-- SLF4J - logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<!-- MyBatis Guice -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-guice</artifactId>
<version>3.6</version>
</dependency>
<!-- Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,125 @@
/*
* 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.auth.jdbc.user.MySQLUserContext;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLRootConnectionGroup;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLConnectionGroup;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupDirectory;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionDirectory;
import org.glyptodon.guacamole.auth.jdbc.connection.MySQLGuacamoleConfiguration;
import org.glyptodon.guacamole.auth.jdbc.connection.MySQLConnection;
import org.glyptodon.guacamole.auth.jdbc.permission.MySQLSystemPermissionSet;
import org.glyptodon.guacamole.auth.jdbc.user.MySQLUser;
import org.glyptodon.guacamole.auth.jdbc.user.UserDirectory;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionMapper;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordMapper;
import org.glyptodon.guacamole.auth.jdbc.connection.ParameterMapper;
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionMapper;
import org.glyptodon.guacamole.auth.jdbc.user.UserMapper;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupService;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService;
import org.glyptodon.guacamole.auth.jdbc.security.SHA256PasswordEncryptionService;
import org.glyptodon.guacamole.auth.jdbc.security.SaltService;
import org.glyptodon.guacamole.auth.jdbc.security.SecureRandomSaltService;
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionService;
import org.glyptodon.guacamole.auth.jdbc.socket.UnrestrictedGuacamoleSocketService;
import org.glyptodon.guacamole.auth.jdbc.user.UserService;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.glyptodon.guacamole.environment.Environment;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
/**
* Guice module which configures the injections used by the JDBC authentication
* provider base. This module MUST be included in the Guice injector, or
* authentication providers based on JDBC will not function.
*
* @author Michael Jumper
* @author James Muehlner
*/
public class JDBCAuthenticationProviderModule extends MyBatisModule {
/**
* The environment of the Guacamole server.
*/
private final Environment environment;
/**
* Creates a new JDBC authentication provider module that configures the
* various injected base classes using the given environment.
*
* @param environment
* The environment to use to configure injected classes.
*/
public JDBCAuthenticationProviderModule(Environment environment) {
this.environment = environment;
}
@Override
protected void initialize() {
// Datasource
bindDataSourceProviderType(PooledDataSourceProvider.class);
// Transaction factory
bindTransactionFactoryType(JdbcTransactionFactory.class);
// Add MyBatis mappers
addMapperClass(ConnectionMapper.class);
addMapperClass(ConnectionGroupMapper.class);
addMapperClass(ConnectionRecordMapper.class);
addMapperClass(ParameterMapper.class);
addMapperClass(SystemPermissionMapper.class);
addMapperClass(UserMapper.class);
// Bind core implementations of guacamole-ext classes
bind(Environment.class).toInstance(environment);
bind(ConnectionDirectory.class);
bind(ConnectionGroupDirectory.class);
bind(MySQLConnection.class);
bind(MySQLConnectionGroup.class);
bind(MySQLGuacamoleConfiguration.class);
bind(MySQLUser.class);
bind(MySQLUserContext.class);
bind(MySQLRootConnectionGroup.class);
bind(MySQLSystemPermissionSet.class);
bind(UserDirectory.class);
// Bind services
bind(ConnectionService.class);
bind(ConnectionGroupService.class);
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
bind(SaltService.class).to(SecureRandomSaltService.class);
bind(SystemPermissionService.class);
bind(UserService.class);
// Bind appropriate socket service based on policy
bind(GuacamoleSocketService.class).to(UnrestrictedGuacamoleSocketService.class);
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.base;
import org.glyptodon.guacamole.net.auth.Identifiable;
/**
* Common base class for objects that will ultimately be made available through
* the Directory class. All such objects will need the same base set of queries
* to fulfill the needs of the Directory class.
*
* @author Michael Jumper
* @param <ModelType>
* The type of model object that corresponds to this object.
*/
public abstract class DirectoryObject<ModelType extends ObjectModel>
extends RestrictedObject<ModelType> implements Identifiable {
@Override
public String getIdentifier() {
return getModel().getIdentifier();
}
@Override
public void setIdentifier(String identifier) {
getModel().setIdentifier(identifier);
}
}

View File

@@ -0,0 +1,140 @@
/*
* 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.base;
import java.util.Collection;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
import org.apache.ibatis.annotations.Param;
/**
* Common interface for objects that will ultimately be made available through
* the Directory class. All such objects will need the same base set of queries
* to fulfill the needs of the Directory class.
*
* @author Michael Jumper
* @param <ModelType>
* The type of object contained within the directory whose objects are
* mapped by this mapper.
*/
public interface DirectoryObjectMapper<ModelType> {
/**
* Selects the identifiers of all objects, regardless of whether they
* are readable by any particular user. This should only be called on
* behalf of a system administrator. If identifiers are needed by a non-
* administrative user who must have explicit read rights, use
* selectReadableIdentifiers() instead.
*
* @return
* A Set containing all identifiers of all objects.
*/
Set<String> selectIdentifiers();
/**
* Selects the identifiers of all objects that are explicitly readable by
* the given user. If identifiers are needed by a system administrator
* (who, by definition, does not need explicit read rights), use
* selectIdentifiers() instead.
*
* @param user
* The user whose permissions should determine whether an identifier
* is returned.
*
* @return
* A Set containing all identifiers of all readable objects.
*/
Set<String> selectReadableIdentifiers(@Param("user") UserModel user);
/**
* Selects all objects which have the given identifiers. If an identifier
* has no corresponding object, it will be ignored. This should only be
* called on behalf of a system administrator. If objects are needed by a
* non-administrative user who must have explicit read rights, use
* selectReadable() instead.
*
* @param identifiers
* The identifiers of the objects to return.
*
* @return
* A Collection of all objects having the given identifiers.
*/
Collection<ModelType> select(@Param("identifiers") Collection<String> identifiers);
/**
* Selects all objects which have the given identifiers and are explicitly
* readably by the given user. If an identifier has no corresponding
* object, or the corresponding object is unreadable, it will be ignored.
* If objects are needed by a system administrator (who, by definition,
* does not need explicit read rights), use select() instead.
*
* @param user
* The user whose permissions should determine whether an object
* is returned.
*
* @param identifiers
* The identifiers of the objects to return.
*
* @return
* A Collection of all objects having the given identifiers.
*/
Collection<ModelType> selectReadable(@Param("user") UserModel user,
@Param("identifiers") Collection<String> identifiers);
/**
* Inserts the given object into the database. If the object already
* exists, this will result in an error.
*
* @param object
* The object to insert.
*
* @return
* The number of rows inserted.
*/
int insert(@Param("object") ModelType object);
/**
* Deletes the given object into the database. If the object does not
* exist, this operation has no effect.
*
* @param identifier
* The identifier of the object to delete.
*
* @return
* The number of rows deleted.
*/
int delete(@Param("identifier") String identifier);
/**
* Updates the given existing object in the database. If the object does
* not actually exist, this operation has no effect.
*
* @param object
* The object to update.
*
* @return
* The number of rows updated.
*/
int update(@Param("object") ModelType object);
}

View File

@@ -0,0 +1,443 @@
/*
* Copyright (C) 2013 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.base;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating users. This service will automatically enforce the
* permissions of the current user.
*
* @author Michael Jumper
* @param <InternalType>
* The specific internal implementation of the type of object this service
* provides access to.
*
* @param <ExternalType>
* The external interface or implementation of the type of object this
* service provides access to, as defined by the guacamole-ext API.
*
* @param <ModelType>
* The underlying model object used to represent InternalType in the
* database.
*/
public abstract class DirectoryObjectService<InternalType extends DirectoryObject<ModelType>,
ExternalType, ModelType extends ObjectModel> {
/**
* Returns an instance of a mapper for the type of object used by this
* service.
*
* @return
* A mapper which provides access to the model objects associated with
* the objects used by this service.
*/
protected abstract DirectoryObjectMapper<ModelType> getObjectMapper();
/**
* Returns an instance of an object which is backed by the given model
* object.
*
* @param currentUser
* The user for whom this object is being created.
*
* @param model
* The model object to use to back the returned object.
*
* @return
* An object which is backed by the given model object.
*/
protected abstract InternalType getObjectInstance(AuthenticatedUser currentUser,
ModelType model);
/**
* Returns an instance of a model object which is based on the given
* object.
*
* @param currentUser
* The user for whom this model object is being created.
*
* @param object
* The object to use to produce the returned model object.
*
* @return
* A model object which is based on the given object.
*/
protected abstract ModelType getModelInstance(AuthenticatedUser currentUser,
ExternalType object);
/**
* Returns whether the given user has permission to create the type of
* objects that this directory object service manages.
*
* @param user
* The user being checked.
*
* @return
* true if the user has object creation permission relevant to this
* directory object service, false otherwise.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected abstract boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException;
/**
* Returns whether the given user has permission to perform a certain
* action on a specific object managed by this directory object service.
*
* @param user
* The user being checked.
*
* @param identifier
* The identifier of the object to check.
*
* @param type
* The type of action that will be performed.
*
* @return
* true if the user has object permission relevant described, false
* otherwise.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected boolean hasObjectPermission(AuthenticatedUser user,
String identifier, ObjectPermission.Type type)
throws GuacamoleException {
// Get object permissions
ObjectPermissionSet permissionSet = getPermissionSet(user);
// Return whether permission is granted
return user.getUser().isAdministrator()
|| permissionSet.hasPermission(type, identifier);
}
/**
* Returns the permission set associated with the given user and related
* to the type of objects handled by this directory object service.
*
* @param user
* The user whose permissions are being retrieved.
*
* @return
* A permission set which contains the permissions associated with the
* given user and related to the type of objects handled by this
* directory object service.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected abstract ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException;
/**
* Returns a collection of objects which are backed by the models in the
* given collection.
*
* @param currentUser
* The user for whom these objects are being created.
*
* @param models
* The model objects to use to back the objects within the returned
* collection.
*
* @return
* A collection of objects which are backed by the models in the given
* collection.
*/
protected Collection<InternalType> getObjectInstances(AuthenticatedUser currentUser,
Collection<ModelType> models) {
// Create new collection of objects by manually converting each model
Collection<InternalType> objects = new ArrayList<InternalType>(models.size());
for (ModelType model : models)
objects.add(getObjectInstance(currentUser, model));
return objects;
}
/**
* Returns whether the given object is valid and can be created as-is. The
* object does not yet exist in the database, but the user desires to
* create a new object with the given values. This function will be called
* prior to any creation operation, and provides a means for the
* implementation to abort prior to completion. The default implementation
* does nothing.
*
* @param user
* The user creating the object.
*
* @param object
* The object to validate.
*
* @throws GuacamoleException
* If the object is invalid, or an error prevents validating the given
* object.
*/
protected void validateNewObject(AuthenticatedUser user,
ExternalType object) throws GuacamoleException {
// By default, do nothing.
}
/**
* Returns whether the given object is valid and can updated as-is. The
* object already exists in the database, but the user desires to update
* the object to the given values. This function will be called prior to
* update operation, and provides a means for the implementation to abort
* prior to completion. The default implementation does nothing.
*
* @param user
* The user updating the existing object.
*
* @param object
* The object to validate.
*
* @throws GuacamoleException
* If the object is invalid, or an error prevents validating the given
* object.
*/
protected void validateExistingObject(AuthenticatedUser user,
InternalType object) throws GuacamoleException {
// By default, do nothing.
}
/**
* Retrieves the single object that has the given identifier, if it exists
* and the user has permission to read it.
*
* @param user
* The user retrieving the object.
*
* @param identifier
* The identifier of the object to retrieve.
*
* @return
* The object having the given identifier, or null if no such object
* exists.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested object.
*/
public InternalType retrieveObject(AuthenticatedUser user,
String identifier) throws GuacamoleException {
// Pull objects having given identifier
Collection<InternalType> objects = retrieveObjects(user, Collections.singleton(identifier));
// If no such object, return null
if (objects.isEmpty())
return null;
// The object collection will have exactly one element unless the
// database has seriously lost integrity
assert(objects.size() == 1);
// Return first and only object
return objects.iterator().next();
}
/**
* Retrieves all objects that have the identifiers in the given collection.
* Only objects that the user has permission to read will be returned.
*
* @param user
* The user retrieving the objects.
*
* @param identifiers
* The identifiers of the objects to retrieve.
*
* @return
* The objects having the given identifiers.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested objects.
*/
public Collection<InternalType> retrieveObjects(AuthenticatedUser user,
Collection<String> identifiers) throws GuacamoleException {
// Do not query if no identifiers given
if (identifiers.isEmpty())
return Collections.EMPTY_LIST;
Collection<ModelType> objects;
// Bypass permission checks if the user is a system admin
if (user.getUser().isAdministrator())
objects = getObjectMapper().select(identifiers);
// Otherwise only return explicitly readable identifiers
else
objects = getObjectMapper().selectReadable(user.getUser().getModel(), identifiers);
// Return collection of requested objects
return getObjectInstances(user, objects);
}
/**
* Creates the given object within the database. If the object already
* exists, an error will be thrown. The internal model object will be
* updated appropriately to contain the new database ID.
*
* @param user
* The user creating the object.
*
* @param object
* The object to create.
*
* @return
* The newly-created object.
*
* @throws GuacamoleException
* If the user lacks permission to create the object, or an error
* occurs while creating the object.
*/
public InternalType createObject(AuthenticatedUser user, ExternalType object)
throws GuacamoleException {
// Only create object if user has permission to do so
if (user.getUser().isAdministrator() || hasCreatePermission(user)) {
// Validate object prior to creation
validateNewObject(user, object);
// Create object
ModelType model = getModelInstance(user, object);
getObjectMapper().insert(model);
// FIXME: Insert implicit object permissions, too.
return getObjectInstance(user, model);
}
// User lacks permission to create
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Deletes the object having the given identifier. If no such object
* exists, this function has no effect.
*
* @param user
* The user deleting the object.
*
* @param identifier
* The identifier of the object to delete.
*
* @throws GuacamoleException
* If the user lacks permission to delete the object, or an error
* occurs while deleting the object.
*/
public void deleteObject(AuthenticatedUser user, String identifier)
throws GuacamoleException {
// Only delete object if user has permission to do so
if (hasObjectPermission(user, identifier, ObjectPermission.Type.DELETE)) {
getObjectMapper().delete(identifier);
return;
}
// User lacks permission to delete
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Updates the given object in the database, applying any changes that have
* been made. If no such object exists, this function has no effect.
*
* @param user
* The user updating the object.
*
* @param object
* The object to update.
*
* @throws GuacamoleException
* If the user lacks permission to update the object, or an error
* occurs while updating the object.
*/
public void updateObject(AuthenticatedUser user, InternalType object)
throws GuacamoleException {
// Only update object if user has permission to do so
if (hasObjectPermission(user, object.getIdentifier(), ObjectPermission.Type.UPDATE)) {
// Validate object prior to creation
validateExistingObject(user, object);
// Update object
getObjectMapper().update(object.getModel());
return;
}
// User lacks permission to update
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Returns the set of all identifiers for all objects in the database that
* the user has read access to.
*
* @param user
* The user retrieving the identifiers.
*
* @return
* The set of all identifiers for all objects in the database.
*
* @throws GuacamoleException
* If an error occurs while reading identifiers.
*/
public Set<String> getIdentifiers(AuthenticatedUser user)
throws GuacamoleException {
// Bypass permission checks if the user is a system admin
if (user.getUser().isAdministrator())
return getObjectMapper().selectIdentifiers();
// Otherwise only return explicitly readable identifiers
else
return getObjectMapper().selectReadableIdentifiers(user.getUser().getModel());
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.base;
/**
* Object representation of a Guacamole object, such as a user or connection,
* as represented in the database.
*
* @author Michael Jumper
*/
public abstract class ObjectModel {
/**
* The ID of this object in the database, if any.
*/
private Integer objectID;
/**
* The unique identifier which identifies this object.
*/
private String identifier;
/**
* Creates a new, empty object.
*/
public ObjectModel() {
}
/**
* Returns the identifier that uniquely identifies this object.
*
* @return
* The identifier that uniquely identifies this object.
*/
public String getIdentifier() {
return identifier;
}
/**
* Sets the identifier that uniquely identifies this object.
*
* @param identifier
* The identifier that uniquely identifies this object.
*/
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
/**
* Returns the ID of this object in the database, if it exists.
*
* @return
* The ID of this object in the database, or null if this object was
* not retrieved from the database.
*/
public Integer getObjectID() {
return objectID;
}
/**
* Sets the ID of this object to the given value.
*
* @param objectID
* The ID to assign to this object.
*/
public void setObjectID(Integer objectID) {
this.objectID = objectID;
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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.base;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
/**
* Common base class for objects that are associated with the users that
* query them, and have an underlying model.
*
* @author Michael Jumper
* @param <ModelType>
* The type of model object which corresponds to this object.
*/
public abstract class RestrictedObject<ModelType> {
/**
* The user this object belongs to. Access is based on his/her permission
* settings.
*/
private AuthenticatedUser currentUser;
/**
* The internal model object containing the values which represent this
* object in the database.
*/
private ModelType model;
/**
* Initializes this object, associating it with the current authenticated
* user and populating it with data from the given model object
*
* @param currentUser
* The user that created or retrieved this object.
*
* @param model
* The backing model object.
*/
public void init(AuthenticatedUser currentUser, ModelType model) {
setCurrentUser(currentUser);
setModel(model);
}
/**
* Returns the user that created or queried this object. This user's
* permissions dictate what operations can be performed on or through this
* object.
*
* @return
* The user that created or queried this object.
*/
public AuthenticatedUser getCurrentUser() {
return currentUser;
}
/**
* Sets the user that created or queried this object. This user's
* permissions dictate what operations can be performed on or through this
* object.
*
* @param currentUser
* The user that created or queried this object.
*/
public void setCurrentUser(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
/**
* Returns the backing model object. Changes to the model object will
* affect this object, and changes to this object will affect the model
* object.
*
* @return
* The backing model object.
*/
public ModelType getModel() {
return model;
}
/**
* Sets the backing model object. This will effectively replace all data
* contained within this object.
*
* @param model
* The backing model object.
*/
public void setModel(ModelType model) {
this.model = model;
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
/**
* Base classes supporting the MySQL authentication provider and defining the
* relationships between the model and the implementations of guacamole-ext
* classes.
*/
package org.glyptodon.guacamole.auth.jdbc.base;

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2013 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.connection;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.Directory;
import org.mybatis.guice.transactional.Transactional;
/**
* A MySQL based implementation of the Connection Directory.
*
* @author James Muehlner
* @author Michael Jumper
*/
public class ConnectionDirectory implements Directory<Connection> {
/**
* The user this connection directory belongs to. Access is based on
* his/her permission settings.
*/
private AuthenticatedUser currentUser;
/**
* Service for managing connection objects.
*/
@Inject
private ConnectionService connectionService;
/**
* Set the user for this directory.
*
* @param currentUser
* The user whose permissions define the visibility of connections in
* this directory.
*/
public void init(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
@Override
public Connection get(String identifier) throws GuacamoleException {
return connectionService.retrieveObject(currentUser, identifier);
}
@Override
@Transactional
public Collection<Connection> getAll(Collection<String> identifiers) throws GuacamoleException {
Collection<MySQLConnection> objects = connectionService.retrieveObjects(currentUser, identifiers);
return Collections.<Connection>unmodifiableCollection(objects);
}
@Override
@Transactional
public Set<String> getIdentifiers() throws GuacamoleException {
return connectionService.getIdentifiers(currentUser);
}
@Override
@Transactional
public void add(Connection object) throws GuacamoleException {
connectionService.createObject(currentUser, object);
}
@Override
@Transactional
public void update(Connection object) throws GuacamoleException {
MySQLConnection connection = (MySQLConnection) object;
connectionService.updateObject(currentUser, connection);
}
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
connectionService.deleteObject(currentUser, identifier);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.connection;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for connection objects.
*
* @author Michael Jumper
*/
public interface ConnectionMapper extends DirectoryObjectMapper<ConnectionModel> {
/**
* Selects the identifiers of all connections within the given parent
* connection group, regardless of whether they are readable by any
* particular user. This should only be called on behalf of a system
* administrator. If identifiers are needed by a non-administrative user
* who must have explicit read rights, use
* selectReadableIdentifiersWithin() instead.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the root
* connection group is to be queried.
*
* @return
* A Set containing all identifiers of all objects.
*/
Set<String> selectIdentifiersWithin(@Param("parentIdentifier") String parentIdentifier);
/**
* Selects the identifiers of all connections within the given parent
* connection group that are explicitly readable by the given user. If
* identifiers are needed by a system administrator (who, by definition,
* does not need explicit read rights), use selectIdentifiersWithin()
* instead.
*
* @param user
* The user whose permissions should determine whether an identifier
* is returned.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the root
* connection group is to be queried.
*
* @return
* A Set containing all identifiers of all readable objects.
*/
Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
@Param("parentIdentifier") String parentIdentifier);
}

View File

@@ -0,0 +1,139 @@
/*
* 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.connection;
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
/**
* Object representation of a Guacamole connection, as represented in the
* database.
*
* @author Michael Jumper
*/
public class ConnectionModel extends ObjectModel {
/**
* The identifier of the parent connection group in the database, or null
* if the parent connection group is the root group.
*/
private String parentIdentifier;
/**
* The human-readable name associated with this connection.
*/
private String name;
/**
* The name of the protocol to use when connecting to this connection.
*/
private String protocol;
/**
* Creates a new, empty connection.
*/
public ConnectionModel() {
}
/**
* Returns the name associated with this connection.
*
* @return
* The name associated with this connection.
*/
public String getName() {
return name;
}
/**
* Sets the name associated with this connection.
*
* @param name
* The name to associate with this connection.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the name of the protocol to use when connecting to this
* connection.
*
* @return
* The name of the protocol to use when connecting to this connection.
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the name of the protocol to use when connecting to this connection.
*
* @param protocol
* The name of the protocol to use when connecting to this connection.
*/
public void setProtocol(String protocol) {
this.protocol = protocol;
}
/**
* Returns the identifier of the parent connection group, or null if the
* parent connection group is the root connection group.
*
* @return
* The identifier of the parent connection group, or null if the parent
* connection group is the root connection group.
*/
public String getParentIdentifier() {
return parentIdentifier;
}
/**
* Sets the identifier of the parent connection group.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the parent
* connection group is the root connection group.
*/
public void setParentIdentifier(String parentIdentifier) {
this.parentIdentifier = parentIdentifier;
}
@Override
public String getIdentifier() {
// If no associated ID, then no associated identifier
Integer id = getObjectID();
if (id == null)
return null;
// Otherwise, the identifier is the ID as a string
return id.toString();
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("Connection identifiers are derived from IDs. They cannot be set.");
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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.connection;
import java.util.List;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for connection record objects.
*
* @author Michael Jumper
*/
public interface ConnectionRecordMapper {
/**
* Returns a collection of all connection records associated with the
* connection having the given identifier.
*
* @param identifier
* The identifier of the connection whose records are to be retrieved.
*
* @return
* A collection of all connection records associated with the
* connection having the given identifier. This collection will be
* empty if no such connection exists.
*/
List<ConnectionRecordModel> select(@Param("identifier") String identifier);
/**
* Inserts the given connection record.
*
* @param record
* The connection record to insert.
*
* @return
* The number of rows inserted.
*/
int insert(@Param("record") ConnectionRecordModel record);
}

View File

@@ -0,0 +1,170 @@
/*
* 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.connection;
import java.util.Date;
/**
* A single connection record representing a past usage of a particular
* connection.
*
* @author Michael Jumper
*/
public class ConnectionRecordModel {
/**
* The identifier of the connection associated with this connection record.
*/
private String connectionIdentifier;
/**
* The database ID of the user associated with this connection record.
*/
private Integer userID;
/**
* The username of the user associated with this connection record.
*/
private String username;
/**
* The time the connection was initiated by the associated user.
*/
private Date startDate;
/**
* The time the connection ended, or null if the end time is not known or
* the connection is still running.
*/
private Date endDate;
/**
* Returns the identifier of the connection associated with this connection
* record.
*
* @return
* The identifier of the connection associated with this connection
* record.
*/
public String getConnectionIdentifier() {
return connectionIdentifier;
}
/**
* Sets the identifier of the connection associated with this connection
* record.
*
* @param connectionIdentifier
* The identifier of the connection to associate with this connection
* record.
*/
public void setConnectionIdentifier(String connectionIdentifier) {
this.connectionIdentifier = connectionIdentifier;
}
/**
* Returns the database ID of the user associated with this connection
* record.
*
* @return
* The database ID of the user associated with this connection record.
*/
public Integer getUserID() {
return userID;
}
/**
* Sets the database ID of the user associated with this connection record.
*
* @param userID
* The database ID of the user to associate with this connection
* record.
*/
public void setUserID(Integer userID) {
this.userID = userID;
}
/**
* Returns the username of the user associated with this connection record.
*
* @return
* The username of the user associated with this connection record.
*/
public String getUsername() {
return username;
}
/**
* Sets the username of the user associated with this connection record.
*
* @param username
* The username of the user to associate with this connection record.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Returns the date that the associated connection was established.
*
* @return
* The date the associated connection was established.
*/
public Date getStartDate() {
return startDate;
}
/**
* Sets the date that the associated connection was established.
*
* @param startDate
* The date that the associated connection was established.
*/
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
/**
* Returns the date that the associated connection ended, or null if no
* end date was recorded. The lack of an end date does not necessarily
* mean that the connection is still active.
*
* @return
* The date the associated connection ended, or null if no end date was
* recorded.
*/
public Date getEndDate() {
return endDate;
}
/**
* Sets the date that the associated connection ended.
*
* @param endDate
* The date that the associated connection ended.
*/
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
}

View File

@@ -0,0 +1,394 @@
/*
* Copyright (C) 2013 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.connection;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating connections.
*
* @author Michael Jumper, James Muehlner
*/
public class ConnectionService extends DirectoryObjectService<MySQLConnection, Connection, ConnectionModel> {
/**
* Mapper for accessing connections.
*/
@Inject
private ConnectionMapper connectionMapper;
/**
* Mapper for accessing connection parameters.
*/
@Inject
private ParameterMapper parameterMapper;
/**
* Mapper for accessing connection history.
*/
@Inject
private ConnectionRecordMapper connectionRecordMapper;
/**
* Provider for creating connections.
*/
@Inject
private Provider<MySQLConnection> mySQLConnectionProvider;
/**
* Service for creating and tracking sockets.
*/
@Inject
private GuacamoleSocketService socketService;
@Override
protected DirectoryObjectMapper<ConnectionModel> getObjectMapper() {
return connectionMapper;
}
@Override
protected MySQLConnection getObjectInstance(AuthenticatedUser currentUser,
ConnectionModel model) {
MySQLConnection connection = mySQLConnectionProvider.get();
connection.init(currentUser, model);
return connection;
}
@Override
protected ConnectionModel getModelInstance(AuthenticatedUser currentUser,
final Connection object) {
// Create new MySQLConnection backed by blank model
ConnectionModel model = new ConnectionModel();
MySQLConnection connection = getObjectInstance(currentUser, model);
// Set model contents through MySQLConnection, copying the provided connection
connection.setParentIdentifier(object.getParentIdentifier());
connection.setName(object.getName());
connection.setConfiguration(object.getConfiguration());
return model;
}
@Override
protected boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException {
// Return whether user has explicit connection creation permission
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_CONNECTION);
}
@Override
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to connections
return user.getUser().getConnectionPermissions();
}
@Override
protected void validateNewObject(AuthenticatedUser user, Connection object)
throws GuacamoleException {
// Name must not be blank
if (object.getName().trim().isEmpty())
throw new GuacamoleClientException("Connection names must not be blank.");
// FIXME: Do not attempt to create duplicate connections
}
@Override
protected void validateExistingObject(AuthenticatedUser user,
MySQLConnection object) throws GuacamoleException {
// Name must not be blank
if (object.getName().trim().isEmpty())
throw new GuacamoleClientException("Connection names must not be blank.");
// FIXME: Check whether such a connection is already present
}
/**
* Given an arbitrary Guacamole connection, produces a collection of
* parameter model objects containing the name/value pairs of that
* connection's parameters.
*
* @param connection
* The connection whose configuration should be used to produce the
* collection of parameter models.
*
* @return
* A collection of parameter models containing the name/value pairs
* of the given connection's parameters.
*/
private Collection<ParameterModel> getParameterModels(MySQLConnection connection) {
Map<String, String> parameters = connection.getConfiguration().getParameters();
// Convert parameters to model objects
Collection<ParameterModel> parameterModels = new ArrayList(parameters.size());
for (Map.Entry<String, String> parameterEntry : parameters.entrySet()) {
// Get parameter name and value
String name = parameterEntry.getKey();
String value = parameterEntry.getValue();
// There is no need to insert empty parameters
if (value.isEmpty())
continue;
// Produce model object from parameter
ParameterModel model = new ParameterModel();
model.setConnectionIdentifier(connection.getIdentifier());
model.setName(name);
model.setValue(value);
// Add model to list
parameterModels.add(model);
}
return parameterModels;
}
@Override
public MySQLConnection createObject(AuthenticatedUser user, Connection object)
throws GuacamoleException {
// Create connection
MySQLConnection connection = super.createObject(user, object);
connection.setConfiguration(object.getConfiguration());
// Insert new parameters, if any
Collection<ParameterModel> parameterModels = getParameterModels(connection);
if (!parameterModels.isEmpty())
parameterMapper.insert(parameterModels);
return connection;
}
@Override
public void updateObject(AuthenticatedUser user, MySQLConnection object)
throws GuacamoleException {
// Update connection
super.updateObject(user, object);
// Replace existing parameters with new parameters
Collection<ParameterModel> parameterModels = getParameterModels(object);
parameterMapper.delete(object.getIdentifier());
parameterMapper.insert(parameterModels);
}
/**
* Returns the set of all identifiers for all connections within the
* connection group having the given identifier. Only connections that the
* user has read access to will be returned.
*
* Permission to read the connection group having the given identifier is
* NOT checked.
*
* @param user
* The user retrieving the identifiers.
*
* @param identifier
* The identifier of the parent connection group, or null to check the
* root connection group.
*
* @return
* The set of all identifiers for all connections in the connection
* group having the given identifier that the user has read access to.
*
* @throws GuacamoleException
* If an error occurs while reading identifiers.
*/
public Set<String> getIdentifiersWithin(AuthenticatedUser user,
String identifier)
throws GuacamoleException {
// Bypass permission checks if the user is a system admin
if (user.getUser().isAdministrator())
return connectionMapper.selectIdentifiersWithin(identifier);
// Otherwise only return explicitly readable identifiers
else
return connectionMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
}
/**
* Retrieves all parameters visible to the given user and associated with
* the connection having the given identifier. If the given user has no
* access to such parameters, or no such connection exists, the returned
* map will be empty.
*
* @param user
* The user retrieving connection parameters.
*
* @param identifier
* The identifier of the connection whose parameters are being
* retrieved.
*
* @return
* A new map of all parameter name/value pairs that the given user has
* access to.
*/
public Map<String, String> retrieveParameters(AuthenticatedUser user,
String identifier) {
Map<String, String> parameterMap = new HashMap<String, String>();
// Determine whether we have permission to read parameters
boolean canRetrieveParameters;
try {
canRetrieveParameters = hasObjectPermission(user, identifier,
ObjectPermission.Type.UPDATE);
}
// Provide empty (but mutable) map if unable to check permissions
catch (GuacamoleException e) {
return parameterMap;
}
// Populate parameter map if we have permission to do so
if (canRetrieveParameters) {
for (ParameterModel parameter : parameterMapper.select(identifier))
parameterMap.put(parameter.getName(), parameter.getValue());
}
return parameterMap;
}
/**
* Retrieves the connection history of the given connection, including any
* active connections.
*
* @param user
* The user retrieving the connection history.
*
* @param connection
* The connection whose history is being retrieved.
*
* @return
* The connection history of the given connection, including any
* active connections.
*
* @throws GuacamoleException
* If permission to read the connection history is denied.
*/
public List<ConnectionRecord> retrieveHistory(AuthenticatedUser user,
MySQLConnection connection) throws GuacamoleException {
String identifier = connection.getIdentifier();
// Retrieve history only if READ permission is granted
if (hasObjectPermission(user, identifier, ObjectPermission.Type.READ)) {
// Retrieve history
List<ConnectionRecordModel> models = connectionRecordMapper.select(identifier);
// Get currently-active connections
List<ConnectionRecord> records = new ArrayList<ConnectionRecord>(socketService.getActiveConnections(connection));
// Add past connections from model objects
for (ConnectionRecordModel model : models)
records.add(new MySQLConnectionRecord(model));
// Return converted history list
return records;
}
// The user does not have permission to read the history
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Connects to the given connection as the given user, using the given
* client information. If the user does not have permission to read the
* connection, permission will be denied.
*
* @param user
* The user connecting to the connection.
*
* @param connection
* The connection being connected to.
*
* @param info
* Information associated with the connecting client.
*
* @return
* A connected GuacamoleSocket associated with a newly-established
* connection.
*
* @throws GuacamoleException
* If permission to connect to this connection is denied.
*/
public GuacamoleSocket connect(AuthenticatedUser user,
MySQLConnection connection, GuacamoleClientInformation info)
throws GuacamoleException {
// Connect only if READ permission is granted
if (hasObjectPermission(user, connection.getIdentifier(), ObjectPermission.Type.READ))
return socketService.getGuacamoleSocket(user, connection, info);
// The user does not have permission to connect
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2013 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.connection;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.List;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLRootConnectionGroup;
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
/**
* A MySQL based implementation of the Connection object.
* @author James Muehlner
*/
public class MySQLConnection extends DirectoryObject<ConnectionModel>
implements Connection {
/**
* Service for managing connections.
*/
@Inject
private ConnectionService connectionService;
/**
* Service for creating and tracking sockets.
*/
@Inject
private GuacamoleSocketService socketService;
/**
* Provider for lazy-loaded, permission-controlled configurations.
*/
@Inject
private Provider<MySQLGuacamoleConfiguration> configProvider;
/**
* The manually-set GuacamoleConfiguration, if any.
*/
private GuacamoleConfiguration config = null;
/**
* Creates a new, empty MySQLConnection.
*/
public MySQLConnection() {
}
@Override
public String getName() {
return getModel().getName();
}
@Override
public void setName(String name) {
getModel().setName(name);
}
@Override
public String getParentIdentifier() {
// Translate null parent to proper identifier
String parentIdentifier = getModel().getParentIdentifier();
if (parentIdentifier == null)
return MySQLRootConnectionGroup.IDENTIFIER;
return parentIdentifier;
}
@Override
public void setParentIdentifier(String parentIdentifier) {
// Translate root identifier back into null
if (parentIdentifier != null
&& parentIdentifier.equals(MySQLRootConnectionGroup.IDENTIFIER))
parentIdentifier = null;
getModel().setParentIdentifier(parentIdentifier);
}
@Override
public GuacamoleConfiguration getConfiguration() {
// If configuration has been manually set, return that
if (config != null)
return config;
// Otherwise, return permission-controlled configuration
MySQLGuacamoleConfiguration restrictedConfig = configProvider.get();
restrictedConfig.init(getCurrentUser(), getModel());
return restrictedConfig;
}
@Override
public void setConfiguration(GuacamoleConfiguration config) {
// Store manually-set configuration internally
this.config = config;
// Update model
getModel().setProtocol(config.getProtocol());
}
@Override
public List<? extends ConnectionRecord> getHistory() throws GuacamoleException {
return connectionService.retrieveHistory(getCurrentUser(), this);
}
@Override
public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
return connectionService.connect(getCurrentUser(), this, info);
}
@Override
public int getActiveConnections() {
return socketService.getActiveConnections(this).size();
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2013 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.connection;
import java.util.Date;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
/**
* A ConnectionRecord which is based on data stored in MySQL.
*
* @author James Muehlner
* @author Michael Jumper
*/
public class MySQLConnectionRecord implements ConnectionRecord {
/**
* The model object backing this connection record.
*/
private ConnectionRecordModel model;
/**
* Creates a new MySQLConnectionRecord backed by the given model object.
* Changes to this record will affect the backing model object, and changes
* to the backing model object will affect this record.
*
* @param model
* The model object to use to back this connection record.
*/
public MySQLConnectionRecord(ConnectionRecordModel model) {
this.model = model;
}
@Override
public Date getStartDate() {
return model.getStartDate();
}
@Override
public Date getEndDate() {
return model.getEndDate();
}
@Override
public String getUsername() {
return model.getUsername();
}
@Override
public boolean isActive() {
return false;
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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.connection;
import com.google.inject.Inject;
import java.util.Map;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
/**
* Implementation of GuacamoleConfiguration which loads parameter values only
* if necessary, and only if allowed.
*
* @author Michael Jumper
*/
public class MySQLGuacamoleConfiguration extends GuacamoleConfiguration {
/**
* The user this configuration belongs to. Access is based on his/her
* permission settings.
*/
private AuthenticatedUser currentUser;
/**
* The internal model object containing the values which represent the
* connection associated with this configuration.
*/
private ConnectionModel connectionModel;
/**
* Service for managing connection parameters.
*/
@Inject
private ConnectionService connectionService;
/**
* The manually-set parameter map, if any.
*/
private Map<String, String> parameters = null;
/**
* Creates a new, empty MySQLGuacamoleConfiguration.
*/
public MySQLGuacamoleConfiguration() {
}
/**
* Initializes this configuration, associating it with the current
* authenticated user and populating it with data from the given model
* object.
*
* @param currentUser
* The user that created or retrieved this configuration.
*
* @param connectionModel
* The model object backing this configuration.
*/
public void init(AuthenticatedUser currentUser, ConnectionModel connectionModel) {
this.currentUser = currentUser;
this.connectionModel = connectionModel;
}
@Override
public String getProtocol() {
return connectionModel.getProtocol();
}
@Override
public void setProtocol(String protocol) {
super.setProtocol(protocol);
connectionModel.setProtocol(protocol);
}
@Override
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
super.setParameters(parameters);
}
@Override
public Map<String, String> getParameters() {
// Retrieve visible parameters, if not overridden by setParameters()
if (parameters == null) {
// Retrieve all visible parameters
Map<String, String> visibleParameters =
connectionService.retrieveParameters(currentUser, connectionModel.getIdentifier());
// Use retrieved parameters to back future operations
super.setParameters(visibleParameters);
}
return super.getParameters();
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.connection;
import java.util.Collection;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for connection parameter objects.
*
* @author Michael Jumper
*/
public interface ParameterMapper {
/**
* Returns a collection of all parameters associated with the connection
* having the given identifier.
*
* @param identifier
* The identifier of the connection whose parameters are to be
* retrieved.
*
* @return
* A collection of all parameters associated with the connection
* having the given identifier. This collection will be empty if no
* such connection exists.
*/
Collection<ParameterModel> select(@Param("identifier") String identifier);
/**
* Inserts each of the parameter model objects in the given collection as
* new connection parameters.
*
* @param parameters
* The connection parameters to insert.
*
* @return
* The number of rows inserted.
*/
int insert(@Param("parameters") Collection<ParameterModel> parameters);
/**
* Deletes all parameters associated with the connection having the given
* identifier.
*
* @param identifier
* The identifier of the connection whose parameters should be
* deleted.
*
* @return
* The number of rows deleted.
*/
int delete(@Param("identifier") String identifier);
}

View File

@@ -0,0 +1,107 @@
/*
* 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.connection;
/**
* A single parameter name/value pair belonging to a connection.
*
* @author Michael Jumper
*/
public class ParameterModel {
/**
* The identifier of the connection associated with this parameter.
*/
private String connectionIdentifier;
/**
* The name of the parameter.
*/
private String name;
/**
* The value the parameter is set to.
*/
private String value;
/**
* Returns the identifier of the connection associated with this parameter.
*
* @return
* The identifier of the connection associated with this parameter.
*/
public String getConnectionIdentifier() {
return connectionIdentifier;
}
/**
* Sets the identifier of the connection associated with this parameter.
*
* @param connectionIdentifier
* The identifier of the connection to associate with this parameter.
*/
public void setConnectionIdentifier(String connectionIdentifier) {
this.connectionIdentifier = connectionIdentifier;
}
/**
* Returns the name of this parameter.
*
* @return
* The name of this parameter.
*/
public String getName() {
return name;
}
/**
* Sets the name of this parameter.
*
* @param name
* The name of this parameter.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the value of this parameter.
*
* @return
* The value of this parameter.
*/
public String getValue() {
return value;
}
/**
* Sets the value of this parameter.
*
* @param value
* The value of this parameter.
*/
public void setValue(String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* Classes related to connections and their parameters and history.
*/
package org.glyptodon.guacamole.auth.jdbc.connection;

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2013 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.connectiongroup;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory;
import org.mybatis.guice.transactional.Transactional;
/**
* A MySQL based implementation of the ConnectionGroup Directory.
*
* @author James Muehlner
* @author Michael Jumper
*/
public class ConnectionGroupDirectory implements Directory<ConnectionGroup> {
/**
* The user this connection group directory belongs to. Access is based on
* his/her permission settings.
*/
private AuthenticatedUser currentUser;
/**
* Service for managing connection group objects.
*/
@Inject
private ConnectionGroupService connectionGroupService;
/**
* Set the user for this directory.
*
* @param currentUser
* The user whose permissions define the visibility of connection
* groups in this directory.
*/
public void init(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
@Override
public ConnectionGroup get(String identifier) throws GuacamoleException {
return connectionGroupService.retrieveObject(currentUser, identifier);
}
@Override
@Transactional
public Collection<ConnectionGroup> getAll(Collection<String> identifiers) throws GuacamoleException {
Collection<MySQLConnectionGroup> objects = connectionGroupService.retrieveObjects(currentUser, identifiers);
return Collections.<ConnectionGroup>unmodifiableCollection(objects);
}
@Override
@Transactional
public Set<String> getIdentifiers() throws GuacamoleException {
return connectionGroupService.getIdentifiers(currentUser);
}
@Override
@Transactional
public void add(ConnectionGroup object) throws GuacamoleException {
connectionGroupService.createObject(currentUser, object);
}
@Override
@Transactional
public void update(ConnectionGroup object) throws GuacamoleException {
MySQLConnectionGroup connectionGroup = (MySQLConnectionGroup) object;
connectionGroupService.updateObject(currentUser, connectionGroup);
}
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
connectionGroupService.deleteObject(currentUser, identifier);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.connectiongroup;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for connection group objects.
*
* @author Michael Jumper
*/
public interface ConnectionGroupMapper extends DirectoryObjectMapper<ConnectionGroupModel> {
/**
* Selects the identifiers of all connection groups within the given parent
* connection group, regardless of whether they are readable by any
* particular user. This should only be called on behalf of a system
* administrator. If identifiers are needed by a non-administrative user
* who must have explicit read rights, use
* selectReadableIdentifiersWithin() instead.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the root
* connection group is to be queried.
*
* @return
* A Set containing all identifiers of all objects.
*/
Set<String> selectIdentifiersWithin(@Param("parentIdentifier") String parentIdentifier);
/**
* Selects the identifiers of all connection groups within the given parent
* connection group that are explicitly readable by the given user. If
* identifiers are needed by a system administrator (who, by definition,
* does not need explicit read rights), use selectIdentifiersWithin()
* instead.
*
* @param user
* The user whose permissions should determine whether an identifier
* is returned.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the root
* connection group is to be queried.
*
* @return
* A Set containing all identifiers of all readable objects.
*/
Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
@Param("parentIdentifier") String parentIdentifier);
}

View File

@@ -0,0 +1,141 @@
/*
* 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.connectiongroup;
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
/**
* Object representation of a Guacamole connection group, as represented in the
* database.
*
* @author Michael Jumper
*/
public class ConnectionGroupModel extends ObjectModel {
/**
* The identifier of the parent connection group in the database, or null
* if the parent connection group is the root group.
*/
private String parentIdentifier;
/**
* The human-readable name associated with this connection group.
*/
private String name;
/**
* The type of this connection group, such as organizational or balancing.
*/
private ConnectionGroup.Type type;
/**
* Creates a new, empty connection group.
*/
public ConnectionGroupModel() {
}
/**
* Returns the name associated with this connection group.
*
* @return
* The name associated with this connection group.
*/
public String getName() {
return name;
}
/**
* Sets the name associated with this connection group.
*
* @param name
* The name to associate with this connection group.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the identifier of the parent connection group, or null if the
* parent connection group is the root connection group.
*
* @return
* The identifier of the parent connection group, or null if the parent
* connection group is the root connection group.
*/
public String getParentIdentifier() {
return parentIdentifier;
}
/**
* Sets the identifier of the parent connection group.
*
* @param parentIdentifier
* The identifier of the parent connection group, or null if the parent
* connection group is the root connection group.
*/
public void setParentIdentifier(String parentIdentifier) {
this.parentIdentifier = parentIdentifier;
}
/**
* Returns the type of this connection group, such as organizational or
* balancing.
*
* @return
* The type of this connection group.
*/
public ConnectionGroup.Type getType() {
return type;
}
/**
* Sets the type of this connection group, such as organizational or
* balancing.
*
* @param type
* The type of this connection group.
*/
public void setType(ConnectionGroup.Type type) {
this.type = type;
}
@Override
public String getIdentifier() {
// If no associated ID, then no associated identifier
Integer id = getObjectID();
if (id == null)
return null;
// Otherwise, the identifier is the ID as a string
return id.toString();
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("Connection group identifiers are derived from IDs. They cannot be set.");
}
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2013 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.connectiongroup;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating connection groups.
*
* @author Michael Jumper, James Muehlner
*/
public class ConnectionGroupService extends DirectoryObjectService<MySQLConnectionGroup,
ConnectionGroup, ConnectionGroupModel> {
/**
* Mapper for accessing connection groups.
*/
@Inject
private ConnectionGroupMapper connectionGroupMapper;
/**
* Provider for creating connection groups.
*/
@Inject
private Provider<MySQLConnectionGroup> connectionGroupProvider;
/**
* Service for creating and tracking sockets.
*/
@Inject
private GuacamoleSocketService socketService;
@Override
protected DirectoryObjectMapper<ConnectionGroupModel> getObjectMapper() {
return connectionGroupMapper;
}
@Override
protected MySQLConnectionGroup getObjectInstance(AuthenticatedUser currentUser,
ConnectionGroupModel model) {
MySQLConnectionGroup connectionGroup = connectionGroupProvider.get();
connectionGroup.init(currentUser, model);
return connectionGroup;
}
@Override
protected ConnectionGroupModel getModelInstance(AuthenticatedUser currentUser,
final ConnectionGroup object) {
// Create new MySQLConnectionGroup backed by blank model
ConnectionGroupModel model = new ConnectionGroupModel();
MySQLConnectionGroup connectionGroup = getObjectInstance(currentUser, model);
// Set model contents through MySQLConnection, copying the provided connection group
connectionGroup.setParentIdentifier(object.getParentIdentifier());
connectionGroup.setName(object.getName());
connectionGroup.setType(object.getType());
return model;
}
@Override
protected boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException {
// Return whether user has explicit connection group creation permission
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_CONNECTION_GROUP);
}
@Override
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to connection groups
return user.getUser().getConnectionGroupPermissions();
}
@Override
protected void validateNewObject(AuthenticatedUser user, ConnectionGroup object)
throws GuacamoleException {
// Name must not be blank
if (object.getName().trim().isEmpty())
throw new GuacamoleClientException("Connection group names must not be blank.");
// FIXME: Do not attempt to create duplicate connection groups
}
@Override
protected void validateExistingObject(AuthenticatedUser user,
MySQLConnectionGroup object) throws GuacamoleException {
// Name must not be blank
if (object.getName().trim().isEmpty())
throw new GuacamoleClientException("Connection group names must not be blank.");
// FIXME: Check whether such a connection group is already present
}
/**
* Returns the set of all identifiers for all connection groups within the
* connection group having the given identifier. Only connection groups
* that the user has read access to will be returned.
*
* Permission to read the connection group having the given identifier is
* NOT checked.
*
* @param user
* The user retrieving the identifiers.
*
* @param identifier
* The identifier of the parent connection group, or null to check the
* root connection group.
*
* @return
* The set of all identifiers for all connection groups in the
* connection group having the given identifier that the user has read
* access to.
*
* @throws GuacamoleException
* If an error occurs while reading identifiers.
*/
public Set<String> getIdentifiersWithin(AuthenticatedUser user,
String identifier)
throws GuacamoleException {
// Bypass permission checks if the user is a system admin
if (user.getUser().isAdministrator())
return connectionGroupMapper.selectIdentifiersWithin(identifier);
// Otherwise only return explicitly readable identifiers
else
return connectionGroupMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
}
/**
* Connects to the given connection group as the given user, using the
* given client information. If the user does not have permission to read
* the connection group, permission will be denied.
*
* @param user
* The user connecting to the connection group.
*
* @param connectionGroup
* The connectionGroup being connected to.
*
* @param info
* Information associated with the connecting client.
*
* @return
* A connected GuacamoleSocket associated with a newly-established
* connection.
*
* @throws GuacamoleException
* If permission to connect to this connection is denied.
*/
public GuacamoleSocket connect(AuthenticatedUser user,
MySQLConnectionGroup connectionGroup, GuacamoleClientInformation info)
throws GuacamoleException {
// Connect only if READ permission is granted
if (hasObjectPermission(user, connectionGroup.getIdentifier(), ObjectPermission.Type.READ))
return socketService.getGuacamoleSocket(user, connectionGroup, info);
// The user does not have permission to connect
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2013 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.connectiongroup;
import com.google.inject.Inject;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
/**
* A MySQL based implementation of the ConnectionGroup object.
*
* @author James Muehlner
*/
public class MySQLConnectionGroup extends DirectoryObject<ConnectionGroupModel>
implements ConnectionGroup {
/**
* Service for managing connections.
*/
@Inject
private ConnectionService connectionService;
/**
* Service for managing connection groups.
*/
@Inject
private ConnectionGroupService connectionGroupService;
/**
* Service for creating and tracking sockets.
*/
@Inject
private GuacamoleSocketService socketService;
/**
* Creates a new, empty MySQLConnection.
*/
public MySQLConnectionGroup() {
}
@Override
public String getName() {
return getModel().getName();
}
@Override
public void setName(String name) {
getModel().setName(name);
}
@Override
public String getParentIdentifier() {
// Translate null parent to proper identifier
String parentIdentifier = getModel().getParentIdentifier();
if (parentIdentifier == null)
return MySQLRootConnectionGroup.IDENTIFIER;
return parentIdentifier;
}
@Override
public void setParentIdentifier(String parentIdentifier) {
// Translate root identifier back into null
if (parentIdentifier != null
&& parentIdentifier.equals(MySQLRootConnectionGroup.IDENTIFIER))
parentIdentifier = null;
getModel().setParentIdentifier(parentIdentifier);
}
@Override
public GuacamoleSocket connect(GuacamoleClientInformation info)
throws GuacamoleException {
return connectionGroupService.connect(getCurrentUser(), this, info);
}
@Override
public int getActiveConnections() {
return socketService.getActiveConnections(this).size();
}
@Override
public void setType(Type type) {
getModel().setType(type);
}
@Override
public Type getType() {
return getModel().getType();
}
@Override
public Set<String> getConnectionIdentifiers()
throws GuacamoleException {
return connectionService.getIdentifiersWithin(getCurrentUser(), getIdentifier());
}
@Override
public Set<String> getConnectionGroupIdentifiers()
throws GuacamoleException {
return connectionGroupService.getIdentifiersWithin(getCurrentUser(), getIdentifier());
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2013 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.connectiongroup;
import com.google.inject.Inject;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
/**
* The root connection group, here represented as its own dedicated object as
* the database does not contain an actual root group.
*
* @author Michael Jumper
*/
public class MySQLRootConnectionGroup implements ConnectionGroup {
/**
* The identifier used to represent the root connection group. There is no
* corresponding entry in the database, thus a reserved identifier that
* cannot collide with database-generated identifiers is needed.
*/
public static final String IDENTIFIER = "ROOT";
/**
* The human-readable name of this connection group. The name of the root
* group is not normally visible, and may even be replaced by the web
* interface for the sake of translation.
*/
public static final String NAME = "ROOT";
/**
* The user this group belongs to. Access is based on his/her permission
* settings.
*/
private AuthenticatedUser currentUser;
/**
* Service for managing connection objects.
*/
@Inject
private ConnectionService connectionService;
/**
* Service for managing connection group objects.
*/
@Inject
private ConnectionGroupService connectionGroupService;
/**
* Creates a new, empty MySQLRootConnectionGroup.
*/
public MySQLRootConnectionGroup() {
}
/**
* Initializes this root connection group, associating it with the current
* authenticated user.
*
* @param currentUser
* The user that created or retrieved this object.
*/
public void init(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
@Override
public String getName() {
return NAME;
}
@Override
public void setName(String name) {
throw new UnsupportedOperationException("The root connection group cannot be modified.");
}
@Override
public String getParentIdentifier() {
return null;
}
@Override
public void setParentIdentifier(String parentIdentifier) {
throw new UnsupportedOperationException("The root connection group cannot be modified.");
}
@Override
public Type getType() {
return ConnectionGroup.Type.ORGANIZATIONAL;
}
@Override
public void setType(Type type) {
throw new UnsupportedOperationException("The root connection group cannot be modified.");
}
@Override
public Set<String> getConnectionIdentifiers() throws GuacamoleException {
return connectionService.getIdentifiersWithin(currentUser, null);
}
@Override
public Set<String> getConnectionGroupIdentifiers()
throws GuacamoleException {
return connectionGroupService.getIdentifiersWithin(currentUser, null);
}
@Override
public String getIdentifier() {
return IDENTIFIER;
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("The root connection group cannot be modified.");
}
@Override
public GuacamoleSocket connect(GuacamoleClientInformation info)
throws GuacamoleException {
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public int getActiveConnections() {
return 0;
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* Classes related to connection groups.
*/
package org.glyptodon.guacamole.auth.jdbc.connectiongroup;

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2013 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.
*/
/**
* The base JDBC authentication provider. This authentication provider serves
* as a basis for other JDBC authentication provider implementations which are
* driven by relatively-common schemas. The only difference between such
* implementations are maintained within database-specific MyBatis mappings.
*/
package org.glyptodon.guacamole.auth.jdbc;

View File

@@ -0,0 +1,120 @@
/*
* 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.permission;
import org.glyptodon.guacamole.auth.jdbc.user.MySQLUser;
import com.google.inject.Inject;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
/**
* A database implementation of SystemPermissionSet which uses an injected
* service to query and manipulate the system permissions associated with a
* particular user.
*
* @author Michael Jumper
*/
public class MySQLSystemPermissionSet implements SystemPermissionSet {
/**
* The user that queried this permission set. Access is based on his/her
* permission settings.
*/
private AuthenticatedUser currentUser;
/**
* The user associated with this permission set. Each of the permissions in
* this permission set is granted to this user.
*/
private MySQLUser user;
/**
* Service for reading and manipulating system permissions.
*/
@Inject
private SystemPermissionService systemPermissionService;
/**
* Creates a new MySQLSystemPermissionSet. The resulting permission set
* must still be initialized by a call to init(), or the information
* necessary to read and modify this set will be missing.
*/
public MySQLSystemPermissionSet() {
}
/**
* Initializes this permission set with the current user and the user
* to whom the permissions in this set are granted.
*
* @param currentUser
* The user who queried this permission set, and whose permissions
* dictate the access level of all operations performed on this set.
*
* @param user
* The user to whom the permissions in this set are granted.
*/
public void init(AuthenticatedUser currentUser, MySQLUser user) {
this.currentUser = currentUser;
this.user = user;
}
@Override
public Set<SystemPermission> getPermissions() throws GuacamoleException {
return systemPermissionService.retrievePermissions(currentUser, user);
}
@Override
public boolean hasPermission(SystemPermission.Type permission)
throws GuacamoleException {
return systemPermissionService.retrievePermission(currentUser, user, permission) != null;
}
@Override
public void addPermission(SystemPermission.Type permission)
throws GuacamoleException {
addPermissions(Collections.singleton(new SystemPermission(permission)));
}
@Override
public void removePermission(SystemPermission.Type permission)
throws GuacamoleException {
removePermissions(Collections.singleton(new SystemPermission(permission)));
}
@Override
public void addPermissions(Set<SystemPermission> permissions)
throws GuacamoleException {
systemPermissionService.createPermissions(currentUser, user, permissions);
}
@Override
public void removePermissions(Set<SystemPermission> permissions)
throws GuacamoleException {
systemPermissionService.deletePermissions(currentUser, user, permissions);
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.permission;
/**
* Mapper for object-related permissions.
*
* @author Michael Jumper
*/
public interface ObjectPermissionMapper extends PermissionMapper<ObjectPermissionModel> {
}

View File

@@ -0,0 +1,91 @@
/*
* 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.permission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
/**
* Object representation of an object-related Guacamole permission, as
* represented in the database.
*
* @author Michael Jumper
*/
public class ObjectPermissionModel extends PermissionModel<ObjectPermission.Type> {
/**
* The database ID of the object affected by this permission.
*/
private Integer affectedID;
/**
* The unique identifier of the object affected by this permission.
*/
private String affectedIdentifier;
/**
* Creates a new, empty object permission.
*/
public ObjectPermissionModel() {
}
/**
* Returns the database ID of the object affected by this permission.
*
* @return
* The database ID of the object affected by this permission.
*/
public Integer getAffectedID() {
return affectedID;
}
/**
* Sets the database ID of the object affected by this permission.
*
* @param affectedID
* The database ID of the object affected by this permission.
*/
public void setAffectedID(Integer affectedID) {
this.affectedID = affectedID;
}
/**
* Returns the unique identifier of the object affected by this permission.
*
* @return
* The unique identifier of the object affected by this permission.
*/
public String getAffectedIdentifier() {
return affectedIdentifier;
}
/**
* Sets the unique identifier of the object affected by this permission.
*
* @param affectedIdentifier
* The unique identifier of the object affected by this permission.
*/
public void setAffectedIdentifier(String affectedIdentifier) {
this.affectedIdentifier = affectedIdentifier;
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2013 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.permission;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.user.MySQLUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* deleting object permissions. This service will automatically enforce the
* permissions of the current user.
*
* @author Michael Jumper
* @param <ModelType>
* The underlying model object used to represent PermissionType in the
* database.
*/
public abstract class ObjectPermissionService<ModelType>
extends PermissionService<ObjectPermissionSet, ObjectPermission, ModelType> {
/**
* Returns the permission set associated with the given user and related
* to the type of objects affected the permissions handled by this
* permission service.
*
* @param user
* The user whose permissions are being retrieved.
*
* @return
* A permission set which contains the permissions associated with the
* given user and related to the type of objects handled by this
* directory object service.
*
* @throws GuacamoleException
* If permission to read the user's permissions is denied.
*/
protected abstract ObjectPermissionSet getAffectedPermissionSet(AuthenticatedUser user)
throws GuacamoleException;
/**
* Determines whether the current user has permission to update the given
* target user, adding or removing the given permissions. Such permission
* depends on whether the current user is a system administrator, whether
* they have explicit UPDATE permission on the target user, and whether
* they have explicit ADMINISTER permission on all affected objects.
*
* @param user
* The user who is changing permissions.
*
* @param targetUser
* The user whose permissions are being changed.
*
* @param permissions
* The permissions that are being added or removed from the target
* user.
*
* @return
* true if the user has permission to change the target users
* permissions as specified, false otherwise.
*
* @throws GuacamoleException
* If an error occurs while checking permission status, or if
* permission is denied to read the current user's permissions.
*/
protected boolean canAlterPermissions(AuthenticatedUser user, MySQLUser targetUser,
Collection<ObjectPermission> permissions)
throws GuacamoleException {
// A system adminstrator can do anything
if (user.getUser().isAdministrator())
return true;
// Verify user has update permission on the target user
ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions();
if (!userPermissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetUser.getIdentifier()))
return false;
// Produce collection of affected identifiers
Collection<String> affectedIdentifiers = new HashSet(permissions.size());
for (ObjectPermission permission : permissions)
affectedIdentifiers.add(permission.getObjectIdentifier());
// Determine subset of affected identifiers that we have admin access to
ObjectPermissionSet affectedPermissionSet = getAffectedPermissionSet(user);
Collection<String> allowedSubset = affectedPermissionSet.getAccessibleObjects(
Collections.singleton(ObjectPermission.Type.ADMINISTER),
affectedIdentifiers
);
// The permissions can be altered if and only if the set of objects we
// are allowed to administer is equal to the set of objects we will be
// affecting.
return affectedIdentifiers.size() == allowedSubset.size();
}
@Override
public void createPermissions(AuthenticatedUser user, MySQLUser targetUser,
Collection<ObjectPermission> permissions)
throws GuacamoleException {
// Create permissions only if user has permission to do so
if (canAlterPermissions(user, targetUser, permissions)) {
Collection<ModelType> models = getModelInstances(targetUser, permissions);
getPermissionMapper().insert(models);
return;
}
// User lacks permission to create object permissions
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public void deletePermissions(AuthenticatedUser user, MySQLUser targetUser,
Collection<ObjectPermission> permissions)
throws GuacamoleException {
// Delete permissions only if user has permission to do so
if (canAlterPermissions(user, targetUser, permissions)) {
Collection<ModelType> models = getModelInstances(targetUser, permissions);
getPermissionMapper().delete(models);
return;
}
// User lacks permission to delete object permissions
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.permission;
import java.util.Collection;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
import org.apache.ibatis.annotations.Param;
/**
* Generic base for mappers which handle permissions.
*
* @author Michael Jumper
* @param <PermissionType>
* The type of permission model object handled by this mapper.
*/
public interface PermissionMapper<PermissionType> {
/**
* Retrieves all permissions associated with the given user.
*
* @param user
* The user to retrieve permissions for.
*
* @return
* All permissions associated with the given user.
*/
Collection<PermissionType> select(@Param("user") UserModel user);
/**
* Inserts the given permissions into the database. If any permissions
* already exist, they will be ignored.
*
* @param permissions
* The permissions to insert.
*
* @return
* The number of rows inserted.
*/
int insert(@Param("permissions") Collection<PermissionType> permissions);
/**
* Deletes the given permissions from the database. If any permissions do
* not exist, they will be ignored.
*
* @param permissions
* The permissions to delete.
*
* @return
* The number of rows deleted.
*/
int delete(@Param("permissions") Collection<PermissionType> permissions);
}

View File

@@ -0,0 +1,110 @@
/*
* 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.permission;
/**
* Generic base permission model which grants a permission of a particular type
* to a specific user.
*
* @author Michael Jumper
* @param <PermissionType>
* The type of permissions allowed within this model.
*/
public abstract class PermissionModel<PermissionType> {
/**
* The database ID of the user to whom this permission is granted.
*/
private Integer userID;
/**
* The username of the user to whom this permission is granted.
*/
private String username;
/**
* The type of action granted by this permission.
*/
private PermissionType type;
/**
* Returns the database ID of the user to whom this permission is granted.
*
* @return
* The database ID of the user to whom this permission is granted.
*/
public Integer getUserID() {
return userID;
}
/**
* Sets the database ID of the user to whom this permission is granted.
*
* @param userID
* The database ID of the user to whom this permission is granted.
*/
public void setUserID(Integer userID) {
this.userID = userID;
}
/**
* Returns the username of the user to whom this permission is granted.
*
* @return
* The username of the user to whom this permission is granted.
*/
public String getUsername() {
return username;
}
/**
* Sets the username of the user to whom this permission is granted.
*
* @param username
* The username of the user to whom this permission is granted.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Returns the type of action granted by this permission.
*
* @return
* The type of action granted by this permission.
*/
public PermissionType getType() {
return type;
}
/**
* Sets the type of action granted by this permission.
*
* @param type
* The type of action granted by this permission.
*/
public void setType(PermissionType type) {
this.type = type;
}
}

View File

@@ -0,0 +1,238 @@
/*
* Copyright (C) 2013 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.permission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.user.MySQLUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.auth.permission.Permission;
import org.glyptodon.guacamole.net.auth.permission.PermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* deleting permissions, and for obtaining the permission sets that contain
* these permissions. This service will automatically enforce the permissions
* of the current user.
*
* @author Michael Jumper
* @param <PermissionSetType>
* The type of permission sets this service provides access to.
*
* @param <PermissionType>
* The type of permission this service provides access to.
*
* @param <ModelType>
* The underlying model object used to represent PermissionType in the
* database.
*/
public abstract class PermissionService<PermissionSetType extends PermissionSet<PermissionType>,
PermissionType extends Permission, ModelType> {
/**
* Returns an instance of a mapper for the type of permission used by this
* service.
*
* @return
* A mapper which provides access to the model objects associated with
* the permissions used by this service.
*/
protected abstract PermissionMapper<ModelType> getPermissionMapper();
/**
* Returns an instance of a permission which is based on the given model
* object.
*
* @param model
* The model object to use to produce the returned permission.
*
* @return
* A permission which is based on the given model object.
*/
protected abstract PermissionType getPermissionInstance(ModelType model);
/**
* Returns a collection of permissions which are based on the models in
* the given collection.
*
* @param models
* The model objects to use to produce the permissions within the
* returned set.
*
* @return
* A set of permissions which are based on the models in the given
* collection.
*/
protected Set<PermissionType> getPermissionInstances(Collection<ModelType> models) {
// Create new collection of permissions by manually converting each model
Set<PermissionType> permissions = new HashSet<PermissionType>(models.size());
for (ModelType model : models)
permissions.add(getPermissionInstance(model));
return permissions;
}
/**
* Returns an instance of a model object which is based on the given
* permission and target user.
*
* @param targetUser
* The user to whom this permission is granted.
*
* @param permission
* The permission to use to produce the returned model object.
*
* @return
* A model object which is based on the given permission and target
* user.
*/
protected abstract ModelType getModelInstance(MySQLUser targetUser,
PermissionType permission);
/**
* Returns a collection of model objects which are based on the given
* permissions and target user.
*
* @param targetUser
* The user to whom this permission is granted.
*
* @param permissions
* The permissions to use to produce the returned model objects.
*
* @return
* A collection of model objects which are based on the given
* permissions and target user.
*/
protected Collection<ModelType> getModelInstances(MySQLUser targetUser,
Collection<PermissionType> permissions) {
// Create new collection of models by manually converting each permission
Collection<ModelType> models = new ArrayList<ModelType>(permissions.size());
for (PermissionType permission : permissions)
models.add(getModelInstance(targetUser, permission));
return models;
}
/**
* Returns a permission set that can be used to retrieve and manipulate the
* permissions of the given user.
*
* @param user
* The user who will be retrieving or manipulating permissions through
* the returned permission set.
*
* @param targetUser
* The user to whom the permissions in the returned permission set are
* granted.
*
* @return
* A permission set that contains all permissions associated with the
* given user, and can be used to manipulate that user's permissions.
*
* @throws GuacamoleException
* If an error occurs while retrieving the permissions of the given
* user, or if permission to retrieve the permissions of the given
* user is denied.
*/
public abstract PermissionSetType getPermissionSet(AuthenticatedUser user,
MySQLUser targetUser) throws GuacamoleException;
/**
* Retrieves all permissions associated with the given user.
*
* @param user
* The user retrieving the permissions.
*
* @param targetUser
* The user associated with the permissions to be retrieved.
*
* @return
* The permissions associated with the given user.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested permissions.
*/
public Set<PermissionType> retrievePermissions(AuthenticatedUser user,
MySQLUser targetUser) throws GuacamoleException {
// Only an admin can read permissions that aren't his own
if (user.getUser().getIdentifier().equals(targetUser.getIdentifier())
|| user.getUser().isAdministrator())
return getPermissionInstances(getPermissionMapper().select(targetUser.getModel()));
// User cannot read this user's permissions
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Creates the given permissions within the database. If any permissions
* already exist, they will be ignored.
*
* @param user
* The user creating the permissions.
*
* @param targetUser
* The user associated with the permissions to be created.
*
* @param permissions
* The permissions to create.
*
* @throws GuacamoleException
* If the user lacks permission to create the permissions, or an error
* occurs while creating the permissions.
*/
public abstract void createPermissions(AuthenticatedUser user,
MySQLUser targetUser,
Collection<PermissionType> permissions) throws GuacamoleException;
/**
* Deletes the given permissions. If any permissions do not exist, they
* will be ignored.
*
* @param user
* The user deleting the permissions.
*
* @param targetUser
* The user associated with the permissions to be deleted.
*
* @param permissions
* The permissions to delete.
*
* @throws GuacamoleException
* If the user lacks permission to delete the permissions, or an error
* occurs while deleting the permissions.
*/
public abstract void deletePermissions(AuthenticatedUser user,
MySQLUser targetUser,
Collection<PermissionType> permissions) throws GuacamoleException;
}

View File

@@ -0,0 +1,53 @@
/*
* 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.permission;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
import org.apache.ibatis.annotations.Param;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
/**
* Mapper for system-level permissions.
*
* @author Michael Jumper
*/
public interface SystemPermissionMapper extends PermissionMapper<SystemPermissionModel> {
/**
* Retrieve the permission of the given type associated with the given
* user, if it exists. If no such permission exists, null is returned.
*
* @param user
* The user to retrieve permissions for.
*
* @param type
* The type of permission to return.
*
* @return
* The requested permission, or null if no such permission is granted
* to the given user.
*/
SystemPermissionModel selectOne(@Param("user") UserModel user,
@Param("type") SystemPermission.Type type);
}

View File

@@ -0,0 +1,41 @@
/*
* 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.permission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
/**
* Object representation of an system-level Guacamole permission, as
* represented in the database.
*
* @author Michael Jumper
*/
public class SystemPermissionModel extends PermissionModel<SystemPermission.Type> {
/**
* Creates a new, empty System permission.
*/
public SystemPermissionModel() {
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2013 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.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.user.MySQLUser;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
/**
* Service which provides convenience methods for creating, retrieving, and
* deleting system permissions. This service will automatically enforce
* the permissions of the current user.
*
* @author Michael Jumper
*/
public class SystemPermissionService
extends PermissionService<MySQLSystemPermissionSet, SystemPermission, SystemPermissionModel> {
/**
* Mapper for system-level permissions.
*/
@Inject
private SystemPermissionMapper systemPermissionMapper;
/**
* Provider for creating system permission sets.
*/
@Inject
private Provider<MySQLSystemPermissionSet> systemPermissionSetProvider;
@Override
protected SystemPermissionMapper getPermissionMapper() {
return systemPermissionMapper;
}
@Override
protected SystemPermission getPermissionInstance(SystemPermissionModel model) {
return new SystemPermission(model.getType());
}
@Override
protected SystemPermissionModel getModelInstance(final MySQLUser targetUser,
final SystemPermission permission) {
SystemPermissionModel model = new SystemPermissionModel();
// Populate model object with data from user and permission
model.setUserID(targetUser.getModel().getObjectID());
model.setUsername(targetUser.getModel().getIdentifier());
model.setType(permission.getType());
return model;
}
@Override
public MySQLSystemPermissionSet getPermissionSet(AuthenticatedUser user,
MySQLUser targetUser) throws GuacamoleException {
// Create permission set for requested user
MySQLSystemPermissionSet permissionSet = systemPermissionSetProvider.get();
permissionSet.init(user, targetUser);
return permissionSet;
}
@Override
public void createPermissions(AuthenticatedUser user, MySQLUser targetUser,
Collection<SystemPermission> permissions) throws GuacamoleException {
// Only an admin can create system permissions
if (user.getUser().isAdministrator()) {
Collection<SystemPermissionModel> models = getModelInstances(targetUser, permissions);
systemPermissionMapper.insert(models);
return;
}
// User lacks permission to create system permissions
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public void deletePermissions(AuthenticatedUser user, MySQLUser targetUser,
Collection<SystemPermission> permissions) throws GuacamoleException {
// Only an admin can delete system permissions
if (user.getUser().isAdministrator()) {
Collection<SystemPermissionModel> models = getModelInstances(targetUser, permissions);
systemPermissionMapper.delete(models);
return;
}
// User lacks permission to delete system permissions
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Retrieves the permission of the given type associated with the given
* user, if it exists. If no such permission exists, null is returned.
*
* @param user
* The user retrieving the permission.
*
* @param targetUser
* The user associated with the permission to be retrieved.
*
* @param type
* The type of permission to retrieve.
*
* @return
* The permission of the given type associated with the given user, or
* null if no such permission exists.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested permission.
*/
public SystemPermission retrievePermission(AuthenticatedUser user,
MySQLUser targetUser, SystemPermission.Type type) throws GuacamoleException {
// Only an admin can read permissions that aren't his own
if (user.getUser().getIdentifier().equals(targetUser.getIdentifier())
|| user.getUser().isAdministrator()) {
// Read permission from database, return null if not found
SystemPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type);
if (model == null)
return null;
return getPermissionInstance(model);
}
// User cannot read this user's permissions
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* Classes related to object- and system-level permissions.
*/
package org.glyptodon.guacamole.auth.jdbc.permission;

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2013 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.security;
/**
* A service to perform password encryption and checking.
* @author James Muehlner
*/
public interface PasswordEncryptionService {
/**
* Creates a password hash based on the provided username, password, and
* salt.
*
* @param password The password to hash.
* @param salt The salt to use when hashing the password.
* @return The generated password hash.
*/
public byte[] createPasswordHash(String password, byte[] salt);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2013 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.security;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
/**
* Provides a SHA-256 based implementation of the password encryption functionality.
* @author James Muehlner
*/
public class SHA256PasswordEncryptionService implements PasswordEncryptionService {
@Override
public byte[] createPasswordHash(String password, byte[] salt) {
try {
// Build salted password
StringBuilder builder = new StringBuilder();
builder.append(password);
builder.append(DatatypeConverter.printHexBinary(salt));
// Hash UTF-8 bytes of salted password
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(builder.toString().getBytes("UTF-8"));
return md.digest();
}
// Should not happen
catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
// Should not happen
catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2013 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.security;
/**
* A service to generate password salts.
* @author James Muehlner
*/
public interface SaltService {
/**
* Generates a new String that can be used as a password salt.
* @return a new salt for password encryption.
*/
public byte[] generateSalt();
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2013 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.security;
import java.security.SecureRandom;
/**
* Generates password salts via SecureRandom.
* @author James Muehlner
*/
public class SecureRandomSaltService implements SaltService {
/**
* Instance of SecureRandom for generating the salt.
*/
private SecureRandom secureRandom = new SecureRandom();
@Override
public byte[] generateSalt() {
byte[] salt = new byte[32];
secureRandom.nextBytes(salt);
return salt;
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* Classes related to hashing or encryption.
*/
package org.glyptodon.guacamole.auth.jdbc.security;

View File

@@ -0,0 +1,288 @@
/*
* 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.socket;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.connection.MySQLConnection;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLConnectionGroup;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordMapper;
import org.glyptodon.guacamole.auth.jdbc.connection.ParameterMapper;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionModel;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordModel;
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.environment.Environment;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.InetGuacamoleSocket;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
import org.glyptodon.guacamole.protocol.ConfiguredGuacamoleSocket;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
import org.glyptodon.guacamole.token.StandardTokens;
import org.glyptodon.guacamole.token.TokenFilter;
/**
* Base implementation of the GuacamoleSocketService, handling retrieval of
* connection parameters, load balancing, and connection usage counts. The
* implementation of concurrency rules is up to policy-specific subclasses.
*
* @author Michael Jumper
*/
public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketService {
/**
* The environment of the Guacamole server.
*/
@Inject
private Environment environment;
/**
* Mapper for accessing connection parameters.
*/
@Inject
private ParameterMapper parameterMapper;
/**
* Mapper for accessing connection history.
*/
@Inject
private ConnectionRecordMapper connectionRecordMapper;
/**
* The current number of concurrent uses of the connection having a given
* identifier.
*/
private final Map<String, LinkedList<ConnectionRecord>> activeConnections =
new HashMap<String, LinkedList<ConnectionRecord>>();
/**
* Atomically increments the current usage count for the given connection.
*
* @param connection
* The connection which is being used.
*/
private void addActiveConnection(Connection connection, ConnectionRecord record) {
synchronized (activeConnections) {
String identifier = connection.getIdentifier();
// Get set of active connection records, creating if necessary
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
if (connections == null) {
connections = new LinkedList<ConnectionRecord>();
activeConnections.put(identifier, connections);
}
// Add active connection
connections.addFirst(record);
}
}
/**
* Atomically decrements the current usage count for the given connection.
* If a combination of incrementUsage() and decrementUsage() calls result
* in the usage counter being reduced to zero, it is guaranteed that one
* of those decrementUsage() calls will remove the value from the map.
*
* @param connection
* The connection which is no longer being used.
*/
private void removeActiveConnection(Connection connection, ConnectionRecord record) {
synchronized (activeConnections) {
String identifier = connection.getIdentifier();
// Get set of active connection records
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
assert(connections != null);
// Remove old record
connections.remove(record);
// If now empty, clean the tracking entry
if (connections.isEmpty())
activeConnections.remove(identifier);
}
}
/**
* Acquires possibly-exclusive access to the given connection on behalf of
* the given user. If access is denied for any reason, an exception is
* thrown.
*
* @param user
* The user acquiring access.
*
* @param connection
* The connection being accessed.
*
* @throws GuacamoleException
* If access is denied to the given user for any reason.
*/
protected abstract void acquire(AuthenticatedUser user,
MySQLConnection connection) throws GuacamoleException;
/**
* Releases possibly-exclusive access to the given connection on behalf of
* the given user. If the given user did not already have access, the
* behavior of this function is undefined.
*
* @param user
* The user releasing access.
*
* @param connection
* The connection being released.
*/
protected abstract void release(AuthenticatedUser user,
MySQLConnection connection);
@Override
public GuacamoleSocket getGuacamoleSocket(final AuthenticatedUser user,
final MySQLConnection connection, GuacamoleClientInformation info)
throws GuacamoleException {
// Create record for active connection
final ActiveConnectionRecord activeConnection = new ActiveConnectionRecord(user);
// Generate configuration from available data
GuacamoleConfiguration config = new GuacamoleConfiguration();
// Set protocol from connection
ConnectionModel model = connection.getModel();
config.setProtocol(model.getProtocol());
// Set parameters from associated data
Collection<ParameterModel> parameters = parameterMapper.select(connection.getIdentifier());
for (ParameterModel parameter : parameters)
config.setParameter(parameter.getName(), parameter.getValue());
// Build token filter containing credential tokens
TokenFilter tokenFilter = new TokenFilter();
StandardTokens.addStandardTokens(tokenFilter, user.getCredentials());
// Filter the configuration
tokenFilter.filterValues(config.getParameters());
// Return new socket
try {
// Atomically gain access to connection
acquire(user, connection);
addActiveConnection(connection, activeConnection);
// Return newly-reserved connection
return new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(
environment.getRequiredProperty(Environment.GUACD_HOSTNAME),
environment.getRequiredProperty(Environment.GUACD_PORT)
),
config
) {
@Override
public void close() throws GuacamoleException {
// Attempt to close connection
super.close();
// Release connection upon close
removeActiveConnection(connection, activeConnection);
release(user, connection);
UserModel userModel = user.getUser().getModel();
ConnectionRecordModel recordModel = new ConnectionRecordModel();
// Copy user information and timestamps into new record
recordModel.setUserID(userModel.getObjectID());
recordModel.setUsername(userModel.getIdentifier());
recordModel.setConnectionIdentifier(connection.getIdentifier());
recordModel.setStartDate(activeConnection.getStartDate());
recordModel.setEndDate(new Date());
// Insert connection record
connectionRecordMapper.insert(recordModel);
}
};
}
// Release connection in case of error
catch (GuacamoleException e) {
// Atomically release access to connection
removeActiveConnection(connection, activeConnection);
release(user, connection);
throw e;
}
}
@Override
public List<ConnectionRecord> getActiveConnections(Connection connection) {
synchronized (activeConnections) {
String identifier = connection.getIdentifier();
// Get set of active connection records
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
if (connections != null)
return Collections.unmodifiableList(connections);
return Collections.EMPTY_LIST;
}
}
@Override
public GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
MySQLConnectionGroup connectionGroup,
GuacamoleClientInformation info) throws GuacamoleException {
// STUB
throw new UnsupportedOperationException("STUB");
}
@Override
public List<ConnectionRecord> getActiveConnections(ConnectionGroup connectionGroup) {
// STUB
return Collections.EMPTY_LIST;
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.socket;
import java.util.Date;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
/**
* A connection record implementation that describes an active connection. As
* the associated connection has not yet ended, getEndDate() will always return
* null, and isActive() will always return true. The associated start date will
* be the time of this objects creation.
*
* @author Michael Jumper
*/
public class ActiveConnectionRecord implements ConnectionRecord {
/**
* The user that connected to the connection associated with this connection
* record.
*/
private final AuthenticatedUser user;
/**
* The time this connection record was created.
*/
private final Date startDate = new Date();
/**
* Creates a new connection record associated with the given user. The
* start date of this connection record will be the time of its creation.
*
* @param user
* The user that connected to the connection associated with this
* connection record.
*/
public ActiveConnectionRecord(AuthenticatedUser user) {
this.user = user;
}
@Override
public Date getStartDate() {
return startDate;
}
@Override
public Date getEndDate() {
// Active connections have not yet ended
return null;
}
@Override
public String getUsername() {
return user.getUser().getIdentifier();
}
@Override
public boolean isActive() {
// Active connections are active by definition
return true;
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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.socket;
import java.util.List;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.connection.MySQLConnection;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLConnectionGroup;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.GuacamoleSocket;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
/**
* Service which creates pre-configured GuacamoleSocket instances for
* connections and balancing groups, applying concurrent usage rules.
*
* @author Michael Jumper
*/
public interface GuacamoleSocketService {
/**
* Creates a socket for the given user which connects to the given
* connection. The given client information will be passed to guacd when
* the connection is established. This function will apply any concurrent
* usage rules in effect, but will NOT test object- or system-level
* permissions.
*
* @param user
* The user for whom the connection is being established.
*
* @param connection
* The connection the user is connecting to.
*
* @param info
* Information describing the Guacamole client connecting to the given
* connection.
*
* @return
* A new GuacamoleSocket which is configured and connected to the given
* connection.
*
* @throws GuacamoleException
* If the connection cannot be established due to concurrent usage
* rules.
*/
GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
MySQLConnection connection, GuacamoleClientInformation info)
throws GuacamoleException;
/**
* Returns a list containing connection records representing all currently-
* active connections using the given connection. These records will have
* usernames and start dates, but no end date.
*
* @param connection
* The connection to check.
*
* @return
* A list containing connection records representing all currently-
* active connections.
*/
public List<ConnectionRecord> getActiveConnections(Connection connection);
/**
* Creates a socket for the given user which connects to the given
* connection group. The given client information will be passed to guacd
* when the connection is established. This function will apply any
* concurrent usage rules in effect, but will NOT test object- or
* system-level permissions.
*
* @param user
* The user for whom the connection is being established.
*
* @param connectionGroup
* The connection group the user is connecting to.
*
* @param info
* Information describing the Guacamole client connecting to the given
* connection group.
*
* @return
* A new GuacamoleSocket which is configured and connected to the given
* connection group.
*
* @throws GuacamoleException
* If the connection cannot be established due to concurrent usage
* rules, or if the connection group is not balancing.
*/
GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
MySQLConnectionGroup connectionGroup,
GuacamoleClientInformation info)
throws GuacamoleException;
/**
* Returns a list containing connection records representing all currently-
* active connections using the given connection group. These records will
* have usernames and start dates, but no end date.
*
* @param connectionGroup
* The connection group to check.
*
* @return
* A list containing connection records representing all currently-
* active connections.
*/
public List<ConnectionRecord> getActiveConnections(ConnectionGroup connectionGroup);
}

View File

@@ -0,0 +1,52 @@
/*
* 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.socket;
import com.google.inject.Singleton;
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
import org.glyptodon.guacamole.auth.jdbc.connection.MySQLConnection;
import org.glyptodon.guacamole.GuacamoleException;
/**
* GuacamoleSocketService implementation which imposes no restrictions
* whatsoever on the number of concurrent or duplicate connections.
*
* @author Michael Jumper
*/
@Singleton
public class UnrestrictedGuacamoleSocketService
extends AbstractGuacamoleSocketService {
@Override
protected void acquire(AuthenticatedUser user, MySQLConnection connection)
throws GuacamoleException {
// Do nothing
}
@Override
protected void release(AuthenticatedUser user, MySQLConnection connection) {
// Do nothing
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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.
*/
/**
* Classes related to obtaining/configuring Guacamole sockets, and restricting
* access to those sockets.
*/
package org.glyptodon.guacamole.auth.jdbc.socket;

View File

@@ -0,0 +1,79 @@
/*
* 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.user;
import org.glyptodon.guacamole.net.auth.Credentials;
/**
* Associates a user with the credentials they used to authenticate.
*
* @author Michael Jumper
*/
public class AuthenticatedUser {
/**
* The user that authenticated.
*/
private final MySQLUser user;
/**
* The credentials given when this user authenticated.
*/
private final Credentials credentials;
/**
* Creates a new AuthenticatedUser associating the given user with their
* corresponding credentials.
*
* @param user
* The user this object should represent.
*
* @param credentials
* The credentials given by the user when they authenticated.
*/
public AuthenticatedUser(MySQLUser user, Credentials credentials) {
this.user = user;
this.credentials = credentials;
}
/**
* Returns the user that authenticated.
*
* @return
* The user that authenticated.
*/
public MySQLUser getUser() {
return user;
}
/**
* Returns the credentials given during authentication by this user.
*
* @return
* The credentials given during authentication by this user.
*/
public Credentials getCredentials() {
return credentials;
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2013 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.user;
import com.google.inject.Inject;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService;
import org.glyptodon.guacamole.auth.jdbc.security.SaltService;
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionService;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
import org.glyptodon.guacamole.net.auth.simple.SimpleObjectPermissionSet;
/**
* A MySQL based implementation of the User object.
* @author James Muehlner
*/
public class MySQLUser extends DirectoryObject<UserModel> implements User {
/**
* Service for hashing passwords.
*/
@Inject
private PasswordEncryptionService encryptionService;
/**
* Service for providing secure, random salts.
*/
@Inject
private SaltService saltService;
/**
* Service for retrieving system permissions.
*/
@Inject
private SystemPermissionService systemPermissionService;
/**
* The plaintext password previously set by a call to setPassword(), if
* any. The password of a user cannot be retrieved once saved into the
* database, so this serves to ensure getPassword() returns a reasonable
* value if setPassword() is called. If no password has been set, or the
* user was retrieved from the database, this will be null.
*/
private String password = null;
/**
* Creates a new, empty MySQLUser.
*/
public MySQLUser() {
}
@Override
public String getPassword() {
return password;
}
@Override
public void setPassword(String password) {
UserModel userModel = getModel();
// Store plaintext password internally
this.password = password;
// If no password provided, clear password salt and hash
if (password == null) {
userModel.setPasswordSalt(null);
userModel.setPasswordHash(null);
}
// Otherwise generate new salt and hash given password using newly-generated salt
else {
byte[] salt = saltService.generateSalt();
byte[] hash = encryptionService.createPasswordHash(password, salt);
// Set stored salt and hash
userModel.setPasswordSalt(salt);
userModel.setPasswordHash(hash);
}
}
/**
* Returns whether this user is a system administrator, and thus is not
* restricted by permissions.
*
* @return
* true if this user is a system administrator, false otherwise.
*
* @throws GuacamoleException
* If an error occurs while determining the user's system administrator
* status.
*/
public boolean isAdministrator() throws GuacamoleException {
SystemPermissionSet systemPermissionSet = getSystemPermissions();
return systemPermissionSet.hasPermission(SystemPermission.Type.ADMINISTER);
}
@Override
public SystemPermissionSet getSystemPermissions()
throws GuacamoleException {
return systemPermissionService.getPermissionSet(getCurrentUser(), this);
}
@Override
public ObjectPermissionSet getConnectionPermissions()
throws GuacamoleException {
// STUB
return new SimpleObjectPermissionSet();
}
@Override
public ObjectPermissionSet getConnectionGroupPermissions()
throws GuacamoleException {
// STUB
return new SimpleObjectPermissionSet();
}
@Override
public ObjectPermissionSet getUserPermissions()
throws GuacamoleException {
// STUB
return new SimpleObjectPermissionSet();
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2013 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.user;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.MySQLRootConnectionGroup;
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupDirectory;
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionDirectory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Connection;
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.UserContext;
/**
* The MySQL representation of a UserContext.
* @author James Muehlner
*/
public class MySQLUserContext implements UserContext {
/**
* The the user owning this context.
*/
private AuthenticatedUser currentUser;
/**
* User directory restricted by the permissions of the user associated
* with this context.
*/
@Inject
private UserDirectory userDirectory;
/**
* Connection directory restricted by the permissions of the user
* associated with this context.
*/
@Inject
private ConnectionDirectory connectionDirectory;
/**
* Connection group directory restricted by the permissions of the user
* associated with this context.
*/
@Inject
private ConnectionGroupDirectory connectionGroupDirectory;
/**
* Provider for creating the root group.
*/
@Inject
private Provider<MySQLRootConnectionGroup> rootGroupProvider;
/**
* Initializes the user and directories associated with this context.
*
* @param currentUser
* The user owning this context.
*/
public void init(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
// Init directories
userDirectory.init(currentUser);
connectionDirectory.init(currentUser);
connectionGroupDirectory.init(currentUser);
}
@Override
public User self() {
return currentUser.getUser();
}
@Override
public Directory<User> getUserDirectory() throws GuacamoleException {
return userDirectory;
}
@Override
public Directory<Connection> getConnectionDirectory() throws GuacamoleException {
return connectionDirectory;
}
@Override
public Directory<ConnectionGroup> getConnectionGroupDirectory() throws GuacamoleException {
return connectionGroupDirectory;
}
@Override
public ConnectionGroup getRootConnectionGroup() throws GuacamoleException {
// Build and return a root group for the current user
MySQLRootConnectionGroup rootGroup = rootGroupProvider.get();
rootGroup.init(currentUser);
return rootGroup;
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.user;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Credentials;
import org.glyptodon.guacamole.net.auth.UserContext;
/**
* Service which creates new UserContext instances for valid users based on
* credentials.
*
* @author Michael Jumper
*/
public class UserContextService {
/**
* Service for accessing users.
*/
@Inject
private UserService userService;
/**
* Provider for retrieving UserContext instances.
*/
@Inject
private Provider<MySQLUserContext> userContextProvider;
/**
* Authenticates the user having the given credentials, returning a new
* UserContext instance if the credentials are valid.
*
* @param credentials
* The credentials to use to produce the UserContext.
*
* @return
* A new UserContext instance for the user identified by the given
* credentials, or null if the credentials are not valid.
*
* @throws GuacamoleException
* If an error occurs during authentication.
*/
public UserContext getUserContext(Credentials credentials)
throws GuacamoleException {
// Authenticate user
MySQLUser user = userService.retrieveUser(credentials);
if (user != null) {
// Upon successful authentication, return new user context
MySQLUserContext context = userContextProvider.get();
context.init(user.getCurrentUser());
return context;
}
// Otherwise, unauthorized
return null;
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2013 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.user;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.Directory;
import org.glyptodon.guacamole.net.auth.User;
import org.mybatis.guice.transactional.Transactional;
/**
* A MySQL based implementation of the User Directory.
*
* @author James Muehlner
* @author Michael Jumper
*/
public class UserDirectory implements Directory<User> {
/**
* The user this user directory belongs to. Access is based on his/her
* permission settings.
*/
private AuthenticatedUser currentUser;
/**
* Service for managing user objects.
*/
@Inject
private UserService userService;
/**
* Set the user for this directory.
*
* @param currentUser
* The user whose permissions define the visibility of other users in
* this directory.
*/
public void init(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
@Override
public User get(String identifier) throws GuacamoleException {
return userService.retrieveObject(currentUser, identifier);
}
@Override
@Transactional
public Collection<User> getAll(Collection<String> identifiers) throws GuacamoleException {
Collection<MySQLUser> objects = userService.retrieveObjects(currentUser, identifiers);
return Collections.<User>unmodifiableCollection(objects);
}
@Override
@Transactional
public Set<String> getIdentifiers() throws GuacamoleException {
return userService.getIdentifiers(currentUser);
}
@Override
@Transactional
public void add(User object) throws GuacamoleException {
userService.createObject(currentUser, object);
}
@Override
@Transactional
public void update(User object) throws GuacamoleException {
MySQLUser user = (MySQLUser) object;
userService.updateObject(currentUser, user);
}
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
userService.deleteObject(currentUser, identifier);
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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.user;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for user objects.
*
* @author Michael Jumper
*/
public interface UserMapper extends DirectoryObjectMapper<UserModel> {
/**
* Returns the user having the given username and password, if any. If no
* such user exists, null is returned.
*
* @param username
* The username of the user to return.
*
* @param password
* The password of the user to return.
*
* @return
* The user having the given username and password, or null if no such
* user exists.
*/
UserModel selectByCredentials(@Param("username") String username,
@Param("password") String password);
}

View File

@@ -0,0 +1,100 @@
/*
* 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.user;
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
/**
* Object representation of a Guacamole user, as represented in the database.
*
* @author Michael Jumper
*/
public class UserModel extends ObjectModel {
/**
* The SHA-256 hash of the password and salt.
*/
private byte[] passwordHash;
/**
* The 32-byte random binary password salt that was appended to the
* password prior to hashing.
*/
private byte[] passwordSalt;
/**
* Creates a new, empty user.
*/
public UserModel() {
}
/**
* Returns the hash of this user's password and password salt. This may be
* null if the user was not retrieved from the database, and setPassword()
* has not yet been called.
*
* @return
* The hash of this user's password and password salt.
*/
public byte[] getPasswordHash() {
return passwordHash;
}
/**
* Sets the hash of this user's password and password salt. This is
* normally only set upon retrieval from the database, or through a call
* to the higher-level setPassword() function.
*
* @param passwordHash
* The hash of this user's password and password salt.
*/
public void setPasswordHash(byte[] passwordHash) {
this.passwordHash = passwordHash;
}
/**
* Returns the random salt that was used when generating this user's
* password hash. This may be null if the user was not retrieved from the
* database, and setPassword() has not yet been called.
*
* @return
* The random salt that was used when generating this user's password
* hash.
*/
public byte[] getPasswordSalt() {
return passwordSalt;
}
/**
* Sets the random salt that was used when generating this user's password
* hash. This is normally only set upon retrieval from the database, or
* through a call to the higher-level setPassword() function.
*
* @param passwordSalt
* The random salt used when generating this user's password hash.
*/
public void setPasswordSalt(byte[] passwordSalt) {
this.passwordSalt = passwordSalt;
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2013 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.user;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
import java.util.Collections;
import org.glyptodon.guacamole.net.auth.Credentials;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating users.
*
* @author Michael Jumper, James Muehlner
*/
public class UserService extends DirectoryObjectService<MySQLUser, User, UserModel> {
/**
* Mapper for accessing users.
*/
@Inject
private UserMapper userMapper;
/**
* Provider for creating users.
*/
@Inject
private Provider<MySQLUser> mySQLUserProvider;
@Override
protected DirectoryObjectMapper<UserModel> getObjectMapper() {
return userMapper;
}
@Override
protected MySQLUser getObjectInstance(AuthenticatedUser currentUser,
UserModel model) {
MySQLUser user = mySQLUserProvider.get();
user.init(currentUser, model);
return user;
}
@Override
protected UserModel getModelInstance(AuthenticatedUser currentUser,
final User object) {
// Create new MySQLUser backed by blank model
UserModel model = new UserModel();
MySQLUser user = getObjectInstance(currentUser, model);
// Set model contents through MySQLUser, copying the provided user
user.setIdentifier(object.getIdentifier());
user.setPassword(object.getPassword());
return model;
}
@Override
protected boolean hasCreatePermission(AuthenticatedUser user)
throws GuacamoleException {
// Return whether user has explicit user creation permission
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_USER);
}
@Override
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to users
return user.getUser().getUserPermissions();
}
@Override
protected void validateNewObject(AuthenticatedUser user, User object)
throws GuacamoleException {
// Username must not be blank
if (object.getIdentifier().trim().isEmpty())
throw new GuacamoleClientException("The username must not be blank.");
// Do not create duplicate users
Collection<UserModel> existing = userMapper.select(Collections.singleton(object.getIdentifier()));
if (!existing.isEmpty())
throw new GuacamoleClientException("User \"" + object.getIdentifier() + "\" already exists.");
}
@Override
protected void validateExistingObject(AuthenticatedUser user,
MySQLUser object) throws GuacamoleException {
// Username must not be blank
if (object.getIdentifier().trim().isEmpty())
throw new GuacamoleClientException("The username must not be blank.");
// Check whether such a user is already present
MySQLUser existing = retrieveObject(user, object.getIdentifier());
if (existing != null) {
UserModel existingModel = existing.getModel();
UserModel updatedModel = object.getModel();
// Do not rename to existing user
if (!existingModel.getObjectID().equals(updatedModel.getObjectID()))
throw new GuacamoleClientException("User \"" + object.getIdentifier() + "\" already exists.");
}
}
/**
* Retrieves the user corresponding to the given credentials from the
* database.
*
* @param credentials The credentials to use when locating the user.
* @return The existing MySQLUser object if the credentials given are
* valid, null otherwise.
*/
public MySQLUser retrieveUser(Credentials credentials) {
// Get username and password
String username = credentials.getUsername();
String password = credentials.getPassword();
// Retrieve user model, if the user exists
UserModel userModel = userMapper.selectByCredentials(username, password);
if (userModel == null)
return null;
// Return corresponding user, set up cyclic reference
MySQLUser user = getObjectInstance(null, userModel);
user.setCurrentUser(new AuthenticatedUser(user, credentials));
return user;
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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.
*/
/**
* Classes related to Guacamole users.
*/
package org.glyptodon.guacamole.auth.jdbc.user;