mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-1020: Implement a new Restrictable interface and make slight name changes to classes.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.restrict;
|
||||
|
||||
import org.apache.guacamole.calendar.RestrictionType;
|
||||
import org.apache.guacamole.net.auth.Attributes;
|
||||
|
||||
/**
|
||||
* An interface which defines methods that apply to items that can have
|
||||
* restrictions applied to them.
|
||||
*/
|
||||
public interface Restrictable extends Attributes {
|
||||
|
||||
/**
|
||||
* Return the restriction state for this restrictable object at the
|
||||
* current date and time. By default returns an implicit denial.
|
||||
*
|
||||
* @return
|
||||
* The restriction status for the current date and time.
|
||||
*/
|
||||
default public RestrictionType getCurrentTimeRestriction() {
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the restriction state for this restrictable object for the host
|
||||
* from which the current user is logged in. By default returns an implicit
|
||||
* denial.
|
||||
*
|
||||
* @return
|
||||
* The restriction status for the host from which the current user is
|
||||
* logged in.
|
||||
*/
|
||||
default public RestrictionType getCurrentHostRestriction() {
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current item is available based on the restrictions
|
||||
* for the given implementation of this interface, or false if the item is
|
||||
* not currently available. The default implementation checks current time
|
||||
* and host restrictions, allowing if both those restrictions allow access.
|
||||
*
|
||||
* @return
|
||||
* true if the item is available, otherwise false.
|
||||
*/
|
||||
default public boolean isAvailable() {
|
||||
return (getCurrentTimeRestriction().isAllowed() && getCurrentHostRestriction().isAllowed());
|
||||
}
|
||||
|
||||
}
|
@@ -19,8 +19,10 @@
|
||||
|
||||
package org.apache.guacamole.auth.restrict;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.restrict.user.RestrictUserContext;
|
||||
import org.apache.guacamole.auth.restrict.user.RestrictedUserContext;
|
||||
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
@@ -43,12 +45,15 @@ public class RestrictionAuthenticationProvider extends AbstractAuthenticationPro
|
||||
AuthenticatedUser authenticatedUser, Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
String remoteAddress = credentials.getRemoteAddress();
|
||||
|
||||
|
||||
// Verify identity of user
|
||||
RestrictionVerificationService.verifyLoginRestrictions(context, authenticatedUser);
|
||||
RestrictionVerificationService.verifyLoginRestrictions(context, remoteAddress);
|
||||
|
||||
// User has been verified, and authentication should be allowed to
|
||||
// continue
|
||||
return new RestrictUserContext(context, credentials.getRemoteAddress());
|
||||
return new RestrictedUserContext(context, remoteAddress);
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +61,7 @@ public class RestrictionAuthenticationProvider extends AbstractAuthenticationPro
|
||||
public UserContext redecorate(UserContext decorated, UserContext context,
|
||||
AuthenticatedUser authenticatedUser, Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
return new RestrictUserContext(context, credentials.getRemoteAddress());
|
||||
return new RestrictedUserContext(context, credentials.getRemoteAddress());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,19 +23,19 @@ import inet.ipaddr.HostName;
|
||||
import inet.ipaddr.HostNameException;
|
||||
import inet.ipaddr.IPAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.restrict.connection.RestrictConnection;
|
||||
import org.apache.guacamole.auth.restrict.user.RestrictUser;
|
||||
import org.apache.guacamole.auth.restrict.usergroup.RestrictUserGroup;
|
||||
import org.apache.guacamole.auth.restrict.connection.RestrictedConnection;
|
||||
import org.apache.guacamole.auth.restrict.user.RestrictedUser;
|
||||
import org.apache.guacamole.auth.restrict.usergroup.RestrictedUserGroup;
|
||||
import org.apache.guacamole.calendar.DailyRestriction;
|
||||
import org.apache.guacamole.calendar.RestrictionType;
|
||||
import org.apache.guacamole.calendar.TimeRestrictionParser;
|
||||
import org.apache.guacamole.host.HostRestrictionParser;
|
||||
import org.apache.guacamole.language.TranslatableGuacamoleSecurityException;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.Directory;
|
||||
import org.apache.guacamole.net.auth.User;
|
||||
import org.apache.guacamole.net.auth.UserContext;
|
||||
import org.apache.guacamole.net.auth.UserGroup;
|
||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||
@@ -56,8 +56,7 @@ public class RestrictionVerificationService {
|
||||
/**
|
||||
* Parse out the provided strings of allowed and denied times, verifying
|
||||
* whether or not a login or connection should be allowed at the current
|
||||
* day and time. A boolean true will be returned if the action should be
|
||||
* allowed, otherwise false will be returned.
|
||||
* day and time, and returning the appropriate restriction type.
|
||||
*
|
||||
* @param allowedTimeString
|
||||
* The string containing the times that should be parsed to determine if
|
||||
@@ -71,47 +70,48 @@ public class RestrictionVerificationService {
|
||||
* action should be denied.
|
||||
*
|
||||
* @return
|
||||
* True if the login or connection should be allowed, otherwise false.
|
||||
* A RestrictionType based on the provided allowed and denied strings.
|
||||
*/
|
||||
private static boolean allowedByTimeRestrictions(String allowedTimeString,
|
||||
public static RestrictionType allowedByTimeRestrictions(String allowedTimeString,
|
||||
String deniedTimeString) {
|
||||
|
||||
// Check for denied entries, first, returning false if the login or
|
||||
// connection should not be allowed.
|
||||
// Check for denied entries, first, returning the explicit deny if the
|
||||
// login or connection should not be allowed.
|
||||
if (deniedTimeString != null && !deniedTimeString.isEmpty()) {
|
||||
List<DailyRestriction> deniedTimes =
|
||||
TimeRestrictionParser.parseString(deniedTimeString);
|
||||
|
||||
for (DailyRestriction restriction : deniedTimes) {
|
||||
if (restriction.appliesNow())
|
||||
return false;
|
||||
return RestrictionType.EXPLICIT_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
// If no allowed entries are present, return true, allowing the login
|
||||
// or connection to continue.
|
||||
// If no allowed entries are present, return the implicit allow, allowing
|
||||
// the login or connection to continue.
|
||||
if (allowedTimeString == null || allowedTimeString.isEmpty())
|
||||
return true;
|
||||
return RestrictionType.IMPLICIT_ALLOW;
|
||||
|
||||
// Pull the list of allowed times.
|
||||
List<DailyRestriction> allowedTimes =
|
||||
TimeRestrictionParser.parseString(allowedTimeString);
|
||||
|
||||
// Allowed entries are present, loop through them and check for a valid time.
|
||||
for (DailyRestriction restriction : allowedTimes) {
|
||||
// If this time allows the login or connection return true.
|
||||
// If this time allows the login or connection return the explicit allow.
|
||||
if (restriction.appliesNow())
|
||||
return true;
|
||||
return RestrictionType.EXPLICIT_ALLOW;
|
||||
}
|
||||
|
||||
// We have allowed entries, but login hasn't matched, so deny it.
|
||||
return false;
|
||||
// We have allowed entries, but login hasn't matched, so implicitly deny it.
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the strings of allowed and denied hosts, verify that the login or
|
||||
* connection should be allowed from the given remote address. If the action
|
||||
* should not be allowed, return false - otherwise, return true.
|
||||
* connection should be allowed from the given remote address, returning
|
||||
* the RestrictionType that matches the provided allowed and denied strings.
|
||||
*
|
||||
* @param allowedHostsString
|
||||
* The string containing a semicolon-separated list of hosts from
|
||||
@@ -129,18 +129,18 @@ public class RestrictionVerificationService {
|
||||
* and restrictions are defined, the login or connection will be denied.
|
||||
*
|
||||
* @return
|
||||
* True if the login or connection should be allowed by the host-based
|
||||
* restrictions, otherwise false.
|
||||
* A RestrictionType that matches the provided allow and deny strings.
|
||||
*/
|
||||
private static boolean allowedByHostRestrictions(String allowedHostsString,
|
||||
public static RestrictionType allowedByHostRestrictions(String allowedHostsString,
|
||||
String deniedHostsString, String remoteAddress) {
|
||||
|
||||
// Convert the string to a HostName
|
||||
HostName remoteHostName = new HostName(remoteAddress);
|
||||
|
||||
// If attributes do not exist or are empty then the action is allowed.
|
||||
if ((allowedHostsString == null || allowedHostsString.isEmpty())
|
||||
&& (deniedHostsString == null || deniedHostsString.isEmpty()))
|
||||
return true;
|
||||
return RestrictionType.IMPLICIT_ALLOW;
|
||||
|
||||
// If the remote address cannot be determined, and restrictions are
|
||||
// in effect, log an error and deny the action.
|
||||
@@ -148,7 +148,7 @@ public class RestrictionVerificationService {
|
||||
LOGGER.warn("Host-based restrictions are present, but the remote "
|
||||
+ "address is invalid or could not be resolved. "
|
||||
+ "The action will not be allowed.");
|
||||
return false;
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
}
|
||||
|
||||
// Split denied hosts attribute and process each entry, checking them
|
||||
@@ -158,24 +158,24 @@ public class RestrictionVerificationService {
|
||||
for (HostName hostName : deniedHosts) {
|
||||
try {
|
||||
if (hostName.isAddress() && hostName.toAddress().contains(remoteHostName.asAddress()))
|
||||
return false;
|
||||
return RestrictionType.EXPLICIT_DENY;
|
||||
|
||||
else
|
||||
for (IPAddress currAddr : hostName.toAllAddresses())
|
||||
if (currAddr.matches(remoteHostName.asAddressString()))
|
||||
return false;
|
||||
return RestrictionType.EXPLICIT_DENY;
|
||||
}
|
||||
catch (UnknownHostException | HostNameException e) {
|
||||
LOGGER.warn("Unknown or invalid host in denied hosts list: \"{}\"", hostName);
|
||||
LOGGER.debug("Exception while trying to resolve host: \"{}\"", hostName, e);
|
||||
return false;
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
// If denied hosts have been checked and allowed hosts are empty, we're
|
||||
// good, and can allow the action.
|
||||
if (allowedHostsString == null || allowedHostsString.isEmpty())
|
||||
return true;
|
||||
return RestrictionType.IMPLICIT_ALLOW;
|
||||
|
||||
// Run through allowed hosts, if there are any, and return, allowing the
|
||||
// action if there are any matches.
|
||||
@@ -184,12 +184,12 @@ public class RestrictionVerificationService {
|
||||
try {
|
||||
// If the entry is an IP or Subnet, check the remote address against it directly
|
||||
if (hostName.isAddress() && hostName.toAddress().contains(remoteHostName.asAddress()))
|
||||
return true;
|
||||
return RestrictionType.EXPLICIT_ALLOW;
|
||||
|
||||
// Entry is a hostname, so resolve to IPs and check each one
|
||||
for (IPAddress currAddr : hostName.toAllAddresses())
|
||||
if (currAddr.matches(remoteHostName.asAddressString()))
|
||||
return true;
|
||||
return RestrictionType.EXPLICIT_ALLOW;
|
||||
|
||||
}
|
||||
// If an entry cannot be resolved we will log a warning.
|
||||
@@ -201,7 +201,270 @@ public class RestrictionVerificationService {
|
||||
|
||||
// If we've made it here, the allowed hosts do not contain the remote
|
||||
// address, and the action should not be allowed;
|
||||
return false;
|
||||
return RestrictionType.IMPLICIT_DENY;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the host restrictions for the user associated with the given
|
||||
* UserContext, throwing an exception if any of the restrictions result
|
||||
* in the user not being allowed to be logged in to Guacamole from this
|
||||
* host.
|
||||
*
|
||||
* @param context
|
||||
* The UserContext associated with the user who is being verified.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote address of the client from which the current user is
|
||||
* logged in.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the restrictions on the user should prevent the user from
|
||||
* logging in from the current client, or if an error occurs attempting
|
||||
* to retrieve permissions.
|
||||
*/
|
||||
public static void verifyHostRestrictions(UserContext context, String remoteAddress) throws GuacamoleException {
|
||||
|
||||
// Get the current user
|
||||
User currentUser = context.self();
|
||||
|
||||
// Admins always have access.
|
||||
if (currentUser.getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.ADMINISTER)) {
|
||||
LOGGER.warn("User \"{}\" has System Administration permissions; additional restrictions will be bypassed.",
|
||||
currentUser.getIdentifier());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user's attributes
|
||||
Map<String, String> userAttributes = currentUser.getAttributes();
|
||||
|
||||
// Verify host-based restrictions specific to the user
|
||||
String allowedHostString = userAttributes.get(RestrictedUser.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = userAttributes.get(RestrictedUser.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType hostRestrictionResult = allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress);
|
||||
|
||||
switch (hostRestrictionResult) {
|
||||
// User-level explicit deny overrides everything
|
||||
case EXPLICIT_DENY:
|
||||
throw new TranslatableInvalidHostLoginException("User \""
|
||||
+ currentUser.getIdentifier()
|
||||
+"\" is not allowed to log in from \""
|
||||
+ remoteAddress + "\"",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_FROM_HOST");
|
||||
|
||||
// User-level explicit allow means the user is allowed.
|
||||
case EXPLICIT_ALLOW:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Gather user's effective groups.
|
||||
Collection<UserGroup> userGroups = context
|
||||
.getPrivileged()
|
||||
.getUserGroupDirectory()
|
||||
.getAll(currentUser.getUserGroups().getObjects());
|
||||
|
||||
// Loop user's effective groups and verify restrictions
|
||||
for (UserGroup userGroup : userGroups) {
|
||||
|
||||
// Get group's attributes
|
||||
Map<String, String> grpAttributes = userGroup.getAttributes();
|
||||
|
||||
// Pull host-based restrictions for this group and verify
|
||||
String grpAllowedHostString = grpAttributes.get(RestrictedUserGroup.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String grpDeniedHostString = grpAttributes.get(RestrictedUserGroup.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType grpRestrictionResult = allowedByHostRestrictions(grpAllowedHostString, grpDeniedHostString, remoteAddress);
|
||||
|
||||
// Any explicit denials are thrown immediately
|
||||
if (grpRestrictionResult == RestrictionType.EXPLICIT_DENY)
|
||||
throw new TranslatableInvalidHostLoginException("User \""
|
||||
+ currentUser.getIdentifier()
|
||||
+ "\" is not allowed to log in from host \""
|
||||
+ remoteAddress
|
||||
+ "\" due to restrictions on group \""
|
||||
+ userGroup.getIdentifier() + "\".",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_FROM_HOST");
|
||||
|
||||
// Compare the two, returning the highest-priority restriction so far.
|
||||
hostRestrictionResult = RestrictionType.getHigherPriority(hostRestrictionResult, grpRestrictionResult);
|
||||
|
||||
}
|
||||
|
||||
// Check the result and log allowed
|
||||
switch (hostRestrictionResult) {
|
||||
// Explicit allow was the highest result, so we log it and return, allowing the user to be logged in.
|
||||
case EXPLICIT_ALLOW:
|
||||
LOGGER.debug("User \"{}\" is explicitly allowed from host \"{}\".",
|
||||
currentUser.getIdentifier(), remoteAddress);
|
||||
return;
|
||||
|
||||
// Implicit allow was the highest result, so we log it and return, allowing the user to be logged in.
|
||||
case IMPLICIT_ALLOW:
|
||||
LOGGER.debug("User \"{}\" is implicitly allowed from host \"{}\".",
|
||||
currentUser.getIdentifier(), remoteAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we reach, here, we've reached an implict deny, so we throw an exception.
|
||||
throw new TranslatableInvalidHostLoginException("User \""
|
||||
+ currentUser.getIdentifier()
|
||||
+ "\" is implicitly denied at this time.",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_FROM_HOST");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the host-based restrictions of the Connection, throwing an
|
||||
* exception if the Connection should be allowed from the host from which
|
||||
* the user is logged in.
|
||||
*
|
||||
* @param restrictable
|
||||
* The Restrictable object that should be verified against host restrictions.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote address of the client from which the current user is
|
||||
* logged in.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the connection should not be allowed from the remote host from
|
||||
* which the user is logged in.
|
||||
*/
|
||||
public void verifyHostRestrictions(Restrictable restrictable, String remoteAddress) throws GuacamoleException {
|
||||
|
||||
// Verify time-based restrictions specific to this connection.
|
||||
String allowedHostsString = restrictable.getAttributes().get(RestrictedConnection.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostsString = restrictable.getAttributes().get(RestrictedConnection.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType hostRestrictionResult = allowedByHostRestrictions(allowedHostsString, deniedHostsString, remoteAddress);
|
||||
|
||||
// If the host is not allowed
|
||||
if (!hostRestrictionResult.isAllowed())
|
||||
throw new TranslatableGuacamoleSecurityException(
|
||||
"Use of this connection is not allowed from this remote host: \"" + remoteAddress + "\".",
|
||||
"RESTRICT.ERROR_CONNECTION_NOT_ALLOWED_NOW"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the time restrictions for this extension and whether or not the
|
||||
* account should be allowed to be logged in to Guacamole at the current
|
||||
* day and time, throwing an exception if any of the restrictions result
|
||||
* in a violation of the time constraints of the account.
|
||||
*
|
||||
* @param context
|
||||
* The UserContext of the user whose access to Guacamole is being
|
||||
* checked.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the time constraints configured for the user result in the
|
||||
* user not being allowed to be logged in to Guacamole, or if errors
|
||||
* occur trying to retrieve permissions or attributes.
|
||||
*/
|
||||
public static void verifyTimeRestrictions(UserContext context) throws GuacamoleException {
|
||||
|
||||
// Retrieve the current User object associated with the UserContext
|
||||
User currentUser = context.self();
|
||||
|
||||
// Admins always have access.
|
||||
if (currentUser.getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.ADMINISTER)) {
|
||||
LOGGER.warn("User \"{}\" has System Administration permissions; additional restrictions will be bypassed.",
|
||||
currentUser.getIdentifier());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get user's attributes
|
||||
Map<String, String> userAttributes = currentUser.getAttributes();
|
||||
|
||||
// Verify time-based restrictions specific to the user
|
||||
String allowedTimeString = userAttributes.get(RestrictedUser.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = userAttributes.get(RestrictedUser.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType timeRestrictionResult = allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
|
||||
|
||||
// Check the time restriction for explicit results.
|
||||
switch (timeRestrictionResult) {
|
||||
// User-level explicit deny overrides everything
|
||||
case EXPLICIT_DENY:
|
||||
throw new TranslatableInvalidTimeLoginException("User \""
|
||||
+ currentUser.getIdentifier()
|
||||
+ "\" is not allowed to log in at this time.",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_NOW");
|
||||
|
||||
// User-level explicit allow means the user is allowed.
|
||||
case EXPLICIT_ALLOW:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Gather user's effective groups.
|
||||
Collection<UserGroup> userGroups = context
|
||||
.getPrivileged()
|
||||
.getUserGroupDirectory()
|
||||
.getAll(currentUser.getUserGroups().getObjects());
|
||||
|
||||
// Loop user's effective groups and verify restrictions
|
||||
for (UserGroup userGroup : userGroups) {
|
||||
|
||||
// Get group's attributes
|
||||
Map<String, String> grpAttributes = userGroup.getAttributes();
|
||||
|
||||
// Pull time-based restrictions for this group and verify
|
||||
String grpAllowedTimeString = grpAttributes.get(RestrictedUserGroup.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String grpDeniedTimeString = grpAttributes.get(RestrictedUserGroup.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType grpRestrictionResult = allowedByTimeRestrictions(grpAllowedTimeString, grpDeniedTimeString);
|
||||
|
||||
// An explicit deny results in immediate denial of the login.
|
||||
if (grpRestrictionResult == RestrictionType.EXPLICIT_DENY)
|
||||
throw new TranslatableInvalidTimeLoginException("User \""
|
||||
+ currentUser.getIdentifier()
|
||||
+"\" is not allowed to log in at this time due to restrictions on group \""
|
||||
+ userGroup + "\".",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_NOW");
|
||||
|
||||
// Compare the two, returning the highest-priority restriction so far.
|
||||
timeRestrictionResult = RestrictionType.getHigherPriority(timeRestrictionResult, grpRestrictionResult);
|
||||
|
||||
}
|
||||
|
||||
switch (timeRestrictionResult) {
|
||||
// Explicit allow was the highest result, so we log it and return, allowing the user to be logged in.
|
||||
case EXPLICIT_ALLOW:
|
||||
LOGGER.debug("User \"{}\" is explicitly allowed at this time.", currentUser.getIdentifier());
|
||||
return;
|
||||
|
||||
// Implicit allow was the highest result, so we log it and return, allowing the user to be logged in.
|
||||
case IMPLICIT_ALLOW:
|
||||
LOGGER.debug("User \"{}\" is implicitly allowed at this time.", currentUser.getIdentifier());
|
||||
return;
|
||||
}
|
||||
|
||||
// If we reach, here, we've reached an implict deny, so we throw an exception.
|
||||
throw new TranslatableInvalidTimeLoginException("User \"{}\" is implicitly denied at this time.", currentUser.getIdentifier());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the time restrictions for the given Connection object, throwing
|
||||
* an exception if the connection should not be allowed, or silently
|
||||
* returning if the connection should be allowed.
|
||||
*
|
||||
* @param restrictable
|
||||
* The item that supports restrictions that is to be verified against
|
||||
* the current time.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the connection should not be allowed at the current time.
|
||||
*/
|
||||
public static void verifyTimeRestrictions(Restrictable restrictable) throws GuacamoleException {
|
||||
|
||||
// Verify time-based restrictions specific to this connection.
|
||||
String allowedTimeString = restrictable.getAttributes().get(RestrictedConnection.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = restrictable.getAttributes().get(RestrictedConnection.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
RestrictionType timeRestriction = allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
|
||||
if (!timeRestriction.isAllowed())
|
||||
throw new TranslatableGuacamoleSecurityException(
|
||||
"Use of this connection or connection group is not allowed at this time.",
|
||||
"RESTRICT.ERROR_CONNECTION_NOT_ALLOWED_NOW"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -213,80 +476,17 @@ public class RestrictionVerificationService {
|
||||
* @param context
|
||||
* The context of the user who is attempting to log in.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The AuthenticatedUser object associated with the user who is
|
||||
* attempting to log in.
|
||||
* @param remoteAddress
|
||||
* The remote address of the client from which the current user is
|
||||
* logged in.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the restrictions should prevent the user from logging in.
|
||||
*/
|
||||
public static void verifyLoginRestrictions(UserContext context,
|
||||
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
||||
public static void verifyLoginRestrictions(UserContext context, String remoteAddress) throws GuacamoleException {
|
||||
|
||||
// Get user's attributes
|
||||
Map<String, String> userAttributes = context.self().getAttributes();
|
||||
String remoteAddress = authenticatedUser.getCredentials().getRemoteAddress();
|
||||
|
||||
if (context.self().getEffectivePermissions().getSystemPermissions().hasPermission(SystemPermission.Type.ADMINISTER)) {
|
||||
LOGGER.warn("User \"{}\" has System Administration permissions; additional restrictions will be bypassed.",
|
||||
authenticatedUser.getIdentifier());
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify time-based restrictions specific to the user
|
||||
String allowedTimeString = userAttributes.get(RestrictUser.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = userAttributes.get(RestrictUser.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByTimeRestrictions(allowedTimeString, deniedTimeString))
|
||||
throw new TranslatableInvalidTimeLoginException("User \""
|
||||
+ authenticatedUser.getIdentifier()
|
||||
+ "\" is not allowed to log in at this time.",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_NOW");
|
||||
|
||||
// Verify host-based restrictions specific to the user
|
||||
String allowedHostString = userAttributes.get(RestrictUser.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = userAttributes.get(RestrictUser.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress))
|
||||
throw new TranslatableInvalidHostLoginException("User \""
|
||||
+ authenticatedUser.getIdentifier()
|
||||
+"\" is not allowed to log in from \""
|
||||
+ remoteAddress + "\"",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_FROM_HOST");
|
||||
|
||||
// Gather user's effective groups.
|
||||
Set<String> userGroups = authenticatedUser.getEffectiveUserGroups();
|
||||
Directory<UserGroup> directoryGroups = context.getPrivileged().getUserGroupDirectory();
|
||||
|
||||
// Loop user's effective groups and verify restrictions
|
||||
for (String userGroup : userGroups) {
|
||||
UserGroup thisGroup = directoryGroups.get(userGroup);
|
||||
if (thisGroup == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get group's attributes
|
||||
Map<String, String> grpAttributes = thisGroup.getAttributes();
|
||||
|
||||
// Pull time-based restrictions for this group and verify
|
||||
String grpAllowedTimeString = grpAttributes.get(RestrictUserGroup.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String grpDeniedTimeString = grpAttributes.get(RestrictUserGroup.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByTimeRestrictions(grpAllowedTimeString, grpDeniedTimeString))
|
||||
throw new TranslatableInvalidTimeLoginException("User \""
|
||||
+ authenticatedUser.getIdentifier()
|
||||
+"\" is not allowed to log in at this time due to restrictions on group \""
|
||||
+ userGroup + "\".",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_NOW");
|
||||
|
||||
// Pull host-based restrictions for this group and verify
|
||||
String grpAllowedHostString = grpAttributes.get(RestrictUserGroup.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String grpDeniedHostString = grpAttributes.get(RestrictUserGroup.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByHostRestrictions(grpAllowedHostString, grpDeniedHostString, remoteAddress))
|
||||
throw new TranslatableInvalidHostLoginException("User \""
|
||||
+ authenticatedUser.getIdentifier()
|
||||
+ "\" is not allowed to log in from this host due to restrictions on group \""
|
||||
+ userGroup + "\".",
|
||||
"RESTRICT.ERROR_USER_LOGIN_NOT_ALLOWED_FROM_HOST");
|
||||
|
||||
}
|
||||
verifyTimeRestrictions(context);
|
||||
verifyHostRestrictions(context, remoteAddress);
|
||||
|
||||
}
|
||||
|
||||
@@ -295,38 +495,24 @@ public class RestrictionVerificationService {
|
||||
* connection the user is attempting to access, throwing an exception if
|
||||
* any of the restrictions result in the connection being unavailable.
|
||||
*
|
||||
* @param connectionAttributes
|
||||
* The attributes of the connection that may contain any additional
|
||||
* restrictions on use of the connection.
|
||||
* @param restrictable
|
||||
* The object that supports restrictions that is to be verified to be
|
||||
* usable within the current restrictions.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote IP address of the user trying to access the connection.
|
||||
* The remote address of the client from which the current user is
|
||||
* logged in.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the restrictions should prevent the connection from being
|
||||
* used by the user at the current time.
|
||||
*/
|
||||
public static void verifyConnectionRestrictions(
|
||||
Map<String, String> connectionAttributes, String remoteAddress)
|
||||
public void verifyConnectionRestrictions(Restrictable restrictable, String remoteAddress)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Verify time-based restrictions specific to this connection.
|
||||
String allowedTimeString = connectionAttributes.get(RestrictConnection.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = connectionAttributes.get(RestrictConnection.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByTimeRestrictions(allowedTimeString, deniedTimeString))
|
||||
throw new TranslatableGuacamoleSecurityException(
|
||||
"Use of this connection is not allowed at this time.",
|
||||
"RESTRICT.ERROR_CONNECTION_NOT_ALLOWED_NOW"
|
||||
);
|
||||
verifyTimeRestrictions(restrictable);
|
||||
verifyHostRestrictions(restrictable, remoteAddress);
|
||||
|
||||
// Verify host-based restrictions specific to this connection.
|
||||
String allowedHostString = connectionAttributes.get(RestrictConnection.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = connectionAttributes.get(RestrictConnection.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
if (!allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress))
|
||||
throw new TranslatableGuacamoleSecurityException(
|
||||
"Use of this connection is not allowed from this remote host: \"" + remoteAddress + "\".",
|
||||
"RESTRICT.ERROR_CONNECTION_NOT_ALLOWED_NOW"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -19,14 +19,17 @@
|
||||
|
||||
package org.apache.guacamole.auth.restrict.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.restrict.Restrictable;
|
||||
import org.apache.guacamole.auth.restrict.RestrictionVerificationService;
|
||||
import org.apache.guacamole.auth.restrict.form.HostRestrictionField;
|
||||
import org.apache.guacamole.auth.restrict.form.TimeRestrictionField;
|
||||
import org.apache.guacamole.calendar.RestrictionType;
|
||||
import org.apache.guacamole.form.Form;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.net.auth.Connection;
|
||||
@@ -37,7 +40,18 @@ import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||
* A Connection implementation that wraps another connection, providing additional
|
||||
* ability to control access to the connection.
|
||||
*/
|
||||
public class RestrictConnection extends DelegatingConnection {
|
||||
public class RestrictedConnection extends DelegatingConnection implements Restrictable {
|
||||
|
||||
/**
|
||||
* The remote address of the client from which the user logged in.
|
||||
*/
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* The restriction verification service.
|
||||
*/
|
||||
@Inject
|
||||
private RestrictionVerificationService verificationService;
|
||||
|
||||
/**
|
||||
* The name of the attribute that contains a list of weekdays and times (UTC)
|
||||
@@ -101,12 +115,6 @@ public class RestrictConnection extends DelegatingConnection {
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The remote address from which the user attempting to access this
|
||||
* connection logged in.
|
||||
*/
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* Wraps the given Connection object, providing capability of further
|
||||
* restricting connection access beyond the default access control provided
|
||||
@@ -116,10 +124,10 @@ public class RestrictConnection extends DelegatingConnection {
|
||||
* The Connection object to wrap.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote address from which the user attempting to access this
|
||||
* connection logged in.
|
||||
* The remote address of the client from which the current user logged
|
||||
* in.
|
||||
*/
|
||||
public RestrictConnection(Connection connection, String remoteAddress) {
|
||||
public RestrictedConnection(Connection connection, String remoteAddress) {
|
||||
super(connection);
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
@@ -175,11 +183,25 @@ public class RestrictConnection extends DelegatingConnection {
|
||||
Map<String, String> tokens) throws GuacamoleException {
|
||||
|
||||
// Verify the restrictions for this connection.
|
||||
RestrictionVerificationService.verifyConnectionRestrictions(getAttributes(), remoteAddress);
|
||||
verificationService.verifyConnectionRestrictions(this, remoteAddress);
|
||||
|
||||
// Connect
|
||||
return super.connect(info, tokens);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentTimeRestriction() {
|
||||
String allowedTimeString = getAttributes().get(RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = getAttributes().get(RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentHostRestriction() {
|
||||
String allowedHostString = getAttributes().get(RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = getAttributes().get(RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress);
|
||||
}
|
||||
|
||||
}
|
@@ -19,14 +19,17 @@
|
||||
|
||||
package org.apache.guacamole.auth.restrict.connectiongroup;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.restrict.Restrictable;
|
||||
import org.apache.guacamole.auth.restrict.RestrictionVerificationService;
|
||||
import org.apache.guacamole.auth.restrict.form.HostRestrictionField;
|
||||
import org.apache.guacamole.auth.restrict.form.TimeRestrictionField;
|
||||
import org.apache.guacamole.calendar.RestrictionType;
|
||||
import org.apache.guacamole.form.Form;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||
@@ -37,7 +40,18 @@ import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||
* A ConnectionGroup implementation that wraps an existing ConnectionGroup,
|
||||
* providing additional ability to control access to the ConnectionGroup.
|
||||
*/
|
||||
public class RestrictConnectionGroup extends DelegatingConnectionGroup {
|
||||
public class RestrictedConnectionGroup extends DelegatingConnectionGroup implements Restrictable {
|
||||
|
||||
/**
|
||||
* The remote address of the client from which the current user logged in.
|
||||
*/
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* The verification service.
|
||||
*/
|
||||
@Inject
|
||||
private RestrictionVerificationService verificationService;
|
||||
|
||||
/**
|
||||
* The name of the attribute that contains a list of weekdays and times (UTC)
|
||||
@@ -102,12 +116,6 @@ public class RestrictConnectionGroup extends DelegatingConnectionGroup {
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* The remote address from which the user accessing this connection group
|
||||
* logged in.
|
||||
*/
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* Wraps the given ConnectionGroup object, providing capability of further
|
||||
* restricting connection group access beyond the default access control
|
||||
@@ -117,10 +125,10 @@ public class RestrictConnectionGroup extends DelegatingConnectionGroup {
|
||||
* The ConnectionGroup object to wrap.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote address from which the user accessing this connection
|
||||
* logged in.
|
||||
* The remote address of the client from which the current user logged
|
||||
* in.
|
||||
*/
|
||||
public RestrictConnectionGroup(ConnectionGroup connectionGroup, String remoteAddress) {
|
||||
public RestrictedConnectionGroup(ConnectionGroup connectionGroup, String remoteAddress) {
|
||||
super(connectionGroup);
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
@@ -177,11 +185,25 @@ public class RestrictConnectionGroup extends DelegatingConnectionGroup {
|
||||
Map<String, String> tokens) throws GuacamoleException {
|
||||
|
||||
// Verify restrictions for this connection group.
|
||||
RestrictionVerificationService.verifyConnectionRestrictions(getAttributes(), remoteAddress);
|
||||
verificationService.verifyConnectionRestrictions(this, remoteAddress);
|
||||
|
||||
// Connect
|
||||
return super.connect(info, tokens);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentTimeRestriction() {
|
||||
String allowedTimeString = getAttributes().get(RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = getAttributes().get(RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentHostRestriction() {
|
||||
String allowedHostString = getAttributes().get(RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = getAttributes().get(RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress);
|
||||
}
|
||||
|
||||
}
|
@@ -23,8 +23,11 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.guacamole.auth.restrict.Restrictable;
|
||||
import org.apache.guacamole.auth.restrict.RestrictionVerificationService;
|
||||
import org.apache.guacamole.auth.restrict.form.HostRestrictionField;
|
||||
import org.apache.guacamole.auth.restrict.form.TimeRestrictionField;
|
||||
import org.apache.guacamole.calendar.RestrictionType;
|
||||
import org.apache.guacamole.form.Form;
|
||||
import org.apache.guacamole.net.auth.DelegatingUser;
|
||||
import org.apache.guacamole.net.auth.User;
|
||||
@@ -33,7 +36,12 @@ import org.apache.guacamole.net.auth.User;
|
||||
* User implementation which wraps a User from another extension and enforces
|
||||
* additional restrictions.
|
||||
*/
|
||||
public class RestrictUser extends DelegatingUser {
|
||||
public class RestrictedUser extends DelegatingUser implements Restrictable {
|
||||
|
||||
/**
|
||||
* The remote address of the client from which the current user is logged in.
|
||||
*/
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* The name of the attribute that contains a list of weekdays and times (UTC)
|
||||
@@ -97,16 +105,20 @@ public class RestrictUser extends DelegatingUser {
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wraps the given User object, providing capability of further restricting
|
||||
* logins beyond the default restrictions provided by default modules.
|
||||
*
|
||||
* @param user
|
||||
* The User object to wrap.
|
||||
*
|
||||
* @param remoteAddress
|
||||
* The remote address of the client from which the current user is logged
|
||||
* in.
|
||||
*/
|
||||
public RestrictUser(User user) {
|
||||
public RestrictedUser(User user, String remoteAddress) {
|
||||
super(user);
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,4 +167,18 @@ public class RestrictUser extends DelegatingUser {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentTimeRestriction() {
|
||||
String allowedTimeString = getAttributes().get(RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedTimeString = getAttributes().get(RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestrictionType getCurrentHostRestriction() {
|
||||
String allowedHostString = getAttributes().get(RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
|
||||
String deniedHostString = getAttributes().get(RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
|
||||
return RestrictionVerificationService.allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress);
|
||||
}
|
||||
|
||||
}
|
@@ -23,9 +23,10 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.restrict.connection.RestrictConnection;
|
||||
import org.apache.guacamole.auth.restrict.connectiongroup.RestrictConnectionGroup;
|
||||
import org.apache.guacamole.auth.restrict.usergroup.RestrictUserGroup;
|
||||
import org.apache.guacamole.auth.restrict.RestrictionVerificationService;
|
||||
import org.apache.guacamole.auth.restrict.connection.RestrictedConnection;
|
||||
import org.apache.guacamole.auth.restrict.connectiongroup.RestrictedConnectionGroup;
|
||||
import org.apache.guacamole.auth.restrict.usergroup.RestrictedUserGroup;
|
||||
import org.apache.guacamole.form.Form;
|
||||
import org.apache.guacamole.net.auth.Connection;
|
||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||
@@ -35,12 +36,19 @@ import org.apache.guacamole.net.auth.Directory;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A UserContext implementation for additional login and connection restrictions
|
||||
* which wraps the UserContext of some other extension.
|
||||
*/
|
||||
public class RestrictUserContext extends DelegatingUserContext {
|
||||
public class RestrictedUserContext extends DelegatingUserContext {
|
||||
|
||||
/**
|
||||
* The logger for this class.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RestrictedUserContext.class);
|
||||
|
||||
/**
|
||||
* The remote address from which this user logged in.
|
||||
@@ -48,7 +56,7 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
private final String remoteAddress;
|
||||
|
||||
/**
|
||||
* Creates a new RestrictUserContext which wraps the given UserContext,
|
||||
* Creates a new RestrictedUserContext which wraps the given UserContext,
|
||||
* providing additional control for user logins and connections.
|
||||
*
|
||||
* @param userContext
|
||||
@@ -57,7 +65,7 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
* @param remoteAddress
|
||||
* The address the user is logging in from, if known.
|
||||
*/
|
||||
public RestrictUserContext(UserContext userContext, String remoteAddress) {
|
||||
public RestrictedUserContext(UserContext userContext, String remoteAddress) {
|
||||
super(userContext);
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
@@ -67,14 +75,14 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
return new DecoratingDirectory<Connection>(super.getConnectionDirectory()) {
|
||||
|
||||
@Override
|
||||
protected Connection decorate(Connection object) {
|
||||
return new RestrictConnection(object, remoteAddress);
|
||||
protected Connection decorate(Connection object) throws GuacamoleException {
|
||||
return new RestrictedConnection(object, remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Connection undecorate(Connection object) {
|
||||
assert(object instanceof RestrictConnection);
|
||||
return ((RestrictConnection) object).getUndecorated();
|
||||
assert(object instanceof RestrictedConnection);
|
||||
return ((RestrictedConnection) object).getUndecorated();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -83,7 +91,7 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
@Override
|
||||
public Collection<Form> getConnectionAttributes() {
|
||||
Collection<Form> connectionAttrs = new HashSet<>(super.getConnectionAttributes());
|
||||
connectionAttrs.add(RestrictConnection.RESTRICT_CONNECTION_FORM);
|
||||
connectionAttrs.add(RestrictedConnection.RESTRICT_CONNECTION_FORM);
|
||||
return Collections.unmodifiableCollection(connectionAttrs);
|
||||
}
|
||||
|
||||
@@ -92,14 +100,14 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
return new DecoratingDirectory<ConnectionGroup>(super.getConnectionGroupDirectory()) {
|
||||
|
||||
@Override
|
||||
protected ConnectionGroup decorate(ConnectionGroup object) {
|
||||
return new RestrictConnectionGroup(object, remoteAddress);
|
||||
protected ConnectionGroup decorate(ConnectionGroup object) throws GuacamoleException {
|
||||
return new RestrictedConnectionGroup(object, remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionGroup undecorate(ConnectionGroup object) {
|
||||
assert(object instanceof RestrictConnectionGroup);
|
||||
return ((RestrictConnectionGroup) object).getUndecorated();
|
||||
assert(object instanceof RestrictedConnectionGroup);
|
||||
return ((RestrictedConnectionGroup) object).getUndecorated();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -108,7 +116,7 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
@Override
|
||||
public Collection<Form> getConnectionGroupAttributes() {
|
||||
Collection<Form> connectionGroupAttrs = new HashSet<>(super.getConnectionGroupAttributes());
|
||||
connectionGroupAttrs.add(RestrictConnectionGroup.RESTRICT_CONNECTIONGROUP_FORM);
|
||||
connectionGroupAttrs.add(RestrictedConnectionGroup.RESTRICT_CONNECTIONGROUP_FORM);
|
||||
return Collections.unmodifiableCollection(connectionGroupAttrs);
|
||||
}
|
||||
|
||||
@@ -118,13 +126,13 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
|
||||
@Override
|
||||
protected User decorate(User object) {
|
||||
return new RestrictUser(object);
|
||||
return new RestrictedUser(object, remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected User undecorate(User object) {
|
||||
assert(object instanceof RestrictUser);
|
||||
return ((RestrictUser) object).getUndecorated();
|
||||
assert(object instanceof RestrictedUser);
|
||||
return ((RestrictedUser) object).getUndecorated();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -133,7 +141,7 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
@Override
|
||||
public Collection<Form> getUserAttributes() {
|
||||
Collection<Form> userAttrs = new HashSet<>(super.getUserAttributes());
|
||||
userAttrs.add(RestrictUser.RESTRICT_LOGIN_FORM);
|
||||
userAttrs.add(RestrictedUser.RESTRICT_LOGIN_FORM);
|
||||
return Collections.unmodifiableCollection(userAttrs);
|
||||
}
|
||||
|
||||
@@ -143,13 +151,13 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
|
||||
@Override
|
||||
protected UserGroup decorate(UserGroup object) {
|
||||
return new RestrictUserGroup(object);
|
||||
return new RestrictedUserGroup(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserGroup undecorate(UserGroup object) {
|
||||
assert(object instanceof RestrictUserGroup);
|
||||
return ((RestrictUserGroup) object).getUndecorated();
|
||||
assert(object instanceof RestrictedUserGroup);
|
||||
return ((RestrictedUserGroup) object).getUndecorated();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -158,8 +166,21 @@ public class RestrictUserContext extends DelegatingUserContext {
|
||||
@Override
|
||||
public Collection<Form> getUserGroupAttributes() {
|
||||
Collection<Form> userGroupAttrs = new HashSet<>(super.getUserGroupAttributes());
|
||||
userGroupAttrs.add(RestrictUserGroup.RESTRICT_LOGIN_FORM);
|
||||
userGroupAttrs.add(RestrictedUserGroup.RESTRICT_LOGIN_FORM);
|
||||
return Collections.unmodifiableCollection(userGroupAttrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
try {
|
||||
// Verify whether or not time restrictions still apply.
|
||||
RestrictionVerificationService.verifyTimeRestrictions(this);
|
||||
return true;
|
||||
}
|
||||
catch (GuacamoleException e) {
|
||||
LOGGER.debug("User account is now restricted and is no longer valid", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -33,7 +33,7 @@ import org.apache.guacamole.net.auth.UserGroup;
|
||||
* UserGroup implementation which wraps a UserGroup from another extension and
|
||||
* enforces additional restrictions for members of that group.
|
||||
*/
|
||||
public class RestrictUserGroup extends DelegatingUserGroup {
|
||||
public class RestrictedUserGroup extends DelegatingUserGroup {
|
||||
|
||||
/**
|
||||
* The name of the attribute that contains a list of weekdays and times (UTC)
|
||||
@@ -107,7 +107,7 @@ public class RestrictUserGroup extends DelegatingUserGroup {
|
||||
* @param userGroup
|
||||
* The UserGroup object to wrap.
|
||||
*/
|
||||
public RestrictUserGroup(UserGroup userGroup) {
|
||||
public RestrictedUserGroup(UserGroup userGroup) {
|
||||
super(userGroup);
|
||||
}
|
||||
|
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.calendar;
|
||||
|
||||
/**
|
||||
* A data type that represents various values of what type of restriction applies
|
||||
* at a given time.
|
||||
*/
|
||||
public enum RestrictionType {
|
||||
|
||||
/**
|
||||
* Access is explicitly allowed.
|
||||
*/
|
||||
EXPLICIT_ALLOW(1, true),
|
||||
|
||||
/**
|
||||
* Access is explicitly denied.
|
||||
*/
|
||||
EXPLICIT_DENY(0, false),
|
||||
|
||||
/**
|
||||
* Access has not been explicitly allowed or denied, therefore it is
|
||||
* implicitly allowed.
|
||||
*/
|
||||
IMPLICIT_ALLOW(3, true),
|
||||
|
||||
/**
|
||||
* Access has not been explicitly allowed or denied, therefore it is
|
||||
* implicitly denied.
|
||||
*/
|
||||
IMPLICIT_DENY(2, false);
|
||||
|
||||
/**
|
||||
* The overall priority of the restriction, with zero being the highest
|
||||
* priority and the priority decreasing as numbers increase from zero.
|
||||
*/
|
||||
final private int priority;
|
||||
|
||||
/**
|
||||
* true if the restriction allows access, otherwise false.
|
||||
*/
|
||||
final private boolean allowed;
|
||||
|
||||
/**
|
||||
* Create the new instance of this RestrictionType, with the given
|
||||
* priority value for the instance.
|
||||
*
|
||||
* @param priority
|
||||
* The priority of the restriction type, where zero is the highest
|
||||
* priority.
|
||||
*
|
||||
* @param allowed
|
||||
* true if the restriction allows access, otherwise false.
|
||||
*/
|
||||
RestrictionType(int priority, boolean allowed) {
|
||||
this.priority = priority;
|
||||
this.allowed = allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates two restrictions, returning the higher priority of the two.
|
||||
*
|
||||
* @param restriction1
|
||||
* The first restriction to compare.
|
||||
*
|
||||
* @param restriction2
|
||||
* The second restriction to compare.
|
||||
*
|
||||
* @return
|
||||
* Return which of the two restrictions is the higher-priority.
|
||||
*/
|
||||
public static RestrictionType getHigherPriority(RestrictionType restriction1, RestrictionType restriction2) {
|
||||
|
||||
// If the second is higher than the first, return the second.
|
||||
if (restriction1.priority > restriction2.priority)
|
||||
return restriction2;
|
||||
|
||||
// Return the first.
|
||||
return restriction1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this restriction allows access, otherwise false.
|
||||
*
|
||||
* @return
|
||||
* true if this restriction allows access, otherwise false.
|
||||
*/
|
||||
public boolean isAllowed() {
|
||||
return this.allowed;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user