blob: 1d3344db9320b58c54c7d2f5184a4e744985f1d2 [file] [log] [blame]
/*
* 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.activeconnection;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.auth.jdbc.base.DirectoryObjectService;
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating active connections.
*/
public class ActiveConnectionService
implements DirectoryObjectService<TrackedActiveConnection, ActiveConnection> {
/**
* Service for creating and tracking tunnels.
*/
@Inject
private GuacamoleTunnelService tunnelService;
/**
* Provider for active connections.
*/
@Inject
private Provider<TrackedActiveConnection> trackedActiveConnectionProvider;
@Override
public TrackedActiveConnection retrieveObject(ModeledAuthenticatedUser user,
String identifier) throws GuacamoleException {
// Pull objects having given identifier
Collection<TrackedActiveConnection> objects = retrieveObjects(user, Collections.singleton(identifier));
// If no such object, return null
if (objects.isEmpty())
return null;
// The object collection will have exactly one element unless the
// database has seriously lost integrity
assert(objects.size() == 1);
// Return first and only object
return objects.iterator().next();
}
@Override
public Collection<TrackedActiveConnection> retrieveObjects(ModeledAuthenticatedUser user,
Collection<String> identifiers) throws GuacamoleException {
String username = user.getIdentifier();
boolean isAdmin = user.getUser().isAdministrator();
Set<String> identifierSet = new HashSet<String>(identifiers);
// Retrieve all visible connections (permissions enforced by tunnel service)
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
// Restrict to subset of records which match given identifiers
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
for (ActiveConnectionRecord record : records) {
// Sensitive information should be included if the connection was
// started by the current user OR the user is an admin
boolean includeSensitiveInformation =
isAdmin || username.equals(record.getUsername());
// Add connection if within requested identifiers
if (identifierSet.contains(record.getUUID().toString())) {
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
activeConnection.init(user, record, includeSensitiveInformation);
activeConnections.add(activeConnection);
}
}
return activeConnections;
}
@Override
public void deleteObject(ModeledAuthenticatedUser user, String identifier)
throws GuacamoleException {
// Close connection, if it exists and we have permission
ActiveConnection activeConnection = retrieveObject(user, identifier);
if (activeConnection == null)
return;
if (hasObjectPermissions(user, identifier, ObjectPermission.Type.DELETE)) {
// Close connection if not already closed
GuacamoleTunnel tunnel = activeConnection.getTunnel();
if (tunnel != null && tunnel.isOpen())
tunnel.close();
}
else
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public Set<String> getIdentifiers(ModeledAuthenticatedUser user)
throws GuacamoleException {
// Retrieve all visible connections (permissions enforced by tunnel service)
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
// Build list of identifiers
Set<String> identifiers = new HashSet<String>(records.size());
for (ActiveConnectionRecord record : records)
identifiers.add(record.getUUID().toString());
return identifiers;
}
@Override
public TrackedActiveConnection createObject(ModeledAuthenticatedUser user,
ActiveConnection object) throws GuacamoleException {
// Updating active connections is not implemented
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public void updateObject(ModeledAuthenticatedUser user, TrackedActiveConnection object)
throws GuacamoleException {
// Updating active connections is not implemented
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Retrieve the permission set for the specified user that relates
* to access to active connections.
*
* @param user
* The user for which to retrieve the permission set.
*
* @return
* A permission set associated with the given user that specifies
* the permissions available for active connection objects.
*
* @throws GuacamoleException
* If permission to read permissions for the user is denied.
*/
private ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user)
throws GuacamoleException {
return user.getUser().getActiveConnectionPermissions();
}
/**
* Return a boolean value representing whether or not a user has the given
* permission available to them on the active connection with the given
* identifier.
*
* @param user
* The user for which the permissions are being queried.
*
* @param identifier
* The identifier of the active connection we are wondering about.
*
* @param type
* The type of permission being requested.
*
* @return
* True if the user has the necessary permission; otherwise false.
*
* @throws GuacamoleException
* If the user does not have access to read permissions.
*/
private boolean hasObjectPermissions(ModeledAuthenticatedUser user,
String identifier, ObjectPermission.Type type)
throws GuacamoleException {
ObjectPermissionSet permissionSet = getPermissionSet(user);
return user.getUser().isAdministrator()
|| permissionSet.hasPermission(type, identifier);
}
}