GUACAMOLE-416: Merge addition of missing translation strings for SQL Server auth.

This commit is contained in:
James Muehlner
2017-10-22 19:43:30 -07:00
131 changed files with 7830 additions and 375 deletions

View File

@@ -1,6 +1,5 @@
.git .git
**/.gitignore
**/*~ **/*~
**/target/ **/target/

View File

@@ -21,29 +21,36 @@
# Dockerfile for guacamole-client # Dockerfile for guacamole-client
# #
# Start from Tomcat image # Use args for Tomcat image label to allow image builder to choose alternatives
FROM tomcat:8.0.20-jre8 # such as `--build-arg TOMCAT_JRE=jre8-alpine`
#
ARG TOMCAT_VERSION=8.0.20
ARG TOMCAT_JRE=jre8
# Environment variables # Use official maven image for the build
FROM maven:3-jdk-8 AS builder
# Build environment variables
ENV \ ENV \
BUILD_DIR=/tmp/guacamole-docker-BUILD \ BUILD_DIR=/tmp/guacamole-docker-BUILD
BUILD_DEPENDENCIES=" \
maven \
openjdk-8-jdk-headless"
# Add configuration scripts # Add configuration scripts
COPY guacamole-docker/bin /opt/guacamole/bin/ COPY guacamole-docker/bin/ /opt/guacamole/bin/
# Copy source to container for sake of build # Copy source to container for sake of build
COPY . "$BUILD_DIR" COPY . "$BUILD_DIR"
# Build latest guacamole-client and authentication # Run the build itself
RUN apt-get update && \ RUN /opt/guacamole/bin/build-guacamole.sh "$BUILD_DIR" /opt/guacamole
apt-get install -y --no-install-recommends $BUILD_DEPENDENCIES && \
/opt/guacamole/bin/build-guacamole.sh "$BUILD_DIR" /opt/guacamole && \ # For the runtime image, we start with the official Tomcat distribution
rm -Rf "$BUILD_DIR" && \ FROM tomcat:${TOMCAT_VERSION}-${TOMCAT_JRE}
rm -Rf /var/lib/apt/lists/* && \
apt-get purge -y --auto-remove $BUILD_DEPENDENCIES # This is where the build artifacts go in the runtime image
WORKDIR /opt/guacamole
# Copy artifacts from builder image into this image
COPY --from=builder /opt/guacamole/ .
# Start Guacamole under Tomcat, listening on 0.0.0.0:8080 # Start Guacamole under Tomcat, listening on 0.0.0.0:8080
EXPOSE 8080 EXPOSE 8080

View File

@@ -107,4 +107,9 @@ public class CASAuthenticationProvider implements AuthenticationProvider {
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -102,4 +102,9 @@ public class DuoAuthenticationProvider implements AuthenticationProvider {
return context; return context;
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -107,4 +107,9 @@ public class HTTPHeaderAuthenticationProvider implements AuthenticationProvider
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -104,4 +104,9 @@ public abstract class InjectedAuthenticationProvider implements AuthenticationPr
authenticatedUser, credentials); authenticatedUser, credentials);
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -27,15 +27,17 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject; import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.ActivityRecordSet.SortableProperty;
import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.net.auth.ConnectionRecord;
/** /**
* A JDBC implementation of ConnectionRecordSet. Calls to asCollection() will * A JDBC implementation of ActivityRecordSet for ConnectionRecords. Calls to
* query connection history records from the database. Which records are * asCollection() will query connection history records from the database. Which
* returned will be determined by the values passed in earlier. * records are returned will be determined by the values passed in earlier.
*/ */
public class ConnectionRecordSet extends RestrictedObject public class ConnectionRecordSet extends RestrictedObject
implements org.apache.guacamole.net.auth.ConnectionRecordSet { implements ActivityRecordSet<ConnectionRecord> {
/** /**
* Service for managing connection objects. * Service for managing connection objects.

View File

@@ -19,7 +19,7 @@
package org.apache.guacamole.auth.jdbc.connection; package org.apache.guacamole.auth.jdbc.connection;
import org.apache.guacamole.net.auth.ConnectionRecordSet; import org.apache.guacamole.net.auth.ActivityRecordSet;
/** /**
* A sort predicate which species the property to use when sorting connection * A sort predicate which species the property to use when sorting connection
@@ -30,7 +30,7 @@ public class ConnectionRecordSortPredicate {
/** /**
* The property to use when sorting ConnectionRecords. * The property to use when sorting ConnectionRecords.
*/ */
private final ConnectionRecordSet.SortableProperty property; private final ActivityRecordSet.SortableProperty property;
/** /**
* Whether the sort order is descending (true) or ascending (false). * Whether the sort order is descending (true) or ascending (false).
@@ -47,7 +47,7 @@ public class ConnectionRecordSortPredicate {
* @param descending * @param descending
* Whether the sort order is descending (true) or ascending (false). * Whether the sort order is descending (true) or ascending (false).
*/ */
public ConnectionRecordSortPredicate(ConnectionRecordSet.SortableProperty property, public ConnectionRecordSortPredicate(ActivityRecordSet.SortableProperty property,
boolean descending) { boolean descending) {
this.property = property; this.property = property;
this.descending = descending; this.descending = descending;
@@ -59,7 +59,7 @@ public class ConnectionRecordSortPredicate {
* @return * @return
* The property that should be used when sorting ConnectionRecords. * The property that should be used when sorting ConnectionRecords.
*/ */
public ConnectionRecordSet.SortableProperty getProperty() { public ActivityRecordSet.SortableProperty getProperty() {
return property; return property;
} }

View File

@@ -24,6 +24,7 @@ import com.google.inject.Provider;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -232,6 +233,11 @@ public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionMod
return getModel().getSharingProfileIdentifiers(); return getModel().getSharingProfileIdentifiers();
} }
@Override
public Date getLastActive() {
return null;
}
@Override @Override
public List<? extends ConnectionRecord> getHistory() throws GuacamoleException { public List<? extends ConnectionRecord> getHistory() throws GuacamoleException {
return connectionService.retrieveHistory(getCurrentUser(), this); return connectionService.retrieveHistory(getCurrentUser(), this);

View File

@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.sharing.connection;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -146,6 +147,11 @@ public class SharedConnection implements Connection {
// Do nothing - changing attributes not supported // Do nothing - changing attributes not supported
} }
@Override
public Date getLastActive() {
return null;
}
@Override @Override
public List<? extends ConnectionRecord> getHistory() public List<? extends ConnectionRecord> getHistory()
throws GuacamoleException { throws GuacamoleException {

View File

@@ -20,9 +20,12 @@
package org.apache.guacamole.auth.jdbc.sharing.user; package org.apache.guacamole.auth.jdbc.sharing.user;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.sharing.permission.SharedObjectPermissionSet; import org.apache.guacamole.auth.jdbc.sharing.permission.SharedObjectPermissionSet;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
@@ -88,6 +91,22 @@ public class SharedUser implements User {
// Do nothing - no attributes supported // Do nothing - no attributes supported
} }
@Override
public Date getLastActive() {
// History is not recorded for shared users
return null;
}
@Override
public List<ActivityRecord> getHistory() throws GuacamoleException {
// History is not recorded for shared users
return Collections.<ActivityRecord>emptyList();
}
@Override @Override
public String getPassword() { public String getPassword() {
return null; return null;

View File

@@ -28,16 +28,18 @@ import org.apache.guacamole.auth.jdbc.sharing.connectiongroup.SharedRootConnecti
import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser; import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser;
import org.apache.guacamole.form.Form; import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.ConnectionRecordSet; import org.apache.guacamole.net.auth.ConnectionRecord;
import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory; import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory;
import org.apache.guacamole.net.auth.simple.SimpleConnectionRecordSet;
import org.apache.guacamole.net.auth.simple.SimpleDirectory; import org.apache.guacamole.net.auth.simple.SimpleDirectory;
/** /**
@@ -175,8 +177,14 @@ public class SharedUserContext implements UserContext {
} }
@Override @Override
public ConnectionRecordSet getConnectionHistory() { public ActivityRecordSet<ConnectionRecord> getConnectionHistory() {
return new SimpleConnectionRecordSet(); return new SimpleActivityRecordSet<ConnectionRecord>();
}
@Override
public ActivityRecordSet<ActivityRecord> getUserHistory()
throws GuacamoleException {
return new SimpleActivityRecordSet<ActivityRecord>();
} }
@Override @Override
@@ -204,4 +212,9 @@ public class SharedUserContext implements UserContext {
return Collections.<Form>emptyList(); return Collections.<Form>emptyList();
} }
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

View File

@@ -235,7 +235,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
// Build token filter containing credential tokens // Build token filter containing credential tokens
TokenFilter tokenFilter = new TokenFilter(); TokenFilter tokenFilter = new TokenFilter();
StandardTokens.addStandardTokens(tokenFilter, user.getCredentials()); StandardTokens.addStandardTokens(tokenFilter, user);
// Filter the configuration // Filter the configuration
tokenFilter.filterValues(config.getParameters()); tokenFilter.filterValues(config.getParameters());
@@ -281,7 +281,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
// Build token filter containing credential tokens // Build token filter containing credential tokens
TokenFilter tokenFilter = new TokenFilter(); TokenFilter tokenFilter = new TokenFilter();
StandardTokens.addStandardTokens(tokenFilter, user.getCredentials()); StandardTokens.addStandardTokens(tokenFilter, user);
// Filter the configuration // Filter the configuration
tokenFilter.filterValues(config.getParameters()); tokenFilter.filterValues(config.getParameters());

View File

@@ -29,6 +29,7 @@ import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObject; import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObject;
@@ -49,6 +50,7 @@ import org.apache.guacamole.form.Form;
import org.apache.guacamole.form.TextField; import org.apache.guacamole.form.TextField;
import org.apache.guacamole.form.TimeField; import org.apache.guacamole.form.TimeField;
import org.apache.guacamole.form.TimeZoneField; import org.apache.guacamole.form.TimeZoneField;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermission; import org.apache.guacamole.net.auth.permission.SystemPermission;
@@ -792,4 +794,14 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
return getModel().isExpired(); return getModel().isExpired();
} }
@Override
public Date getLastActive() {
return null;
}
@Override
public List<ActivityRecord> getHistory() throws GuacamoleException {
return Collections.<ActivityRecord>emptyList();
}
} }

View File

@@ -36,12 +36,15 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileDirectory; import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileDirectory;
import org.apache.guacamole.form.Form; import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
/** /**
* UserContext implementation which is driven by an arbitrary, underlying * UserContext implementation which is driven by an arbitrary, underlying
@@ -161,6 +164,12 @@ public class ModeledUserContext extends RestrictedObject
return connectionRecordSet; return connectionRecordSet;
} }
@Override
public ActivityRecordSet<ActivityRecord> getUserHistory()
throws GuacamoleException {
return new SimpleActivityRecordSet<ActivityRecord>();
}
@Override @Override
public ConnectionGroup getRootConnectionGroup() throws GuacamoleException { public ConnectionGroup getRootConnectionGroup() throws GuacamoleException {
@@ -191,4 +200,9 @@ public class ModeledUserContext extends RestrictedObject
return ModeledSharingProfile.ATTRIBUTES; return ModeledSharingProfile.ATTRIBUTES;
} }
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

View File

@@ -136,4 +136,9 @@ public abstract class RemoteAuthenticatedUser implements AuthenticatedUser {
return authenticationProvider; return authenticationProvider;
} }
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

View File

@@ -63,6 +63,14 @@
"NAME" : "Shared Connections (PostgreSQL)" "NAME" : "Shared Connections (PostgreSQL)"
}, },
"DATA_SOURCE_SQLSERVER" : {
"NAME" : "SQL Server"
},
"DATA_SOURCe_SQLSERVER_SHARED" : {
"NAME" : "Shared Connections (SQL Server)"
},
"HOME" : { "HOME" : {
"INFO_SHARED_BY" : "Shared by {USERNAME}" "INFO_SHARED_BY" : "Shared by {USERNAME}"
}, },

View File

@@ -109,6 +109,13 @@
<version>0.9.13-incubating</version> <version>0.9.13-incubating</version>
</dependency> </dependency>
<!-- SQL Server Authentication Extension -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc-sqlserver</artifactId>
<version>0.9.13-incubating</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -49,6 +49,14 @@
</includes> </includes>
</dependencySet> </dependencySet>
<!-- SQL Server extension .jar -->
<dependencySet>
<outputDirectory>sqlserver</outputDirectory>
<includes>
<include>org.apache.guacamole:guacamole-auth-jdbc-sqlserver</include>
</includes>
</dependencySet>
</dependencySets> </dependencySets>
<!-- Include extension schema scripts --> <!-- Include extension schema scripts -->
@@ -72,6 +80,12 @@
<directory>../guacamole-auth-jdbc-postgresql/schema</directory> <directory>../guacamole-auth-jdbc-postgresql/schema</directory>
</fileSet> </fileSet>
<!-- SQL Server schema scripts -->
<fileSet>
<outputDirectory>sqlserver/schema</outputDirectory>
<directory>../guacamole-auth-jdbc-sqlserver/schema</directory>
</fileSet>
</fileSets> </fileSets>
</assembly> </assembly>

View File

@@ -129,7 +129,7 @@
</foreach> </foreach>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates --> <!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate" <foreach collection="sortPredicates" item="sortPredicate"
@@ -199,7 +199,7 @@
</foreach> </foreach>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates --> <!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate" <foreach collection="sortPredicates" item="sortPredicate"

View File

@@ -31,6 +31,7 @@
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/> <result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
<result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/> <result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/>
<result column="disabled" property="disabled" jdbcType="BOOLEAN"/> <result column="disabled" property="disabled" jdbcType="BOOLEAN"/>
<result column="expired" property="expired" jdbcType="BOOLEAN"/>
<result column="access_window_start" property="accessWindowStart" jdbcType="TIME"/> <result column="access_window_start" property="accessWindowStart" jdbcType="TIME"/>
<result column="access_window_end" property="accessWindowEnd" jdbcType="TIME"/> <result column="access_window_end" property="accessWindowEnd" jdbcType="TIME"/>
<result column="valid_from" property="validFrom" jdbcType="DATE"/> <result column="valid_from" property="validFrom" jdbcType="DATE"/>

View File

@@ -127,7 +127,7 @@
</foreach> </foreach>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates --> <!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate" <foreach collection="sortPredicates" item="sortPredicate"
@@ -197,7 +197,7 @@
</foreach> </foreach>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates --> <!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate" <foreach collection="sortPredicates" item="sortPredicate"

View File

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

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc-sqlserver</artifactId>
<packaging>jar</packaging>
<name>guacamole-auth-jdbc-sqlserver</name>
<url>http://guacamole.incubator.apache.org/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc</artifactId>
<version>0.9.13-incubating</version>
<relativePath>../../</relativePath>
</parent>
<build>
<plugins>
<!-- Written for 1.6 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Werror</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
<!-- Copy dependencies prior to packaging -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Verify format using Apache RAT -->
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<version>0.12</version>
<configuration>
<excludes>
<exclude>**/*.json</exclude>
</excludes>
</configuration>
<!-- Bind RAT to validate phase -->
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<scope>provided</scope>
</dependency>
<!-- Guacamole JDBC Authentication -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc-base</artifactId>
<version>0.9.13-incubating</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,467 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Turn on ANSI_NULLS for the entire DB to make it ISO-compliant.
*/
ALTER DATABASE CURRENT SET ANSI_NULLS ON;
GO;
/**
* Turn on QUOTED_IDENTIFIER for the entire DB.
*/
ALTER DATABASE CURRENT SET QUOTED_IDENTIFIER ON;
/**
* List for permission data type.
*/
CREATE RULE [guacamole_permission_list]
AS
@list IN ('READ','UPDATE','DELETE','ADMINISTER');
GO;
/**
* List for system permission data type.
*/
CREATE RULE [guacamole_system_permission_list]
AS
@list IN ('CREATE_CONNECTION',
'CREATE_CONNECTION_GROUP',
'CREATE_SHARING_PROFILE',
'CREATE_USER',
'ADMINISTER');
GO;
/**
* The permission data type.
*/
CREATE TYPE [guacamole_permission] FROM [nvarchar](10) NOT NULL;
EXEC sp_bindrule 'guacamole_permission_list','guacamole_permission';
/**
* The system permission data type.
*/
CREATE TYPE [guacamole_system_permission] FROM [nvarchar](32) NOT NULL;
EXEC sp_bindrule 'guacamole_system_permission_list','guacamole_system_permission';
GO;
/**
* The connection_group table stores organizational and balancing groups.
*/
CREATE TABLE [guacamole_connection_group](
[connection_group_id] [int] IDENTITY(1,1) NOT NULL,
[parent_id] [int] NULL,
[connection_group_name] [nvarchar](128) NOT NULL,
[type] [nvarchar](32) NOT NULL,
[max_connections] [int] NULL,
[max_connections_per_user] [int] NULL,
[enable_session_affinity] [bit] NOT NULL,
CONSTRAINT [PK_guacmaole_connection_group] PRIMARY KEY CLUSTERED
([connection_group_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for connection_group table.
*/
ALTER TABLE [guacamole_connection_group]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_group_connection_group_id] FOREIGN KEY([parent_id])
REFERENCES [guacamole_connection_group] ([connection_group_id]);
ALTER TABLE [guacamole_connection_group]
CHECK CONSTRAINT [FK_guacamole_connection_group_connection_group_id];
ALTER TABLE [guacamole_connection_group]
WITH CHECK ADD CONSTRAINT [CK_guacamole_connection_group_type]
CHECK (([type]='BALANCING' OR [type]='ORGANIZATIONAL'));
ALTER TABLE [guacamole_connection_group]
CHECK CONSTRAINT [CK_guacamole_connection_group_type];
/**
* Default values for connection_group table.
*/
ALTER TABLE [guacamole_connection_group]
ADD CONSTRAINT [DF_guacamole_connection_group_type] DEFAULT (N'ORGANIZATIONAL') FOR [type];
ALTER TABLE [guacamole_connection_group]
ADD CONSTRAINT [DF_guacamole_connection_group_enable_session_affinity] DEFAULT ((0)) FOR [enable_session_affinity];
GO;
/**
* The connection table, for storing connections and attributes.
*/
CREATE TABLE [guacamole_connection](
[connection_id] [int] IDENTITY(1,1) NOT NULL,
[connection_name] [nvarchar](128) NOT NULL,
[parent_id] [int] NULL,
[protocol] [nvarchar](32) NOT NULL,
[proxy_port] [int] NULL,
[proxy_hostname] [nvarchar](512) NULL,
[proxy_encryption_method] [nvarchar](4) NULL,
[max_connections] [int] NULL,
[max_connections_per_user] [int] NULL,
[connection_weight] [int] NULL,
[failover_only] [bit] NOT NULL,
CONSTRAINT [PK_guacamole_connection] PRIMARY KEY CLUSTERED
([connection_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
ALTER TABLE [guacamole_connection]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_connection_group] FOREIGN KEY([parent_id])
REFERENCES [guacamole_connection_group] ([connection_group_id]);
ALTER TABLE [guacamole_connection]
CHECK CONSTRAINT [FK_guacamole_connection_connection_group];
ALTER TABLE [guacamole_connection]
WITH CHECK ADD CONSTRAINT [CK_proxy_encryption_method]
CHECK (([proxy_encryption_method]='SSL' OR [proxy_encryption_method]='NONE'));
ALTER TABLE [guacamole_connection]
CHECK CONSTRAINT [CK_proxy_encryption_method];
ALTER TABLE [guacamole_connection]
ADD CONSTRAINT [DF_guacamole_connection_failover_only] DEFAULT ((0)) FOR [failover_only];
GO;
/**
* The user table stores user accounts, passwords, and properties.
*/
CREATE TABLE [guacamole_user](
[user_id] [int] IDENTITY(1,1) NOT NULL,
[username] [nvarchar](128) NOT NULL,
[password_hash] [binary](32) NOT NULL,
[password_salt] [binary](32) NULL,
[password_date] [datetime] NOT NULL,
[disabled] [bit] NOT NULL,
[expired] [bit] NOT NULL,
[access_window_start] [time](7) NULL,
[access_window_end] [time](7) NULL,
[valid_from] [date] NULL,
[valid_until] [date] NULL,
[timezone] [nvarchar](64) NULL,
[full_name] [nvarchar](256) NULL,
[email_address] [nvarchar](256) NULL,
[organization] [nvarchar](256) NULL,
[organizational_role] [nvarchar](256) NULL,
CONSTRAINT [PK_guacamole_user] PRIMARY KEY CLUSTERED
([user_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Defaults for user table
*/
ALTER TABLE [guacamole_user]
ADD CONSTRAINT [DF_guacamole_user_disabled] DEFAULT ((0)) FOR [disabled];
ALTER TABLE [guacamole_user]
ADD CONSTRAINT [DF_guacamole_user_expired] DEFAULT ((0)) FOR [expired];
GO;
/**
* The sharing_profile table stores profiles that allow
* connections to be shared amongst multiple users.
*/
CREATE TABLE [guacamole_sharing_profile](
[sharing_profile_id] [int] IDENTITY(1,1) NOT NULL,
[sharing_profile_name] [nvarchar](128) NOT NULL,
[primary_connection_id] [int] NOT NULL,
CONSTRAINT [PK_guacamole_sharing_profile] PRIMARY KEY CLUSTERED
([sharing_profile_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for sharing_profile table.
*/
ALTER TABLE [guacamole_sharing_profile]
WITH CHECK ADD CONSTRAINT [FK_guacamole_sharing_profile_connection] FOREIGN KEY([primary_connection_id])
REFERENCES [guacamole_connection] ([connection_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_sharing_profile]
CHECK CONSTRAINT [FK_guacamole_sharing_profile_connection];
GO;
/**
* The connection_parameter table stores parameters for
* connection objects.
*/
CREATE TABLE [guacamole_connection_parameter](
[connection_id] [int] NOT NULL,
[parameter_name] [nvarchar](128) NOT NULL,
[parameter_value] [nvarchar](4000) NOT NULL,
CONSTRAINT [PK_guacamole_connection_parameter] PRIMARY KEY CLUSTERED
([connection_id] ASC, [parameter_name] ASC) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];
/**
* Foreign keys for the connection_parameter table.
*/
ALTER TABLE [guacamole_connection_parameter]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_parameter_connection] FOREIGN KEY([connection_id])
REFERENCES [guacamole_connection] ([connection_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_connection_parameter]
CHECK CONSTRAINT [FK_guacamole_connection_parameter_connection];
GO;
/**
* The sharing_profile_parameter table stores parameters
* for sharing_profile objects.
*/
CREATE TABLE [guacamole_sharing_profile_parameter](
[sharing_profile_id] [int] NOT NULL,
[parameter_name] [nvarchar](128) NOT NULL,
[parameter_value] [nvarchar](4000) NOT NULL,
CONSTRAINT [PK_guacamole_sharing_profile_parameter] PRIMARY KEY CLUSTERED
([sharing_profile_id] ASC, [parameter_name] ASC) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];
/**
* Foreign keys for the sharing_profile_parameter
* table.
*/
ALTER TABLE [guacamole_sharing_profile_parameter]
WITH CHECK ADD CONSTRAINT [FK_guacamole_sharing_profile_parameter_sharing_profile] FOREIGN KEY([sharing_profile_id])
REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_sharing_profile_parameter]
CHECK CONSTRAINT [FK_guacamole_sharing_profile_parameter_sharing_profile];
GO;
/**
* The connection_permission table stores permission
* mappings for connection objects.
*/
CREATE TABLE [guacamole_connection_permission](
[user_id] [int] NOT NULL,
[connection_id] [int] NOT NULL,
[permission] [guacamole_permission] NOT NULL,
CONSTRAINT [PK_guacamole_connection_permission] PRIMARY KEY CLUSTERED
([user_id] ASC, [connection_id] ASC, [permission] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for the connection_permission table.
*/
ALTER TABLE [guacamole_connection_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_permission_connection1] FOREIGN KEY([connection_id])
REFERENCES [guacamole_connection] ([connection_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_connection_permission]
CHECK CONSTRAINT [FK_guacamole_connection_permission_connection1];
ALTER TABLE [guacamole_connection_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_permission_user1] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_connection_permission]
CHECK CONSTRAINT [FK_guacamole_connection_permission_user1];
GO;
/**
* The connection_group_permission table stores permission mappings for
* connection_group objects.
*/
CREATE TABLE [guacamole_connection_group_permission](
[user_id] [int] NOT NULL,
[connection_group_id] [int] NOT NULL,
[permission] [guacamole_permission] NOT NULL,
CONSTRAINT [PK_guacamole_connection_group_permission] PRIMARY KEY CLUSTERED
([user_id] ASC, [connection_group_id] ASC, [permission] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for the connection_group_permission table.
*/
ALTER TABLE [guacamole_connection_group_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_group_permission_connection_group] FOREIGN KEY([connection_group_id])
REFERENCES [guacamole_connection_group] ([connection_group_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_connection_group_permission]
CHECK CONSTRAINT [FK_guacamole_connection_group_permission_connection_group];
ALTER TABLE [guacamole_connection_group_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_group_permission_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_connection_group_permission]
CHECK CONSTRAINT [FK_guacamole_connection_group_permission_user];
GO;
/**
* The sharing_profile_permission table stores permission
* mappings for sharing_profile objects.
*/
CREATE TABLE [guacamole_sharing_profile_permission](
[user_id] [int] NOT NULL,
[sharing_profile_id] [int] NOT NULL,
[permission] [guacamole_permission] NOT NULL,
CONSTRAINT [PK_guacamole_sharing_profile_permission] PRIMARY KEY CLUSTERED
([user_id] ASC, [sharing_profile_id] ASC, [permission] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for the sharing_profile_permission table.
*/
ALTER TABLE [guacamole_sharing_profile_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_sharing_profile_permission_sharing_profile] FOREIGN KEY([sharing_profile_id])
REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_sharing_profile_permission]
CHECK CONSTRAINT [FK_guacamole_sharing_profile_permission_sharing_profile];
ALTER TABLE [guacamole_sharing_profile_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_sharing_profile_permission_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_sharing_profile_permission]
CHECK CONSTRAINT [FK_guacamole_sharing_profile_permission_user];
GO;
/**
* The system_permission table stores permission mappings
* for system-level operations.
*/
CREATE TABLE [guacamole_system_permission](
[user_id] [int] NOT NULL,
[permission] [guacamole_system_permission] NOT NULL,
CONSTRAINT [PK_guacamole_system_permission] PRIMARY KEY CLUSTERED
([user_id] ASC, [permission] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for system_permission table.
*/
ALTER TABLE [guacamole_system_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_system_permission_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_system_permission]
CHECK CONSTRAINT [FK_guacamole_system_permission_user];
GO;
/**
* The user_permission table stores permission mappings
* for users to other users.
*/
CREATE TABLE [guacamole_user_permission](
[user_id] [int] NOT NULL,
[affected_user_id] [int] NOT NULL,
[permission] [guacamole_permission] NOT NULL,
CONSTRAINT [PK_guacamole_user_permission] PRIMARY KEY CLUSTERED
([user_id] ASC, [affected_user_id] ASC, [permission] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for user_permission table.
*/
ALTER TABLE [guacamole_user_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_user_permission_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_user_permission]
CHECK CONSTRAINT [FK_guacamole_user_permission_user];
ALTER TABLE [guacamole_user_permission]
WITH CHECK ADD CONSTRAINT [FK_guacamole_user_permission_user1] FOREIGN KEY([affected_user_id])
REFERENCES [guacamole_user] ([user_id]);
ALTER TABLE [guacamole_user_permission]
CHECK CONSTRAINT [FK_guacamole_user_permission_user1];
GO;
/**
* The connection_history table stores records for historical
* connections.
*/
CREATE TABLE [guacamole_connection_history](
[history_id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NULL,
[username] [nvarchar](128) NOT NULL,
[remote_host] [nvarchar](256) NULL,
[connection_id] [int] NULL,
[connection_name] [nvarchar](128) NOT NULL,
[sharing_profile_id] [int] NULL,
[sharing_profile_name] [nvarchar](128) NULL,
[start_date] [datetime] NOT NULL,
[end_date] [datetime] NULL,
CONSTRAINT [PK_guacamole_connection_history] PRIMARY KEY CLUSTERED
([history_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for connection_history table
*/
ALTER TABLE [guacamole_connection_history]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_history_connection] FOREIGN KEY([connection_id])
REFERENCES [guacamole_connection] ([connection_id])
ON UPDATE CASCADE
ON DELETE SET NULL;
ALTER TABLE [guacamole_connection_history]
CHECK CONSTRAINT [FK_guacamole_connection_history_connection];
ALTER TABLE [guacamole_connection_history]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_history_sharing_profile] FOREIGN KEY([sharing_profile_id])
REFERENCES [guacamole_sharing_profile] ([sharing_profile_id]);
ALTER TABLE [guacamole_connection_history]
CHECK CONSTRAINT [FK_guacamole_connection_history_sharing_profile];
ALTER TABLE [guacamole_connection_history]
WITH CHECK ADD CONSTRAINT [FK_guacamole_connection_history_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE SET NULL;
ALTER TABLE [guacamole_connection_history]
CHECK CONSTRAINT [FK_guacamole_connection_history_user];
GO;
/**
* The user_password_history table stores password history
* for users, allowing for enforcing rules associated with
* reuse of passwords.
*/
CREATE TABLE [guacamole_user_password_history](
[password_history_id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NOT NULL,
[password_hash] [binary](32) NOT NULL,
[password_salt] [binary](32) NULL,
[password_date] [datetime] NOT NULL,
CONSTRAINT [PK_guacamole_user_password_history] PRIMARY KEY CLUSTERED
([password_history_id] ASC) ON [PRIMARY]
) ON [PRIMARY];
/**
* Foreign keys for user_password_history table
*/
ALTER TABLE [guacamole_user_password_history]
WITH CHECK ADD CONSTRAINT [FK_guacamole_user_password_history_user] FOREIGN KEY([user_id])
REFERENCES [guacamole_user] ([user_id])
ON UPDATE CASCADE
ON DELETE CASCADE;
ALTER TABLE [guacamole_user_password_history]
CHECK CONSTRAINT [FK_guacamole_user_password_history_user];
GO;

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Create the default admin user account and set up full privileges.
*/
INSERT INTO [guacamole_user] (username, password_hash, password_salt, password_date)
VALUES ('guacadmin',
0xCA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960,
0xFE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264,
getdate());
INSERT INTO [guacamole_user_permission]
SELECT [guacamole_user].[user_id], [affected].[user_id], permission
FROM (
SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'READ' AS permission
UNION SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'UPDATE' AS permission
UNION SELECT 'guacadmin' AS username, 'guacadmin' AS affected_username, 'ADMINISTER' AS permission)
permissions
JOIN [guacamole_user] ON permissions.username = [guacamole_user].[username]
JOIN [guacamole_user] affected ON permissions.affected_username = affected.username;
INSERT INTO [guacamole_system_permission]
SELECT user_id, permission
FROM (
SELECT 'guacadmin' AS username, 'CREATE_CONNECTION' AS permission
UNION SELECT 'guacadmin' AS username, 'CREATE_CONNECTION_GROUP' AS permission
UNION SELECT 'guacadmin' AS username, 'CREATE_SHARING_PROFILE' AS permission
UNION SELECT 'guacadmin' AS username, 'CREATE_USER' AS permission
UNION SELECT 'guacadmin' AS username, 'ADMINISTER' AS permission)
permissions
JOIN [guacamole_user] ON permissions.username = [guacamole_user].[username];
GO;

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.InjectedAuthenticationProvider;
import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderService;
/**
* Provides a SQLServer-based implementation of the AuthenticationProvider
* functionality.
*/
public class SQLServerAuthenticationProvider extends InjectedAuthenticationProvider {
/**
* Creates a new SQLServerAuthenticationProvider that reads and writes
* authentication data to a SQLServer database defined by properties in
* guacamole.properties.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public SQLServerAuthenticationProvider() throws GuacamoleException {
super(new SQLServerInjectorProvider(), JDBCAuthenticationProviderService.class);
}
@Override
public String getIdentifier() {
return "sqlserver";
}
}

View File

@@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.name.Names;
import java.lang.UnsupportedOperationException;
import java.util.Properties;
import org.apache.guacamole.GuacamoleException;
import org.mybatis.guice.datasource.helper.JdbcHelper;
/**
* Guice module which configures SQLServer-specific injections.
*/
public class SQLServerAuthenticationProviderModule implements Module {
/**
* MyBatis-specific configuration properties.
*/
private final Properties myBatisProperties = new Properties();
/**
* SQLServer-specific driver configuration properties.
*/
private final Properties driverProperties = new Properties();
/**
* Which SQL Server driver should be used.
*/
private SQLServerDriver sqlServerDriver;
/**
* Creates a new SQLServer authentication provider module that configures
* driver and MyBatis properties using the given environment.
*
* @param environment
* The environment to use when configuring MyBatis and the underlying
* JDBC driver.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public SQLServerAuthenticationProviderModule(SQLServerEnvironment environment)
throws GuacamoleException {
// Set the SQLServer-specific properties for MyBatis.
myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
myBatisProperties.setProperty("JDBC.host", environment.getSQLServerHostname());
myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getSQLServerPort()));
myBatisProperties.setProperty("JDBC.schema", environment.getSQLServerDatabase());
myBatisProperties.setProperty("JDBC.username", environment.getSQLServerUsername());
myBatisProperties.setProperty("JDBC.password", environment.getSQLServerPassword());
myBatisProperties.setProperty("JDBC.autoCommit", "false");
myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true");
myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1");
// Use UTF-8 in database
driverProperties.setProperty("characterEncoding", "UTF-8");
// Capture which driver to use for the connection.
this.sqlServerDriver = environment.getSQLServerDriver();
}
@Override
public void configure(Binder binder) {
// Bind SQLServer-specific properties with the configured driver.
switch(sqlServerDriver) {
case JTDS:
JdbcHelper.SQL_Server_jTDS.configure(binder);
break;
case DATA_DIRECT:
JdbcHelper.SQL_Server_DataDirect.configure(binder);
break;
case MICROSOFT_LEGACY:
JdbcHelper.SQL_Server_MS_Driver.configure(binder);
break;
case MICROSOFT_2005:
JdbcHelper.SQL_Server_2005_MS_Driver.configure(binder);
break;
default:
throw new UnsupportedOperationException(
"A driver has been specified that is not supported by this module."
);
}
// Bind MyBatis properties
Names.bindProperties(binder, myBatisProperties);
// Bind JDBC driver properties
binder.bind(Properties.class)
.annotatedWith(Names.named("JDBC.driverProperties"))
.toInstance(driverProperties);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
/**
* The possible SQL Server drivers to use when using a TDS-compatible database.
*/
public enum SQLServerDriver {
/**
* The open source jTDS driver.
*/
JTDS,
/**
* The Progress DataDirect driver.
*/
DATA_DIRECT,
/**
* The Microsoft Legacy SQL Server driver.
*/
MICROSOFT_LEGACY,
/**
* The Microsoft 2005 SQL Server driver.
*/
MICROSOFT_2005;
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.properties.GuacamoleProperty;
/**
* A property whose value is a SQLServerDriver. The incoming string values of "jtds", "datadirect",
* "microsoft", and "microsoft2005" into the corresponding SQLServerDriver enum value. Any
* values that are not valid result in a parse error.
*/
public abstract class SQLServerDriverProperty implements GuacamoleProperty<SQLServerDriver> {
@Override
public SQLServerDriver parseValue(String value) throws GuacamoleException {
// If no value provided, return null.
if (value == null)
return null;
// jTDS Driver
if (value.equals("jtds"))
return SQLServerDriver.JTDS;
// Progress DataDirect Driver
if (value.equals("datadirect"))
return SQLServerDriver.DATA_DIRECT;
// Microsoft Legacy Driver
if (value.equals("microsoft"))
return SQLServerDriver.MICROSOFT_LEGACY;
// Microsoft 2005 Driver
if (value.equals("microsoft2005"))
return SQLServerDriver.MICROSOFT_2005;
throw new GuacamoleServerException("SQLServer driver must be one of \"jtds\", \"datadirect\", \"microsoft\", \"microsoft2005\".");
}
}

View File

@@ -0,0 +1,254 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
/**
* A SQLServer-specific implementation of JDBCEnvironment provides database
* properties specifically for SQLServer.
*/
public class SQLServerEnvironment extends JDBCEnvironment {
/**
* Logger for this class.
*/
private static final Logger logger = LoggerFactory.getLogger(SQLServerEnvironment.class);
/**
* The default host to connect to, if SQLSERVER_HOSTNAME is not specified.
*/
private static final String DEFAULT_HOSTNAME = "localhost";
/**
* The default port to connect to, if SQLSERVER_PORT is not specified.
*/
private static final int DEFAULT_PORT = 1433;
/**
* Whether a database user account is required by default for authentication
* to succeed.
*/
private static final boolean DEFAULT_USER_REQUIRED = false;
/**
* The default value for the maximum number of connections to be
* allowed to the Guacamole server overall.
*/
private static final int DEFAULT_ABSOLUTE_MAX_CONNECTIONS = 0;
/**
* The default value for the default maximum number of connections to be
* allowed per user to any one connection.
*/
private static final int DEFAULT_MAX_CONNECTIONS_PER_USER = 1;
/**
* The default value for the default maximum number of connections to be
* allowed per user to any one connection group.
*/
private static final int DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER = 1;
/**
* The default value for the default maximum number of connections to be
* allowed to any one connection.
*/
private static final int DEFAULT_MAX_CONNECTIONS = 0;
/**
* The default value for the default maximum number of connections to be
* allowed to any one connection group.
*/
private static final int DEFAULT_MAX_GROUP_CONNECTIONS = 0;
/**
* The default SQLServer driver to use.
*/
public static final SQLServerDriver SQLSERVER_DEFAULT_DRIVER = SQLServerDriver.MICROSOFT_2005;
/**
* Constructs a new SQLServerEnvironment, providing access to SQLServer-specific
* configuration options.
*
* @throws GuacamoleException
* If an error occurs while setting up the underlying JDBCEnvironment
* or while parsing legacy SQLServer configuration options.
*/
public SQLServerEnvironment() throws GuacamoleException {
// Init underlying JDBC environment
super();
}
@Override
public boolean isUserRequired() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_USER_REQUIRED,
DEFAULT_USER_REQUIRED
);
}
@Override
public int getAbsoluteMaxConnections() throws GuacamoleException {
return getProperty(SQLServerGuacamoleProperties.SQLSERVER_ABSOLUTE_MAX_CONNECTIONS,
DEFAULT_ABSOLUTE_MAX_CONNECTIONS
);
}
@Override
public int getDefaultMaxConnections() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_DEFAULT_MAX_CONNECTIONS,
DEFAULT_MAX_CONNECTIONS
);
}
@Override
public int getDefaultMaxGroupConnections() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_DEFAULT_MAX_GROUP_CONNECTIONS,
DEFAULT_MAX_GROUP_CONNECTIONS
);
}
@Override
public int getDefaultMaxConnectionsPerUser() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_DEFAULT_MAX_CONNECTIONS_PER_USER,
DEFAULT_MAX_CONNECTIONS_PER_USER
);
}
@Override
public int getDefaultMaxGroupConnectionsPerUser() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER,
DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER
);
}
@Override
public PasswordPolicy getPasswordPolicy() {
return new SQLServerPasswordPolicy(this);
}
/**
* Returns the hostname of the SQLServer server hosting the Guacamole
* authentication tables. If unspecified, this will be "localhost".
*
* @return
* The URL of the SQLServer server.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public String getSQLServerHostname() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_HOSTNAME,
DEFAULT_HOSTNAME
);
}
/**
* Returns the port number of the SQLServer server hosting the Guacamole
* authentication tables. If unspecified, this will be the default
* SQLServer port of 5432.
*
* @return
* The port number of the SQLServer server.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public int getSQLServerPort() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_PORT,
DEFAULT_PORT
);
}
/**
* Returns the name of the SQLServer database containing the Guacamole
* authentication tables.
*
* @return
* The name of the SQLServer database.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value, or if the
* value was not set, as this property is required.
*/
public String getSQLServerDatabase() throws GuacamoleException {
return getRequiredProperty(SQLServerGuacamoleProperties.SQLSERVER_DATABASE);
}
/**
* Returns the username that should be used when authenticating with the
* SQLServer database containing the Guacamole authentication tables.
*
* @return
* The username for the SQLServer database.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value, or if the
* value was not set, as this property is required.
*/
public String getSQLServerUsername() throws GuacamoleException {
return getRequiredProperty(SQLServerGuacamoleProperties.SQLSERVER_USERNAME);
}
/**
* Returns the password that should be used when authenticating with the
* SQLServer database containing the Guacamole authentication tables.
*
* @return
* The password for the SQLServer database.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value, or if the
* value was not set, as this property is required.
*/
public String getSQLServerPassword() throws GuacamoleException {
return getRequiredProperty(SQLServerGuacamoleProperties.SQLSERVER_PASSWORD);
}
/**
* Returns which JDBC driver should be used to make the SQLServer/TDS connection.
*
* @return
* Which TDS-compatible JDBC driver should be used.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value, or if the
* value was not set, as this property is required.
*/
public SQLServerDriver getSQLServerDriver() throws GuacamoleException {
return getProperty(
SQLServerGuacamoleProperties.SQLSERVER_DRIVER,
SQLSERVER_DEFAULT_DRIVER
);
}
}

View File

@@ -0,0 +1,185 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Properties used by the SQLServer Authentication plugin.
*/
public class SQLServerGuacamoleProperties {
/**
* This class should not be instantiated.
*/
private SQLServerGuacamoleProperties() {}
/**
* The URL of the SQLServer server hosting the Guacamole authentication tables.
*/
public static final StringGuacamoleProperty SQLSERVER_HOSTNAME =
new StringGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-hostname"; }
};
/**
* The port of the SQLServer server hosting the Guacamole authentication
* tables.
*/
public static final IntegerGuacamoleProperty SQLSERVER_PORT =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-port"; }
};
/**
* The name of the SQLServer database containing the Guacamole
* authentication tables.
*/
public static final StringGuacamoleProperty SQLSERVER_DATABASE =
new StringGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-database"; }
};
/**
* The username used to authenticate to the SQLServer database containing
* the Guacamole authentication tables.
*/
public static final StringGuacamoleProperty SQLSERVER_USERNAME =
new StringGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-username"; }
};
/**
* The password used to authenticate to the SQLServer database containing
* the Guacamole authentication tables.
*/
public static final StringGuacamoleProperty SQLSERVER_PASSWORD =
new StringGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-password"; }
};
/**
* Whether a user account within the database is required for authentication
* to succeed, even if the user has been authenticated via another
* authentication provider.
*/
public static final BooleanGuacamoleProperty
SQLSERVER_USER_REQUIRED = new BooleanGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-required"; }
};
/**
* The maximum number of concurrent connections to allow overall. Zero
* denotes unlimited.
*/
public static final IntegerGuacamoleProperty
SQLSERVER_ABSOLUTE_MAX_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-absolute-max-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
SQLSERVER_DEFAULT_MAX_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-default-max-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection group. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
SQLSERVER_DEFAULT_MAX_GROUP_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-default-max-group-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection by an individual user. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
SQLSERVER_DEFAULT_MAX_CONNECTIONS_PER_USER =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-default-max-connections-per-user"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection group by an individual user. Zero denotes
* unlimited.
*/
public static final IntegerGuacamoleProperty
SQLSERVER_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-default-max-group-connections-per-user"; }
};
/**
* Which TDS-compatible JDBC driver should be used for the connection.
*/
public static final SQLServerDriverProperty
SQLSERVER_DRIVER = new SQLServerDriverProperty() {
@Override
public String getName() { return "sqlserver-driver"; }
};
}

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
import org.apache.guacamole.auth.jdbc.JDBCInjectorProvider;
/**
* JDBCInjectorProvider implementation which configures Guice injections for
* connecting to a SQLServer database based on SQLServer-specific options
* provided via guacamole.properties.
*/
public class SQLServerInjectorProvider extends JDBCInjectorProvider {
@Override
protected Injector create() throws GuacamoleException {
// Get local environment
SQLServerEnvironment environment = new SQLServerEnvironment();
// Set up Guice injector
return Guice.createInjector(
new JDBCAuthenticationProviderModule(environment),
new SQLServerAuthenticationProviderModule(environment)
);
}
}

View File

@@ -0,0 +1,194 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
/**
* PasswordPolicy implementation which reads the details of the policy from
* SQLServer-specific properties in guacamole.properties.
*/
public class SQLServerPasswordPolicy implements PasswordPolicy {
/**
* The property which specifies the minimum length required of all user
* passwords. By default, this will be zero.
*/
private static final IntegerGuacamoleProperty MIN_LENGTH =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-min-length"; }
};
/**
* The property which specifies the minimum number of days which must
* elapse before a user may reset their password. If set to zero, the
* default, then this restriction does not apply.
*/
private static final IntegerGuacamoleProperty MIN_AGE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-min-age"; }
};
/**
* The property which specifies the maximum number of days which may
* elapse before a user is required to reset their password. If set to zero,
* the default, then this restriction does not apply.
*/
private static final IntegerGuacamoleProperty MAX_AGE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-max-age"; }
};
/**
* The property which specifies the number of previous passwords remembered
* for each user. If set to zero, the default, then this restriction does
* not apply.
*/
private static final IntegerGuacamoleProperty HISTORY_SIZE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-history-size"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one lowercase character and one uppercase character. By default,
* no such restriction is imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_MULTIPLE_CASE =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-require-multiple-case"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one numeric character (digit). By default, no such restriction is
* imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_DIGIT =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-require-digit"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one non-alphanumeric character (symbol). By default, no such
* restriction is imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_SYMBOL =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-require-symbol"; }
};
/**
* The property which specifies whether users are prohibited from including
* their own username in their password. By default, no such restriction is
* imposed.
*/
private static final BooleanGuacamoleProperty PROHIBIT_USERNAME =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "sqlserver-user-password-prohibit-username"; }
};
/**
* The Guacamole server environment.
*/
private final JDBCEnvironment environment;
/**
* Creates a new SQLServerPasswordPolicy which reads the details of the
* policy from the properties exposed by the given environment.
*
* @param environment
* The environment from which password policy properties should be
* read.
*/
public SQLServerPasswordPolicy(JDBCEnvironment environment) {
this.environment = environment;
}
@Override
public int getMinimumLength() throws GuacamoleException {
return environment.getProperty(MIN_LENGTH, 0);
}
@Override
public int getMinimumAge() throws GuacamoleException {
return environment.getProperty(MIN_AGE, 0);
}
@Override
public int getMaximumAge() throws GuacamoleException {
return environment.getProperty(MAX_AGE, 0);
}
@Override
public int getHistorySize() throws GuacamoleException {
return environment.getProperty(HISTORY_SIZE, 0);
}
@Override
public boolean isMultipleCaseRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_MULTIPLE_CASE, false);
}
@Override
public boolean isNumericRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_DIGIT, false);
}
@Override
public boolean isNonAlphanumericRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_SYMBOL, false);
}
@Override
public boolean isUsernameProhibited() throws GuacamoleException {
return environment.getProperty(PROHIBIT_USERNAME, false);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sqlserver;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.InjectedAuthenticationProvider;
import org.apache.guacamole.auth.jdbc.sharing.SharedAuthenticationProviderService;
/**
* Provides a implementation of AuthenticationProvider which interacts with the
* SQLServer AuthenticationProvider, accepting share keys as credentials and
* providing access to the shared connections.
*/
public class SQLServerSharedAuthenticationProvider extends InjectedAuthenticationProvider {
/**
* Creates a new SQLServerSharedAuthenticationProvider that provides access
* to shared connections exposed by the SQLServerAuthenticationProvider.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public SQLServerSharedAuthenticationProvider() throws GuacamoleException {
super(new SQLServerInjectorProvider(), SharedAuthenticationProviderService.class);
}
@Override
public String getIdentifier() {
return "sqlserver-shared";
}
}

View File

@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* The SQLServer authentication provider.
*/
package org.apache.guacamole.auth.sqlserver;

View File

@@ -0,0 +1,28 @@
{
"guacamoleVersion" : "0.9.13-incubating",
"name" : "SQLServer Authentication",
"namespace" : "guac-sqlserver",
"authProviders" : [
"org.apache.guacamole.auth.sqlserver.SQLServerAuthenticationProvider",
"org.apache.guacamole.auth.sqlserver.SQLServerSharedAuthenticationProvider"
],
"css" : [
"styles/jdbc.css"
],
"html" : [
"html/shared-connection.html"
],
"translations" : [
"translations/en.json",
"translations/fr.json",
"translations/ru.json"
]
}

View File

@@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper" >
<!-- Result mapper for connection objects -->
<resultMap id="ConnectionResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionModel" >
<!-- Connection properties -->
<id column="connection_id" property="objectID" jdbcType="INTEGER"/>
<result column="connection_name" property="name" jdbcType="VARCHAR"/>
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
<result column="protocol" property="protocol" jdbcType="VARCHAR"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="proxy_hostname" property="proxyHostname" jdbcType="VARCHAR"/>
<result column="proxy_port" property="proxyPort" jdbcType="INTEGER"/>
<result column="proxy_encryption_method" property="proxyEncryptionMethod" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.GuacamoleProxyConfiguration$EncryptionMethod"/>
<result column="connection_weight" property="connectionWeight" jdbcType="INTEGER"/>
<result column="failover_only" property="failoverOnly" jdbcType="BOOLEAN"/>
<!-- Associated sharing profiles -->
<collection property="sharingProfileIdentifiers" resultSet="sharingProfiles" ofType="java.lang.String"
column="connection_id" foreignColumn="primary_connection_id">
<result column="sharing_profile_id"/>
</collection>
</resultMap>
<!-- Select all connection identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT connection_id
FROM [guacamole_connection]
</select>
<!-- Select identifiers of all readable connections -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT connection_id
FROM [guacamole_connection_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select all connection identifiers within a particular connection group -->
<select id="selectIdentifiersWithin" resultType="string">
SELECT connection_id
FROM [guacamole_connection]
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
</select>
<!-- Select identifiers of all readable connections within a particular connection group -->
<select id="selectReadableIdentifiersWithin" resultType="string">
SELECT [guacamole_connection].connection_id
FROM [guacamole_connection]
JOIN [guacamole_connection_permission] ON [guacamole_connection_permission].connection_id = [guacamole_connection].connection_id
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select multiple connections by identifier -->
<select id="select" resultMap="ConnectionResultMap"
resultSets="connections,sharingProfiles">
SELECT
connection_id,
connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only
FROM [guacamole_connection]
WHERE connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>;
SELECT primary_connection_id, sharing_profile_id
FROM [guacamole_sharing_profile]
WHERE primary_connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>;
</select>
<!-- Select multiple connections by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionResultMap"
resultSets="connections,sharingProfiles">
SELECT
[guacamole_connection].connection_id,
connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only
FROM [guacamole_connection]
JOIN [guacamole_connection_permission] ON [guacamole_connection_permission].connection_id = [guacamole_connection].connection_id
WHERE [guacamole_connection].connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT primary_connection_id, [guacamole_sharing_profile].sharing_profile_id
FROM [guacamole_sharing_profile]
JOIN [guacamole_sharing_profile_permission] ON [guacamole_sharing_profile_permission].sharing_profile_id = [guacamole_sharing_profile].sharing_profile_id
WHERE primary_connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
</select>
<!-- Select single connection by name -->
<select id="selectOneByName" resultMap="ConnectionResultMap">
SELECT
connection_id,
connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only
FROM [guacamole_connection]
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND connection_name = #{name,jdbcType=VARCHAR}
</select>
<!-- Delete single connection by identifier -->
<delete id="delete">
DELETE FROM [guacamole_connection]
WHERE connection_id = #{identifier,jdbcType=INTEGER}
</delete>
<!-- Insert single connection -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionModel">
INSERT INTO [guacamole_connection] (
connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER},
#{object.protocol,jdbcType=VARCHAR},
#{object.maxConnections,jdbcType=INTEGER},
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
#{object.proxyHostname,jdbcType=VARCHAR},
#{object.proxyPort,jdbcType=INTEGER},
#{object.proxyEncryptionMethod,jdbcType=VARCHAR},
#{object.connectionWeight,jdbcType=INTEGER},
#{object.failoverOnly,jdbcType=INTEGER}
)
</insert>
<!-- Update single connection -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionModel">
UPDATE [guacamole_connection]
SET connection_name = #{object.name,jdbcType=VARCHAR},
parent_id = #{object.parentIdentifier,jdbcType=INTEGER},
protocol = #{object.protocol,jdbcType=VARCHAR},
max_connections = #{object.maxConnections,jdbcType=INTEGER},
max_connections_per_user = #{object.maxConnectionsPerUser,jdbcType=INTEGER},
proxy_hostname = #{object.proxyHostname,jdbcType=VARCHAR},
proxy_port = #{object.proxyPort,jdbcType=INTEGER},
proxy_encryption_method = #{object.proxyEncryptionMethod,jdbcType=VARCHAR},
connection_weight = #{object.connectionWeight,jdbcType=INTEGER},
failover_only = #{object.failoverOnly,jdbcType=INTEGER}
WHERE connection_id = #{object.objectID,jdbcType=INTEGER}
</update>
</mapper>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper">
<!-- Result mapper for connection parameters -->
<resultMap id="ParameterResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterModel">
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
<result column="parameter_name" property="name" jdbcType="VARCHAR"/>
<result column="parameter_value" property="value" jdbcType="VARCHAR"/>
</resultMap>
<!-- Select all parameters of a given connection -->
<select id="select" resultMap="ParameterResultMap">
SELECT
connection_id,
parameter_name,
parameter_value
FROM [guacamole_connection_parameter]
WHERE
connection_id = #{identifier,jdbcType=INTEGER}
</select>
<!-- Delete all parameters of a given connection -->
<delete id="delete">
DELETE FROM [guacamole_connection_parameter]
WHERE connection_id = #{identifier,jdbcType=INTEGER}
</delete>
<!-- Insert all given parameters -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterModel">
INSERT INTO [guacamole_connection_parameter] (
connection_id,
parameter_name,
parameter_value
)
VALUES
<foreach collection="parameters" item="parameter" separator=",">
(#{parameter.connectionIdentifier,jdbcType=INTEGER},
#{parameter.name,jdbcType=VARCHAR},
#{parameter.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
<result column="sharing_profile_id" property="sharingProfileIdentifier" jdbcType="INTEGER"/>
<result column="sharing_profile_name" property="sharingProfileName" jdbcType="VARCHAR"/>
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="start_date" property="startDate" jdbcType="TIMESTAMP"/>
<result column="end_date" property="endDate" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- Select all connection records from a given connection -->
<select id="select" resultMap="ConnectionRecordResultMap">
SELECT
[guacamole_connection_history].connection_id,
[guacamole_connection_history].connection_name,
[guacamole_connection_history].remote_host,
[guacamole_connection_history].sharing_profile_id,
[guacamole_connection_history].sharing_profile_name,
[guacamole_connection_history].user_id,
[guacamole_connection_history].username,
[guacamole_connection_history].start_date,
[guacamole_connection_history].end_date
FROM [guacamole_connection_history]
WHERE
[guacamole_connection_history].connection_id = #{identifier,jdbcType=INTEGER}
ORDER BY
[guacamole_connection_history].start_date DESC,
[guacamole_connection_history].end_date DESC
</select>
<!-- Insert the given connection record -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
INSERT INTO [guacamole_connection_history] (
connection_id,
connection_name,
remote_host,
sharing_profile_id,
sharing_profile_name,
user_id,
username,
start_date,
end_date
)
VALUES (
#{record.connectionIdentifier,jdbcType=INTEGER},
#{record.connectionName,jdbcType=VARCHAR},
#{record.remoteHost,jdbcType=VARCHAR},
#{record.sharingProfileIdentifier,jdbcType=INTEGER},
#{record.sharingProfileName,jdbcType=VARCHAR},
(SELECT user_id FROM [guacamole_user]
WHERE username = #{record.username,jdbcType=VARCHAR}),
#{record.username,jdbcType=VARCHAR},
#{record.startDate,jdbcType=TIMESTAMP},
#{record.endDate,jdbcType=TIMESTAMP}
)
</insert>
<!-- Search for specific connection records -->
<select id="search" resultMap="ConnectionRecordResultMap">
SELECT TOP (#{limit,jdbcType=INTEGER})
[guacamole_connection_history].connection_id,
[guacamole_connection_history].connection_name,
[guacamole_connection_history].remote_host,
[guacamole_connection_history].sharing_profile_id,
[guacamole_connection_history].sharing_profile_name,
[guacamole_connection_history].user_id,
[guacamole_connection_history].username,
[guacamole_connection_history].start_date,
[guacamole_connection_history].end_date
FROM [guacamole_connection_history]
<!-- Search terms -->
<foreach collection="terms" item="term"
open="WHERE " separator=" AND ">
(
[guacamole_connection_history].user_id IN (
SELECT user_id
FROM [guacamole_user]
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
)
OR [guacamole_connection_history].connection_id IN (
SELECT connection_id
FROM [guacamole_connection]
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN connection_name) > 0
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">[guacamole_connection_history].start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
</select>
<!-- Search for specific connection records -->
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
SELECT TOP (#{limit,jdbcType=INTEGER})
[guacamole_connection_history].connection_id,
[guacamole_connection_history].connection_name,
[guacamole_connection_history].remote_host,
[guacamole_connection_history].sharing_profile_id,
[guacamole_connection_history].sharing_profile_name,
[guacamole_connection_history].user_id,
[guacamole_connection_history].username,
[guacamole_connection_history].start_date,
[guacamole_connection_history].end_date
FROM [guacamole_connection_history]
LEFT JOIN [guacamole_connection] ON [guacamole_connection_history].connection_id = [guacamole_connection].connection_id
LEFT JOIN [guacamole_user] ON [guacamole_connection_history].user_id = [guacamole_user].user_id
<!-- Restrict to readable connections -->
JOIN [guacamole_connection_permission] ON
[guacamole_connection_history].connection_id = [guacamole_connection_permission].connection_id
AND [guacamole_connection_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND [guacamole_connection_permission].permission = 'READ'
<!-- Restrict to readable users -->
JOIN [guacamole_user_permission] ON
[guacamole_connection_history].user_id = [guacamole_user_permission].affected_user_id
AND [guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND [guacamole_user_permission].permission = 'READ'
<!-- Search terms -->
<foreach collection="terms" item="term"
open="WHERE " separator=" AND ">
(
[guacamole_connection_history].user_id IN (
SELECT user_id
FROM [guacamole_user]
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
)
OR [guacamole_connection_history].connection_id IN (
SELECT connection_id
FROM [guacamole_connection]
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN connection_name) > 0
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">[guacamole_connection_history].start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
</select>
</mapper>

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper" >
<!-- Result mapper for connection objects -->
<resultMap id="ConnectionGroupResultMap" type="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel" >
<!-- Connection group properties -->
<id column="connection_group_id" property="objectID" jdbcType="INTEGER"/>
<result column="connection_group_name" property="name" jdbcType="VARCHAR"/>
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
<result column="type" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.ConnectionGroup$Type"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="enable_session_affinity" property="sessionAffinityEnabled" jdbcType="INTEGER"/>
<!-- Child connection groups -->
<collection property="connectionGroupIdentifiers" resultSet="childConnectionGroups" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_group_id"/>
</collection>
<!-- Child connections -->
<collection property="connectionIdentifiers" resultSet="childConnections" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_id"/>
</collection>
</resultMap>
<!-- Select all connection group identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT connection_group_id
FROM [guacamole_connection_group]
</select>
<!-- Select identifiers of all readable connection groups -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT connection_group_id
FROM [guacamole_connection_group_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select all connection identifiers within a particular connection group -->
<select id="selectIdentifiersWithin" resultType="string">
SELECT connection_group_id
FROM [guacamole_connection_group]
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
</select>
<!-- Select identifiers of all readable connection groups within a particular connection group -->
<select id="selectReadableIdentifiersWithin" resultType="string">
SELECT [guacamole_connection_group].connection_group_id
FROM [guacamole_connection_group]
JOIN [guacamole_connection_group_permission] ON [guacamole_connection_group_permission].connection_group_id = [guacamole_connection_group].connection_group_id
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select multiple connection groups by identifier -->
<select id="select" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections">
SELECT
connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM [guacamole_connection_group]
WHERE connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>;
SELECT parent_id, connection_group_id
FROM [guacamole_connection_group]
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>;
SELECT parent_id, connection_id
FROM [guacamole_connection]
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>;
</select>
<!-- Select multiple connection groups by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections">
SELECT
[guacamole_connection_group].connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM [guacamole_connection_group]
JOIN [guacamole_connection_group_permission] ON [guacamole_connection_group_permission].connection_group_id = [guacamole_connection_group].connection_group_id
WHERE [guacamole_connection_group].connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, [guacamole_connection_group].connection_group_id
FROM [guacamole_connection_group]
JOIN [guacamole_connection_group_permission] ON [guacamole_connection_group_permission].connection_group_id = [guacamole_connection_group].connection_group_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, [guacamole_connection].connection_id
FROM [guacamole_connection]
JOIN [guacamole_connection_permission] ON [guacamole_connection_permission].connection_id = [guacamole_connection].connection_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
</select>
<!-- Select single connection group by name -->
<select id="selectOneByName" resultMap="ConnectionGroupResultMap">
SELECT
connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM [guacamole_connection_group]
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND connection_group_name = #{name,jdbcType=VARCHAR}
</select>
<!-- Delete single connection group by identifier -->
<delete id="delete">
DELETE FROM [guacamole_connection_group]
WHERE connection_group_id = #{identifier,jdbcType=INTEGER}
</delete>
<!-- Insert single connection -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
INSERT INTO [guacamole_connection_group] (
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER},
#{object.type,jdbcType=VARCHAR},
#{object.maxConnections,jdbcType=INTEGER},
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
#{object.sessionAffinityEnabled,jdbcType=INTEGER}
)
</insert>
<!-- Update single connection group -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
UPDATE [guacamole_connection_group]
SET connection_group_name = #{object.name,jdbcType=VARCHAR},
parent_id = #{object.parentIdentifier,jdbcType=INTEGER},
type = #{object.type,jdbcType=VARCHAR},
max_connections = #{object.maxConnections,jdbcType=INTEGER},
max_connections_per_user = #{object.maxConnectionsPerUser,jdbcType=INTEGER},
enable_session_affinity = #{object.sessionAffinityEnabled,jdbcType=INTEGER}
WHERE connection_group_id = #{object.objectID,jdbcType=INTEGER}
</update>
</mapper>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper" >
<!-- Result mapper for connection permissions -->
<resultMap id="ConnectionGroupPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="connection_group_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="ConnectionGroupPermissionResultMap">
SELECT
[guacamole_connection_group_permission].user_id,
username,
permission,
connection_group_id
FROM [guacamole_connection_group_permission]
JOIN [guacamole_user] ON [guacamole_connection_group_permission].user_id = [guacamole_user].user_id
WHERE [guacamole_connection_group_permission].user_id = #{user.objectID,jdbcType=INTEGER}
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="ConnectionGroupPermissionResultMap">
SELECT
[guacamole_connection_group_permission].user_id,
username,
permission,
connection_group_id
FROM [guacamole_connection_group_permission]
JOIN [guacamole_user] ON [guacamole_connection_group_permission].user_id = [guacamole_user].user_id
WHERE
[guacamole_connection_group_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = #{type,jdbcType=VARCHAR}
AND connection_group_id = #{identifier,jdbcType=INTEGER}
</select>
<!-- Select identifiers accessible by the given user for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT connection_group_id
FROM [guacamole_connection_group_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM [guacamole_connection_group_permission]
WHERE (user_id, permission, connection_group_id) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.userID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR},
#{permission.objectIdentifier,jdbcType=INTEGER})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO [guacamole_connection_group_permission] (
user_id,
permission,
connection_group_id
)
SELECT DISTINCT
permissions.user_id,
permissions.permission,
permissions.connection_group_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
#{permission.type,jdbcType=VARCHAR} AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER} AS connection_group_id
</foreach>
AS permissions
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_connection_group_permission]
WHERE [guacamole_connection_group_permission].user_id = permissions.user_id AND
[guacamole_connection_group_permission].permission = permissions.permission AND
[guacamole_connection_group_permission].connection_group_id = permissions.connection_group_id
);
</insert>
</mapper>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper" >
<!-- Result mapper for connection permissions -->
<resultMap id="ConnectionPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="connection_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="ConnectionPermissionResultMap">
SELECT
[guacamole_connection_permission].user_id,
username,
permission,
connection_id
FROM [guacamole_connection_permission]
JOIN [guacamole_user] ON [guacamole_connection_permission].user_id = [guacamole_user].user_id
WHERE [guacamole_connection_permission].user_id = #{user.objectID,jdbcType=INTEGER}
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="ConnectionPermissionResultMap">
SELECT
[guacamole_connection_permission].user_id,
username,
permission,
connection_id
FROM [guacamole_connection_permission]
JOIN [guacamole_user] ON [guacamole_connection_permission].user_id = [guacamole_user].user_id
WHERE
[guacamole_connection_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = #{type,jdbcType=VARCHAR}
AND connection_id = #{identifier,jdbcType=INTEGER}
</select>
<!-- Select identifiers accessible by the given user for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT connection_id
FROM [guacamole_connection_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM [guacamole_connection_permission]
WHERE
<foreach collection="permissions" item="permission"
open="(" separator=" OR " close=")">
(user_id = #{permission.userID,jdbcType=INTEGER} AND
permission = #{permission.type,jdbcType=VARCHAR} AND
connection_id = #{permission.objectIdentifier,jdbcType=INTEGER})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO [guacamole_connection_permission] (
user_id,
permission,
connection_id
)
SELECT DISTINCT
permissions.user_id,
permissions.permission,
permissions.connection_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
#{permission.type,jdbcType=VARCHAR} AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER} AS connection_id
</foreach>
AS permissions
WHERE NOT EXISTS ( SELECT 1 FROM [guacamole_connection_permission]
WHERE [guacamole_connection_permission].user_id = permissions.user_id AND
[guacamole_connection_permission].permission = permissions.permission AND
[guacamole_connection_permission].connection_id = permissions.connection_id
);
</insert>
</mapper>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper">
<!-- Result mapper for sharing profile permissions -->
<resultMap id="SharingProfilePermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="sharing_profile_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="SharingProfilePermissionResultMap">
SELECT
[guacamole_sharing_profile_permission].user_id,
username,
permission,
sharing_profile_id
FROM [guacamole_sharing_profile_permission]
JOIN [guacamole_user] ON [guacamole_sharing_profile_permission].user_id = [guacamole_user].user_id
WHERE [guacamole_sharing_profile_permission].user_id = #{user.objectID,jdbcType=INTEGER}
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="SharingProfilePermissionResultMap">
SELECT
[guacamole_sharing_profile_permission].user_id,
username,
permission,
sharing_profile_id
FROM [guacamole_sharing_profile_permission]
JOIN [guacamole_user] ON [guacamole_sharing_profile_permission].user_id = [guacamole_user].user_id
WHERE
[guacamole_sharing_profile_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = #{type,jdbcType=VARCHAR}
AND sharing_profile_id = #{identifier,jdbcType=INTEGER}
</select>
<!-- Select identifiers accessible by the given user for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT sharing_profile_id
FROM [guacamole_sharing_profile_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM [guacamole_sharing_profile_permission]
WHERE
<foreach collection="permissions" item="permission"
open="(" separator=" OR " close=")">
(user_id = #{permission.userID,jdbcType=INTEGER} AND
permission = #{permission.type,jdbcType=VARCHAR} AND
sharing_profile_id = #{permission.objectIdentifier,jdbcType=INTEGER})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO [guacamole_sharing_profile_permission] (
user_id,
permission,
sharing_profile_id
)
SELECT DISTINCT
permissions.user_id,
permissions.permission,
permissions.sharing_profile_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
#{permission.type,jdbcType=VARCHAR} AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER} AS sharing_profile_id
</foreach>
AS permissions
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_sharing_profile_permission]
WHERE [guacamole_sharing_profile_permission].user_id = permissions.user_id
AND [guacamole_sharing_profile_permission].permission = permissions.permission
AND [guacamole_sharing_profile_permission].sharing_profile_id = permissions.sharing_profile_id
);
</insert>
</mapper>

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.SystemPermissionMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="SystemPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.SystemPermission$Type"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="SystemPermissionResultMap">
SELECT
[guacamole_system_permission].user_id,
username,
permission
FROM [guacamole_system_permission]
JOIN [guacamole_user] ON [guacamole_system_permission].user_id = [guacamole_user].user_id
WHERE [guacamole_system_permission].user_id = #{user.objectID,jdbcType=INTEGER}
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="SystemPermissionResultMap">
SELECT
[guacamole_system_permission].user_id,
username,
permission
FROM [guacamole_system_permission]
JOIN [guacamole_user] ON [guacamole_system_permission].user_id = [guacamole_user].user_id
WHERE
[guacamole_system_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = #{type,jdbcType=VARCHAR}
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
DELETE FROM [guacamole_system_permission]
WHERE
<foreach collection="permissions" item="permission"
open="(" separator=" OR " close=")">
(user_id = #{permission.userID,jdbcType=INTEGER}
AND permission = #{permission.type,jdbcType=VARCHAR})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
INSERT INTO [guacamole_system_permission] (
user_id,
permission
)
SELECT DISTINCT
permissions.user_id,
permissions.permission
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
#{permission.type,jdbcType=VARCHAR} AS permission
</foreach>
AS permissions
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_system_permission]
WHERE [guacamole_system_permission].user_id = permissions.user_id
AND [guacamole_system_permission].permission = permissions.permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper" >
<!-- Result mapper for user permissions -->
<resultMap id="UserPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="affected_username" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="UserPermissionResultMap">
SELECT
[guacamole_user_permission].user_id,
[guacamole_user].username,
permission,
affected.username AS affected_username
FROM [guacamole_user_permission]
JOIN [guacamole_user] ON [guacamole_user_permission].user_id = [guacamole_user].user_id
JOIN [guacamole_user] affected ON [guacamole_user_permission].affected_user_id = affected.user_id
WHERE [guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="UserPermissionResultMap">
SELECT
[guacamole_user_permission].user_id,
[guacamole_user].username,
permission,
affected.username AS affected_username
FROM [guacamole_user_permission]
JOIN [guacamole_user] ON [guacamole_user_permission].user_id = [guacamole_user].user_id
JOIN [guacamole_user] affected ON [guacamole_user_permission].affected_user_id = affected.user_id
WHERE
[guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = #{type,jdbcType=VARCHAR}
AND affected.username = #{identifier,jdbcType=INTEGER}
</select>
<!-- Select identifiers accessible by the given user for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT username
FROM [guacamole_user_permission]
JOIN [guacamole_user] ON [guacamole_user_permission].affected_user_id = [guacamole_user].user_id
WHERE
[guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND username IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM [guacamole_user_permission]
USING [guacamole_user] affected
WHERE
[guacamole_user_permission].affected_user_id = affected.user_id
AND ([guacamole_user_permission].user_id, permission, affected.username) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.userID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR},
#{permission.objectIdentifier,jdbcType=INTEGER})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO [guacamole_user_permission] (
user_id,
permission,
affected_user_id
)
SELECT DISTINCT
permissions.user_id,
permissions.permission,
[guacamole_user].user_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
#{permission.type,jdbcType=VARCHAR} AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER} AS username
</foreach>
AS permissions
JOIN [guacamole_user] ON [guacamole_user].username = permissions.username
WHERE NOT EXISTS (SELECT 1 FROM [guacamole_user_permission]
WHERE [guacamole_user_permission].user_id = permissions.user_id
AND [guacamole_user_permission].permission = permissions.permission
AND [guacamole_user_permission].affected_user_id = [guacamole_user].user_id
);
</insert>
</mapper>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper">
<!-- Result mapper for sharing profile objects -->
<resultMap id="SharingProfileResultMap" type="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
<id column="sharing_profile_id" property="objectID" jdbcType="INTEGER"/>
<result column="sharing_profile_name" property="name" jdbcType="VARCHAR"/>
<result column="primary_connection_id" property="parentIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all sharing profile identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT sharing_profile_id
FROM [guacamole_sharing_profile]
</select>
<!-- Select identifiers of all readable sharing profiles -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT sharing_profile_id
FROM [guacamole_sharing_profile_permission]
WHERE
user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select multiple sharing profiles by identifier -->
<select id="select" resultMap="SharingProfileResultMap">
SELECT
sharing_profile_id,
sharing_profile_name,
primary_connection_id
FROM [guacamole_sharing_profile]
WHERE sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
</select>
<!-- Select multiple sharing profiles by identifier only if readable -->
<select id="selectReadable" resultMap="SharingProfileResultMap">
SELECT
[guacamole_sharing_profile].sharing_profile_id,
[guacamole_sharing_profile].sharing_profile_name,
primary_connection_id
FROM [guacamole_sharing_profile]
JOIN [guacamole_sharing_profile_permission] ON [guacamole_sharing_profile_permission].sharing_profile_id = [guacamole_sharing_profile].sharing_profile_id
WHERE [guacamole_sharing_profile].sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select single sharing profile by name -->
<select id="selectOneByName" resultMap="SharingProfileResultMap">
SELECT
sharing_profile_id,
sharing_profile_name,
primary_connection_id
FROM [guacamole_sharing_profile]
WHERE
primary_connection_id = #{parentIdentifier,jdbcType=INTEGER}
AND sharing_profile_name = #{name,jdbcType=VARCHAR}
</select>
<!-- Delete single sharing profile by identifier -->
<delete id="delete">
DELETE FROM [guacamole_sharing_profile]
WHERE sharing_profile_id = #{identifier,jdbcType=INTEGER}
</delete>
<!-- Insert single sharing profile -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
INSERT INTO [guacamole_sharing_profile] (
sharing_profile_name,
primary_connection_id
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER}
)
</insert>
<!-- Update single sharing profile -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
UPDATE [guacamole_sharing_profile]
SET sharing_profile_name = #{object.name,jdbcType=VARCHAR},
primary_connection_id = #{object.parentIdentifier,jdbcType=INTEGER}
WHERE sharing_profile_id = #{object.objectID,jdbcType=INTEGER}
</update>
</mapper>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper">
<!-- Result mapper for sharing profile parameters -->
<resultMap id="ParameterResultMap" type="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterModel">
<result column="sharing_profile_id" property="sharingProfileIdentifier" jdbcType="INTEGER"/>
<result column="parameter_name" property="name" jdbcType="VARCHAR"/>
<result column="parameter_value" property="value" jdbcType="VARCHAR"/>
</resultMap>
<!-- Select all parameters of a given sharing profile -->
<select id="select" resultMap="ParameterResultMap">
SELECT
sharing_profile_id,
parameter_name,
parameter_value
FROM [guacamole_sharing_profile_parameter]
WHERE
sharing_profile_id = #{identifier,jdbcType=INTEGER}
</select>
<!-- Delete all parameters of a given sharing profile -->
<delete id="delete">
DELETE FROM [guacamole_sharing_profile_parameter]
WHERE sharing_profile_id = #{identifier,jdbcType=INTEGER}
</delete>
<!-- Insert all given parameters -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterModel">
INSERT INTO [guacamole_sharing_profile_parameter] (
sharing_profile_id,
parameter_name,
parameter_value
)
VALUES
<foreach collection="parameters" item="parameter" separator=",">
(#{parameter.sharingProfileIdentifier,jdbcType=INTEGER},
#{parameter.name,jdbcType=VARCHAR},
#{parameter.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper" >
<!-- Result mapper for historical passwords -->
<resultMap id="PasswordRecordResultMap" type="org.apache.guacamole.auth.jdbc.user.PasswordRecordModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="password_hash" property="passwordHash" jdbcType="BINARY"/>
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
<result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- Select all password records for a given user -->
<select id="select" resultMap="PasswordRecordResultMap">
SELECT
[guacamole_user_password_history].user_id,
[guacamole_user_password_history].password_hash,
[guacamole_user_password_history].password_salt,
[guacamole_user_password_history].password_date
FROM [guacamole_user_password_history]
JOIN [guacamole_user] ON [guacamole_user_password_history].user_id = [guacamole_user].user_id
WHERE
[guacamole_user].username = #{username,jdbcType=VARCHAR}
ORDER BY
[guacamole_user_password_history].password_date DESC
LIMIT #{maxHistorySize}
</select>
<!-- Insert the given password record -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.user.PasswordRecordModel">
INSERT INTO [guacamole_user_password_history] (
user_id,
password_hash,
password_salt,
password_date
)
VALUES (
#{record.userID,jdbcType=INTEGER},
#{record.passwordHash,jdbcType=BINARY},
#{record.passwordSalt,jdbcType=BINARY},
#{record.passwordDate,jdbcType=TIMESTAMP}
);
DELETE FROM [guacamole_user_password_history]
WHERE password_history_id IN (
SELECT password_history_id
FROM [guacamole_user_password_history]
WHERE user_id = #{record.userID,jdbcType=INTEGER}
ORDER BY password_date DESC
OFFSET #{maxHistorySize}
);
</insert>
</mapper>

View File

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.UserMapper" >
<!-- Result mapper for user objects -->
<resultMap id="UserResultMap" type="org.apache.guacamole.auth.jdbc.user.UserModel" >
<id column="user_id" property="objectID" jdbcType="INTEGER"/>
<result column="username" property="identifier" jdbcType="VARCHAR"/>
<result column="password_hash" property="passwordHash" jdbcType="BINARY"/>
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
<result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/>
<result column="disabled" property="disabled" jdbcType="INTEGER"/>
<result column="expired" property="expired" jdbcType="INTEGER"/>
<result column="access_window_start" property="accessWindowStart" jdbcType="TIME"/>
<result column="access_window_end" property="accessWindowEnd" jdbcType="TIME"/>
<result column="valid_from" property="validFrom" jdbcType="DATE"/>
<result column="valid_until" property="validUntil" jdbcType="DATE"/>
<result column="timezone" property="timeZone" jdbcType="VARCHAR"/>
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
<result column="email_address" property="emailAddress" jdbcType="VARCHAR"/>
<result column="organization" property="organization" jdbcType="VARCHAR"/>
<result column="organizational_role" property="organizationalRole" jdbcType="VARCHAR"/>
</resultMap>
<!-- Select all usernames -->
<select id="selectIdentifiers" resultType="string">
SELECT username
FROM [guacamole_user]
</select>
<!-- Select usernames of all readable users -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT username
FROM [guacamole_user]
JOIN [guacamole_user_permission] ON affected_user_id = [guacamole_user].user_id
WHERE
[guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select multiple users by username -->
<select id="select" resultMap="UserResultMap">
SELECT
user_id,
username,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role
FROM [guacamole_user]
WHERE username IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</select>
<!-- Select multiple users by username only if readable -->
<select id="selectReadable" resultMap="UserResultMap">
SELECT
[guacamole_user].user_id,
username,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role
FROM [guacamole_user]
JOIN [guacamole_user_permission] ON affected_user_id = [guacamole_user].user_id
WHERE username IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND [guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ'
</select>
<!-- Select single user by username -->
<select id="selectOne" resultMap="UserResultMap">
SELECT
user_id,
username,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role
FROM [guacamole_user]
WHERE
username = #{username,jdbcType=VARCHAR}
</select>
<!-- Delete single user by username -->
<delete id="delete">
DELETE FROM [guacamole_user]
WHERE username = #{identifier,jdbcType=VARCHAR}
</delete>
<!-- Insert single user -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.user.UserModel">
INSERT INTO [guacamole_user] (
username,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role
)
VALUES (
#{object.identifier,jdbcType=VARCHAR},
#{object.passwordHash,jdbcType=BINARY},
#{object.passwordSalt,jdbcType=BINARY},
#{object.passwordDate,jdbcType=TIMESTAMP},
#{object.disabled,jdbcType=INTEGER},
#{object.expired,jdbcType=INTEGER},
#{object.accessWindowStart,jdbcType=TIME},
#{object.accessWindowEnd,jdbcType=TIME},
#{object.validFrom,jdbcType=DATE},
#{object.validUntil,jdbcType=DATE},
#{object.timeZone,jdbcType=VARCHAR},
#{object.fullName,jdbcType=VARCHAR},
#{object.emailAddress,jdbcType=VARCHAR},
#{object.organization,jdbcType=VARCHAR},
#{object.organizationalRole,jdbcType=VARCHAR}
)
</insert>
<!-- Update single user -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.user.UserModel">
UPDATE [guacamole_user]
SET password_hash = #{object.passwordHash,jdbcType=BINARY},
password_salt = #{object.passwordSalt,jdbcType=BINARY},
password_date = #{object.passwordDate,jdbcType=TIMESTAMP},
disabled = #{object.disabled,jdbcType=INTEGER},
expired = #{object.expired,jdbcType=INTEGER},
access_window_start = #{object.accessWindowStart,jdbcType=TIME},
access_window_end = #{object.accessWindowEnd,jdbcType=TIME},
valid_from = #{object.validFrom,jdbcType=DATE},
valid_until = #{object.validUntil,jdbcType=DATE},
timezone = #{object.timeZone,jdbcType=VARCHAR},
full_name = #{object.fullName,jdbcType=VARCHAR},
email_address = #{object.emailAddress,jdbcType=VARCHAR},
organization = #{object.organization,jdbcType=VARCHAR},
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
</update>
</mapper>

View File

@@ -70,6 +70,7 @@
<!-- Database-specific implementations --> <!-- Database-specific implementations -->
<module>modules/guacamole-auth-jdbc-mysql</module> <module>modules/guacamole-auth-jdbc-mysql</module>
<module>modules/guacamole-auth-jdbc-postgresql</module> <module>modules/guacamole-auth-jdbc-postgresql</module>
<module>modules/guacamole-auth-jdbc-sqlserver</module>
</modules> </modules>

View File

@@ -103,5 +103,10 @@ public class LDAPAuthenticationProvider implements AuthenticationProvider {
return context; return context;
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -123,7 +123,7 @@ public class ConnectionService {
// Build token filter containing credential tokens // Build token filter containing credential tokens
TokenFilter tokenFilter = new TokenFilter(); TokenFilter tokenFilter = new TokenFilter();
StandardTokens.addStandardTokens(tokenFilter, user.getCredentials()); StandardTokens.addStandardTokens(tokenFilter, user);
// Produce connections for each readable configuration // Produce connections for each readable configuration
Map<String, Connection> connections = new HashMap<String, Connection>(); Map<String, Connection> connections = new HashMap<String, Connection>();

View File

@@ -28,17 +28,19 @@ import org.apache.guacamole.auth.ldap.connection.ConnectionService;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.form.Form; import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.ConnectionRecordSet; import org.apache.guacamole.net.auth.ConnectionRecord;
import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
import org.apache.guacamole.net.auth.simple.SimpleConnectionGroup; import org.apache.guacamole.net.auth.simple.SimpleConnectionGroup;
import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory; import org.apache.guacamole.net.auth.simple.SimpleConnectionGroupDirectory;
import org.apache.guacamole.net.auth.simple.SimpleConnectionRecordSet;
import org.apache.guacamole.net.auth.simple.SimpleDirectory; import org.apache.guacamole.net.auth.simple.SimpleDirectory;
import org.apache.guacamole.net.auth.simple.SimpleUser; import org.apache.guacamole.net.auth.simple.SimpleUser;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -204,9 +206,15 @@ public class UserContext implements org.apache.guacamole.net.auth.UserContext {
} }
@Override @Override
public ConnectionRecordSet getConnectionHistory() public ActivityRecordSet<ConnectionRecord> getConnectionHistory()
throws GuacamoleException { throws GuacamoleException {
return new SimpleConnectionRecordSet(); return new SimpleActivityRecordSet<ConnectionRecord>();
}
@Override
public ActivityRecordSet<ActivityRecord> getUserHistory()
throws GuacamoleException {
return new SimpleActivityRecordSet<ActivityRecord>();
} }
@Override @Override
@@ -229,4 +237,9 @@ public class UserContext implements org.apache.guacamole.net.auth.UserContext {
return Collections.<Form>emptyList(); return Collections.<Form>emptyList();
} }
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

View File

@@ -0,0 +1,3 @@
*~
target/
src/main/resources/generated/

View File

@@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-openid</artifactId>
<packaging>jar</packaging>
<version>0.9.13-incubating</version>
<name>guacamole-auth-openid</name>
<url>http://guacamole.incubator.apache.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>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Werror</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
<!-- Pre-cache Angular templates with maven-angular-plugin -->
<plugin>
<groupId>com.keithbranton.mojo</groupId>
<artifactId>angular-maven-plugin</artifactId>
<version>0.3.2</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>html2js</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDir>${basedir}/src/main/resources</sourceDir>
<include>**/*.html</include>
<target>${basedir}/src/main/resources/generated/templates-main/templates.js</target>
<prefix>app/ext/guac-openid</prefix>
</configuration>
</plugin>
<!-- JS/CSS Minification Plugin -->
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.5</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<charset>UTF-8</charset>
<webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
<webappTargetDir>${project.build.directory}/classes</webappTargetDir>
<cssSourceDir>/</cssSourceDir>
<cssTargetDir>/</cssTargetDir>
<cssFinalFile>openid.css</cssFinalFile>
<cssSourceFiles>
<cssSourceFile>license.txt</cssSourceFile>
</cssSourceFiles>
<cssSourceIncludes>
<cssSourceInclude>**/*.css</cssSourceInclude>
</cssSourceIncludes>
<jsSourceDir>/</jsSourceDir>
<jsTargetDir>/</jsTargetDir>
<jsFinalFile>openid.js</jsFinalFile>
<jsSourceFiles>
<jsSourceFile>license.txt</jsSourceFile>
</jsSourceFiles>
<jsSourceIncludes>
<jsSourceInclude>**/*.js</jsSourceInclude>
</jsSourceIncludes>
<!-- Do not minify and include tests -->
<jsSourceExcludes>
<jsSourceExclude>**/*.test.js</jsSourceExclude>
</jsSourceExcludes>
<jsEngine>CLOSURE</jsEngine>
<!-- Disable warnings for JSDoc annotations -->
<closureWarningLevels>
<misplacedTypeAnnotation>OFF</misplacedTypeAnnotation>
<nonStandardJsDocs>OFF</nonStandardJsDocs>
</closureWarningLevels>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Copy dependencies prior to packaging -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Assembly plugin - for easy distribution -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</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>
<!-- Verify format using Apache RAT -->
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<version>0.12</version>
<configuration>
<excludes>
<exclude>**/*.json</exclude>
<exclude>src/licenses/**/*</exclude>
<exclude>src/main/resources/templates/*.html</exclude>
</excludes>
</configuration>
<!-- Bind RAT to validate phase -->
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>0.9.13-incubating</version>
<scope>provided</scope>
</dependency>
<!-- Java implementation of JOSE (jose.4.j) -->
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>0.5.5</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>3.0</version>
</dependency>
<!-- Java servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,7 @@
Apache Guacamole is an effort undergoing incubation at The Apache Software
Foundation (ASF). Incubation is required of all newly accepted projects until a
further review indicates that the infrastructure, communications, and decision
making process have stabilized in a manner consistent with other successful ASF
projects. While incubation status is not necessarily a reflection of the
completeness or stability of the code, it does indicate that the project has
yet to be fully endorsed by the ASF.

View File

@@ -0,0 +1,248 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
APACHE GUACAMOLE SUBCOMPONENTS
Apache Guacamole includes a number of subcomponents with separate copyright
notices and license terms. Your use of these subcomponents is subject to the
terms and conditions of the following licenses.
AOP Alliance (http://aopalliance.sourceforge.net/)
--------------------------------------------------
Version: 1.0
From: 'AOP Alliance' (http://aopalliance.sourceforge.net/members.html)
License(s):
Public Domain (bundled/aopalliance-1.0/LICENSE)
Google Guice (https://github.com/google/guice)
----------------------------------------------
Version: 3.0
From: 'Google Inc.' (http://www.google.com/)
License(s):
Apache v2.0 (bundled/guice-3.0/COPYING)
jose.4.j (https://bitbucket.org/b_c/jose4j/)
--------------------------------------------
Version: 0.5.5
From: 'Brian Campbell' (https://bitbucket.org/b_c/)
License(s):
Apache v2.0 (bundled/jose4j-0.5.5/LICENSE)
JSR-330 / Dependency Injection for Java (http://code.google.com/p/atinject/)
----------------------------------------------------------------------------
Version: 1
From: 'JSR-330 Expert Group' (https://jcp.org/en/jsr/detail?id=330)
License(s):
Apache v2.0 (bundled/javax.inject-1/LICENSE-2.0.txt)

View File

@@ -0,0 +1,5 @@
Apache Guacamole
Copyright 2016 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View File

@@ -0,0 +1,4 @@
Apache Guacamole includes a number of subcomponents with separate copyright
notices and license terms. Your use of these subcomponents is subject to the
terms and conditions of their respective licenses, included within this
directory for reference.

View File

@@ -0,0 +1,4 @@
From http://aopalliance.sourceforge.net/:
LICENCE: all the source code provided by AOP Alliance is Public Domain.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,14 @@
jose4j
Copyright 2012-2015 Brian Campbell
EcdsaUsingShaAlgorithm contains code for converting the concatenated
R & S values of the signature to and from DER, which was originally
derived from the Apache Santuario XML Security library's SignatureECDSA
implementation. http://santuario.apache.org/
The Base64 implementation in this software was derived from the
Apache Commons Codec project. http://commons.apache.org/proper/commons-codec/
JSON processing in this software was derived from the JSON.simple toolkit.
https://code.google.com/p/json-simple/

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<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 licenses and extension .jar -->
<fileSets>
<!-- Include licenses -->
<fileSet>
<outputDirectory></outputDirectory>
<directory>src/licenses</directory>
</fileSet>
<!-- Include extension .jar -->
<fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,132 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
import org.apache.guacamole.auth.openid.form.TokenField;
import org.apache.guacamole.auth.openid.token.NonceService;
import org.apache.guacamole.auth.openid.token.TokenValidationService;
import org.apache.guacamole.auth.openid.user.AuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service providing convenience functions for the OpenID AuthenticationProvider
* implementation.
*/
public class AuthenticationProviderService {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class);
/**
* Service for retrieving OpenID configuration information.
*/
@Inject
private ConfigurationService confService;
/**
* Service for validating and generating unique nonce values.
*/
@Inject
private NonceService nonceService;
/**
* Service for validating received ID tokens.
*/
@Inject
private TokenValidationService tokenService;
/**
* Provider for AuthenticatedUser objects.
*/
@Inject
private Provider<AuthenticatedUser> authenticatedUserProvider;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
String username = null;
// Validate OpenID token in request, if present, and derive username
HttpServletRequest request = credentials.getRequest();
if (request != null) {
String token = request.getParameter(TokenField.PARAMETER_NAME);
if (token != null)
username = tokenService.processUsername(token);
}
// If the username was successfully retrieved from the token, produce
// authenticated user
if (username != null) {
// Create corresponding authenticated user
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials);
return authenticatedUser;
}
// Request OpenID token
throw new GuacamoleInvalidCredentialsException("Invalid login.",
new CredentialsInfo(Arrays.asList(new Field[] {
// OpenID-specific token (will automatically redirect the user
// to the authorization page via JavaScript)
new TokenField(
confService.getAuthorizationEndpoint(),
confService.getScope(),
confService.getClientID(),
confService.getRedirectURI(),
nonceService.generate(confService.getMaxNonceValidity() * 60000L)
)
}))
);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.UserContext;
/**
* Guacamole authentication backend which authenticates users using an
* arbitrary external system implementing OpenID. No storage for connections is
* provided - only authentication. Storage must be provided by some other
* extension.
*/
public class OpenIDAuthenticationProvider implements AuthenticationProvider {
/**
* Injector which will manage the object graph of this authentication
* provider.
*/
private final Injector injector;
/**
* Creates a new OpenIDAuthenticationProvider that authenticates users
* against an OpenID service.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public OpenIDAuthenticationProvider() throws GuacamoleException {
// Set up Guice injector.
injector = Guice.createInjector(
new OpenIDAuthenticationProviderModule(this)
);
}
@Override
public String getIdentifier() {
return "openid";
}
@Override
public Object getResource() throws GuacamoleException {
return null;
}
@Override
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Attempt to authenticate user with given credentials
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
return authProviderService.authenticateUser(credentials);
}
@Override
public AuthenticatedUser updateAuthenticatedUser(
AuthenticatedUser authenticatedUser, Credentials credentials)
throws GuacamoleException {
// No update necessary
return authenticatedUser;
}
@Override
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
throws GuacamoleException {
// No associated data whatsoever
return null;
}
@Override
public UserContext updateUserContext(UserContext context,
AuthenticatedUser authenticatedUser, Credentials credentials)
throws GuacamoleException {
// No update necessary
return context;
}
@Override
public void shutdown() {
// Do nothing
}
}

View File

@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid;
import com.google.inject.AbstractModule;
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
import org.apache.guacamole.auth.openid.token.NonceService;
import org.apache.guacamole.auth.openid.token.TokenValidationService;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
/**
* Guice module which configures openid-specific injections.
*/
public class OpenIDAuthenticationProviderModule extends AbstractModule {
/**
* Guacamole server environment.
*/
private final Environment environment;
/**
* A reference to the OpenIDAuthenticationProvider on behalf of which this
* module has configured injection.
*/
private final AuthenticationProvider authProvider;
/**
* Creates a new OpenID authentication provider module which configures
* injection for the OpenIDAuthenticationProvider.
*
* @param authProvider
* The AuthenticationProvider for which injection is being configured.
*
* @throws GuacamoleException
* If an error occurs while retrieving the Guacamole server
* environment.
*/
public OpenIDAuthenticationProviderModule(AuthenticationProvider authProvider)
throws GuacamoleException {
// Get local environment
this.environment = new LocalEnvironment();
// Store associated auth provider
this.authProvider = authProvider;
}
@Override
protected void configure() {
// Bind core implementations of guacamole-ext classes
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(Environment.class).toInstance(environment);
// Bind openid-specific services
bind(ConfigurationService.class);
bind(NonceService.class);
bind(TokenValidationService.class);
}
}

View File

@@ -0,0 +1,362 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid.conf;
import com.google.inject.Inject;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Service for retrieving configuration information regarding the OpenID
* service.
*/
public class ConfigurationService {
/**
* The default claim type to use to retrieve an authenticated user's
* username.
*/
private static final String DEFAULT_USERNAME_CLAIM_TYPE = "email";
/**
* The default space-separated list of OpenID scopes to request.
*/
private static final String DEFAULT_SCOPE = "openid email profile";
/**
* The default amount of clock skew tolerated for timestamp comparisons
* between the Guacamole server and OpenID service clocks, in seconds.
*/
private static final int DEFAULT_ALLOWED_CLOCK_SKEW = 30;
/**
* The default maximum amount of time that an OpenID token should remain
* valid, in minutes.
*/
private static final int DEFAULT_MAX_TOKEN_VALIDITY = 300;
/**
* The default maximum amount of time that a nonce generated by the
* Guacamole server should remain valid, in minutes.
*/
private static final int DEFAULT_MAX_NONCE_VALIDITY = 10;
/**
* The authorization endpoint (URI) of the OpenID service.
*/
private static final StringGuacamoleProperty OPENID_AUTHORIZATION_ENDPOINT =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-authorization-endpoint"; }
};
/**
* The endpoint (URI) of the JWKS service which defines how received ID
* tokens (JWTs) shall be validated.
*/
private static final StringGuacamoleProperty OPENID_JWKS_ENDPOINT =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-jwks-endpoint"; }
};
/**
* The issuer to expect for all received ID tokens.
*/
private static final StringGuacamoleProperty OPENID_ISSUER =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-issuer"; }
};
/**
* The claim type which contains the authenticated user's username within
* any valid JWT.
*/
private static final StringGuacamoleProperty OPENID_USERNAME_CLAIM_TYPE =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-username-claim-type"; }
};
/**
* The space-separated list of OpenID scopes to request.
*/
private static final StringGuacamoleProperty OPENID_SCOPE =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-scope"; }
};
/**
* The amount of clock skew tolerated for timestamp comparisons between the
* Guacamole server and OpenID service clocks, in seconds.
*/
private static final IntegerGuacamoleProperty OPENID_ALLOWED_CLOCK_SKEW =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "openid-allowed-clock-skew"; }
};
/**
* The maximum amount of time that an OpenID token should remain valid, in
* minutes.
*/
private static final IntegerGuacamoleProperty OPENID_MAX_TOKEN_VALIDITY =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "openid-max-token-validity"; }
};
/**
* The maximum amount of time that a nonce generated by the Guacamole server
* should remain valid, in minutes. As each OpenID request has a unique
* nonce value, this imposes an upper limit on the amount of time any
* particular OpenID request can result in successful authentication within
* Guacamole.
*/
private static final IntegerGuacamoleProperty OPENID_MAX_NONCE_VALIDITY =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "openid-max-nonce-validity"; }
};
/**
* OpenID client ID which should be submitted to the OpenID service when
* necessary. This value is typically provided by the OpenID service when
* OpenID credentials are generated for your application.
*/
private static final StringGuacamoleProperty OPENID_CLIENT_ID =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-client-id"; }
};
/**
* The URI that the OpenID service should redirect to after the
* authentication process is complete. This must be the full URL that a
* user would enter into their browser to access Guacamole.
*/
private static final StringGuacamoleProperty OPENID_REDIRECT_URI =
new StringGuacamoleProperty() {
@Override
public String getName() { return "openid-redirect-uri"; }
};
/**
* The Guacamole server environment.
*/
@Inject
private Environment environment;
/**
* Returns the authorization endpoint (URI) of the OpenID service as
* configured with guacamole.properties.
*
* @return
* The authorization endpoint of the OpenID service, as configured with
* guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the authorization
* endpoint property is missing.
*/
public String getAuthorizationEndpoint() throws GuacamoleException {
return environment.getRequiredProperty(OPENID_AUTHORIZATION_ENDPOINT);
}
/**
* Returns the OpenID client ID which should be submitted to the OpenID
* service when necessary, as configured with guacamole.properties. This
* value is typically provided by the OpenID service when OpenID credentials
* are generated for your application.
*
* @return
* The client ID to use when communicating with the OpenID service,
* as configured with guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the client ID
* property is missing.
*/
public String getClientID() throws GuacamoleException {
return environment.getRequiredProperty(OPENID_CLIENT_ID);
}
/**
* Returns the URI that the OpenID service should redirect to after
* the authentication process is complete, as configured with
* guacamole.properties. This must be the full URL that a user would enter
* into their browser to access Guacamole.
*
* @return
* The client secret to use when communicating with the OpenID service,
* as configured with guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the redirect URI
* property is missing.
*/
public String getRedirectURI() throws GuacamoleException {
return environment.getRequiredProperty(OPENID_REDIRECT_URI);
}
/**
* Returns the issuer to expect for all received ID tokens, as configured
* with guacamole.properties.
*
* @return
* The issuer to expect for all received ID tokens, as configured with
* guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the issuer property
* is missing.
*/
public String getIssuer() throws GuacamoleException {
return environment.getRequiredProperty(OPENID_ISSUER);
}
/**
* Returns the endpoint (URI) of the JWKS service which defines how
* received ID tokens (JWTs) shall be validated, as configured with
* guacamole.properties.
*
* @return
* The endpoint (URI) of the JWKS service which defines how received ID
* tokens (JWTs) shall be validated, as configured with
* guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed, or if the JWKS endpoint
* property is missing.
*/
public String getJWKSEndpoint() throws GuacamoleException {
return environment.getRequiredProperty(OPENID_JWKS_ENDPOINT);
}
/**
* Returns the claim type which contains the authenticated user's username
* within any valid JWT, as configured with guacamole.properties. By
* default, this will be "email".
*
* @return
* The claim type which contains the authenticated user's username
* within any valid JWT, as configured with guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public String getUsernameClaimType() throws GuacamoleException {
return environment.getProperty(OPENID_USERNAME_CLAIM_TYPE, DEFAULT_USERNAME_CLAIM_TYPE);
}
/**
* Returns the space-separated list of OpenID scopes to request. By default,
* this will be "openid email profile". The OpenID scopes determine the
* information returned within the OpenID token, and thus affect what
* values can be used as an authenticated user's username.
*
* @return
* The space-separated list of OpenID scopes to request when identifying
* a user.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public String getScope() throws GuacamoleException {
return environment.getProperty(OPENID_SCOPE, DEFAULT_SCOPE);
}
/**
* Returns the amount of clock skew tolerated for timestamp comparisons
* between the Guacamole server and OpenID service clocks, in seconds. Too
* much clock skew will affect token expiration calculations, possibly
* allowing old tokens to be used. By default, this will be 30.
*
* @return
* The amount of clock skew tolerated for timestamp comparisons, in
* seconds.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getAllowedClockSkew() throws GuacamoleException {
return environment.getProperty(OPENID_ALLOWED_CLOCK_SKEW, DEFAULT_ALLOWED_CLOCK_SKEW);
}
/**
* Returns the maximum amount of time that an OpenID token should remain
* valid, in minutes. A token received from an OpenID service which is
* older than this amount of time will be rejected, even if it is otherwise
* valid. By default, this will be 300 (5 hours).
*
* @return
* The maximum amount of time that an OpenID token should remain valid,
* in minutes.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getMaxTokenValidity() throws GuacamoleException {
return environment.getProperty(OPENID_MAX_TOKEN_VALIDITY, DEFAULT_MAX_TOKEN_VALIDITY);
}
/**
* Returns the maximum amount of time that a nonce generated by the
* Guacamole server should remain valid, in minutes. As each OpenID request
* has a unique nonce value, this imposes an upper limit on the amount of
* time any particular OpenID request can result in successful
* authentication within Guacamole. By default, this will be 10.
*
* @return
* The maximum amount of time that a nonce generated by the Guacamole
* server should remain valid, in minutes.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getMaxNonceValidity() throws GuacamoleException {
return environment.getProperty(OPENID_MAX_NONCE_VALIDITY, DEFAULT_MAX_NONCE_VALIDITY);
}
}

View File

@@ -0,0 +1,106 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid.form;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.guacamole.form.Field;
/**
* Field definition which represents the token returned by an OpenID Connect
* service.
*/
public class TokenField extends Field {
/**
* The standard HTTP parameter which will be included within the URL by all
* OpenID services upon successful authentication and redirect.
*/
public static final String PARAMETER_NAME = "id_token";
/**
* The full URI which the field should link to.
*/
private final String authorizationURI;
/**
* Creates a new field which requests authentication via OpenID connect.
* Successful authentication at the OpenID Connect service will result in
* the client being redirected to the specified redirect URI. The OpenID
* token will be embedded in the fragment (the part following the hash
* symbol) of that URI, which the JavaScript side of this extension will
* move to the query parameters.
*
* @param authorizationEndpoint
* The full URL of the endpoint accepting OpenID authentication
* requests.
*
* @param scope
* The space-delimited list of OpenID scopes to request from the
* identity provider, such as "openid" or "openid email profile".
*
* @param clientID
* The ID of the OpenID client. This is normally determined ahead of
* time by the OpenID service through some manual credential request
* procedure.
*
* @param redirectURI
* The URI that the OpenID service should redirect to upon successful
* authentication.
*
* @param nonce
* A random string unique to this request. To defend against replay
* attacks, this value must cease being valid after its first use.
*/
public TokenField(String authorizationEndpoint, String scope,
String clientID, String redirectURI, String nonce) {
// Init base field properties
super(PARAMETER_NAME, "GUAC_OPENID_TOKEN");
// Build authorization URI from given values
try {
this.authorizationURI = authorizationEndpoint
+ "?scope=" + URLEncoder.encode(scope, "UTF-8")
+ "&response_type=id_token"
+ "&client_id=" + URLEncoder.encode(clientID, "UTF-8")
+ "&redirect_uri=" + URLEncoder.encode(redirectURI, "UTF-8")
+ "&nonce=" + nonce;
}
// Java is required to provide UTF-8 support
catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
}
}
/**
* Returns the full URI that this field should link to when a new token
* needs to be obtained from the OpenID service.
*
* @return
* The full URI that this field should link to.
*/
public String getAuthorizationURI() {
return authorizationURI;
}
}

View File

@@ -0,0 +1,135 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid.token;
import com.google.inject.Singleton;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Service for generating and validating single-use random tokens (nonces).
*/
@Singleton
public class NonceService {
/**
* Cryptographically-secure random number generator for generating the
* required nonce.
*/
private final SecureRandom random = new SecureRandom();
/**
* Map of all generated nonces to their corresponding expiration timestamps.
* This Map must be periodically swept of expired nonces to avoid growing
* without bound.
*/
private final Map<String, Long> nonces = new ConcurrentHashMap<String, Long>();
/**
* The timestamp of the last expired nonce sweep.
*/
private long lastSweep = System.currentTimeMillis();
/**
* The minimum amount of time to wait between sweeping expired nonces from
* the Map.
*/
private static final long SWEEP_INTERVAL = 60000;
/**
* Iterates through the entire Map of generated nonces, removing any nonce
* that has exceeded its expiration timestamp. If insufficient time has
* elapsed since the last sweep, as dictated by SWEEP_INTERVAL, this
* function has no effect.
*/
private void sweepExpiredNonces() {
// Do not sweep until enough time has elapsed since the last sweep
long currentTime = System.currentTimeMillis();
if (currentTime - lastSweep < SWEEP_INTERVAL)
return;
// Record time of sweep
lastSweep = currentTime;
// For each stored nonce
Iterator<Map.Entry<String, Long>> entries = nonces.entrySet().iterator();
while (entries.hasNext()) {
// Remove all entries which have expired
Map.Entry<String, Long> current = entries.next();
if (current.getValue() <= System.currentTimeMillis())
entries.remove();
}
}
/**
* Generates a cryptographically-secure nonce value. The nonce is intended
* to be used to prevent replay attacks.
*
* @param maxAge
* The maximum amount of time that the generated nonce should remain
* valid, in milliseconds.
*
* @return
* A cryptographically-secure nonce value.
*/
public String generate(long maxAge) {
// Sweep expired nonces if enough time has passed
sweepExpiredNonces();
// Generate and store nonce, along with expiration timestamp
String nonce = new BigInteger(130, random).toString(32);
nonces.put(nonce, System.currentTimeMillis() + maxAge);
return nonce;
}
/**
* Returns whether the give nonce value is valid. A nonce is valid if and
* only if it was generated by this instance of the NonceService. Testing
* nonce validity through this function immediately and permanently
* invalidates that nonce.
*
* @param nonce
* The nonce value to test.
*
* @return
* true if the provided nonce is valid, false otherwise.
*/
public boolean isValid(String nonce) {
// Remove nonce, verifying whether it was present at all
Long expires = nonces.remove(nonce);
if (expires == null)
return false;
// Nonce is only valid if it hasn't expired
return expires > System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,140 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid.token;
import com.google.inject.Inject;
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
import org.apache.guacamole.GuacamoleException;
import org.jose4j.jwk.HttpsJwks;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service for validating ID tokens forwarded to us by the client, verifying
* that they did indeed come from the OpenID service.
*/
public class TokenValidationService {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(TokenValidationService.class);
/**
* Service for retrieving OpenID configuration information.
*/
@Inject
private ConfigurationService confService;
/**
* Service for validating and generating unique nonce values.
*/
@Inject
private NonceService nonceService;
/**
* Validates and parses the given ID token, returning the username contained
* therein, as defined by the username claim type given in
* guacamole.properties. If the username claim type is missing or the ID
* token is invalid, null is returned.
*
* @param token
* The ID token to validate and parse.
*
* @return
* The username contained within the given ID token, or null if the ID
* token is not valid or the username claim type is missing,
*
* @throws GuacamoleException
* If guacamole.properties could not be parsed.
*/
public String processUsername(String token) throws GuacamoleException {
// Validating the token requires a JWKS key resolver
HttpsJwks jwks = new HttpsJwks(confService.getJWKSEndpoint());
HttpsJwksVerificationKeyResolver resolver = new HttpsJwksVerificationKeyResolver(jwks);
// Create JWT consumer for validating received token
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime()
.setMaxFutureValidityInMinutes(confService.getMaxTokenValidity())
.setAllowedClockSkewInSeconds(confService.getAllowedClockSkew())
.setRequireSubject()
.setExpectedIssuer(confService.getIssuer())
.setExpectedAudience(confService.getClientID())
.setVerificationKeyResolver(resolver)
.build();
try {
String usernameClaim = confService.getUsernameClaimType();
// Validate JWT
JwtClaims claims = jwtConsumer.processToClaims(token);
// Verify a nonce is present
String nonce = claims.getStringClaimValue("nonce");
if (nonce == null) {
logger.info("Rejected OpenID token without nonce.");
return null;
}
// Verify that we actually generated the nonce, and that it has not
// already been used
if (!nonceService.isValid(nonce)) {
logger.debug("Rejected OpenID token with invalid/old nonce.");
return null;
}
// Pull username from claims
String username = claims.getStringClaimValue(usernameClaim);
if (username != null)
return username;
// Warn if username was not present in token, as it likely means
// the system is not set up correctly
logger.warn("Username claim \"{}\" missing from token. Perhaps the "
+ "OpenID scope and/or username claim type are "
+ "misconfigured?", usernameClaim);
}
// Log any failures to validate/parse the JWT
catch (InvalidJwtException e) {
logger.info("Rejected invalid OpenID token: {}", e.getMessage());
logger.debug("Invalid JWT received.", e);
}
catch (MalformedClaimException e) {
logger.info("Rejected OpenID token with malformed claim: {}", e.getMessage());
logger.debug("Malformed claim within received JWT.", e);
}
// Could not retrieve username from JWT
return null;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.openid.user;
import com.google.inject.Inject;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
/**
* An openid-specific implementation of AuthenticatedUser, associating a
* username and particular set of credentials with the OpenID authentication
* provider.
*/
public class AuthenticatedUser extends AbstractAuthenticatedUser {
/**
* Reference to the authentication provider associated with this
* authenticated user.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* The credentials provided when this user was authenticated.
*/
private Credentials credentials;
/**
* Initializes this AuthenticatedUser using the given username and
* credentials.
*
* @param username
* The username of the user that was authenticated.
*
* @param credentials
* The credentials provided when this user was authenticated.
*/
public void init(String username, Credentials credentials) {
this.credentials = credentials;
setIdentifier(username);
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public Credentials getCredentials() {
return credentials;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Config block which registers openid-specific field types.
*/
angular.module('guacOpenID').config(['formServiceProvider',
function guacOpenIDConfig(formServiceProvider) {
// Define field for token from OpenID service
formServiceProvider.registerFieldType("GUAC_OPENID_TOKEN", {
templateUrl : 'app/ext/guac-openid/templates/openidTokenField.html',
controller : 'guacOpenIDController',
module : 'guacOpenID'
});
}]);
/**
* Config block which augments the existing routing, providing special handling
* for the "id_token=" fragments provided by OpenID Connect.
*/
angular.module('index').config(['$routeProvider',
function indexRouteConfig($routeProvider) {
// Transform "/#/id_token=..." to "/#/?id_token=..."
$routeProvider.when('/id_token=:response', {
template : '',
controller : ['$location', function reroute($location) {
var params = $location.path().substring(1);
$location.url('/');
$location.search(params);
}]
});
}]);

View File

@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Controller for the "GUAC_OPENID_TOKEN" field which simply redirects the user
* immediately to the authorization URI.
*/
angular.module('guacOpenID').controller('guacOpenIDController', ['$scope',
function guacOpenIDController($scope) {
// Redirect to authorization URI
window.location = $scope.field.authorizationURI;
}]);

View File

@@ -0,0 +1,28 @@
{
"guacamoleVersion" : "0.9.13-incubating",
"name" : "OpenID Authentication Extension",
"namespace" : "guac-openid",
"authProviders" : [
"org.apache.guacamole.auth.openid.OpenIDAuthenticationProvider"
],
"translations" : [
"translations/en.json"
],
"js" : [
"openid.min.js"
],
"css" : [
"openid.min.css"
],
"resources" : {
"templates/openidTokenField.html" : "text/html"
}
}

View File

@@ -0,0 +1,18 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

View File

@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Module which provides handling for OpenID authentication.
*/
angular.module('guacOpenID', [
'form'
]);
// Ensure the OpenID module is loaded along with the rest of the app
angular.module('index').requires.push('guacOpenID');

View File

@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
.openid-token-field-container {
height: 100%;
width: 100%;
position: fixed;
left: 0;
top: 0;
display: table;
background: white;
}
.openid-token-field {
width: 100%;
display: table-cell;
vertical-align: middle;
text-align: center;
}

View File

@@ -0,0 +1,5 @@
<div class="openid-token-field-container">
<div class="openid-token-field">
<p>{{ 'LOGIN.INFO_REDIRECT_PENDING' | translate }}</p>
</div>
</div>

View File

@@ -0,0 +1,12 @@
{
"DATA_SOURCE_OPENID" : {
"NAME" : "OpenID SSO Backend"
},
"LOGIN" : {
"FIELD_HEADER_ID_TOKEN" : "",
"INFO_REDIRECT_PENDING" : "Please wait, redirecting to identity provider..."
}
}

View File

@@ -306,7 +306,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain) {
var message_xmlhttprequest = new XMLHttpRequest(); var message_xmlhttprequest = new XMLHttpRequest();
message_xmlhttprequest.open("POST", TUNNEL_WRITE + tunnel.uuid); message_xmlhttprequest.open("POST", TUNNEL_WRITE + tunnel.uuid);
message_xmlhttprequest.withCredentials = withCredentials; message_xmlhttprequest.withCredentials = withCredentials;
message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); message_xmlhttprequest.setRequestHeader("Content-type", "application/octet-stream");
// Once response received, send next queued event. // Once response received, send next queued event.
message_xmlhttprequest.onreadystatechange = function() { message_xmlhttprequest.onreadystatechange = function() {

View File

@@ -54,7 +54,6 @@ mkdir -p "$DESTINATION"
cd "$BUILD_DIR" cd "$BUILD_DIR"
mvn package mvn package
rm -Rf ~/.m2
# #
# Copy guacamole.war to destination # Copy guacamole.war to destination

View File

@@ -29,4 +29,9 @@ public abstract class AbstractAuthenticatedUser extends AbstractIdentifiable
// Prior functionality now resides within AbstractIdentifiable // Prior functionality now resides within AbstractIdentifiable
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

View File

@@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.net.auth;
import java.util.Date;
/**
* A logging record describing when a user started and ended a particular
* activity.
*/
public interface ActivityRecord {
/**
* Returns the date and time the activity began.
*
* @return
* The date and time the activity began.
*/
public Date getStartDate();
/**
* Returns the date and time the activity ended, if applicable.
*
* @return
* The date and time the activity ended, or null if the activity is
* still ongoing or if the end time is unknown.
*/
public Date getEndDate();
/**
* Returns the hostname or IP address of the remote host that performed the
* activity associated with this record, if known. If the hostname or IP
* address is not known, null is returned.
*
* @return
* The hostname or IP address of the remote host, or null if this
* information is not available.
*/
public String getRemoteHost();
/**
* Returns the name of the user who performed or is performing the activity
* at the times given by this record.
*
* @return
* The name of the user who performed or is performing the associated
* activity.
*/
public String getUsername();
/**
* Returns whether the activity associated with this record is still
* ongoing.
*
* @return
* true if the activity associated with this record is still ongoing,
* false otherwise.
*/
public boolean isActive();
}

View File

@@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.net.auth;
import java.util.Collection;
import org.apache.guacamole.GuacamoleException;
/**
* A set of all available records related to a type of activity which has a
* defined start and end time, such as a user being logged in or connected, or a
* subset of those records.
*
* @param <RecordType>
* The type of ActivityRecord contained within this set.
*/
public interface ActivityRecordSet<RecordType extends ActivityRecord> {
/**
* All properties of activity records which can be used as sorting
* criteria.
*/
enum SortableProperty {
/**
* The date and time when the activity associated with the record
* began.
*/
START_DATE
};
/**
* Returns all records within this set as a standard Collection.
*
* @return
* A collection containing all records within this set.
*
* @throws GuacamoleException
* If an error occurs while retrieving the records within this set.
*/
Collection<RecordType> asCollection() throws GuacamoleException;
/**
* Returns the subset of records which contain the given value. The
* properties and semantics involved with determining whether a particular
* record "contains" the given value is implementation dependent. This
* function may affect the contents of the current ActivityRecordSet. The
* contents of the current ActivityRecordSet should NOT be relied upon
* after this function is called.
*
* @param value
* The value which all records within the resulting subset should
* contain.
*
* @return
* The subset of records which contain the specified value.
*
* @throws GuacamoleException
* If an error occurs while restricting the current subset.
*/
ActivityRecordSet<RecordType> contains(String value)
throws GuacamoleException;
/**
* Returns the subset of records containing only the first
* <code>limit</code> records. If the subset has fewer than
* <code>limit</code> records, then this function has no effect. This
* function may also affect the contents of the current ActivityRecordSet.
* The contents of the current ActivityRecordSet should NOT be relied upon
* after this function is called.
*
* @param limit
* The maximum number of records that the new subset should contain.
*
* @return
* The subset of records that containing only the first
* <code>limit</code> records.
*
* @throws GuacamoleException
* If an error occurs while limiting the current subset.
*/
ActivityRecordSet<RecordType> limit(int limit) throws GuacamoleException;
/**
* Returns a ActivityRecordSet containing identically the records within
* this set, sorted according to the specified criteria. The sort operation
* performed is guaranteed to be stable with respect to any past call to
* sort(). This function may also affect the contents of the current
* ActivityRecordSet. The contents of the current ActivityRecordSet
* should NOT be relied upon after this function is called.
*
* @param property
* The property by which the records within the resulting set should be
* sorted.
*
* @param desc
* Whether the records should be sorted according to the specified
* property in descending order. If false, records will be sorted
* according to the specified property in ascending order.
*
* @return
* The ActivityRecordSet, sorted according to the specified criteria.
*
* @throws GuacamoleException
* If an error occurs while sorting the current subset, or if the given
* property is not supported by the implementation.
*/
ActivityRecordSet<RecordType> sort(SortableProperty property, boolean desc)
throws GuacamoleException;
}

View File

@@ -49,4 +49,11 @@ public interface AuthenticatedUser extends Identifiable {
*/ */
Credentials getCredentials(); Credentials getCredentials();
/**
* Invalidates this authenticated user and their associated token such that
* they are no longer logged in. This function will be automatically
* invoked when the user logs out, or when their session expires.
*/
void invalidate();
} }

View File

@@ -167,5 +167,12 @@ public interface AuthenticationProvider {
UserContext updateUserContext(UserContext context, UserContext updateUserContext(UserContext context,
AuthenticatedUser authenticatedUser, AuthenticatedUser authenticatedUser,
Credentials credentials) throws GuacamoleException; Credentials credentials) throws GuacamoleException;
/**
* Frees all resources associated with this AuthenticationProvider. This
* function will be automatically invoked when the Guacamole server is
* shutting down.
*/
void shutdown();
} }

View File

@@ -19,6 +19,7 @@
package org.apache.guacamole.net.auth; package org.apache.guacamole.net.auth;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -102,6 +103,18 @@ public interface Connection extends Identifiable, Connectable {
*/ */
void setAttributes(Map<String, String> attributes); void setAttributes(Map<String, String> attributes);
/**
* Returns the date and time that this connection was last used. If the
* connection was never used, the time that the connection was last used is
* unknown, or this information is not visible to the current user, this
* may be null.
*
* @return
* The date and time this connection was last used, or null if this
* information is unavailable or inapplicable.
*/
Date getLastActive();
/** /**
* Returns a list of ConnectionRecords representing the usage history * Returns a list of ConnectionRecords representing the usage history
* of this Connection, including any active users. ConnectionRecords * of this Connection, including any active users. ConnectionRecords

View File

@@ -19,13 +19,11 @@
package org.apache.guacamole.net.auth; package org.apache.guacamole.net.auth;
import java.util.Date;
/** /**
* A logging record describing when a user started and ended usage of a * A logging record describing when a user started and ended usage of a
* particular connection. * particular connection.
*/ */
public interface ConnectionRecord { public interface ConnectionRecord extends ActivityRecord {
/** /**
* Returns the identifier of the connection associated with this * Returns the identifier of the connection associated with this
@@ -72,48 +70,4 @@ public interface ConnectionRecord {
*/ */
public String getSharingProfileName(); public String getSharingProfileName();
/**
* Returns the date and time the connection began.
*
* @return The date and time the connection began.
*/
public Date getStartDate();
/**
* Returns the date and time the connection ended, if applicable.
*
* @return The date and time the connection ended, or null if the
* connection is still running or if the end time is unknown.
*/
public Date getEndDate();
/**
* Returns the hostname or IP address of the remote host that used the
* connection associated with this record, if known. If the hostname or IP
* address is not known, null is returned.
*
* @return
* The hostname or IP address of the remote host, or null if this
* information is not available.
*/
public String getRemoteHost();
/**
* Returns the name of the user who used or is using the connection at the
* times given by this connection record.
*
* @return The name of the user who used or is using the associated
* connection.
*/
public String getUsername();
/**
* Returns whether the connection associated with this record is still
* active.
*
* @return true if the connection associated with this record is still
* active, false otherwise.
*/
public boolean isActive();
} }

View File

@@ -19,107 +19,13 @@
package org.apache.guacamole.net.auth; package org.apache.guacamole.net.auth;
import java.util.Collection;
import org.apache.guacamole.GuacamoleException;
/** /**
* The set of all available connection records, or a subset of those records. * The set of all available connection records, or a subset of those records.
*
* @deprecated
* Use {@link ActivityRecordSet}&lt;{@link ConnectionRecord}&gt; instead.
*/ */
public interface ConnectionRecordSet { @Deprecated
public interface ConnectionRecordSet
/** extends ActivityRecordSet<ConnectionRecord> {
* All properties of connection records which can be used as sorting
* criteria.
*/
enum SortableProperty {
/**
* The date and time when the connection associated with the
* connection record began.
*/
START_DATE
};
/**
* Returns all connection records within this set as a standard Collection.
*
* @return
* A collection containing all connection records within this set.
*
* @throws GuacamoleException
* If an error occurs while retrieving the connection records within
* this set.
*/
Collection<ConnectionRecord> asCollection() throws GuacamoleException;
/**
* Returns the subset of connection records to only those where the
* connection name, user identifier, or any associated date field contain
* the given value. This function may also affect the contents of the
* current ConnectionRecordSet. The contents of the current
* ConnectionRecordSet should NOT be relied upon after this function is
* called.
*
* @param value
* The value which all connection records within the resulting subset
* should contain within their associated connection name or user
* identifier.
*
* @return
* The subset of connection history records which contain the specified
* value within their associated connection name or user identifier.
*
* @throws GuacamoleException
* If an error occurs while restricting the current subset.
*/
ConnectionRecordSet contains(String value) throws GuacamoleException;
/**
* Returns the subset of connection history records containing only the
* first <code>limit</code> records. If the subset has fewer than
* <code>limit</code> records, then this function has no effect. This
* function may also affect the contents of the current
* ConnectionRecordSet. The contents of the current ConnectionRecordSet
* should NOT be relied upon after this function is called.
*
* @param limit
* The maximum number of records that the new subset should contain.
*
* @return
* The subset of connection history records that containing only the
* first <code>limit</code> records.
*
* @throws GuacamoleException
* If an error occurs while limiting the current subset.
*/
ConnectionRecordSet limit(int limit) throws GuacamoleException;
/**
* Returns a ConnectionRecordSet containing identically the records within
* this set, sorted according to the specified criteria. The sort operation
* performed is guaranteed to be stable with respect to any past call to
* sort(). This function may also affect the contents of the current
* ConnectionRecordSet. The contents of the current ConnectionRecordSet
* should NOT be relied upon after this function is called.
*
* @param property
* The property by which the connection records within the resulting
* set should be sorted.
*
* @param desc
* Whether the records should be sorted according to the specified
* property in descending order. If false, records will be sorted
* according to the specified property in ascending order.
*
* @return
* The ConnnectionRecordSet, sorted according to the specified
* criteria.
*
* @throws GuacamoleException
* If an error occurs while sorting the current subset.
*/
ConnectionRecordSet sort(SortableProperty property, boolean desc)
throws GuacamoleException;
} }

View File

@@ -19,6 +19,8 @@
package org.apache.guacamole.net.auth; package org.apache.guacamole.net.auth;
import java.util.Date;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
@@ -100,6 +102,34 @@ public interface User extends Identifiable {
*/ */
void setAttributes(Map<String, String> attributes); void setAttributes(Map<String, String> attributes);
/**
* Returns the date and time that this user was last active. If the user
* was never active, the time that the user was last active is unknown, or
* this information is not visible to the current user, this may be null.
*
* @return
* The date and time this user was last active, or null if this
* information is unavailable or inapplicable.
*/
Date getLastActive();
/**
* Returns a list of ActivityRecords representing the login history
* of this user, including any active sessions. ActivityRecords
* in this list will be sorted in descending order of end time (active
* sessions are first), and then in descending order of start time
* (newer sessions are first).
*
* @return
* A list of ActivityRecords representing the login history of this
* User.
*
* @throws GuacamoleException
* If an error occurs while reading the history of this user, or if
* permission is denied.
*/
List<? extends ActivityRecord> getHistory() throws GuacamoleException;
/** /**
* Returns all system-level permissions given to this user. * Returns all system-level permissions given to this user.
* *

View File

@@ -143,9 +143,11 @@ public interface UserContext {
throws GuacamoleException; throws GuacamoleException;
/** /**
* Retrieves all connection records visible to current user. The resulting * Retrieves all connection records visible to current user. Connection
* set of connection records can be further filtered and ordered using the * history records describe the start and end times of connections, and
* methods defined on ConnectionRecordSet. * correspond to the times that users connect or disconnect to individual
* remote desktops. The resulting set of connection records can be further
* filtered and ordered using the methods defined on ActivityRecordSet.
* *
* @return * @return
* A set of all connection records visible to the current user. * A set of all connection records visible to the current user.
@@ -153,7 +155,23 @@ public interface UserContext {
* @throws GuacamoleException * @throws GuacamoleException
* If an error occurs while retrieving the connection records. * If an error occurs while retrieving the connection records.
*/ */
ConnectionRecordSet getConnectionHistory() throws GuacamoleException; ActivityRecordSet<ConnectionRecord> getConnectionHistory()
throws GuacamoleException;
/**
* Retrieves all user history records visible to current user. User history
* records describe the start and end times of user sessions, and correspond
* to the times that users logged in or out. The resulting set of user
* records can be further filtered and ordered using the methods defined on
* ActivityRecordSet.
*
* @return
* A set of all user records visible to the current user.
*
* @throws GuacamoleException
* If an error occurs while retrieving the user records.
*/
ActivityRecordSet<ActivityRecord> getUserHistory() throws GuacamoleException;
/** /**
* Retrieves a connection group which can be used to view and manipulate * Retrieves a connection group which can be used to view and manipulate
@@ -212,4 +230,11 @@ public interface UserContext {
*/ */
Collection<Form> getSharingProfileAttributes(); Collection<Form> getSharingProfileAttributes();
/**
* Invalidates this user context, releasing all associated resources. This
* function will be invoked when the user logs out, or when their session
* is automatically invalidated.
*/
void invalidate();
} }

View File

@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.net.auth.simple;
import java.util.Collection;
import java.util.Collections;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.ActivityRecordSet.SortableProperty;
/**
* An immutable and empty ActivityRecordSet.
*
* @param <RecordType>
* The type of ActivityRecord contained within this set.
*/
public class SimpleActivityRecordSet<RecordType extends ActivityRecord>
implements ActivityRecordSet<RecordType> {
@Override
public Collection<RecordType> asCollection()
throws GuacamoleException {
return Collections.<RecordType>emptyList();
}
@Override
public ActivityRecordSet<RecordType> contains(String value)
throws GuacamoleException {
return this;
}
@Override
public ActivityRecordSet<RecordType> limit(int limit)
throws GuacamoleException {
return this;
}
@Override
public ActivityRecordSet<RecordType> sort(SortableProperty property,
boolean desc) throws GuacamoleException {
return this;
}
}

View File

@@ -260,4 +260,9 @@ public abstract class SimpleAuthenticationProvider
} }
@Override
public void shutdown() {
// Do nothing
}
} }

View File

@@ -20,6 +20,7 @@
package org.apache.guacamole.net.auth.simple; package org.apache.guacamole.net.auth.simple;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
@@ -136,6 +137,11 @@ public class SimpleConnection extends AbstractConnection {
} }
@Override
public Date getLastActive() {
return null;
}
@Override @Override
public List<ConnectionRecord> getHistory() throws GuacamoleException { public List<ConnectionRecord> getHistory() throws GuacamoleException {
return Collections.<ConnectionRecord>emptyList(); return Collections.<ConnectionRecord>emptyList();

View File

@@ -23,12 +23,16 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.net.auth.ConnectionRecord;
import org.apache.guacamole.net.auth.ConnectionRecordSet;
/** /**
* An immutable and empty ConnectionRecordSet. * An immutable and empty ConnectionRecordSet.
*
* @deprecated
* Use {@link SimpleActivityRecordSet}&lt;{@link ConnectionRecord}&gt;
* instead.
*/ */
public class SimpleConnectionRecordSet implements ConnectionRecordSet { @Deprecated
public class SimpleConnectionRecordSet implements org.apache.guacamole.net.auth.ConnectionRecordSet {
@Override @Override
public Collection<ConnectionRecord> asCollection() public Collection<ConnectionRecord> asCollection()
@@ -37,19 +41,19 @@ public class SimpleConnectionRecordSet implements ConnectionRecordSet {
} }
@Override @Override
public ConnectionRecordSet contains(String value) public org.apache.guacamole.net.auth.ConnectionRecordSet contains(String value)
throws GuacamoleException { throws GuacamoleException {
return this; return this;
} }
@Override @Override
public ConnectionRecordSet limit(int limit) public org.apache.guacamole.net.auth.ConnectionRecordSet limit(int limit)
throws GuacamoleException { throws GuacamoleException {
return this; return this;
} }
@Override @Override
public ConnectionRecordSet sort(SortableProperty property, boolean desc) public org.apache.guacamole.net.auth.ConnectionRecordSet sort(SortableProperty property, boolean desc)
throws GuacamoleException { throws GuacamoleException {
return this; return this;
} }

View File

@@ -21,11 +21,14 @@ package org.apache.guacamole.net.auth.simple;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractUser; import org.apache.guacamole.net.auth.AbstractUser;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.permission.ObjectPermission; import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet; import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
@@ -163,6 +166,16 @@ public class SimpleUser extends AbstractUser {
// Do nothing - there are no attributes // Do nothing - there are no attributes
} }
@Override
public Date getLastActive() {
return null;
}
@Override
public List<ActivityRecord> getHistory() throws GuacamoleException {
return Collections.<ActivityRecord>emptyList();
}
@Override @Override
public SystemPermissionSet getSystemPermissions() public SystemPermissionSet getSystemPermissions()
throws GuacamoleException { throws GuacamoleException {

View File

@@ -27,10 +27,12 @@ import java.util.UUID;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.form.Form; import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.ActivityRecordSet;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.ConnectionRecordSet; import org.apache.guacamole.net.auth.ConnectionRecord;
import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User; import org.apache.guacamole.net.auth.User;
@@ -209,9 +211,15 @@ public class SimpleUserContext implements UserContext {
} }
@Override @Override
public ConnectionRecordSet getConnectionHistory() public ActivityRecordSet<ConnectionRecord> getConnectionHistory()
throws GuacamoleException { throws GuacamoleException {
return new SimpleConnectionRecordSet(); return new SimpleActivityRecordSet<ConnectionRecord>();
}
@Override
public ActivityRecordSet<ActivityRecord> getUserHistory()
throws GuacamoleException {
return new SimpleActivityRecordSet<ActivityRecord>();
} }
@Override @Override
@@ -234,4 +242,9 @@ public class SimpleUserContext implements UserContext {
return Collections.<Form>emptyList(); return Collections.<Form>emptyList();
} }
@Override
public void invalidate() {
// Nothing to invalidate
}
} }

Some files were not shown because too many files have changed in this diff Show More