diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
index ac9856240..9c99593bf 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
@@ -94,12 +94,6 @@
guice
-
-
- com.google.inject.extensions
- guice-assistedinject
-
-
com.google.guava
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java
index e47ccf259..5ae0ea53f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java
@@ -20,8 +20,6 @@
package org.apache.guacamole.auth.jdbc;
import com.google.inject.Scopes;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
-
import javax.sql.DataSource;
import org.apache.guacamole.auth.jdbc.user.ModeledUserContext;
import org.apache.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
@@ -40,8 +38,6 @@ import org.apache.guacamole.auth.jdbc.permission.SystemPermissionMapper;
import org.apache.guacamole.auth.jdbc.user.UserMapper;
import org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupService;
import org.apache.guacamole.auth.jdbc.connection.ConnectionService;
-import org.apache.guacamole.auth.jdbc.tunnel.AccessEnforcingDelegatingTunnel;
-import org.apache.guacamole.auth.jdbc.tunnel.AccessEnforcingDelegatingTunnelFactory;
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
import org.apache.guacamole.auth.jdbc.security.SHA256PasswordEncryptionService;
@@ -200,14 +196,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(UserGroupPermissionService.class);
bind(UserPermissionService.class);
bind(UserService.class);
-
- // Bind Factories
- install(new FactoryModuleBuilder()
- .implement(
- AccessEnforcingDelegatingTunnel.class,
- AccessEnforcingDelegatingTunnel.class)
- .build(AccessEnforcingDelegatingTunnelFactory.class));
-
+
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
index 778d5b29f..77f038734 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
@@ -230,12 +230,11 @@ public abstract class JDBCEnvironment extends DelegatingEnvironment {
/**
* Returns a boolean value representing whether access time windows should
* be enforced for active connections - i.e. whether a currently-connected
- * user should be disconnected upon the closure of an access window, or
- * when the user is disabled.
+ * user should be disconnected upon the closure of an access window.
*
* @return
- * True if a connected user should be disconnected upon an access time
- * window closing, or the user being disabled.
+ * true if a connected user should be disconnected upon an access time
+ * window closing, false otherwise.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionDirectory.java
index b9a149933..b0d6324aa 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionDirectory.java
@@ -44,40 +44,34 @@ public class ActiveConnectionDirectory extends RestrictedObject
@Override
public ActiveConnection get(String identifier) throws GuacamoleException {
- validateUserAccess();
return activeConnectionService.retrieveObject(getCurrentUser(), identifier);
}
@Override
public Collection getAll(Collection identifiers)
throws GuacamoleException {
- validateUserAccess();
Collection objects = activeConnectionService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.unmodifiableCollection(objects);
}
@Override
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return activeConnectionService.getIdentifiers(getCurrentUser());
}
@Override
public void add(ActiveConnection object) throws GuacamoleException {
- validateUserAccess();
activeConnectionService.createObject(getCurrentUser(), object);
}
@Override
public void update(ActiveConnection object) throws GuacamoleException {
- validateUserAccess();
TrackedActiveConnection connection = (TrackedActiveConnection) object;
activeConnectionService.updateObject(getCurrentUser(), connection);
}
@Override
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
activeConnectionService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RestrictedObject.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RestrictedObject.java
index 461ce5804..66979d487 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RestrictedObject.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RestrictedObject.java
@@ -19,13 +19,7 @@
package org.apache.guacamole.auth.jdbc.base;
-import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleUnauthorizedException;
-import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
-
-import com.google.inject.Inject;
/**
* Common base class for objects that are associated with the users that
@@ -39,12 +33,6 @@ public abstract class RestrictedObject {
*/
private ModeledAuthenticatedUser currentUser;
- /**
- * The environment of the Guacamole server.
- */
- @Inject
- private JDBCEnvironment environment;
-
/**
* Initializes this object, associating it with the current authenticated
* user and populating it with data from the given model object
@@ -80,39 +68,4 @@ public abstract class RestrictedObject {
this.currentUser = currentUser;
}
- /**
- * Validate that the current user is within a valid access time window
- * and not disabled. If the user account is disabled or not within a
- * valid access window, a GuacamoleUnauthorizedException will be thrown.
- *
- * This method can be called by RestrictedObject implementations before
- * any operation that's specific to the current logged in user, to make
- * sure that their access is still valid and enabled.
- *
- * If accessWindowCheckEnabled is set to false, the check will be skipped,
- * and GuacamoleUnauthorizedException will never be thrown.
- *
- * @throws GuacamoleException
- * If the user is outside of a valid access window, the user is
- * disabled, or an error occurs while trying to determine access time
- * restriction configuration.
- */
- protected void validateUserAccess() throws GuacamoleException {
-
- // If access windows shouldn't be checked for active sessions, skip
- // this check entirely
- if (!environment.enforceAccessWindowsForActiveSessions())
- return;
-
- // If the user is outside of a valid access time window or disabled,
- // throw an exception to immediately log them out
- ModeledUser modeledUser = getCurrentUser().getUser();
- if (
- !modeledUser.isAccountAccessible()
- || !modeledUser.isAccountValid()
- || modeledUser.isDisabled()
- )
- throw new GuacamoleUnauthorizedException("Permission Denied.");
- }
-
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionDirectory.java
index 54ca79033..52a127df4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionDirectory.java
@@ -45,14 +45,12 @@ public class ConnectionDirectory extends RestrictedObject
@Override
public Connection get(String identifier) throws GuacamoleException {
- validateUserAccess();
return connectionService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection getAll(Collection identifiers) throws GuacamoleException {
- validateUserAccess();
Collection objects = connectionService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.unmodifiableCollection(objects);
}
@@ -60,21 +58,18 @@ public class ConnectionDirectory extends RestrictedObject
@Override
@Transactional
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return connectionService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(Connection object) throws GuacamoleException {
- validateUserAccess();
connectionService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(Connection object) throws GuacamoleException {
- validateUserAccess();
ModeledConnection connection = (ModeledConnection) object;
connectionService.updateObject(getCurrentUser(), connection);
}
@@ -82,7 +77,6 @@ public class ConnectionDirectory extends RestrictedObject
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
connectionService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupDirectory.java
index 030432793..9f3930597 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupDirectory.java
@@ -45,14 +45,12 @@ public class ConnectionGroupDirectory extends RestrictedObject
@Override
public ConnectionGroup get(String identifier) throws GuacamoleException {
- validateUserAccess();
return connectionGroupService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection getAll(Collection identifiers) throws GuacamoleException {
- validateUserAccess();
Collection objects = connectionGroupService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.unmodifiableCollection(objects);
}
@@ -60,21 +58,18 @@ public class ConnectionGroupDirectory extends RestrictedObject
@Override
@Transactional
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return connectionGroupService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(ConnectionGroup object) throws GuacamoleException {
- validateUserAccess();
connectionGroupService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(ConnectionGroup object) throws GuacamoleException {
- validateUserAccess();
ModeledConnectionGroup connectionGroup = (ModeledConnectionGroup) object;
connectionGroupService.updateObject(getCurrentUser(), connectionGroup);
}
@@ -82,7 +77,6 @@ public class ConnectionGroupDirectory extends RestrictedObject
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
connectionGroupService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java
index 57ccb6d63..632557052 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java
@@ -44,14 +44,12 @@ public class SharingProfileDirectory extends RestrictedObject
@Override
public SharingProfile get(String identifier) throws GuacamoleException {
- validateUserAccess();
return sharingProfileService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection getAll(Collection identifiers) throws GuacamoleException {
- validateUserAccess();
return Collections.unmodifiableCollection(
sharingProfileService.retrieveObjects(getCurrentUser(), identifiers)
);
@@ -60,21 +58,18 @@ public class SharingProfileDirectory extends RestrictedObject
@Override
@Transactional
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return sharingProfileService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(SharingProfile object) throws GuacamoleException {
- validateUserAccess();
sharingProfileService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(SharingProfile object) throws GuacamoleException {
- validateUserAccess();
ModeledSharingProfile sharingProfile = (ModeledSharingProfile) object;
sharingProfileService.updateObject(getCurrentUser(), sharingProfile);
}
@@ -82,7 +77,6 @@ public class SharingProfileDirectory extends RestrictedObject
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
sharingProfileService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
index f26b8ea13..8c16363a6 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
@@ -46,7 +46,6 @@ import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.GuacamoleUpstreamException;
-import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.connection.ConnectionMapper;
import org.apache.guacamole.net.GuacamoleSocket;
import org.apache.guacamole.net.GuacamoleTunnel;
@@ -64,7 +63,6 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper;
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterModel;
import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.UserService;
import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration;
import org.apache.guacamole.protocol.FailoverGuacamoleSocket;
import org.slf4j.Logger;
@@ -119,24 +117,6 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
@Inject
private SharedConnectionMap connectionMap;
- /**
- * Service for fetching users.
- */
- @Inject
- private UserService userService;
-
- /**
- * The environment of the Guacamole server.
- */
- @Inject
- private JDBCEnvironment environment;
-
- /**
- * Provider for creating AccessEnforcingDelegatingTunnel instances.
- */
- @Inject
- private AccessEnforcingDelegatingTunnelFactory accessEnforcingTunnelFactory;
-
/**
* All active connections through the tunnel having a given UUID.
*/
@@ -405,21 +385,13 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
* connection, which MUST already be acquired via acquire(). The given
* client information will be passed to guacd when the connection is
* established.
- *
+ *
* The connection will be automatically released when it closes, or if it
* fails to establish entirely.
*
- * If user access window restrictions are enabled for active sessions,
- * they will be automatically enforced for any valid database users as the
- * tunnel is used.
- *
* @param activeConnection
* The active connection record of the connection in use.
*
- * @param user
- * The user record in the database for the user connecting to the
- * connection, if any.
- *
* @param info
* Information describing the Guacamole client connecting to the given
* connection.
@@ -440,10 +412,8 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
* If an error occurs while the connection is being established, or
* while connection configuration information is being retrieved.
*/
- private GuacamoleTunnel assignGuacamoleTunnel(
- ActiveConnectionRecord activeConnection,
- ModeledAuthenticatedUser user, GuacamoleClientInformation info,
- Map tokens,
+ private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConnection,
+ GuacamoleClientInformation info, Map tokens,
boolean interceptErrors) throws GuacamoleException {
// Record new active connection
@@ -506,21 +476,12 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
getUnconfiguredGuacamoleSocket(connection.getGuacamoleProxyConfiguration(),
cleanupTask), config, info);
- // Assign new tunnel
- GuacamoleTunnel tunnel;
+ // Assign and return new tunnel
if (interceptErrors)
- tunnel = activeConnection.assignGuacamoleTunnel(new FailoverGuacamoleSocket(socket), socket.getConnectionID());
+ return activeConnection.assignGuacamoleTunnel(new FailoverGuacamoleSocket(socket), socket.getConnectionID());
else
- tunnel = activeConnection.assignGuacamoleTunnel(socket, socket.getConnectionID());
-
- // If there is an associated database user, and access window
- // restrictions are enabled for active sessions, wrap the tunnel
- // in order to check user login validity on every instruction read
- if (user != null && environment.enforceAccessWindowsForActiveSessions()) {
- tunnel = accessEnforcingTunnelFactory.create(tunnel, user);
- }
-
- return tunnel;
+ return activeConnection.assignGuacamoleTunnel(socket, socket.getConnectionID());
+
}
// Execute cleanup if socket could not be created
@@ -670,10 +631,8 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
acquire(user, Collections.singletonList(connection), true);
// Connect only if the connection was successfully acquired
- ActiveConnectionRecord connectionRecord = new ActiveConnectionRecord(
- connectionMap, user, connection);
- return assignGuacamoleTunnel(
- connectionRecord, user, info, tokens, false);
+ ActiveConnectionRecord connectionRecord = new ActiveConnectionRecord(connectionMap, user, connection);
+ return assignGuacamoleTunnel(connectionRecord, info, tokens, false);
}
@@ -718,10 +677,9 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
try {
// Connect to acquired child
- ActiveConnectionRecord connectionRecord = new ActiveConnectionRecord(
- connectionMap, user, connectionGroup, connection);
- GuacamoleTunnel tunnel = assignGuacamoleTunnel(
- connectionRecord, user, info, tokens, connections.size() > 1);
+ ActiveConnectionRecord connectionRecord = new ActiveConnectionRecord(connectionMap, user, connectionGroup, connection);
+ GuacamoleTunnel tunnel = assignGuacamoleTunnel(connectionRecord,
+ info, tokens, connections.size() > 1);
// If session affinity is enabled, prefer this connection going forward
if (connectionGroup.isSessionAffinityEnabled())
@@ -778,10 +736,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
user, definition.getActiveConnection(), definition.getSharingProfile());
// Connect to shared connection described by the created record
- GuacamoleTunnel tunnel = assignGuacamoleTunnel(
- connectionRecord, userService.retrieveAuthenticatedUser(
- user.getAuthenticationProvider(), user.getCredentials()),
- info, tokens, false);
+ GuacamoleTunnel tunnel = assignGuacamoleTunnel(connectionRecord, info, tokens, false);
// Register tunnel, such that it is closed when the
// SharedConnectionDefinition is invalidated
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnel.java
deleted file mode 100644
index 5ee08330c..000000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnel.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.jdbc.tunnel;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.annotation.Nonnull;
-
-import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleUnauthorizedException;
-import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
-import org.apache.guacamole.auth.jdbc.user.UserService;
-import org.apache.guacamole.io.GuacamoleReader;
-import org.apache.guacamole.net.DelegatingGuacamoleTunnel;
-import org.apache.guacamole.net.GuacamoleTunnel;
-import org.apache.guacamole.protocol.FilteredGuacamoleReader;
-import org.apache.guacamole.protocol.GuacamoleFilter;
-import org.apache.guacamole.protocol.GuacamoleInstruction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-import com.google.inject.assistedinject.AssistedInject;
-
-/**
- * A tunnel implementation that enforces access window restriction for the
- * provided ModeledUser, throwing a GuacamoleUnauthorizedException if the
- * user's configured access window has closed, or if the user has become
- * disabled. All other tunnel implementation is delegated to the underlying
- * tunnel object.
- */
-public class AccessEnforcingDelegatingTunnel extends DelegatingGuacamoleTunnel {
-
- /**
- * Logger for this class.
- */
- private static final Logger logger = LoggerFactory.getLogger(
- AccessEnforcingDelegatingTunnel.class);
-
- /**
- * The number of milliseconds between subsequent refreshes of the user
- * from the DB.
- */
- private static final long USER_MODEL_REFRESH_INTERVAL = 10000;
-
- /**
- * The user who's access window restrictions should be applied for the
- * wrapped tunnel.
- */
- private final AtomicReference user;
-
- /**
- * A thread that will continously refresh the user
- */
- private final Thread userRefreshThread;
-
- /**
- * A service to use for refreshing the user from the DB.
- */
- @Inject
- private UserService userService;
-
- /**
- * Create a new tunnel that will enforce the access window restrictions of
- * the provided user, during usage of the provided tunnel.
- *
- * @param tunnel
- * The tunnel to delegate to.
- *
- * @param modeledAuthenticatedUser
- * The user whose access restrictions should be applied.
- *
- */
- @AssistedInject
- public AccessEnforcingDelegatingTunnel(
- @Nonnull @Assisted GuacamoleTunnel tunnel,
- @Nonnull @Assisted ModeledAuthenticatedUser modeledAuthenticatedUser) {
-
- super(tunnel);
- this.user = new AtomicReference<>(modeledAuthenticatedUser.getUser());
-
- this.userRefreshThread = new Thread(() -> {
- while (true) {
-
- try {
-
- // Fetch an up-to-date user record from the DB to ensure
- // that any access restrictions modified while this tunnel
- // is open will be taken into account
- this.user.set(userService.retrieveUser(
- modeledAuthenticatedUser.getAuthenticationProvider(),
- modeledAuthenticatedUser));
- }
-
- // If an error occurs while trying to fetch the updated user,
- // log the warning / exception and stop the refresh thread
- catch (GuacamoleException e) {
-
- logger.warn(
- "Aborting user refresh thread due to error: {}",
- e.getMessage());
- logger.debug(
- "Exception caught while attempting to refresh user.", e);
-
- return;
- }
-
- try {
-
- // Wait a bit before refreshing the user record again
- Thread.sleep(USER_MODEL_REFRESH_INTERVAL);
- }
-
- // If interrupted by the tunnel, exit immediately
- catch (InterruptedException e) {
- return;
- }
- }
- });
- }
-
- @Override
- public GuacamoleReader acquireReader() {
-
- // Start periodically refreshing the user record
- userRefreshThread.start();
-
- // Filter received instructions, checking if the user's login
- // is still valid for each one. If the login is invalid,
- // log them out immediately and close the tunnel.
- return new FilteredGuacamoleReader(
- super.acquireReader(),
- new GuacamoleFilter() {
-
- @Override
- public GuacamoleInstruction filter(
- GuacamoleInstruction instruction) throws GuacamoleException {
-
- // The user record, at most USER_MODEL_REFRESH_INTERVAL
- // milliseconds old
- ModeledUser modeledUser = user.get();
-
- // If the user is outside of a valid access time window,
- // or disabled, throw an exception to immediately log them out
- if (
- !modeledUser.isAccountAccessible()
- || !modeledUser.isAccountValid()
- || modeledUser.isDisabled()
- ) {
- throw new GuacamoleUnauthorizedException("Permission Denied.");
- }
-
- return instruction;
- }
- }
- );
- }
-
- @Override
- public void releaseReader() {
-
- // Interrupt the refresh thread; it will clean itself up
- userRefreshThread.interrupt();
-
- super.releaseReader();
- }
-
- @Override
- public void close() throws GuacamoleException {
-
- // Interrupt the refresh thread; it will clean itself up
- userRefreshThread.interrupt();
-
- super.close();
- }
-
-}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnelFactory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnelFactory.java
deleted file mode 100644
index 0c6350766..000000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AccessEnforcingDelegatingTunnelFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.jdbc.tunnel;
-
-import javax.annotation.Nonnull;
-
-import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.net.GuacamoleTunnel;
-
-/**
- * A factory for creating AccessEnforcingDelegatingTunnel instances.
- */
-public interface AccessEnforcingDelegatingTunnelFactory {
-
- /**
- * Create and return a new AccessEnforcingDelegatingTunnel wrapping the
- * provided tunnel and enforcing the user restrictions associated with the
- * provided user.
- *
- * @param tunnel
- * The tunnel to delegate to.
- *
- * @param user
- * The user whose access window restrictions should be applied for the
- * wrapped tunel.
- *
- * @return
- * A new AccessEnforcingDelegatingTunnel wrapping the provided tunnel
- * and enforcing the user restrictions associated with the provided
- * user.
- *
- */
- public AccessEnforcingDelegatingTunnel create(
- @Nonnull GuacamoleTunnel tunnel,
- @Nonnull ModeledAuthenticatedUser user);
-
-}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java
index df25159a9..c3150ca97 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/ActiveConnectionRecord.java
@@ -21,9 +21,6 @@ package org.apache.guacamole.auth.jdbc.tunnel;
import java.util.Date;
import java.util.UUID;
-
-import javax.annotation.Nonnull;
-
import org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel;
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
import org.apache.guacamole.auth.jdbc.connection.ModeledConnectionRecord;
@@ -380,8 +377,6 @@ public class ActiveConnectionRecord extends ModeledConnectionRecord {
* @return
* The newly-created tunnel associated with this connection record.
*/
- @Nonnull
- @SuppressWarnings("null")
public GuacamoleTunnel assignGuacamoleTunnel(final GuacamoleSocket socket,
String connectionID) {
@@ -405,8 +400,6 @@ public class ActiveConnectionRecord extends ModeledConnectionRecord {
this.connectionID = connectionID;
// Return newly-created tunnel
- // NOTE: Guaranteed to be non-null since it was just set in this
- // method, and there is no functionality to set it to null
return this.tunnel;
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
index 1416b0b39..e5ad5d2ea 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.Date;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
+import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionDirectory;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
import org.apache.guacamole.auth.jdbc.connection.ConnectionRecordSet;
@@ -50,6 +51,8 @@ import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.net.auth.UserGroup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* UserContext implementation which is driven by an arbitrary, underlying
@@ -58,6 +61,11 @@ import org.apache.guacamole.net.auth.UserGroup;
public class ModeledUserContext extends RestrictedObject
implements org.apache.guacamole.net.auth.UserContext {
+ /**
+ * Logger for this class.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(ModeledUserContext.class);
+
/**
* User directory restricted by the permissions of the user associated
* with this context.
@@ -130,6 +138,12 @@ public class ModeledUserContext extends RestrictedObject
@Inject
private UserRecordMapper userRecordMapper;
+ /**
+ * The environment of the Guacamole server.
+ */
+ @Inject
+ private JDBCEnvironment environment;
+
/**
* The activity record associated with this user's Guacamole session. If
* this user's session will not have an associated activity record, such as
@@ -296,4 +310,31 @@ public class ModeledUserContext extends RestrictedObject
}
+ @Override
+ public boolean isValid() {
+
+ try {
+ // If access window enforcement is disabled for active sessions,
+ // skip validity checks entirely
+ if (!environment.enforceAccessWindowsForActiveSessions())
+ return true;
+ }
+
+ catch (GuacamoleException e) {
+
+ logger.warn(
+ "Unable to determine if access window enforcement is"
+ + " enabled for active sessions; enforcing by default: {}"
+ , e.getMessage());
+ logger.debug("Unable to determine access window enforcement policy.", e);
+
+ }
+
+ // A user context is valid if the associated user's account is valid
+ // for the current date, and the user is within an access time window
+ ModeledUser user = getCurrentUser().getUser();
+ return user.isAccountValid() && user.isAccountAccessible();
+
+ }
+
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserDirectory.java
index db8bea12f..dffd8e2ec 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserDirectory.java
@@ -45,14 +45,12 @@ public class UserDirectory extends RestrictedObject
@Override
public User get(String identifier) throws GuacamoleException {
- validateUserAccess();
return userService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection getAll(Collection identifiers) throws GuacamoleException {
- validateUserAccess();
Collection objects = userService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.unmodifiableCollection(objects);
}
@@ -60,21 +58,18 @@ public class UserDirectory extends RestrictedObject
@Override
@Transactional
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return userService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(User object) throws GuacamoleException {
- validateUserAccess();
userService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(User object) throws GuacamoleException {
- validateUserAccess();
ModeledUser user = (ModeledUser) object;
userService.updateObject(getCurrentUser(), user);
}
@@ -82,7 +77,6 @@ public class UserDirectory extends RestrictedObject
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
userService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/usergroup/UserGroupDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/usergroup/UserGroupDirectory.java
index f61af0bea..911b8521f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/usergroup/UserGroupDirectory.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/usergroup/UserGroupDirectory.java
@@ -44,14 +44,12 @@ public class UserGroupDirectory extends RestrictedObject
@Override
public UserGroup get(String identifier) throws GuacamoleException {
- validateUserAccess();
return userGroupService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection getAll(Collection identifiers) throws GuacamoleException {
- validateUserAccess();
Collection objects = userGroupService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.unmodifiableCollection(objects);
}
@@ -59,21 +57,18 @@ public class UserGroupDirectory extends RestrictedObject
@Override
@Transactional
public Set getIdentifiers() throws GuacamoleException {
- validateUserAccess();
return userGroupService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(UserGroup object) throws GuacamoleException {
- validateUserAccess();
userGroupService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(UserGroup object) throws GuacamoleException {
- validateUserAccess();
ModeledUserGroup group = (ModeledUserGroup) object;
userGroupService.updateObject(getCurrentUser(), group);
}
@@ -81,7 +76,6 @@ public class UserGroupDirectory extends RestrictedObject
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
- validateUserAccess();
userGroupService.deleteObject(getCurrentUser(), identifier);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
index c676feaad..ca17757a4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/org/apache/guacamole/auth/mysql/conf/MySQLGuacamoleProperties.java
@@ -281,7 +281,7 @@ public class MySQLGuacamoleProperties {
/**
* Whether or not user-specific access time windows should be enforced for active sessions,
* i.e. whether users with active sessions should be logged out immediately when an access
- * window closes or the user is disabled.
+ * window closes.
*/
public static final BooleanGuacamoleProperty MYSQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS =
new BooleanGuacamoleProperty() {
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
index 636c0a1c7..3f33ec44f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/apache/guacamole/auth/postgresql/conf/PostgreSQLGuacamoleProperties.java
@@ -293,7 +293,7 @@ public class PostgreSQLGuacamoleProperties {
/**
* Whether or not user-specific access time windows should be enforced for active sessions,
* i.e. whether users with active sessions should be logged out immediately when an access
- * window closes or the user is disabled.
+ * window closes.
*/
public static final BooleanGuacamoleProperty POSTGRESQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS =
new BooleanGuacamoleProperty() {
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
index e7b1c6982..1f2500350 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/java/org/apache/guacamole/auth/sqlserver/conf/SQLServerGuacamoleProperties.java
@@ -223,7 +223,7 @@ public class SQLServerGuacamoleProperties {
/**
* Whether or not user-specific access time windows should be enforced for active sessions,
* i.e. whether users with active sessions should be logged out immediately when an access
- * window closes or the user is disabled.
+ * window closes.
*/
public static final BooleanGuacamoleProperty SQLSERVER_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS =
new BooleanGuacamoleProperty() {
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java
index 4b0343181..7431fa899 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java
@@ -162,4 +162,9 @@ public class DelegatingUserContext implements UserContext {
return userContext.getPrivileged();
}
+ @Override
+ public boolean isValid() {
+ return userContext.isValid();
+ }
+
}
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java
index 3f75b899c..a9ea7ea0c 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java
@@ -40,6 +40,27 @@ public interface UserContext {
*/
User self();
+ /**
+ * Returns true if the session for the User associated with this user
+ * context is valid, or false otherwise. If the session is not valid,
+ * the webapp can be expected to terminate the session within a short
+ * period of time.
+ *
+ * NOTE: The webapp currently checks once a minute, and terminates any
+ * session marked as invalid.
+ *
+ * @return
+ * true if the session for the User associated with this user
+ * context is valid, or false otherwise.
+ */
+ default boolean isValid() {
+
+ // A user context is always valid unless explicitly updated by an
+ // implementation
+ return true;
+
+ }
+
/**
* Returns an arbitrary REST resource representing this UserContext. The
* REST resource returned must be properly annotated with JSR-311
diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
index 3e8d488c3..0458639d1 100644
--- a/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
+++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleSession.java
@@ -132,6 +132,22 @@ public class GuacamoleSession {
return Collections.unmodifiableList(userContexts);
}
+ /**
+ * Returns true if all user contexts associated with this session are
+ * valid, or false if any user context is not valid. If a session is not
+ * valid, it may no longer be used, and invalidate() should be invoked.
+ *
+ * @return
+ * true if all user contexts associated with this session are
+ * valid, or false if any user context is not valid.
+ */
+ public boolean isValid() {
+
+ // Immediately return false if any user context is not valid
+ return !userContexts.stream().anyMatch(
+ userContext -> !userContext.isValid());
+ }
+
/**
* Returns the UserContext associated with this session that originated
* from the AuthenticationProvider with the given identifier. If no such
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/auth/HashTokenSessionMap.java b/guacamole/src/main/java/org/apache/guacamole/rest/auth/HashTokenSessionMap.java
index 24f653098..15d11eb62 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/auth/HashTokenSessionMap.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/auth/HashTokenSessionMap.java
@@ -94,7 +94,8 @@ public class HashTokenSessionMap implements TokenSessionMap {
/**
* Task which iterates through all active sessions, evicting those sessions
- * which are beyond the session timeout.
+ * which are beyond the session timeout, or are marked as invalid by an
+ * extension.
*/
private class SessionEvictionTask implements Runnable {
@@ -105,7 +106,8 @@ public class HashTokenSessionMap implements TokenSessionMap {
/**
* Creates a new task which automatically evicts sessions which are
- * older than the specified timeout.
+ * older than the specified timeout, or are marked as invalid by an
+ * extension.
*
* @param sessionTimeout The maximum age of any session, in
* milliseconds.
@@ -116,16 +118,16 @@ public class HashTokenSessionMap implements TokenSessionMap {
/**
* Iterates through all active sessions, evicting those sessions which
- * are beyond the session timeout. Internal errors which would
- * otherwise stop the session eviction process are caught, logged, and
- * the process is allowed to proceed.
+ * are beyond the session timeout, or are marked as invalid. Internal
+ * errors which would otherwise stop the session eviction process are
+ * caught, logged, and the process is allowed to proceed.
*/
- private void evictExpiredSessions() {
+ private void evictExpiredOrInvalidSessions() {
// Get start time of session check time
long sessionCheckStart = System.currentTimeMillis();
- logger.debug("Checking for expired sessions...");
+ logger.debug("Checking for expired or invalid sessions...");
// For each session, remove sesions which have expired
Iterator> entries = sessionMap.entrySet().iterator();
@@ -136,6 +138,15 @@ public class HashTokenSessionMap implements TokenSessionMap {
try {
+ // Invalidate any sessions which have been flagged as invalid by extensions
+ if (!session.isValid()) {
+ logger.debug(
+ "Session \"{}\" has been invalidated by an extension.",
+ entry.getKey());
+ entries.remove();
+ session.invalidate();
+ }
+
// Do not expire sessions which are active
if (session.hasTunnels())
continue;
@@ -170,13 +181,13 @@ public class HashTokenSessionMap implements TokenSessionMap {
@Override
public void run() {
- // The evictExpiredSessions() function should already
+ // The evictExpiredOrInvalidSessions() function should already
// automatically handle and log all unexpected internal errors,
// but wrap the entire call in a try/catch plus additional logging
// to ensure that absolutely no errors can result in the entire
// thread dying
try {
- evictExpiredSessions();
+ evictExpiredOrInvalidSessions();
}
catch (Throwable t) {
logger.error("An unexpected internal error prevented the "