GUACAMOLE-942: Correct race condition in retrieval of readable connection identifiers.

As activeTunnels is a live map which may change while
getActiveConnections() is running, it is possible for an initial call
to activeTunnels.isEmpty() to pass yet for the set of connection
identifiers produced to be empty.
This commit is contained in:
Michael Jumper
2020-08-20 19:17:45 -07:00
parent f00f6d6935
commit 0bddff8bad

View File

@@ -623,21 +623,26 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
public Collection<ActiveConnectionRecord> getActiveConnections(ModeledAuthenticatedUser user) public Collection<ActiveConnectionRecord> getActiveConnections(ModeledAuthenticatedUser user)
throws GuacamoleException { throws GuacamoleException {
// Simply return empty list if there are no active tunnels
Collection<ActiveConnectionRecord> records = activeTunnels.values();
if (records.isEmpty())
return Collections.<ActiveConnectionRecord>emptyList();
// Privileged users (such as system administrators) can view all // Privileged users (such as system administrators) can view all
// connections; no need to filter // connections; no need to filter
Collection<ActiveConnectionRecord> records = activeTunnels.values();
if (user.isPrivileged()) if (user.isPrivileged())
return records; return records;
// Build set of all connection identifiers associated with active tunnels // Build set of all connection identifiers associated with active tunnels
Set<String> identifiers = new HashSet<String>(records.size()); Set<String> identifiers = new HashSet<>(records.size());
for (ActiveConnectionRecord record : records) for (ActiveConnectionRecord record : records)
identifiers.add(record.getConnection().getIdentifier()); identifiers.add(record.getConnection().getIdentifier());
// Simply return empty list if there are no active tunnels (note that
// this check cannot be performed prior to building the set of
// identifiers, as activeTunnels may be non-empty at the beginning of
// the call to getActiveConnections() yet become empty before the
// set of identifiers is built, resulting in an error within
// selectReadable()
if (identifiers.isEmpty())
return Collections.<ActiveConnectionRecord>emptyList();
// Produce collection of readable connection identifiers // Produce collection of readable connection identifiers
Collection<ConnectionModel> connections = Collection<ConnectionModel> connections =
connectionMapper.selectReadable(user.getUser().getModel(), connectionMapper.selectReadable(user.getUser().getModel(),
@@ -649,7 +654,7 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
identifiers.add(connection.getIdentifier()); identifiers.add(connection.getIdentifier());
// Produce readable subset of records // Produce readable subset of records
Collection<ActiveConnectionRecord> visibleRecords = new ArrayList<ActiveConnectionRecord>(records.size()); Collection<ActiveConnectionRecord> visibleRecords = new ArrayList<>(records.size());
for (ActiveConnectionRecord record : records) { for (ActiveConnectionRecord record : records) {
if (identifiers.contains(record.getConnection().getIdentifier())) if (identifiers.contains(record.getConnection().getIdentifier()))
visibleRecords.add(record); visibleRecords.add(record);