mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
Merge guacamole-auth-mysql as extension.
This commit is contained in:
2
extensions/guacamole-auth-mysql/.gitignore
vendored
Normal file
2
extensions/guacamole-auth-mysql/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
target/
|
||||||
|
*~
|
171
extensions/guacamole-auth-mysql/README
Normal file
171
extensions/guacamole-auth-mysql/README
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
About this README
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
This README is intended to provide quick and to-the-point documentation for
|
||||||
|
technical users intending to compile parts of Guacamole themselves.
|
||||||
|
|
||||||
|
Distribution-specific packages are available from the files section of the main
|
||||||
|
project page:
|
||||||
|
|
||||||
|
http://sourceforge.net/projects/guacamole/files/
|
||||||
|
|
||||||
|
Distribution-specific documentation is provided on the Guacamole wiki:
|
||||||
|
|
||||||
|
http://guac-dev.org/
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
What is guacamole-auth-mysql?
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
guacamole-auth-ldap is a Java library for use with the Guacamole web
|
||||||
|
application to provide MySQL based authentication.
|
||||||
|
|
||||||
|
guacamole-auth-mysql provides an authentication provider which can be
|
||||||
|
set in guacamole.properties to allow MySQL authentication of Guacamole
|
||||||
|
users. Additional properties are required to configure the mysql
|
||||||
|
connection parameters.
|
||||||
|
|
||||||
|
A schema file are provided to create the required tables in your
|
||||||
|
mysql database.
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
Compiling and installing guacamole-auth-mysql
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
guacamole-auth-mysql is built using Maven. Building guacamole-auth-mysql
|
||||||
|
compiles all classes and packages them into a redistributable .jar file. This
|
||||||
|
.jar file can be installed in the library directory configured in
|
||||||
|
guacamole.properties such that the authentication provider is available.
|
||||||
|
|
||||||
|
1) Set up a MySQL database with the Guacamole schema.
|
||||||
|
|
||||||
|
When guacamole-auth-mysql is compiling, it needs to generate source
|
||||||
|
based on a database schema. Because the source generator uses a
|
||||||
|
connection to an actual database to do this, you must have a MySQL
|
||||||
|
database running with the Guacamole schema set up.
|
||||||
|
|
||||||
|
First, create a database. For the sake of these instructions, we will
|
||||||
|
call the database "guacamole", and will run all scripts as the root user:
|
||||||
|
|
||||||
|
$ mysql -u root -p
|
||||||
|
Enter password:
|
||||||
|
mysql> CREATE DATABASE guacamole;
|
||||||
|
Query OK, 1 row affected (0.00 sec)
|
||||||
|
|
||||||
|
mysql> exit
|
||||||
|
Bye
|
||||||
|
|
||||||
|
The schema files are in the schema/ subdirectory of the source. If run
|
||||||
|
in order, they will create the schema and a default user:
|
||||||
|
|
||||||
|
$ cat schema/*.sql | mysql -u root -p guacamole
|
||||||
|
|
||||||
|
2) Set up your ~/.m2/settings.xml
|
||||||
|
|
||||||
|
Once the database is set up, Maven will need to have the credentials
|
||||||
|
required to connect to it and query the schema. This information is
|
||||||
|
specified in properties inside your ~/.m2/settings.xml file. If this
|
||||||
|
file does not exist yet, simply create it.
|
||||||
|
|
||||||
|
For ease of compilation, we've included an example settings.xml
|
||||||
|
defining the required properties in doc/example/settings.xml. You can
|
||||||
|
simply copy this file into ~/.m2 and edit as necessary.
|
||||||
|
|
||||||
|
If you wish to write the file yourself, the file should look like this in
|
||||||
|
general:
|
||||||
|
|
||||||
|
<settings>
|
||||||
|
<profiles>
|
||||||
|
...profiles...
|
||||||
|
</profiles>
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
We need to add a profile which defines the required properties by
|
||||||
|
placing a section like the following within the "profiles" section of your
|
||||||
|
settings.xml:
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>guacamole-mybatis</id>
|
||||||
|
<properties>
|
||||||
|
<guacamole.database.catalog>DATABASE</guacamole.database.catalog>
|
||||||
|
<guacamole.database.user>USERNAME</guacamole.database.user>
|
||||||
|
<guacamole.database.password>PASSWORD</guacamole.database.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
Obviously, the DATABASE, USERNAME, and PASSWORD placeholders above must
|
||||||
|
be replaced with the appropriate values for your system.
|
||||||
|
|
||||||
|
Finally, to make the profile available to the build, it must be activated.
|
||||||
|
Place a section like the following at the bottom of your settings.xml,
|
||||||
|
right after the profiles section:
|
||||||
|
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>guacamole-mybatis</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
|
||||||
|
Maven's documentation has more details on writing the settings.xml file
|
||||||
|
if you have different needs or the above directions are not clear.
|
||||||
|
|
||||||
|
3) Run mvn package
|
||||||
|
|
||||||
|
$ mvn package
|
||||||
|
|
||||||
|
Maven will download any needed dependencies for building the .jar file.
|
||||||
|
Once all dependencies have been downloaded, the .jar file will be
|
||||||
|
created in the target/ subdirectory of the current directory.
|
||||||
|
|
||||||
|
If this process fails, check the build errors, and verify that the
|
||||||
|
contents of your settings.xml file is correct.
|
||||||
|
|
||||||
|
4) Extract the .tar.gz file now present in the target/ directory, and
|
||||||
|
place the .jar files in the extracted lib/ subdirectory in the library
|
||||||
|
directory specified in guacamole.properties.
|
||||||
|
|
||||||
|
You will likely need to do this as root.
|
||||||
|
|
||||||
|
If you do not have a library directory configured in your
|
||||||
|
guacamole.properties, you will need to specify one. The directory
|
||||||
|
is specified using the "lib-directory" property.
|
||||||
|
|
||||||
|
5) Set up your MySQL database to authenticate Guacamole users
|
||||||
|
|
||||||
|
A schema file is provided in the schema directory for creating
|
||||||
|
the guacamole authentication tables in your MySQL database.
|
||||||
|
|
||||||
|
Additionally, a script is provided to create a default admin user
|
||||||
|
with username 'guacadmin' and password 'guacadmin'. This user can
|
||||||
|
be used to set up any other connections and users.
|
||||||
|
|
||||||
|
6) Configure guacamole.properties for MySQL
|
||||||
|
|
||||||
|
There are additional properties required by the MySQL JDBC driver
|
||||||
|
which must be added/changed in your guacamole.properties:
|
||||||
|
|
||||||
|
# Configuration for MySQL connection
|
||||||
|
mysql-hostname: mysql.host.name
|
||||||
|
mysql-port: 3306
|
||||||
|
mysql-database: guacamole.database.name
|
||||||
|
mysql-username: user
|
||||||
|
mysql-password: pass
|
||||||
|
|
||||||
|
Optionally, the authentication provider can be configured
|
||||||
|
not to allow multiple users to use the same connection
|
||||||
|
at the same time:
|
||||||
|
|
||||||
|
mysql-disallow-simultaneous-connections: true
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
Reporting problems
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
Please report any bugs encountered by opening a new ticket at the Trac system
|
||||||
|
hosted at:
|
||||||
|
|
||||||
|
http://guac-dev.org/trac/
|
||||||
|
|
21
extensions/guacamole-auth-mysql/doc/example/settings.xml
Normal file
21
extensions/guacamole-auth-mysql/doc/example/settings.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<settings>
|
||||||
|
|
||||||
|
<!-- Profile defining the properties required for a MyBatis build -->
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>guacamole-mybatis</id>
|
||||||
|
<properties>
|
||||||
|
<guacamole.database.catalog>SCHEMA</guacamole.database.catalog>
|
||||||
|
<guacamole.database.schema>DATABASE</guacamole.database.schema>
|
||||||
|
<guacamole.database.user>USER</guacamole.database.user>
|
||||||
|
<guacamole.database.password>PASS</guacamole.database.password>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<!-- Activate by default -->
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>guacamole-mybatis</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
|
||||||
|
</settings>
|
141
extensions/guacamole-auth-mysql/pom.xml
Normal file
141
extensions/guacamole-auth-mysql/pom.xml
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<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>net.sourceforge.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-mysql</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>0.8.0</version>
|
||||||
|
<name>guacamole-auth-mysql</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>
|
||||||
|
|
||||||
|
<!-- Assembly plugin - for easy distribution -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>2.2-beta-5</version>
|
||||||
|
<configuration>
|
||||||
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/dist.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>make-dist-archive</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- MyBatis Generator plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.mybatis.generator</groupId>
|
||||||
|
<artifactId>mybatis-generator-maven-plugin</artifactId>
|
||||||
|
<version>1.3.2</version>
|
||||||
|
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>Generate MyBatis Artifacts</id>
|
||||||
|
<goals>
|
||||||
|
<goal>generate</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
|
||||||
|
<!-- MySQL Connector -->
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>5.1.23</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Guacamole Java API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sourceforge.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-common</artifactId>
|
||||||
|
<version>0.8.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Guacamole Extension API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sourceforge.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-ext</artifactId>
|
||||||
|
<version>0.8.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SLF4J - logging -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.6.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-jcl</artifactId>
|
||||||
|
<version>1.6.1</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MyBatis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MyBatis Guice -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis-guice</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Google Collections -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.collections</groupId>
|
||||||
|
<artifactId>google-collections</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
|
||||||
|
<!-- Central Guacamole repository -->
|
||||||
|
<repository>
|
||||||
|
<id>guac-dev</id>
|
||||||
|
<url>http://guac-dev.org/repo</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
153
extensions/guacamole-auth-mysql/schema/001-create-schema.sql
Normal file
153
extensions/guacamole-auth-mysql/schema/001-create-schema.sql
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connections. Each connection has a name, protocol, and
|
||||||
|
-- associated set of parameters.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection` (
|
||||||
|
|
||||||
|
`connection_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`connection_name` varchar(128) NOT NULL,
|
||||||
|
`protocol` varchar(32) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`connection_id`),
|
||||||
|
UNIQUE KEY `connection_name` (`connection_name`)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of users. Each user has a unique username and a hashed password
|
||||||
|
-- with corresponding salt.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user` (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`username` varchar(128) NOT NULL,
|
||||||
|
`password_hash` binary(32) NOT NULL,
|
||||||
|
`password_salt` binary(32) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`),
|
||||||
|
UNIQUE KEY `username` (`username`)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection parameters. Each parameter is simply a name/value pair
|
||||||
|
-- associated with a connection.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_parameter` (
|
||||||
|
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`parameter_name` varchar(128) NOT NULL,
|
||||||
|
`parameter_value` varchar(4096) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`connection_id`,`parameter_name`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_parameter_ibfk_1`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection permissions. Each connection permission grants a user
|
||||||
|
-- specific access to a connection.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_permission` (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`,`connection_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_permission_ibfk_2`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of system permissions. Each system permission grants a user a
|
||||||
|
-- system-level privilege of some kind.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_system_permission` (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('CREATE_CONNECTION',
|
||||||
|
'CREATE_USER',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_system_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of user permissions. Each user permission grants a user access to
|
||||||
|
-- another user (the "affected" user) for a specific type of operation.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_user_permission` (
|
||||||
|
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`affected_user_id` int(11) NOT NULL,
|
||||||
|
`permission` enum('READ',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ADMINISTER') NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`user_id`,`affected_user_id`,`permission`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_permission_ibfk_1`
|
||||||
|
FOREIGN KEY (`affected_user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_user_permission_ibfk_2`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table of connection history records. Each record defines a specific user's
|
||||||
|
-- session, including the connection used, the start time, and the end time
|
||||||
|
-- (if any).
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `guacamole_connection_history` (
|
||||||
|
|
||||||
|
`history_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`connection_id` int(11) NOT NULL,
|
||||||
|
`start_date` datetime NOT NULL,
|
||||||
|
`end_date` datetime DEFAULT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`history_id`),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
KEY `connection_id` (`connection_id`),
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_history_ibfk_1`
|
||||||
|
FOREIGN KEY (`user_id`)
|
||||||
|
REFERENCES `guacamole_user` (`user_id`) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
CONSTRAINT `guacamole_connection_history_ibfk_2`
|
||||||
|
FOREIGN KEY (`connection_id`)
|
||||||
|
REFERENCES `guacamole_connection` (`connection_id`) ON DELETE CASCADE
|
||||||
|
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
-- Create default user "guacadmin" with password "guacadmin"
|
||||||
|
insert into guacamole_user values(1, 'guacadmin',
|
||||||
|
x'CA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960', -- 'guacadmin'
|
||||||
|
x'FE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264');
|
||||||
|
|
||||||
|
-- Grant this user create permissions
|
||||||
|
insert into guacamole_system_permission values(1, 'CREATE_CONNECTION');
|
||||||
|
insert into guacamole_system_permission values(1, 'CREATE_USER');
|
||||||
|
insert into guacamole_system_permission values(1, 'ADMINISTER');
|
||||||
|
|
||||||
|
-- Grant admin permission to read/update/administer self
|
||||||
|
insert into guacamole_user_permission values(1, 1, 'READ');
|
||||||
|
insert into guacamole_user_permission values(1, 1, 'UPDATE');
|
||||||
|
insert into guacamole_user_permission values(1, 1, 'ADMINISTER');
|
||||||
|
|
54
extensions/guacamole-auth-mysql/src/main/assembly/dist.xml
Normal file
54
extensions/guacamole-auth-mysql/src/main/assembly/dist.xml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<assembly
|
||||||
|
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||||
|
|
||||||
|
<id>dist</id>
|
||||||
|
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
||||||
|
|
||||||
|
<!-- Output tar.gz -->
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
|
||||||
|
<!-- Include docs and schema -->
|
||||||
|
<fileSets>
|
||||||
|
|
||||||
|
<!-- Include docs -->
|
||||||
|
<fileSet>
|
||||||
|
<outputDirectory>/</outputDirectory>
|
||||||
|
<directory>doc</directory>
|
||||||
|
</fileSet>
|
||||||
|
|
||||||
|
<!-- Include schema -->
|
||||||
|
<fileSet>
|
||||||
|
<outputDirectory>/schema</outputDirectory>
|
||||||
|
<directory>schema</directory>
|
||||||
|
</fileSet>
|
||||||
|
|
||||||
|
</fileSets>
|
||||||
|
|
||||||
|
<!-- Include self and all dependencies except guacamole-common
|
||||||
|
and guacamole-ext -->
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
|
||||||
|
<outputDirectory>/lib</outputDirectory>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<unpack>false</unpack>
|
||||||
|
<useProjectArtifact>true</useProjectArtifact>
|
||||||
|
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||||
|
|
||||||
|
<excludes>
|
||||||
|
|
||||||
|
<!-- Do not include guacamole-common -->
|
||||||
|
<exclude>net.sourceforge.guacamole:guacamole-common</exclude>
|
||||||
|
|
||||||
|
<!-- Do not include guacamole-ext -->
|
||||||
|
<exclude>net.sourceforge.guacamole:guacamole-ext</exclude>
|
||||||
|
|
||||||
|
</excludes>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
|
||||||
|
</assembly>
|
@@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the set of currently active Connections. Whenever a socket is
|
||||||
|
* opened, the connection ID should be added to this set, and whenever a socket
|
||||||
|
* is closed, the connection ID should be removed from this set.
|
||||||
|
*
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class ActiveConnectionSet {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing connection history.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionHistoryMapper connectionHistoryDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of all the connections that are currently active.
|
||||||
|
*/
|
||||||
|
private Set<Integer> activeConnectionSet = new HashSet<Integer>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a connection is currently in use.
|
||||||
|
* @param connectionID The connection to check the status of.
|
||||||
|
* @return true if the connection is currently in use.
|
||||||
|
*/
|
||||||
|
public boolean isActive(int connectionID) {
|
||||||
|
return activeConnectionSet.contains(connectionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a connection as open.
|
||||||
|
* @param connectionID The ID of the connection that is being opened.
|
||||||
|
* @param userID The ID of the user who is opening the connection.
|
||||||
|
* @return The ID of the history record created for this open connection.
|
||||||
|
*/
|
||||||
|
public int openConnection(int connectionID, int userID) {
|
||||||
|
|
||||||
|
// Create the connection history record
|
||||||
|
ConnectionHistory connectionHistory = new ConnectionHistory();
|
||||||
|
connectionHistory.setConnection_id(connectionID);
|
||||||
|
connectionHistory.setUser_id(userID);
|
||||||
|
connectionHistory.setStart_date(new Date());
|
||||||
|
connectionHistoryDAO.insert(connectionHistory);
|
||||||
|
|
||||||
|
// Mark the connection as active
|
||||||
|
activeConnectionSet.add(connectionID);
|
||||||
|
|
||||||
|
return connectionHistory.getHistory_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a connection as closed.
|
||||||
|
* @param connectionID The ID of the connection that is being opened.
|
||||||
|
* @param historyID The ID of the history record about the open connection.
|
||||||
|
* @throws GuacamoleException If the open connection history is not found.
|
||||||
|
*/
|
||||||
|
public void closeConnection(int connectionID, int historyID)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get the existing history record
|
||||||
|
ConnectionHistory connectionHistory =
|
||||||
|
connectionHistoryDAO.selectByPrimaryKey(historyID);
|
||||||
|
|
||||||
|
if(connectionHistory == null)
|
||||||
|
throw new GuacamoleException("History record not found.");
|
||||||
|
|
||||||
|
// Update the connection history record to mark that it is now closed
|
||||||
|
connectionHistory.setEnd_date(new Date());
|
||||||
|
connectionHistoryDAO.updateByPrimaryKey(connectionHistory);
|
||||||
|
|
||||||
|
// Remove the connection from the set of active connections.
|
||||||
|
activeConnectionSet.remove(connectionID);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,254 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleClientException;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Connection;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Directory;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||||
|
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
import org.mybatis.guice.transactional.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MySQL-based implementation of the connection directory.
|
||||||
|
*
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class ConnectionDirectory implements Directory<String, Connection>{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the user who this connection directory belongs to.
|
||||||
|
* Access is based on his/her permission settings.
|
||||||
|
*/
|
||||||
|
private int user_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for checking permissions.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PermissionCheckService permissionCheckService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service managing connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionService connectionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for manipulating connection permissions in the database.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionPermissionMapper connectionPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for manipulating connection parameters in the database.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionParameterMapper connectionParameterDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user for this directory.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user owning this connection directory.
|
||||||
|
*/
|
||||||
|
public void init(int user_id) {
|
||||||
|
this.user_id = user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public Connection get(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get connection
|
||||||
|
MySQLConnection connection =
|
||||||
|
connectionService.retrieveConnection(identifier, user_id);
|
||||||
|
|
||||||
|
// Verify access is granted
|
||||||
|
permissionCheckService.verifyConnectionAccess(
|
||||||
|
this.user_id,
|
||||||
|
connection.getConnectionID(),
|
||||||
|
MySQLConstants.CONNECTION_READ);
|
||||||
|
|
||||||
|
// Return connection
|
||||||
|
return connection;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||||
|
return permissionCheckService.retrieveConnectionNames(user_id,
|
||||||
|
MySQLConstants.CONNECTION_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void add(Connection object) throws GuacamoleException {
|
||||||
|
|
||||||
|
String identifier = object.getIdentifier().trim();
|
||||||
|
if(identifier.isEmpty())
|
||||||
|
throw new GuacamoleClientException("The connection identifier cannot be blank.");
|
||||||
|
|
||||||
|
// Verify permission to create
|
||||||
|
permissionCheckService.verifySystemAccess(this.user_id,
|
||||||
|
MySQLConstants.SYSTEM_CONNECTION_CREATE);
|
||||||
|
|
||||||
|
// Verify that no connection already exists with this identifier.
|
||||||
|
MySQLConnection previousConnection =
|
||||||
|
connectionService.retrieveConnection(identifier, user_id);
|
||||||
|
if(previousConnection != null)
|
||||||
|
throw new GuacamoleClientException("That connection identifier is already in use.");
|
||||||
|
|
||||||
|
// Create connection
|
||||||
|
MySQLConnection connection = connectionService.createConnection(
|
||||||
|
identifier, object.getConfiguration().getProtocol(),
|
||||||
|
user_id);
|
||||||
|
|
||||||
|
// Add connection parameters
|
||||||
|
createConfigurationValues(connection.getConnectionID(),
|
||||||
|
object.getConfiguration());
|
||||||
|
|
||||||
|
// Finally, give the current user full access to the newly created
|
||||||
|
// connection.
|
||||||
|
ConnectionPermissionKey newConnectionPermission = new ConnectionPermissionKey();
|
||||||
|
newConnectionPermission.setUser_id(this.user_id);
|
||||||
|
newConnectionPermission.setConnection_id(connection.getConnectionID());
|
||||||
|
|
||||||
|
// Read permission
|
||||||
|
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_READ);
|
||||||
|
connectionPermissionDAO.insert(newConnectionPermission);
|
||||||
|
|
||||||
|
// Update permission
|
||||||
|
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_UPDATE);
|
||||||
|
connectionPermissionDAO.insert(newConnectionPermission);
|
||||||
|
|
||||||
|
// Delete permission
|
||||||
|
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_DELETE);
|
||||||
|
connectionPermissionDAO.insert(newConnectionPermission);
|
||||||
|
|
||||||
|
// Administer permission
|
||||||
|
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_ADMINISTER);
|
||||||
|
connectionPermissionDAO.insert(newConnectionPermission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts all parameter values from the given configuration into the
|
||||||
|
* database, associating them with the connection having the givenID.
|
||||||
|
*
|
||||||
|
* @param connection_id The ID of the connection to associate all
|
||||||
|
* parameters with.
|
||||||
|
* @param config The GuacamoleConfiguration to read parameters from.
|
||||||
|
*/
|
||||||
|
private void createConfigurationValues(int connection_id,
|
||||||
|
GuacamoleConfiguration config) {
|
||||||
|
|
||||||
|
// Insert new parameters for each parameter in the config
|
||||||
|
for (String name : config.getParameterNames()) {
|
||||||
|
|
||||||
|
// Create a ConnectionParameter based on the current parameter
|
||||||
|
ConnectionParameter parameter = new ConnectionParameter();
|
||||||
|
parameter.setConnection_id(connection_id);
|
||||||
|
parameter.setParameter_name(name);
|
||||||
|
parameter.setParameter_value(config.getParameter(name));
|
||||||
|
|
||||||
|
// Insert connection parameter
|
||||||
|
connectionParameterDAO.insert(parameter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void update(Connection object) throws GuacamoleException {
|
||||||
|
|
||||||
|
// If connection not actually from this auth provider, we can't handle
|
||||||
|
// the update
|
||||||
|
if (!(object instanceof MySQLConnection))
|
||||||
|
throw new GuacamoleException("Connection not from database.");
|
||||||
|
|
||||||
|
MySQLConnection mySQLConnection = (MySQLConnection) object;
|
||||||
|
|
||||||
|
// Verify permission to update
|
||||||
|
permissionCheckService.verifyConnectionAccess(this.user_id,
|
||||||
|
mySQLConnection.getConnectionID(),
|
||||||
|
MySQLConstants.CONNECTION_UPDATE);
|
||||||
|
|
||||||
|
// Perform update
|
||||||
|
connectionService.updateConnection(mySQLConnection);
|
||||||
|
|
||||||
|
// Delete old connection parameters
|
||||||
|
ConnectionParameterExample parameterExample = new ConnectionParameterExample();
|
||||||
|
parameterExample.createCriteria().andConnection_idEqualTo(mySQLConnection.getConnectionID());
|
||||||
|
connectionParameterDAO.deleteByExample(parameterExample);
|
||||||
|
|
||||||
|
// Add connection parameters
|
||||||
|
createConfigurationValues(mySQLConnection.getConnectionID(),
|
||||||
|
object.getConfiguration());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public void remove(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get connection
|
||||||
|
MySQLConnection mySQLConnection =
|
||||||
|
connectionService.retrieveConnection(identifier, user_id);
|
||||||
|
|
||||||
|
// Verify permission to delete
|
||||||
|
permissionCheckService.verifyConnectionAccess(this.user_id,
|
||||||
|
mySQLConnection.getConnectionID(),
|
||||||
|
MySQLConstants.CONNECTION_DELETE);
|
||||||
|
|
||||||
|
// Delete the connection itself
|
||||||
|
connectionService.deleteConnection(mySQLConnection.getConnectionID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,177 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Binder;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.name.Names;
|
||||||
|
import java.util.Properties;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Credentials;
|
||||||
|
import net.sourceforge.guacamole.net.auth.UserContext;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.SaltService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.SecureRandomSaltService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.SHA256PasswordEncryptionService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
|
||||||
|
import net.sourceforge.guacamole.properties.GuacamoleProperties;
|
||||||
|
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||||
|
import org.mybatis.guice.MyBatisModule;
|
||||||
|
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
|
||||||
|
import org.mybatis.guice.datasource.helper.JdbcHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a MySQL based implementation of the AuthenticationProvider
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of all active connections.
|
||||||
|
*/
|
||||||
|
private ActiveConnectionSet activeConnectionSet = new ActiveConnectionSet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injector which will manage the object graph of this authentication
|
||||||
|
* provider.
|
||||||
|
*/
|
||||||
|
private Injector injector;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserContext getUserContext(Credentials credentials) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get user service
|
||||||
|
UserService userService = injector.getInstance(UserService.class);
|
||||||
|
|
||||||
|
// Get user
|
||||||
|
MySQLUser authenticatedUser = userService.retrieveUser(credentials);
|
||||||
|
if (authenticatedUser != null) {
|
||||||
|
MySQLUserContext context = injector.getInstance(MySQLUserContext.class);
|
||||||
|
context.init(authenticatedUser.getUserID());
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, unauthorized
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new MySQLAuthenticationProvider that reads and writes
|
||||||
|
* authentication data to a MySQL database defined by properties in
|
||||||
|
* guacamole.properties.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException If a required property is missing, or
|
||||||
|
* an error occurs while parsing a property.
|
||||||
|
*/
|
||||||
|
public MySQLAuthenticationProvider() throws GuacamoleException {
|
||||||
|
|
||||||
|
final Properties myBatisProperties = new Properties();
|
||||||
|
|
||||||
|
// Set the mysql properties for MyBatis.
|
||||||
|
myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
|
||||||
|
myBatisProperties.setProperty("JDBC.host", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_HOSTNAME));
|
||||||
|
myBatisProperties.setProperty("JDBC.port", String.valueOf(GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PORT)));
|
||||||
|
myBatisProperties.setProperty("JDBC.schema", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE));
|
||||||
|
myBatisProperties.setProperty("JDBC.username", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME));
|
||||||
|
myBatisProperties.setProperty("JDBC.password", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD));
|
||||||
|
myBatisProperties.setProperty("JDBC.autoCommit", "false");
|
||||||
|
|
||||||
|
// Set up Guice injector.
|
||||||
|
injector = Guice.createInjector(
|
||||||
|
JdbcHelper.MySQL,
|
||||||
|
|
||||||
|
new Module() {
|
||||||
|
@Override
|
||||||
|
public void configure(Binder binder) {
|
||||||
|
Names.bindProperties(binder, myBatisProperties);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new MyBatisModule() {
|
||||||
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
|
||||||
|
// Datasource
|
||||||
|
bindDataSourceProviderType(PooledDataSourceProvider.class);
|
||||||
|
|
||||||
|
// Transaction factory
|
||||||
|
bindTransactionFactoryType(JdbcTransactionFactory.class);
|
||||||
|
|
||||||
|
// Add MyBatis mappers
|
||||||
|
addMapperClass(ConnectionHistoryMapper.class);
|
||||||
|
addMapperClass(ConnectionMapper.class);
|
||||||
|
addMapperClass(ConnectionParameterMapper.class);
|
||||||
|
addMapperClass(ConnectionPermissionMapper.class);
|
||||||
|
addMapperClass(SystemPermissionMapper.class);
|
||||||
|
addMapperClass(UserMapper.class);
|
||||||
|
addMapperClass(UserPermissionMapper.class);
|
||||||
|
|
||||||
|
// Bind interfaces
|
||||||
|
bind(MySQLUserContext.class);
|
||||||
|
bind(UserDirectory.class);
|
||||||
|
bind(MySQLUser.class);
|
||||||
|
bind(SaltService.class).to(SecureRandomSaltService.class);
|
||||||
|
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
|
||||||
|
bind(PermissionCheckService.class);
|
||||||
|
bind(ConnectionService.class);
|
||||||
|
bind(UserService.class);
|
||||||
|
bind(ActiveConnectionSet.class).toInstance(activeConnectionSet);
|
||||||
|
|
||||||
|
}
|
||||||
|
} // end of mybatis module
|
||||||
|
|
||||||
|
);
|
||||||
|
} // end of constructor
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,132 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.GuacamoleSocket;
|
||||||
|
import net.sourceforge.guacamole.net.auth.AbstractConnection;
|
||||||
|
import net.sourceforge.guacamole.net.auth.ConnectionRecord;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||||
|
import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
|
||||||
|
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MySQL based implementation of the Connection object.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLConnection extends AbstractConnection {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID associated with this connection in the database.
|
||||||
|
*/
|
||||||
|
private Integer connectionID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the user who queried or created this connection.
|
||||||
|
*/
|
||||||
|
private int userID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History of this connection.
|
||||||
|
*/
|
||||||
|
private List<ConnectionRecord> history = new ArrayList<ConnectionRecord>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for managing connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionService connectionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a default, empty connection.
|
||||||
|
*/
|
||||||
|
public MySQLConnection() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of the corresponding connection record.
|
||||||
|
* @return The ID of the corresponding connection, if any.
|
||||||
|
*/
|
||||||
|
public Integer getConnectionID() {
|
||||||
|
return connectionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ID of the corresponding connection record.
|
||||||
|
* @param connectionID The ID to assign to this connection.
|
||||||
|
*/
|
||||||
|
public void setConnectionID(Integer connectionID) {
|
||||||
|
this.connectionID = connectionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize from explicit values.
|
||||||
|
*
|
||||||
|
* @param connectionID The ID of the associated database record, if any.
|
||||||
|
* @param identifier The unique identifier associated with this connection.
|
||||||
|
* @param config The GuacamoleConfiguration associated with this connection.
|
||||||
|
* @param history All ConnectionRecords associated with this connection.
|
||||||
|
* @param userID The IID of the user who queried this connection.
|
||||||
|
*/
|
||||||
|
public void init(Integer connectionID, String identifier,
|
||||||
|
GuacamoleConfiguration config,
|
||||||
|
List<? extends ConnectionRecord> history, int userID) {
|
||||||
|
|
||||||
|
this.connectionID = connectionID;
|
||||||
|
setIdentifier(identifier);
|
||||||
|
setConfiguration(config);
|
||||||
|
this.history.addAll(history);
|
||||||
|
this.userID = userID;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
|
||||||
|
return connectionService.connect(this, info, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends ConnectionRecord> getHistory() throws GuacamoleException {
|
||||||
|
return Collections.unmodifiableList(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import net.sourceforge.guacamole.net.auth.ConnectionRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ConnectionRecord which is based on data stored in MySQL.
|
||||||
|
*
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLConnectionRecord implements ConnectionRecord {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start date of the ConnectionRecord.
|
||||||
|
*/
|
||||||
|
private Date startDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The end date of the ConnectionRecord.
|
||||||
|
*/
|
||||||
|
private Date endDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the user that is associated with this ConnectionRecord.
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this MySQLConnectionRecord with the start/end dates,
|
||||||
|
* and the name of the user it represents.
|
||||||
|
*
|
||||||
|
* @param startDate The start date of the connection history.
|
||||||
|
* @param endDate The end date of the connection history.
|
||||||
|
* @param username The name of the user that used the connection.
|
||||||
|
*/
|
||||||
|
public MySQLConnectionRecord(Date startDate, Date endDate,
|
||||||
|
String username) {
|
||||||
|
if (startDate != null) this.startDate = new Date(startDate.getTime());
|
||||||
|
if (endDate != null) this.endDate = new Date(endDate.getTime());
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getStartDate() {
|
||||||
|
if (startDate == null) return null;
|
||||||
|
return new Date(startDate.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getEndDate() {
|
||||||
|
if (endDate == null) return null;
|
||||||
|
return new Date(endDate.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
// If the end date hasn't been stored yet, the connection is still open.
|
||||||
|
return endDate == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,186 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of constants that are useful for the MySQL-based authentication provider.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public final class MySQLConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class should not be instantiated.
|
||||||
|
*/
|
||||||
|
private MySQLConstants() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent READ access to a user.
|
||||||
|
*/
|
||||||
|
public static final String USER_READ = "READ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent UPDATE access to a user.
|
||||||
|
*/
|
||||||
|
public static final String USER_UPDATE = "UPDATE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent DELETE access to a user.
|
||||||
|
*/
|
||||||
|
public static final String USER_DELETE = "DELETE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent ADMINISTER access to a
|
||||||
|
* user.
|
||||||
|
*/
|
||||||
|
public static final String USER_ADMINISTER = "ADMINISTER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent READ access to a
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public static final String CONNECTION_READ = "READ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent UPDATE access to a
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public static final String CONNECTION_UPDATE = "UPDATE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent DELETE access to a
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public static final String CONNECTION_DELETE = "DELETE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent ADMINISTER access to a
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public static final String CONNECTION_ADMINISTER = "ADMINISTER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent permission to create
|
||||||
|
* users.
|
||||||
|
*/
|
||||||
|
public static final String SYSTEM_USER_CREATE = "CREATE_USER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent permission to create
|
||||||
|
* connections.
|
||||||
|
*/
|
||||||
|
public static final String SYSTEM_CONNECTION_CREATE = "CREATE_CONNECTION";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The string stored in the database to represent permission to administer
|
||||||
|
* the system as a whole.
|
||||||
|
*/
|
||||||
|
public static final String SYSTEM_ADMINISTER = "ADMINISTER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the type of a permission affecting a user, returns the MySQL
|
||||||
|
* constant representing that permission type.
|
||||||
|
*
|
||||||
|
* @param type The type of permission to look up.
|
||||||
|
* @return The MySQL constant corresponding to the given permission type.
|
||||||
|
*/
|
||||||
|
public static String getUserConstant(ObjectPermission.Type type) {
|
||||||
|
|
||||||
|
// Convert permission type to MySQL constant
|
||||||
|
switch (type) {
|
||||||
|
case READ: return USER_READ;
|
||||||
|
case UPDATE: return USER_UPDATE;
|
||||||
|
case ADMINISTER: return USER_ADMINISTER;
|
||||||
|
case DELETE: return USER_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, permission support was not properly implemented
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported permission type: " + type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the type of a permission affecting a connection, returns the MySQL
|
||||||
|
* constant representing that permission type.
|
||||||
|
*
|
||||||
|
* @param type The type of permission to look up.
|
||||||
|
* @return The MySQL constant corresponding to the given permission type.
|
||||||
|
*/
|
||||||
|
public static String getConnectionConstant(ObjectPermission.Type type) {
|
||||||
|
|
||||||
|
// Convert permission type to MySQL constant
|
||||||
|
switch (type) {
|
||||||
|
case READ: return CONNECTION_READ;
|
||||||
|
case UPDATE: return CONNECTION_UPDATE;
|
||||||
|
case ADMINISTER: return CONNECTION_ADMINISTER;
|
||||||
|
case DELETE: return CONNECTION_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, permission support was not properly implemented
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported permission type: " + type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the type of a permission affecting the system, returns the MySQL
|
||||||
|
* constant representing that permission type.
|
||||||
|
*
|
||||||
|
* @param type The type of permission to look up.
|
||||||
|
* @return The MySQL constant corresponding to the given permission type.
|
||||||
|
*/
|
||||||
|
public static String getSystemConstant(SystemPermission.Type type) {
|
||||||
|
|
||||||
|
// Convert permission type to MySQL constant
|
||||||
|
switch (type) {
|
||||||
|
case CREATE_USER: return SYSTEM_USER_CREATE;
|
||||||
|
case CREATE_CONNECTION: return SYSTEM_CONNECTION_CREATE;
|
||||||
|
case ADMINISTER: return SYSTEM_ADMINISTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, permission support was not properly implemented
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported permission type: " + type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.io.GuacamoleReader;
|
||||||
|
import net.sourceforge.guacamole.io.GuacamoleWriter;
|
||||||
|
import net.sourceforge.guacamole.net.GuacamoleSocket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MySQL specific wrapper around a ConfiguredGuacamoleSocket.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLGuacamoleSocket implements GuacamoleSocket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injected ActiveConnectionSet which will contain all active connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ActiveConnectionSet activeConnectionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The wrapped socket.
|
||||||
|
*/
|
||||||
|
private GuacamoleSocket socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID associated with the connection associated with the wrapped
|
||||||
|
* socket.
|
||||||
|
*/
|
||||||
|
private int connectionID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the history record associated with this instance of the
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
private int historyID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this MySQLGuacamoleSocket with the provided GuacamoleSocket.
|
||||||
|
*
|
||||||
|
* @param socket The ConfiguredGuacamoleSocket to wrap.
|
||||||
|
* @param connectionID The ID of the connection associated with the given
|
||||||
|
* socket.
|
||||||
|
* @param historyID The ID of the history record associated with this
|
||||||
|
* instance of the connection.
|
||||||
|
*/
|
||||||
|
public void init(GuacamoleSocket socket, int connectionID, int historyID) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.connectionID = connectionID;
|
||||||
|
this.historyID = historyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuacamoleReader getReader() {
|
||||||
|
return socket.getReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuacamoleWriter getWriter() {
|
||||||
|
return socket.getWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Close socket
|
||||||
|
socket.close();
|
||||||
|
|
||||||
|
// Mark this connection as inactive
|
||||||
|
activeConnectionSet.closeConnection(connectionID, historyID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpen() {
|
||||||
|
return socket.isOpen();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,193 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.AbstractUser;
|
||||||
|
import net.sourceforge.guacamole.net.auth.User;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.Permission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MySQL based implementation of the User object.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLUser extends AbstractUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of this user in the database, if any.
|
||||||
|
*/
|
||||||
|
private Integer userID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of current permissions a user has.
|
||||||
|
*/
|
||||||
|
private Set<Permission> permissions = new HashSet<Permission>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any newly added permissions that have yet to be committed.
|
||||||
|
*/
|
||||||
|
private Set<Permission> newPermissions = new HashSet<Permission>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any newly deleted permissions that have yet to be deleted.
|
||||||
|
*/
|
||||||
|
private Set<Permission> removedPermissions = new HashSet<Permission>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new, empty MySQLUser.
|
||||||
|
*/
|
||||||
|
public MySQLUser() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new MySQLUser having the given username.
|
||||||
|
*
|
||||||
|
* @param name The name to assign to this MySQLUser.
|
||||||
|
*/
|
||||||
|
public void init(String name) {
|
||||||
|
init(null, name, null, Collections.EMPTY_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new MySQLUser, copying all data from the given user
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param user The user object to copy.
|
||||||
|
* @throws GuacamoleException If an error occurs while reading the user
|
||||||
|
* data in the given object.
|
||||||
|
*/
|
||||||
|
public void init(User user) throws GuacamoleException {
|
||||||
|
init(null, user.getUsername(), user.getPassword(), user.getPermissions());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new MySQLUser initialized from the given data from the
|
||||||
|
* database.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user in the database, if any.
|
||||||
|
* @param username The username of this user.
|
||||||
|
* @param password The password to assign to this user.
|
||||||
|
* @param permissions The permissions to assign to this user, as
|
||||||
|
* retrieved from the database.
|
||||||
|
*/
|
||||||
|
public void init(Integer userID, String username, String password,
|
||||||
|
Set<Permission> permissions) {
|
||||||
|
this.userID = userID;
|
||||||
|
setUsername(username);
|
||||||
|
setPassword(password);
|
||||||
|
this.permissions.addAll(permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current set of permissions this user has.
|
||||||
|
* @return the current set of permissions.
|
||||||
|
*/
|
||||||
|
public Set<Permission> getCurrentPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get any new permissions that have yet to be inserted.
|
||||||
|
* @return the new set of permissions.
|
||||||
|
*/
|
||||||
|
public Set<Permission> getNewPermissions() {
|
||||||
|
return newPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get any permissions that have not yet been deleted.
|
||||||
|
* @return the permissions that need to be deleted.
|
||||||
|
*/
|
||||||
|
public Set<Permission> getRemovedPermissions() {
|
||||||
|
return removedPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the new and removed permission sets after they are
|
||||||
|
* no longer needed.
|
||||||
|
*/
|
||||||
|
public void resetPermissions() {
|
||||||
|
newPermissions.clear();
|
||||||
|
removedPermissions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ID of this user in the database, if it exists.
|
||||||
|
*
|
||||||
|
* @return The ID of this user in the database, or null if this user
|
||||||
|
* was not retrieved from the database.
|
||||||
|
*/
|
||||||
|
public Integer getUserID() {
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ID of this user to the given value.
|
||||||
|
*
|
||||||
|
* @param userID The ID to assign to this user.
|
||||||
|
*/
|
||||||
|
public void setUserID(Integer userID) {
|
||||||
|
this.userID = userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Permission> getPermissions() throws GuacamoleException {
|
||||||
|
return Collections.unmodifiableSet(permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(Permission permission) throws GuacamoleException {
|
||||||
|
return permissions.contains(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPermission(Permission permission) throws GuacamoleException {
|
||||||
|
permissions.add(permission);
|
||||||
|
newPermissions.add(permission);
|
||||||
|
removedPermissions.remove(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePermission(Permission permission) throws GuacamoleException {
|
||||||
|
permissions.remove(permission);
|
||||||
|
newPermissions.remove(permission);
|
||||||
|
removedPermissions.add(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Connection;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Directory;
|
||||||
|
import net.sourceforge.guacamole.net.auth.User;
|
||||||
|
import net.sourceforge.guacamole.net.auth.UserContext;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MySQL representation of a UserContext.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLUserContext implements UserContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the user owning this context. The permissions of this user
|
||||||
|
* dictate the access given via the user and connection directories.
|
||||||
|
*/
|
||||||
|
private int user_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for accessing users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the user and directories associated with this context.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user owning this context.
|
||||||
|
*/
|
||||||
|
public void init(int user_id) {
|
||||||
|
this.user_id = user_id;
|
||||||
|
userDirectory.init(user_id);
|
||||||
|
connectionDirectory.init(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User self() {
|
||||||
|
return userService.retrieveUser(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory<String, User> getUserDirectory() throws GuacamoleException {
|
||||||
|
return userDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory<String, Connection> getConnectionDirectory() throws GuacamoleException {
|
||||||
|
return connectionDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,601 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleClientException;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleSecurityException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Directory;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.ConnectionPermission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.Permission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.UserPermission;
|
||||||
|
import org.mybatis.guice.transactional.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A MySQL based implementation of the User Directory.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class UserDirectory implements Directory<String, net.sourceforge.guacamole.net.auth.User> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the user who this user directory belongs to.
|
||||||
|
* Access is based on his/her permission settings.
|
||||||
|
*/
|
||||||
|
private int user_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for accessing users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for accessing connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionService connectionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing user permissions, which will be injected.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserPermissionMapper userPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing connection permissions, which will be injected.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionPermissionMapper connectionPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing system permissions, which will be injected.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private SystemPermissionMapper systemPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for checking various permissions, which will be injected.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PermissionCheckService permissionCheckService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user for this directory.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user whose permissions define the visibility
|
||||||
|
* of other users in this directory.
|
||||||
|
*/
|
||||||
|
public void init(int user_id) {
|
||||||
|
this.user_id = user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public net.sourceforge.guacamole.net.auth.User get(String identifier)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get user
|
||||||
|
MySQLUser user = userService.retrieveUser(identifier);
|
||||||
|
|
||||||
|
// Verify access is granted
|
||||||
|
permissionCheckService.verifyUserAccess(this.user_id,
|
||||||
|
user.getUserID(),
|
||||||
|
MySQLConstants.USER_READ);
|
||||||
|
|
||||||
|
// Return user
|
||||||
|
return userService.retrieveUser(identifier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||||
|
return permissionCheckService.retrieveUsernames(user_id,
|
||||||
|
MySQLConstants.USER_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void add(net.sourceforge.guacamole.net.auth.User object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
String username = object.getUsername().trim();
|
||||||
|
if(username.isEmpty())
|
||||||
|
throw new GuacamoleClientException("The username cannot be blank.");
|
||||||
|
|
||||||
|
// Verify current user has permission to create users
|
||||||
|
permissionCheckService.verifySystemAccess(this.user_id,
|
||||||
|
MySQLConstants.SYSTEM_USER_CREATE);
|
||||||
|
Preconditions.checkNotNull(object);
|
||||||
|
|
||||||
|
// Verify that no user already exists with this username.
|
||||||
|
MySQLUser previousUser = userService.retrieveUser(username);
|
||||||
|
if(previousUser != null)
|
||||||
|
throw new GuacamoleClientException("That username is already in use.");
|
||||||
|
|
||||||
|
// Create new user
|
||||||
|
MySQLUser user = userService.createUser(username, object.getPassword());
|
||||||
|
|
||||||
|
// Create permissions of new user in database
|
||||||
|
createPermissions(user.getUserID(), object.getPermissions());
|
||||||
|
|
||||||
|
// Give the current user full access to the newly created user.
|
||||||
|
UserPermissionKey newUserPermission = new UserPermissionKey();
|
||||||
|
newUserPermission.setUser_id(this.user_id);
|
||||||
|
newUserPermission.setAffected_user_id(user.getUserID());
|
||||||
|
|
||||||
|
// READ permission on new user
|
||||||
|
newUserPermission.setPermission(MySQLConstants.USER_READ);
|
||||||
|
userPermissionDAO.insert(newUserPermission);
|
||||||
|
|
||||||
|
// UPDATE permission on new user
|
||||||
|
newUserPermission.setPermission(MySQLConstants.USER_UPDATE);
|
||||||
|
userPermissionDAO.insert(newUserPermission);
|
||||||
|
|
||||||
|
// DELETE permission on new user
|
||||||
|
newUserPermission.setPermission(MySQLConstants.USER_DELETE);
|
||||||
|
userPermissionDAO.insert(newUserPermission);
|
||||||
|
|
||||||
|
// ADMINISTER permission on new user
|
||||||
|
newUserPermission.setPermission(MySQLConstants.USER_ADMINISTER);
|
||||||
|
userPermissionDAO.insert(newUserPermission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given permissions to the given user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user whose permissions should be updated.
|
||||||
|
* @param permissions The permissions to add.
|
||||||
|
* @throws GuacamoleException If an error occurs while updating the
|
||||||
|
* permissions of the given user.
|
||||||
|
*/
|
||||||
|
private void createPermissions(int user_id, Set<Permission> permissions) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Partition given permissions by permission type
|
||||||
|
List<UserPermission> newUserPermissions = new ArrayList<UserPermission>();
|
||||||
|
List<ConnectionPermission> newConnectionPermissions = new ArrayList<ConnectionPermission>();
|
||||||
|
List<SystemPermission> newSystemPermissions = new ArrayList<SystemPermission>();
|
||||||
|
|
||||||
|
for (Permission permission : permissions) {
|
||||||
|
|
||||||
|
if (permission instanceof UserPermission)
|
||||||
|
newUserPermissions.add((UserPermission) permission);
|
||||||
|
|
||||||
|
else if (permission instanceof ConnectionPermission)
|
||||||
|
newConnectionPermissions.add((ConnectionPermission) permission);
|
||||||
|
|
||||||
|
else if (permission instanceof SystemPermission)
|
||||||
|
newSystemPermissions.add((SystemPermission) permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the new permissions
|
||||||
|
createUserPermissions(user_id, newUserPermissions);
|
||||||
|
createConnectionPermissions(user_id, newConnectionPermissions);
|
||||||
|
createSystemPermissions(user_id, newSystemPermissions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given permissions from the given user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user whose permissions should be updated.
|
||||||
|
* @param permissions The permissions to remove.
|
||||||
|
* @throws GuacamoleException If an error occurs while updating the
|
||||||
|
* permissions of the given user.
|
||||||
|
*/
|
||||||
|
private void removePermissions(int user_id, Set<Permission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Partition given permissions by permission type
|
||||||
|
List<UserPermission> removedUserPermissions = new ArrayList<UserPermission>();
|
||||||
|
List<ConnectionPermission> removedConnectionPermissions = new ArrayList<ConnectionPermission>();
|
||||||
|
List<SystemPermission> removedSystemPermissions = new ArrayList<SystemPermission>();
|
||||||
|
|
||||||
|
for (Permission permission : permissions) {
|
||||||
|
|
||||||
|
if (permission instanceof UserPermission)
|
||||||
|
removedUserPermissions.add((UserPermission) permission);
|
||||||
|
|
||||||
|
else if (permission instanceof ConnectionPermission)
|
||||||
|
removedConnectionPermissions.add((ConnectionPermission) permission);
|
||||||
|
|
||||||
|
else if (permission instanceof SystemPermission)
|
||||||
|
removedSystemPermissions.add((SystemPermission) permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the removed permissions.
|
||||||
|
deleteUserPermissions(user_id, removedUserPermissions);
|
||||||
|
deleteConnectionPermissions(user_id, removedConnectionPermissions);
|
||||||
|
deleteSystemPermissions(user_id, removedSystemPermissions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the given user permissions for the given user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user to change the permissions of.
|
||||||
|
* @param permissions The new permissions the given user should have when
|
||||||
|
* this operation completes.
|
||||||
|
* @throws GuacamoleException If permission to alter the access permissions
|
||||||
|
* of affected objects is denied.
|
||||||
|
*/
|
||||||
|
private void createUserPermissions(int user_id,
|
||||||
|
Collection<UserPermission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if(permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get list of administerable user IDs
|
||||||
|
List<Integer> administerableUserIDs =
|
||||||
|
permissionCheckService.retrieveUserIDs(this.user_id,
|
||||||
|
MySQLConstants.USER_ADMINISTER);
|
||||||
|
|
||||||
|
// Get set of usernames corresponding to administerable users
|
||||||
|
Map<String, Integer> administerableUsers =
|
||||||
|
userService.translateUsernames(administerableUserIDs);
|
||||||
|
|
||||||
|
// Insert all given permissions
|
||||||
|
for (UserPermission permission : permissions) {
|
||||||
|
|
||||||
|
// Get original ID
|
||||||
|
Integer affected_id =
|
||||||
|
administerableUsers.get(permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Verify that the user actually has permission to administrate
|
||||||
|
// every one of these users
|
||||||
|
if (affected_id == null)
|
||||||
|
throw new GuacamoleSecurityException(
|
||||||
|
"User #" + this.user_id
|
||||||
|
+ " does not have permission to administrate user "
|
||||||
|
+ permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Create new permission
|
||||||
|
UserPermissionKey newPermission = new UserPermissionKey();
|
||||||
|
newPermission.setUser_id(user_id);
|
||||||
|
newPermission.setPermission(MySQLConstants.getUserConstant(permission.getType()));
|
||||||
|
newPermission.setAffected_user_id(affected_id);
|
||||||
|
userPermissionDAO.insert(newPermission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete permissions having to do with users for a given user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user to change the permissions of.
|
||||||
|
* @param permissions The permissions the given user should no longer have
|
||||||
|
* when this operation completes.
|
||||||
|
* @throws GuacamoleException If permission to alter the access permissions
|
||||||
|
* of affected objects is denied.
|
||||||
|
*/
|
||||||
|
private void deleteUserPermissions(int user_id,
|
||||||
|
Collection<UserPermission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if(permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get list of administerable user IDs
|
||||||
|
List<Integer> administerableUserIDs =
|
||||||
|
permissionCheckService.retrieveUserIDs(this.user_id,
|
||||||
|
MySQLConstants.USER_ADMINISTER);
|
||||||
|
|
||||||
|
// Get set of usernames corresponding to administerable users
|
||||||
|
Map<String, Integer> administerableUsers =
|
||||||
|
userService.translateUsernames(administerableUserIDs);
|
||||||
|
|
||||||
|
// Delete requested permissions
|
||||||
|
for (UserPermission permission : permissions) {
|
||||||
|
|
||||||
|
// Get original ID
|
||||||
|
Integer affected_id =
|
||||||
|
administerableUsers.get(permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Verify that the user actually has permission to administrate
|
||||||
|
// every one of these users
|
||||||
|
if (affected_id == null)
|
||||||
|
throw new GuacamoleSecurityException(
|
||||||
|
"User #" + this.user_id
|
||||||
|
+ " does not have permission to administrate user "
|
||||||
|
+ permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Delete requested permission
|
||||||
|
UserPermissionExample userPermissionExample = new UserPermissionExample();
|
||||||
|
userPermissionExample.createCriteria()
|
||||||
|
.andUser_idEqualTo(user_id)
|
||||||
|
.andPermissionEqualTo(MySQLConstants.getUserConstant(permission.getType()))
|
||||||
|
.andAffected_user_idEqualTo(affected_id);
|
||||||
|
userPermissionDAO.deleteByExample(userPermissionExample);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create any new permissions having to do with connections for a given
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user to assign or remove permissions from.
|
||||||
|
* @param permissions The new permissions the user should have after this
|
||||||
|
* operation completes.
|
||||||
|
* @throws GuacamoleException If permission to alter the access permissions
|
||||||
|
* of affected objects is deniedD
|
||||||
|
*/
|
||||||
|
private void createConnectionPermissions(int user_id,
|
||||||
|
Collection<ConnectionPermission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if(permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get list of administerable connection IDs
|
||||||
|
List<Integer> administerableConnectionIDs =
|
||||||
|
permissionCheckService.retrieveConnectionIDs(this.user_id,
|
||||||
|
MySQLConstants.CONNECTION_ADMINISTER);
|
||||||
|
|
||||||
|
// Get set of names corresponding to administerable connections
|
||||||
|
Map<String, Integer> administerableConnections =
|
||||||
|
connectionService.translateNames(administerableConnectionIDs);
|
||||||
|
|
||||||
|
// Insert all given permissions
|
||||||
|
for (ConnectionPermission permission : permissions) {
|
||||||
|
|
||||||
|
// Get original ID
|
||||||
|
Integer connection_id =
|
||||||
|
administerableConnections.get(permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Throw exception if permission to administer this connection
|
||||||
|
// is not granted
|
||||||
|
if (connection_id == null)
|
||||||
|
throw new GuacamoleSecurityException(
|
||||||
|
"User #" + this.user_id
|
||||||
|
+ " does not have permission to administrate connection "
|
||||||
|
+ permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
|
||||||
|
// Create new permission
|
||||||
|
ConnectionPermissionKey newPermission = new ConnectionPermissionKey();
|
||||||
|
newPermission.setUser_id(user_id);
|
||||||
|
newPermission.setPermission(MySQLConstants.getConnectionConstant(permission.getType()));
|
||||||
|
newPermission.setConnection_id(connection_id);
|
||||||
|
connectionPermissionDAO.insert(newPermission);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete permissions having to do with connections for a given user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user to change the permissions of.
|
||||||
|
* @param permissions The permissions the given user should no longer have
|
||||||
|
* when this operation completes.
|
||||||
|
* @throws GuacamoleException If permission to alter the access permissions
|
||||||
|
* of affected objects is denied.
|
||||||
|
*/
|
||||||
|
private void deleteConnectionPermissions(int user_id,
|
||||||
|
Collection<ConnectionPermission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if(permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get list of administerable connection IDs
|
||||||
|
List<Integer> administerableConnectionIDs =
|
||||||
|
permissionCheckService.retrieveConnectionIDs(this.user_id,
|
||||||
|
MySQLConstants.CONNECTION_ADMINISTER);
|
||||||
|
|
||||||
|
// Get set of names corresponding to administerable connections
|
||||||
|
Map<String, Integer> administerableConnections =
|
||||||
|
connectionService.translateNames(administerableConnectionIDs);
|
||||||
|
|
||||||
|
// Delete requested permissions
|
||||||
|
for (ConnectionPermission permission : permissions) {
|
||||||
|
|
||||||
|
// Get original ID
|
||||||
|
Integer connection_id =
|
||||||
|
administerableConnections.get(permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
// Verify that the user actually has permission to administrate
|
||||||
|
// every one of these connections
|
||||||
|
if (connection_id == null)
|
||||||
|
throw new GuacamoleSecurityException(
|
||||||
|
"User #" + this.user_id
|
||||||
|
+ " does not have permission to administrate connection "
|
||||||
|
+ permission.getObjectIdentifier());
|
||||||
|
|
||||||
|
ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample();
|
||||||
|
connectionPermissionExample.createCriteria()
|
||||||
|
.andUser_idEqualTo(user_id)
|
||||||
|
.andPermissionEqualTo(MySQLConstants.getConnectionConstant(permission.getType()))
|
||||||
|
.andConnection_idEqualTo(connection_id);
|
||||||
|
connectionPermissionDAO.deleteByExample(connectionPermissionExample);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create any new system permissions for a given user. All permissions in
|
||||||
|
* the given list will be inserted.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user whose permissions should be updated.
|
||||||
|
* @param permissions The new system permissions that the given user should
|
||||||
|
* have when this operation completes.
|
||||||
|
* @throws GuacamoleException If permission to administer system permissions
|
||||||
|
* is denied.
|
||||||
|
*/
|
||||||
|
private void createSystemPermissions(int user_id,
|
||||||
|
Collection<SystemPermission> permissions) throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if(permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Only a system administrator can add system permissions.
|
||||||
|
permissionCheckService.verifySystemAccess(
|
||||||
|
this.user_id, SystemPermission.Type.ADMINISTER.name());
|
||||||
|
|
||||||
|
// Insert all requested permissions
|
||||||
|
for (SystemPermission permission : permissions) {
|
||||||
|
|
||||||
|
// Insert permission
|
||||||
|
SystemPermissionKey newSystemPermission = new SystemPermissionKey();
|
||||||
|
newSystemPermission.setUser_id(user_id);
|
||||||
|
newSystemPermission.setPermission(MySQLConstants.getSystemConstant(permission.getType()));
|
||||||
|
systemPermissionDAO.insert(newSystemPermission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete system permissions for a given user. All permissions in
|
||||||
|
* the given list will be removed from the user.
|
||||||
|
*
|
||||||
|
* @param user_id The ID of the user whose permissions should be updated.
|
||||||
|
* @param permissions The permissions the given user should no longer have
|
||||||
|
* when this operation completes.
|
||||||
|
* @throws GuacamoleException If the permissions specified could not be
|
||||||
|
* removed due to system restrictions.
|
||||||
|
*/
|
||||||
|
private void deleteSystemPermissions(int user_id,
|
||||||
|
Collection<SystemPermission> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no permissions given, stop now
|
||||||
|
if (permissions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Prevent self-de-adminifying
|
||||||
|
if (user_id == this.user_id)
|
||||||
|
throw new GuacamoleClientException("Removing your own administrative permissions is not allowed.");
|
||||||
|
|
||||||
|
// Build list of requested system permissions
|
||||||
|
List<String> systemPermissionTypes = new ArrayList<String>();
|
||||||
|
for (SystemPermission permission : permissions)
|
||||||
|
systemPermissionTypes.add(MySQLConstants.getSystemConstant(permission.getType()));
|
||||||
|
|
||||||
|
// Delete the requested system permissions for this user
|
||||||
|
SystemPermissionExample systemPermissionExample = new SystemPermissionExample();
|
||||||
|
systemPermissionExample.createCriteria().andUser_idEqualTo(user_id)
|
||||||
|
.andPermissionIn(systemPermissionTypes);
|
||||||
|
systemPermissionDAO.deleteByExample(systemPermissionExample);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void update(net.sourceforge.guacamole.net.auth.User object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If user not actually from this auth provider, we can't handle updated
|
||||||
|
// permissions.
|
||||||
|
if (!(object instanceof MySQLUser))
|
||||||
|
throw new GuacamoleException("User not from database.");
|
||||||
|
|
||||||
|
MySQLUser mySQLUser = (MySQLUser) object;
|
||||||
|
|
||||||
|
// Validate permission to update this user is granted
|
||||||
|
permissionCheckService.verifyUserAccess(this.user_id,
|
||||||
|
mySQLUser.getUserID(),
|
||||||
|
MySQLConstants.USER_UPDATE);
|
||||||
|
|
||||||
|
// Update the user in the database
|
||||||
|
userService.updateUser(mySQLUser);
|
||||||
|
|
||||||
|
// Update permissions in database
|
||||||
|
createPermissions(mySQLUser.getUserID(), mySQLUser.getNewPermissions());
|
||||||
|
removePermissions(mySQLUser.getUserID(), mySQLUser.getRemovedPermissions());
|
||||||
|
|
||||||
|
// The appropriate permissions have been inserted and deleted, so
|
||||||
|
// reset the new and removed permission sets.
|
||||||
|
mySQLUser.resetPermissions();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void remove(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get user pending deletion
|
||||||
|
MySQLUser user = userService.retrieveUser(identifier);
|
||||||
|
|
||||||
|
// Prevent self-deletion
|
||||||
|
if (user.getUserID() == this.user_id)
|
||||||
|
throw new GuacamoleClientException("Deleting your own user is not allowed.");
|
||||||
|
|
||||||
|
// Validate current user has permission to remove the specified user
|
||||||
|
permissionCheckService.verifyUserAccess(this.user_id,
|
||||||
|
user.getUserID(),
|
||||||
|
MySQLConstants.USER_DELETE);
|
||||||
|
|
||||||
|
// Delete specified user
|
||||||
|
userService.deleteUser(user.getUserID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Base classes which support the MySQL authentication provider, including
|
||||||
|
* the authentication provider itself.
|
||||||
|
*/
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql;
|
||||||
|
|
@@ -0,0 +1,112 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.properties;
|
||||||
|
|
||||||
|
import net.sourceforge.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
|
import net.sourceforge.guacamole.properties.IntegerGuacamoleProperty;
|
||||||
|
import net.sourceforge.guacamole.properties.StringGuacamoleProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties used by the MySQL Authentication plugin.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class MySQLGuacamoleProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class should not be instantiated.
|
||||||
|
*/
|
||||||
|
private MySQLGuacamoleProperties() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of the MySQL server hosting the guacamole authentication tables.
|
||||||
|
*/
|
||||||
|
public static final StringGuacamoleProperty MYSQL_HOSTNAME = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-hostname"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port of the MySQL server hosting the guacamole authentication tables.
|
||||||
|
*/
|
||||||
|
public static final IntegerGuacamoleProperty MYSQL_PORT = new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-port"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the MySQL database containing the guacamole authentication tables.
|
||||||
|
*/
|
||||||
|
public static final StringGuacamoleProperty MYSQL_DATABASE = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-database"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username used to authenticate to the MySQL database containing the guacamole authentication tables.
|
||||||
|
*/
|
||||||
|
public static final StringGuacamoleProperty MYSQL_USERNAME = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-username"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password used to authenticate to the MySQL database containing the guacamole authentication tables.
|
||||||
|
*/
|
||||||
|
public static final StringGuacamoleProperty MYSQL_PASSWORD = new StringGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-password"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not multiple users accessing the same connection at the same time should be disallowed.
|
||||||
|
*/
|
||||||
|
public static final BooleanGuacamoleProperty MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS = new BooleanGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-disallow-simultaneous-connections"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Properties which control the configuration of the MySQL authentication
|
||||||
|
* provider.
|
||||||
|
*/
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.properties;
|
||||||
|
|
@@ -0,0 +1,456 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleClientException;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.GuacamoleSocket;
|
||||||
|
import net.sourceforge.guacamole.net.InetGuacamoleSocket;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.ActiveConnectionSet;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.MySQLConnectionRecord;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.MySQLGuacamoleSocket;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.Connection;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistoryExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
|
||||||
|
import net.sourceforge.guacamole.properties.GuacamoleProperties;
|
||||||
|
import net.sourceforge.guacamole.protocol.ConfiguredGuacamoleSocket;
|
||||||
|
import net.sourceforge.guacamole.protocol.GuacamoleClientInformation;
|
||||||
|
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service which provides convenience methods for creating, retrieving, and
|
||||||
|
* manipulating connections.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper, James Muehlner
|
||||||
|
*/
|
||||||
|
public class ConnectionService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionMapper connectionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing connection parameters.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionParameterMapper connectionParameterDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing connection history.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionHistoryMapper connectionHistoryDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider which creates MySQLConnections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Provider<MySQLConnection> mySQLConnectionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider which creates MySQLGuacamoleSockets.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Provider<MySQLGuacamoleSocket> mySQLGuacamoleSocketProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of all currently active connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ActiveConnectionSet activeConnectionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service managing users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the connection having the given name from the database.
|
||||||
|
*
|
||||||
|
* @param name The name of the connection to return.
|
||||||
|
* @param userID The ID of the user who queried this connection.
|
||||||
|
* @return The connection having the given name, or null if no such
|
||||||
|
* connection could be found.
|
||||||
|
*/
|
||||||
|
public MySQLConnection retrieveConnection(String name, int userID) {
|
||||||
|
|
||||||
|
// Query connection by connection identifier (name)
|
||||||
|
ConnectionExample example = new ConnectionExample();
|
||||||
|
example.createCriteria().andConnection_nameEqualTo(name);
|
||||||
|
List<Connection> connections =
|
||||||
|
connectionDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// If no connection found, return null
|
||||||
|
if(connections.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Assert only one connection found
|
||||||
|
assert connections.size() == 1 : "Multiple connections with same name.";
|
||||||
|
|
||||||
|
// Otherwise, return found connection
|
||||||
|
return toMySQLConnection(connections.get(0), userID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the connection having the given ID from the database.
|
||||||
|
*
|
||||||
|
* @param id The ID of the connection to retrieve.
|
||||||
|
* @param userID The ID of the user who queried this connection.
|
||||||
|
* @return The connection having the given ID, or null if no such
|
||||||
|
* connection was found.
|
||||||
|
*/
|
||||||
|
public MySQLConnection retrieveConnection(int id, int userID) {
|
||||||
|
|
||||||
|
// Query connection by ID
|
||||||
|
Connection connection = connectionDAO.selectByPrimaryKey(id);
|
||||||
|
|
||||||
|
// If no connection found, return null
|
||||||
|
if(connection == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Otherwise, return found connection
|
||||||
|
return toMySQLConnection(connection, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a translation map of connection names to their corresponding
|
||||||
|
* IDs.
|
||||||
|
*
|
||||||
|
* @param ids The IDs of the connections to retrieve the names of.
|
||||||
|
* @return A map containing the names of all connections and their
|
||||||
|
* corresponding IDs.
|
||||||
|
*/
|
||||||
|
public Map<String, Integer> translateNames(List<Integer> ids) {
|
||||||
|
|
||||||
|
// If no IDs given, just return empty map
|
||||||
|
if (ids.isEmpty())
|
||||||
|
return Collections.EMPTY_MAP;
|
||||||
|
|
||||||
|
// Map of all names onto their corresponding IDs.
|
||||||
|
Map<String, Integer> names = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
// Get all connections having the given IDs
|
||||||
|
ConnectionExample example = new ConnectionExample();
|
||||||
|
example.createCriteria().andConnection_idIn(ids);
|
||||||
|
List<Connection> connections = connectionDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Produce set of names
|
||||||
|
for (Connection connection : connections)
|
||||||
|
names.put(connection.getConnection_name(),
|
||||||
|
connection.getConnection_id());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a map of all connection names for the given IDs.
|
||||||
|
*
|
||||||
|
* @param ids The IDs of the connections to retrieve the names of.
|
||||||
|
* @return A map containing the names of all connections and their
|
||||||
|
* corresponding IDs.
|
||||||
|
*/
|
||||||
|
public Map<Integer, String> retrieveNames(Collection<Integer> ids) {
|
||||||
|
|
||||||
|
// If no IDs given, just return empty map
|
||||||
|
if (ids.isEmpty())
|
||||||
|
return Collections.EMPTY_MAP;
|
||||||
|
|
||||||
|
// Map of all names onto their corresponding IDs.
|
||||||
|
Map<Integer, String> names = new HashMap<Integer, String>();
|
||||||
|
|
||||||
|
// Get all connections having the given IDs
|
||||||
|
ConnectionExample example = new ConnectionExample();
|
||||||
|
example.createCriteria().andConnection_idIn(Lists.newArrayList(ids));
|
||||||
|
List<Connection> connections = connectionDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Produce set of names
|
||||||
|
for (Connection connection : connections)
|
||||||
|
names.put(connection.getConnection_id(),
|
||||||
|
connection.getConnection_name());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given database-retrieved Connection into a MySQLConnection.
|
||||||
|
* The parameters of the given connection will be read and added to the
|
||||||
|
* MySQLConnection in the process.
|
||||||
|
*
|
||||||
|
* @param connection The connection to convert.
|
||||||
|
* @param userID The user who queried this connection.
|
||||||
|
* @return A new MySQLConnection containing all data associated with the
|
||||||
|
* specified connection.
|
||||||
|
*/
|
||||||
|
private MySQLConnection toMySQLConnection(Connection connection, int userID) {
|
||||||
|
|
||||||
|
// Build configuration
|
||||||
|
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||||
|
|
||||||
|
// Query parameters for configuration
|
||||||
|
ConnectionParameterExample connectionParameterExample = new ConnectionParameterExample();
|
||||||
|
connectionParameterExample.createCriteria().andConnection_idEqualTo(connection.getConnection_id());
|
||||||
|
List<ConnectionParameter> connectionParameters =
|
||||||
|
connectionParameterDAO.selectByExample(connectionParameterExample);
|
||||||
|
|
||||||
|
// Set protocol
|
||||||
|
config.setProtocol(connection.getProtocol());
|
||||||
|
|
||||||
|
// Set all values for all parameters
|
||||||
|
for (ConnectionParameter parameter : connectionParameters)
|
||||||
|
config.setParameter(parameter.getParameter_name(),
|
||||||
|
parameter.getParameter_value());
|
||||||
|
|
||||||
|
// Create new MySQLConnection from retrieved data
|
||||||
|
MySQLConnection mySQLConnection = mySQLConnectionProvider.get();
|
||||||
|
mySQLConnection.init(
|
||||||
|
connection.getConnection_id(),
|
||||||
|
connection.getConnection_name(),
|
||||||
|
config,
|
||||||
|
retrieveHistory(connection.getConnection_id()),
|
||||||
|
userID
|
||||||
|
);
|
||||||
|
|
||||||
|
return mySQLConnection;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the history of the connection having the given ID.
|
||||||
|
*
|
||||||
|
* @param connectionID The ID of the connection to retrieve the history of.
|
||||||
|
* @return A list of MySQLConnectionRecord documenting the history of this
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public List<MySQLConnectionRecord> retrieveHistory(int connectionID) {
|
||||||
|
|
||||||
|
// Retrieve history records relating to given connection ID
|
||||||
|
ConnectionHistoryExample example = new ConnectionHistoryExample();
|
||||||
|
example.createCriteria().andConnection_idEqualTo(connectionID);
|
||||||
|
|
||||||
|
// We want to return the newest records first
|
||||||
|
example.setOrderByClause("start_date DESC");
|
||||||
|
|
||||||
|
// Set the maximum number of history records returned to 100
|
||||||
|
RowBounds rowBounds = new RowBounds(0, 100);
|
||||||
|
|
||||||
|
// Retrieve all connection history entries
|
||||||
|
List<ConnectionHistory> connectionHistories =
|
||||||
|
connectionHistoryDAO.selectByExampleWithRowbounds(example, rowBounds);
|
||||||
|
|
||||||
|
// Convert history entries to connection records
|
||||||
|
List<MySQLConnectionRecord> connectionRecords = new ArrayList<MySQLConnectionRecord>();
|
||||||
|
Set<Integer> userIDSet = new HashSet<Integer>();
|
||||||
|
for(ConnectionHistory history : connectionHistories) {
|
||||||
|
userIDSet.add(history.getUser_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all the usernames for the users who are in the history
|
||||||
|
Map<Integer, String> usernameMap = userService.retrieveUsernames(userIDSet);
|
||||||
|
|
||||||
|
// Create the new ConnectionRecords
|
||||||
|
for(ConnectionHistory history : connectionHistories) {
|
||||||
|
Date startDate = history.getStart_date();
|
||||||
|
Date endDate = history.getEnd_date();
|
||||||
|
String username = usernameMap.get(history.getUser_id());
|
||||||
|
MySQLConnectionRecord connectionRecord = new MySQLConnectionRecord(startDate, endDate, username);
|
||||||
|
connectionRecords.add(connectionRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a MySQLGuacamoleSocket using the provided connection.
|
||||||
|
*
|
||||||
|
* @param connection The connection to use when connecting the socket.
|
||||||
|
* @param info The information to use when performing the connection
|
||||||
|
* handshake.
|
||||||
|
* @param userID The ID of the user who is connecting to the socket.
|
||||||
|
* @return The connected socket.
|
||||||
|
* @throws GuacamoleException If an error occurs while connecting the
|
||||||
|
* socket.
|
||||||
|
*/
|
||||||
|
public MySQLGuacamoleSocket connect(MySQLConnection connection,
|
||||||
|
GuacamoleClientInformation info, int userID)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If the given connection is active, and multiple simultaneous
|
||||||
|
// connections are not allowed, disallow connection
|
||||||
|
if(GuacamoleProperties.getProperty(
|
||||||
|
MySQLGuacamoleProperties.MYSQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false)
|
||||||
|
&& activeConnectionSet.isActive(connection.getConnectionID()))
|
||||||
|
throw new GuacamoleClientException("Cannot connect. This connection is in use.");
|
||||||
|
|
||||||
|
// Get guacd connection information
|
||||||
|
String host = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_HOSTNAME);
|
||||||
|
int port = GuacamoleProperties.getProperty(GuacamoleProperties.GUACD_PORT);
|
||||||
|
|
||||||
|
// Get socket
|
||||||
|
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
|
||||||
|
new InetGuacamoleSocket(host, port),
|
||||||
|
connection.getConfiguration(), info
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mark this connection as active
|
||||||
|
int historyID = activeConnectionSet.openConnection(connection.getConnectionID(), userID);
|
||||||
|
|
||||||
|
// Return new MySQLGuacamoleSocket
|
||||||
|
MySQLGuacamoleSocket mySQLGuacamoleSocket = mySQLGuacamoleSocketProvider.get();
|
||||||
|
mySQLGuacamoleSocket.init(socket, connection.getConnectionID(), historyID);
|
||||||
|
return mySQLGuacamoleSocket;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new connection having the given name and protocol.
|
||||||
|
*
|
||||||
|
* @param name The name to assign to the new connection.
|
||||||
|
* @param protocol The protocol to assign to the new connection.
|
||||||
|
* @param userID The ID of the user who created this connection.
|
||||||
|
* @return A new MySQLConnection containing the data of the newly created
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
public MySQLConnection createConnection(String name, String protocol, int userID) {
|
||||||
|
|
||||||
|
// Initialize database connection
|
||||||
|
Connection connection = new Connection();
|
||||||
|
connection.setConnection_name(name);
|
||||||
|
connection.setProtocol(protocol);
|
||||||
|
|
||||||
|
// Create connection
|
||||||
|
connectionDAO.insert(connection);
|
||||||
|
return toMySQLConnection(connection, userID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the connection having the given ID from the database.
|
||||||
|
* @param id The ID of the connection to delete.
|
||||||
|
*/
|
||||||
|
public void deleteConnection(int id) {
|
||||||
|
connectionDAO.deleteByPrimaryKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the connection in the database corresponding to the given
|
||||||
|
* MySQLConnection.
|
||||||
|
*
|
||||||
|
* @param mySQLConnection The MySQLConnection to update (save) to the
|
||||||
|
* database. This connection must already exist.
|
||||||
|
*/
|
||||||
|
public void updateConnection(MySQLConnection mySQLConnection) {
|
||||||
|
|
||||||
|
// Populate connection
|
||||||
|
Connection connection = new Connection();
|
||||||
|
connection.setConnection_id(mySQLConnection.getConnectionID());
|
||||||
|
connection.setConnection_name(mySQLConnection.getIdentifier());
|
||||||
|
connection.setProtocol(mySQLConnection.getConfiguration().getProtocol());
|
||||||
|
|
||||||
|
// Update the connection in the database
|
||||||
|
connectionDAO.updateByPrimaryKeySelective(connection);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the names of all the connections defined in the system.
|
||||||
|
*
|
||||||
|
* @return A Set of names of all the connections defined in the system.
|
||||||
|
*/
|
||||||
|
public Set<String> getAllConnectionNames() {
|
||||||
|
|
||||||
|
// Set of all present connection names
|
||||||
|
Set<String> names = new HashSet<String>();
|
||||||
|
|
||||||
|
// Query all connection names
|
||||||
|
List<Connection> connections =
|
||||||
|
connectionDAO.selectByExample(new ConnectionExample());
|
||||||
|
for (Connection connection : connections)
|
||||||
|
names.add(connection.getConnection_name());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the connection IDs of all the connections defined in the system.
|
||||||
|
*
|
||||||
|
* @return A list of connection IDs of all the connections defined in the system.
|
||||||
|
*/
|
||||||
|
public List<Integer> getAllConnectionIDs() {
|
||||||
|
|
||||||
|
// Set of all present connection IDs
|
||||||
|
List<Integer> connectionIDs = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
// Query all connection IDs
|
||||||
|
List<Connection> connections =
|
||||||
|
connectionDAO.selectByExample(new ConnectionExample());
|
||||||
|
for (Connection connection : connections)
|
||||||
|
connectionIDs.add(connection.getConnection_id());
|
||||||
|
|
||||||
|
return connectionIDs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service to perform password encryption and checking.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public interface PasswordEncryptionService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the provided, unhashed password matches the given
|
||||||
|
* hash/salt pair.
|
||||||
|
*
|
||||||
|
* @param password The unhashed password to validate.
|
||||||
|
* @param hashedPassword The hashed password to compare the given password
|
||||||
|
* against.
|
||||||
|
* @param salt The salt used when the hashed password given was created.
|
||||||
|
* @return true if the provided credentials match the values given, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
public boolean checkPassword(String password, byte[] hashedPassword,
|
||||||
|
byte[] salt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
@@ -0,0 +1,497 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleSecurityException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.MySQLConstants;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserPermissionKey;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.ConnectionPermission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.Permission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
import net.sourceforge.guacamole.net.auth.permission.UserPermission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service to retrieve information about what objects a user has permission to.
|
||||||
|
* @author James Muehlner
|
||||||
|
*/
|
||||||
|
public class PermissionCheckService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for accessing users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for accessing connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionService connectionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing permissions related to users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserPermissionMapper userPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing permissions related to connections.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ConnectionPermissionMapper connectionPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing permissions related to the system as a whole.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private SystemPermissionMapper systemPermissionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the user has the specified access to the given other
|
||||||
|
* user. If permission is denied, a GuacamoleSecurityException is thrown.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param affectedUserID The user that would be affected by the operation
|
||||||
|
* if permission is granted.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @throws GuacamoleSecurityException If the specified permission is not
|
||||||
|
* granted.
|
||||||
|
*/
|
||||||
|
public void verifyUserAccess(int userID, int affectedUserID,
|
||||||
|
String permissionType) throws GuacamoleSecurityException {
|
||||||
|
|
||||||
|
// If permission does not exist, throw exception
|
||||||
|
if(!checkUserAccess(userID, affectedUserID, permissionType))
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the user has the specified access to the given connection.
|
||||||
|
* If permission is denied, a GuacamoleSecurityException is thrown.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param affectedConnectionID The connection that would be affected by the
|
||||||
|
* operation if permission is granted.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @throws GuacamoleSecurityException If the specified permission is not
|
||||||
|
* granted.
|
||||||
|
*/
|
||||||
|
public void verifyConnectionAccess(int userID, int affectedConnectionID, String permissionType) throws GuacamoleSecurityException {
|
||||||
|
|
||||||
|
// If permission does not exist, throw exception
|
||||||
|
if(!checkConnectionAccess(userID, affectedConnectionID, permissionType))
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Verifies that the user has the specified access to the system. If
|
||||||
|
* permission is denied, a GuacamoleSecurityException is thrown.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param systemPermissionType The type of permission to check for.
|
||||||
|
* @throws GuacamoleSecurityException If the specified permission is not
|
||||||
|
* granted.
|
||||||
|
*/
|
||||||
|
public void verifySystemAccess(int userID, String systemPermissionType)
|
||||||
|
throws GuacamoleSecurityException {
|
||||||
|
|
||||||
|
// If permission does not exist, throw exception
|
||||||
|
if(!checkSystemAccess(userID, systemPermissionType))
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user has the specified type of access to the affected
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param affectedUserID The user that would be affected by the operation
|
||||||
|
* if permission is granted.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @return true if the specified permission is granted, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean checkUserAccess(int userID, Integer affectedUserID, String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has full access to everything.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check existence of requested permission
|
||||||
|
UserPermissionExample example = new UserPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).andAffected_user_idEqualTo(affectedUserID).andPermissionEqualTo(permissionType);
|
||||||
|
return userPermissionDAO.countByExample(example) > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user has the specified type of access to the affected
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param affectedConnectionID The connection that would be affected by the
|
||||||
|
* operation if permission is granted.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @return true if the specified permission is granted, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean checkConnectionAccess(int userID, Integer affectedConnectionID, String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has full access to everything.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check existence of requested permission
|
||||||
|
ConnectionPermissionExample example = new ConnectionPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).andConnection_idEqualTo(affectedConnectionID).andPermissionEqualTo(permissionType);
|
||||||
|
return connectionPermissionDAO.countByExample(example) > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user has the specified type of access to the system.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param systemPermissionType The type of permission to check for.
|
||||||
|
* @return true if the specified permission is granted, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean checkSystemAccess(int userID, String systemPermissionType) {
|
||||||
|
|
||||||
|
// A system administrator has full access to everything.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check existence of requested permission
|
||||||
|
SystemPermissionExample example = new SystemPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(systemPermissionType);
|
||||||
|
return systemPermissionDAO.countByExample(example) > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a user has system administrator access to the system.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @return true if the system administrator access exists, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean checkSystemAdministratorAccess(int userID) {
|
||||||
|
|
||||||
|
// Check existence of system administrator permission
|
||||||
|
SystemPermissionExample example = new SystemPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).
|
||||||
|
andPermissionEqualTo(MySQLConstants.SYSTEM_ADMINISTER);
|
||||||
|
return systemPermissionDAO.countByExample(example) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the list of the IDs of all users a user has permission to.
|
||||||
|
* The access type is defined by permissionType.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @return A list of all user IDs this user has the specified access to.
|
||||||
|
*/
|
||||||
|
public List<Integer> retrieveUserIDs(int userID, String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has access to all users.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return userService.getAllUserIDs();
|
||||||
|
|
||||||
|
// Query all user permissions for the given user and permission type
|
||||||
|
UserPermissionExample example = new UserPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType);
|
||||||
|
example.setDistinct(true);
|
||||||
|
List<UserPermissionKey> userPermissions =
|
||||||
|
userPermissionDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Convert result into list of IDs
|
||||||
|
List<Integer> userIDs = new ArrayList<Integer>(userPermissions.size());
|
||||||
|
for(UserPermissionKey permission : userPermissions)
|
||||||
|
userIDs.add(permission.getAffected_user_id());
|
||||||
|
|
||||||
|
return userIDs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the list of the IDs of all connections a user has permission to.
|
||||||
|
* The access type is defined by permissionType.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to check.
|
||||||
|
* @param permissionType The type of permission to check for.
|
||||||
|
* @return A list of all connection IDs this user has the specified access
|
||||||
|
* to.
|
||||||
|
*/
|
||||||
|
public List<Integer> retrieveConnectionIDs(int userID,
|
||||||
|
String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has access to all connections.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return connectionService.getAllConnectionIDs();
|
||||||
|
|
||||||
|
// Query all connection permissions for the given user and permission type
|
||||||
|
ConnectionPermissionExample example = new ConnectionPermissionExample();
|
||||||
|
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType);
|
||||||
|
example.setDistinct(true);
|
||||||
|
List<ConnectionPermissionKey> connectionPermissions =
|
||||||
|
connectionPermissionDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Convert result into list of IDs
|
||||||
|
List<Integer> connectionIDs = new ArrayList<Integer>(connectionPermissions.size());
|
||||||
|
for(ConnectionPermissionKey permission : connectionPermissions)
|
||||||
|
connectionIDs.add(permission.getConnection_id());
|
||||||
|
|
||||||
|
return connectionIDs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all existing usernames that the given user has permission to
|
||||||
|
* perform the given operation upon.
|
||||||
|
*
|
||||||
|
* @param userID The user whose permissions should be checked.
|
||||||
|
* @param permissionType The permission to check.
|
||||||
|
* @return A set of all usernames for which the given user has the given
|
||||||
|
* permission.
|
||||||
|
*/
|
||||||
|
public Set<String> retrieveUsernames(int userID, String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has access to all users.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return userService.getAllUsernames();
|
||||||
|
|
||||||
|
// List of all user IDs for which this user has read access
|
||||||
|
List<Integer> userIDs =
|
||||||
|
retrieveUserIDs(userID, MySQLConstants.USER_READ);
|
||||||
|
|
||||||
|
// Query all associated users
|
||||||
|
return userService.translateUsernames(userIDs).keySet();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all existing connection names that the given user has permission
|
||||||
|
* to perform the given operation upon.
|
||||||
|
*
|
||||||
|
* @param userID The user whose permissions should be checked.
|
||||||
|
* @param permissionType The permission to check.
|
||||||
|
* @return A set of all connection names for which the given user has the
|
||||||
|
* given permission.
|
||||||
|
*/
|
||||||
|
public Set<String> retrieveConnectionNames(int userID, String permissionType) {
|
||||||
|
|
||||||
|
// A system administrator has access to all connections.
|
||||||
|
if(checkSystemAdministratorAccess(userID))
|
||||||
|
return connectionService.getAllConnectionNames();
|
||||||
|
|
||||||
|
// List of all connection IDs for which this connection has read access
|
||||||
|
List<Integer> connectionIDs =
|
||||||
|
retrieveConnectionIDs(userID, MySQLConstants.CONNECTION_READ);
|
||||||
|
|
||||||
|
// Query all associated connections
|
||||||
|
return connectionService.translateNames(connectionIDs).keySet();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all user permissions granted to the user having the given ID.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to retrieve permissions of.
|
||||||
|
* @return A set of all user permissions granted to the user having the
|
||||||
|
* given ID.
|
||||||
|
*/
|
||||||
|
public Set<UserPermission> retrieveUserPermissions(int userID) {
|
||||||
|
|
||||||
|
// Set of all permissions
|
||||||
|
Set<UserPermission> permissions = new HashSet<UserPermission>();
|
||||||
|
|
||||||
|
// Query all user permissions
|
||||||
|
UserPermissionExample userPermissionExample = new UserPermissionExample();
|
||||||
|
userPermissionExample.createCriteria().andUser_idEqualTo(userID);
|
||||||
|
List<UserPermissionKey> userPermissions =
|
||||||
|
userPermissionDAO.selectByExample(userPermissionExample);
|
||||||
|
|
||||||
|
// Get list of affected user IDs
|
||||||
|
List<Integer> affectedUserIDs = new ArrayList<Integer>();
|
||||||
|
for(UserPermissionKey userPermission : userPermissions)
|
||||||
|
affectedUserIDs.add(userPermission.getAffected_user_id());
|
||||||
|
|
||||||
|
// Get corresponding usernames
|
||||||
|
Map<Integer, String> affectedUsers =
|
||||||
|
userService.retrieveUsernames(affectedUserIDs);
|
||||||
|
|
||||||
|
// Add user permissions
|
||||||
|
for(UserPermissionKey userPermission : userPermissions) {
|
||||||
|
|
||||||
|
// Construct permission from data
|
||||||
|
UserPermission permission = new UserPermission(
|
||||||
|
UserPermission.Type.valueOf(userPermission.getPermission()),
|
||||||
|
affectedUsers.get(userPermission.getAffected_user_id())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add to set
|
||||||
|
permissions.add(permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all connection permissions granted to the user having the
|
||||||
|
* given ID.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to retrieve permissions of.
|
||||||
|
* @return A set of all connection permissions granted to the user having
|
||||||
|
* the given ID.
|
||||||
|
*/
|
||||||
|
public Set<ConnectionPermission> retrieveConnectionPermissions(int userID) {
|
||||||
|
|
||||||
|
// Set of all permissions
|
||||||
|
Set<ConnectionPermission> permissions = new HashSet<ConnectionPermission>();
|
||||||
|
|
||||||
|
// Query all connection permissions
|
||||||
|
ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample();
|
||||||
|
connectionPermissionExample.createCriteria().andUser_idEqualTo(userID);
|
||||||
|
List<ConnectionPermissionKey> connectionPermissions =
|
||||||
|
connectionPermissionDAO.selectByExample(connectionPermissionExample);
|
||||||
|
|
||||||
|
// Get list of affected connection IDs
|
||||||
|
List<Integer> connectionIDs = new ArrayList<Integer>();
|
||||||
|
for(ConnectionPermissionKey connectionPermission : connectionPermissions)
|
||||||
|
connectionIDs.add(connectionPermission.getConnection_id());
|
||||||
|
|
||||||
|
// Get corresponding names
|
||||||
|
Map<Integer, String> affectedConnections =
|
||||||
|
connectionService.retrieveNames(connectionIDs);
|
||||||
|
|
||||||
|
// Add connection permissions
|
||||||
|
for(ConnectionPermissionKey connectionPermission : connectionPermissions) {
|
||||||
|
|
||||||
|
// Construct permission from data
|
||||||
|
ConnectionPermission permission = new ConnectionPermission(
|
||||||
|
ConnectionPermission.Type.valueOf(connectionPermission.getPermission()),
|
||||||
|
affectedConnections.get(connectionPermission.getConnection_id())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add to set
|
||||||
|
permissions.add(permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all system permissions granted to the user having the
|
||||||
|
* given ID.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to retrieve permissions of.
|
||||||
|
* @return A set of all system permissions granted to the user having the
|
||||||
|
* given ID.
|
||||||
|
*/
|
||||||
|
public Set<SystemPermission> retrieveSystemPermissions(int userID) {
|
||||||
|
|
||||||
|
// Set of all permissions
|
||||||
|
Set<SystemPermission> permissions = new HashSet<SystemPermission>();
|
||||||
|
|
||||||
|
// And finally, system permissions
|
||||||
|
SystemPermissionExample systemPermissionExample = new SystemPermissionExample();
|
||||||
|
systemPermissionExample.createCriteria().andUser_idEqualTo(userID);
|
||||||
|
List<SystemPermissionKey> systemPermissions =
|
||||||
|
systemPermissionDAO.selectByExample(systemPermissionExample);
|
||||||
|
for(SystemPermissionKey systemPermission : systemPermissions) {
|
||||||
|
|
||||||
|
// User creation permission
|
||||||
|
if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_USER_CREATE))
|
||||||
|
permissions.add(new SystemPermission(SystemPermission.Type.CREATE_USER));
|
||||||
|
|
||||||
|
// System creation permission
|
||||||
|
else if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_CONNECTION_CREATE))
|
||||||
|
permissions.add(new SystemPermission(SystemPermission.Type.CREATE_CONNECTION));
|
||||||
|
|
||||||
|
// System administration permission
|
||||||
|
else if(systemPermission.getPermission().equals(MySQLConstants.SYSTEM_ADMINISTER))
|
||||||
|
permissions.add(new SystemPermission(SystemPermission.Type.ADMINISTER));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all permissions granted to the user having the given ID.
|
||||||
|
*
|
||||||
|
* @param userID The ID of the user to retrieve permissions of.
|
||||||
|
* @return A set of all permissions granted to the user having the given
|
||||||
|
* ID.
|
||||||
|
*/
|
||||||
|
public Set<Permission> retrieveAllPermissions(int userID) {
|
||||||
|
|
||||||
|
// Set which will contain all permissions
|
||||||
|
Set<Permission> allPermissions = new HashSet<Permission>();
|
||||||
|
|
||||||
|
// Add user permissions
|
||||||
|
allPermissions.addAll(retrieveUserPermissions(userID));
|
||||||
|
|
||||||
|
// Add connection permissions
|
||||||
|
allPermissions.addAll(retrieveConnectionPermissions(userID));
|
||||||
|
|
||||||
|
// Add system permissions
|
||||||
|
allPermissions.addAll(retrieveSystemPermissions(userID));
|
||||||
|
|
||||||
|
return allPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,90 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
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 boolean checkPassword(String password, byte[] hashedPassword,
|
||||||
|
byte[] salt) {
|
||||||
|
|
||||||
|
// Compare bytes of password in credentials against hashed password
|
||||||
|
byte[] passwordBytes = createPasswordHash(password, salt);
|
||||||
|
return Arrays.equals(passwordBytes, hashedPassword);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,381 @@
|
|||||||
|
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is guacamole-auth-mysql.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* James Muehlner.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.sourceforge.guacamole.GuacamoleException;
|
||||||
|
import net.sourceforge.guacamole.net.auth.Credentials;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.MySQLUser;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.User;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserExample;
|
||||||
|
import net.sourceforge.guacamole.net.auth.mysql.model.UserWithBLOBs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service which provides convenience methods for creating, retrieving, and
|
||||||
|
* manipulating users.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper, James Muehlner
|
||||||
|
*/
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO for accessing users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserMapper userDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider for creating users.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private Provider<MySQLUser> mySQLUserProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for checking permissions.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PermissionCheckService permissionCheckService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for encrypting passwords.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private PasswordEncryptionService passwordService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for generating random salts.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private SaltService saltService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MySQLUser based on the provided User.
|
||||||
|
*
|
||||||
|
* @param user The User to use when populating the data of the given
|
||||||
|
* MySQLUser.
|
||||||
|
* @return A new MySQLUser object, populated with the data of the given
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException If an error occurs while reading the data
|
||||||
|
* of the provided User.
|
||||||
|
*/
|
||||||
|
public MySQLUser toMySQLUser(net.sourceforge.guacamole.net.auth.User user) throws GuacamoleException {
|
||||||
|
MySQLUser mySQLUser = mySQLUserProvider.get();
|
||||||
|
mySQLUser.init(user);
|
||||||
|
return mySQLUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MySQLUser based on the provided database record.
|
||||||
|
*
|
||||||
|
* @param user The database record describing the user.
|
||||||
|
* @return A new MySQLUser object, populated with the data of the given
|
||||||
|
* database record.
|
||||||
|
*/
|
||||||
|
private MySQLUser toMySQLUser(UserWithBLOBs user) {
|
||||||
|
|
||||||
|
// Retrieve user from provider
|
||||||
|
MySQLUser mySQLUser = mySQLUserProvider.get();
|
||||||
|
|
||||||
|
// Init with data from given database user
|
||||||
|
mySQLUser.init(
|
||||||
|
user.getUser_id(),
|
||||||
|
user.getUsername(),
|
||||||
|
null,
|
||||||
|
permissionCheckService.retrieveAllPermissions(user.getUser_id())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return new user
|
||||||
|
return mySQLUser;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the user having the given ID from the database.
|
||||||
|
*
|
||||||
|
* @param id The ID of the user to retrieve.
|
||||||
|
* @return The existing MySQLUser object if found, null otherwise.
|
||||||
|
*/
|
||||||
|
public MySQLUser retrieveUser(int id) {
|
||||||
|
|
||||||
|
// Query user by ID
|
||||||
|
UserWithBLOBs user = userDAO.selectByPrimaryKey(id);
|
||||||
|
|
||||||
|
// If no user found, return null
|
||||||
|
if(user == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Otherwise, return found user
|
||||||
|
return toMySQLUser(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the user having the given username from the database.
|
||||||
|
*
|
||||||
|
* @param name The username of the user to retrieve.
|
||||||
|
* @return The existing MySQLUser object if found, null otherwise.
|
||||||
|
*/
|
||||||
|
public MySQLUser retrieveUser(String name) {
|
||||||
|
|
||||||
|
// Query user by ID
|
||||||
|
UserExample example = new UserExample();
|
||||||
|
example.createCriteria().andUsernameEqualTo(name);
|
||||||
|
List<UserWithBLOBs> users = userDAO.selectByExampleWithBLOBs(example);
|
||||||
|
|
||||||
|
// If no user found, return null
|
||||||
|
if(users.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Otherwise, return found user
|
||||||
|
return toMySQLUser(users.get(0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
// No null users in database
|
||||||
|
if (credentials.getUsername() == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Query user
|
||||||
|
UserExample userExample = new UserExample();
|
||||||
|
userExample.createCriteria().andUsernameEqualTo(credentials.getUsername());
|
||||||
|
List<UserWithBLOBs> users = userDAO.selectByExampleWithBLOBs(userExample);
|
||||||
|
|
||||||
|
// Check that a user was found
|
||||||
|
if (users.isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Assert only one user found
|
||||||
|
assert users.size() == 1 : "Multiple users with same username.";
|
||||||
|
|
||||||
|
// Get first (and only) user
|
||||||
|
UserWithBLOBs user = users.get(0);
|
||||||
|
|
||||||
|
// Check password, if invalid return null
|
||||||
|
if (!passwordService.checkPassword(credentials.getPassword(),
|
||||||
|
user.getPassword_hash(), user.getPassword_salt()))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Return found user
|
||||||
|
return toMySQLUser(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a translation map of usernames to their corresponding IDs.
|
||||||
|
*
|
||||||
|
* @param ids The IDs of the users to retrieve the usernames of.
|
||||||
|
* @return A map containing the names of all users and their corresponding
|
||||||
|
* IDs.
|
||||||
|
*/
|
||||||
|
public Map<String, Integer> translateUsernames(List<Integer> ids) {
|
||||||
|
|
||||||
|
// If no IDs given, just return empty map
|
||||||
|
if (ids.isEmpty())
|
||||||
|
return Collections.EMPTY_MAP;
|
||||||
|
|
||||||
|
// Map of all names onto their corresponding IDs
|
||||||
|
Map<String, Integer> names = new HashMap<String, Integer>();
|
||||||
|
|
||||||
|
// Get all users having the given IDs
|
||||||
|
UserExample example = new UserExample();
|
||||||
|
example.createCriteria().andUser_idIn(ids);
|
||||||
|
List<User> users =
|
||||||
|
userDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Produce set of names
|
||||||
|
for (User user : users)
|
||||||
|
names.put(user.getUsername(), user.getUser_id());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a map of all usernames for the given IDs.
|
||||||
|
*
|
||||||
|
* @param ids The IDs of the users to retrieve the usernames of.
|
||||||
|
* @return A map containing the names of all users and their corresponding
|
||||||
|
* IDs.
|
||||||
|
*/
|
||||||
|
public Map<Integer, String> retrieveUsernames(Collection<Integer> ids) {
|
||||||
|
|
||||||
|
// If no IDs given, just return empty map
|
||||||
|
if (ids.isEmpty())
|
||||||
|
return Collections.EMPTY_MAP;
|
||||||
|
|
||||||
|
// Map of all names onto their corresponding IDs
|
||||||
|
Map<Integer, String> names = new HashMap<Integer, String>();
|
||||||
|
|
||||||
|
// Get all users having the given IDs
|
||||||
|
UserExample example = new UserExample();
|
||||||
|
example.createCriteria().andUser_idIn(Lists.newArrayList(ids));
|
||||||
|
List<User> users =
|
||||||
|
userDAO.selectByExample(example);
|
||||||
|
|
||||||
|
// Produce set of names
|
||||||
|
for (User user : users)
|
||||||
|
names.put(user.getUser_id(), user.getUsername());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new user having the given username and password.
|
||||||
|
*
|
||||||
|
* @param username The username to assign to the new user.
|
||||||
|
* @param password The password to assign to the new user.
|
||||||
|
* @return A new MySQLUser containing the data of the newly created
|
||||||
|
* user.
|
||||||
|
*/
|
||||||
|
public MySQLUser createUser(String username, String password) {
|
||||||
|
|
||||||
|
// Initialize database user
|
||||||
|
UserWithBLOBs user = new UserWithBLOBs();
|
||||||
|
user.setUsername(username);
|
||||||
|
|
||||||
|
// Set password if specified
|
||||||
|
if (password != null) {
|
||||||
|
byte[] salt = saltService.generateSalt();
|
||||||
|
user.setPassword_salt(salt);
|
||||||
|
user.setPassword_hash(
|
||||||
|
passwordService.createPasswordHash(password, salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create user
|
||||||
|
userDAO.insert(user);
|
||||||
|
return toMySQLUser(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the user having the given ID from the database.
|
||||||
|
* @param user_id The ID of the user to delete.
|
||||||
|
*/
|
||||||
|
public void deleteUser(int user_id) {
|
||||||
|
userDAO.deleteByPrimaryKey(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the user in the database corresponding to the given MySQLUser.
|
||||||
|
*
|
||||||
|
* @param mySQLUser The MySQLUser to update (save) to the database. This
|
||||||
|
* user must already exist.
|
||||||
|
*/
|
||||||
|
public void updateUser(MySQLUser mySQLUser) {
|
||||||
|
|
||||||
|
UserWithBLOBs user = new UserWithBLOBs();
|
||||||
|
user.setUser_id(mySQLUser.getUserID());
|
||||||
|
user.setUsername(mySQLUser.getUsername());
|
||||||
|
|
||||||
|
// Set password if specified
|
||||||
|
if (mySQLUser.getPassword() != null) {
|
||||||
|
byte[] salt = saltService.generateSalt();
|
||||||
|
user.setPassword_salt(salt);
|
||||||
|
user.setPassword_hash(
|
||||||
|
passwordService.createPasswordHash(mySQLUser.getPassword(), salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the user in the database
|
||||||
|
userDAO.updateByPrimaryKeySelective(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the usernames of all the users defined in the system.
|
||||||
|
*
|
||||||
|
* @return A Set of usernames of all the users defined in the system.
|
||||||
|
*/
|
||||||
|
public Set<String> getAllUsernames() {
|
||||||
|
|
||||||
|
// Set of all present usernames
|
||||||
|
Set<String> usernames = new HashSet<String>();
|
||||||
|
|
||||||
|
// Query all usernames
|
||||||
|
List<User> users =
|
||||||
|
userDAO.selectByExample(new UserExample());
|
||||||
|
for (User user : users)
|
||||||
|
usernames.add(user.getUsername());
|
||||||
|
|
||||||
|
return usernames;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user IDs of all the users defined in the system.
|
||||||
|
*
|
||||||
|
* @return A list of user IDs of all the users defined in the system.
|
||||||
|
*/
|
||||||
|
public List<Integer> getAllUserIDs() {
|
||||||
|
|
||||||
|
// Set of all present user IDs
|
||||||
|
List<Integer> userIDs = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
// Query all user IDs
|
||||||
|
List<User> users =
|
||||||
|
userDAO.selectByExample(new UserExample());
|
||||||
|
for (User user : users)
|
||||||
|
userIDs.add(user.getUser_id());
|
||||||
|
|
||||||
|
return userIDs;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Service classes which help fill the needs of the MySQL authentication
|
||||||
|
* provider.
|
||||||
|
*/
|
||||||
|
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||||
|
|
@@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE generatorConfiguration
|
||||||
|
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
|
||||||
|
|
||||||
|
<generatorConfiguration>
|
||||||
|
<context id="guacamoleTables" targetRuntime="MyBatis3">
|
||||||
|
|
||||||
|
<!-- Allow selectByExample with RowBounds -->
|
||||||
|
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/>
|
||||||
|
|
||||||
|
<!-- MySQL JDBC driver class. -->
|
||||||
|
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
|
||||||
|
connectionURL="jdbc:mysql://127.0.0.1:3306"
|
||||||
|
userId="${guacamole.database.user}"
|
||||||
|
password="${guacamole.database.password}"/>
|
||||||
|
|
||||||
|
<javaModelGenerator
|
||||||
|
targetPackage="net.sourceforge.guacamole.net.auth.mysql.model"
|
||||||
|
targetProject="MAVEN"/>
|
||||||
|
|
||||||
|
<sqlMapGenerator
|
||||||
|
targetPackage="net.sourceforge.guacamole.net.auth.mysql.dao"
|
||||||
|
targetProject="MAVEN"/>
|
||||||
|
|
||||||
|
<javaClientGenerator type="XMLMAPPER"
|
||||||
|
targetPackage="net.sourceforge.guacamole.net.auth.mysql.dao"
|
||||||
|
targetProject="MAVEN"/>
|
||||||
|
|
||||||
|
<!-- TABLES -->
|
||||||
|
|
||||||
|
<table tableName="guacamole_connection"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="Connection" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
<generatedKey column="connection_id" identity="true"
|
||||||
|
sqlStatement="SELECT LAST_INSERT_ID()"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_connection_parameter"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="ConnectionParameter" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_connection_permission"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="ConnectionPermission" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_system_permission"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="SystemPermission" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_user"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="User" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
<generatedKey column="user_id" identity="true"
|
||||||
|
sqlStatement="SELECT LAST_INSERT_ID()"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_user_permission"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="UserPermission" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table tableName="guacamole_connection_history"
|
||||||
|
catalog="${guacamole.database.catalog}"
|
||||||
|
schema="${guacamole.database.schema}"
|
||||||
|
domainObjectName="ConnectionHistory" >
|
||||||
|
<property name="useActualColumnNames" value="true"/>
|
||||||
|
<property name="ignoreQualifiersAtRuntime" value="true"/>
|
||||||
|
<generatedKey column="history_id" identity="true"
|
||||||
|
sqlStatement="SELECT LAST_INSERT_ID()"/>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</context>
|
||||||
|
</generatorConfiguration>
|
||||||
|
|
Reference in New Issue
Block a user