Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-2013: There is a typo in the Russian translation in the Guacamole interface "секуны", it needs to be fixed to "секунды". #1047

Open
wants to merge 32 commits into
base: patch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fff7ba4
Merge changes from patch branch back to main.
mike-jumper Aug 6, 2024
3310272
Merge patch branch changes to main.
necouchman Aug 18, 2024
7a66ec9
GUACAMOLE-1979: Allow setting required properties for connecting to M…
jmuehlner Aug 13, 2024
30716c6
GUACAMOLE-1979: Merge allow setting required properties for connectin…
necouchman Aug 23, 2024
ad3a007
Merge patch branch changes to main.
necouchman Aug 25, 2024
d3b784d
Merge changes from patch branch back to main.
mike-jumper Aug 28, 2024
468c050
Merge changes from patch branch back to main.
mike-jumper Aug 28, 2024
bef7e30
Merge changes from patch branch back to main.
mike-jumper Aug 30, 2024
f95a218
Merge changes from patch branch back to main.
mike-jumper Sep 2, 2024
ea43caa
Merge patch branch changes to main
necouchman Sep 25, 2024
38dd5a4
Merge patch branch changes to main.
necouchman Sep 25, 2024
40620e4
Merge patch branch changes to main.
necouchman Oct 1, 2024
9320cdb
Merge changes from patch branch back to main.
mike-jumper Oct 2, 2024
2bf93c1
Merge changes from patch branch back to main.
mike-jumper Oct 2, 2024
3839f9c
Merge changes from patch branch back to main.
mike-jumper Oct 4, 2024
d558a44
Merge changes from patch branch back to main.
mike-jumper Oct 11, 2024
56fb1dd
GUACAMOLE-1989: Add the ability to open guacamole as an independent a…
corentin-soriano Oct 7, 2024
bbede31
GUACAMOLE-1989: Merge the ability to open guacamole as an independent…
necouchman Oct 14, 2024
32eaffc
GUACAMOLE-1701: Implement connection date and time before and after r…
necouchman Oct 4, 2024
8d1bf03
GUACAMOLE-1976: Add OPTIONAL token modifier.
necouchman Aug 9, 2024
55d1b0d
GUACAMOLE-1976: Merge new OPTIONAL token modifier.
jmuehlner Oct 18, 2024
397467a
GUACAMOLE-1701: Merge new configurable connection date and time restr…
jmuehlner Oct 18, 2024
2770ef3
GUACAMOLE-1974: Allow deferring received pipe streams for later consu…
jmuehlner Jul 30, 2024
b5c9a08
GUACAMOLE-1974: Merge changes to allow deferring received pipe stream…
aleitner Oct 31, 2024
494c4ce
Merge changes from patch branch back to main.
mike-jumper Nov 10, 2024
607e611
Merge patch branch changes to main.
necouchman Dec 2, 2024
0995eb8
Merge patch branch changes to main.
necouchman Jan 3, 2025
85abb6e
GUACAMOLE-2013: There is a typo in the Russian translation in the Gua…
VAGurko Jan 15, 2025
4c40256
Merge changes from patch branch back to main.
mike-jumper Jan 15, 2025
65954c2
Merge patch branch changes to main.
necouchman Jan 15, 2025
fff0015
Merge changes from patch branch back to main.
mike-jumper Jan 20, 2025
bc076c1
Merge branch 'apache:main' into GUACAMOLE-2013
VAGurko Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ public MySQLAuthenticationProviderModule(MySQLEnvironment environment)
myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true");
myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1");

// Set whether public key retrieval from the server is allowed
driverProperties.setProperty("allowPublicKeyRetrieval",
environment.getMYSQLAllowPublicKeyRetrieval() ? "true" : "false");

// Use UTF-8 in database
driverProperties.setProperty("characterEncoding", "UTF-8");

Expand Down Expand Up @@ -121,10 +125,22 @@ public MySQLAuthenticationProviderModule(MySQLEnvironment environment)
if (clientPassword != null)
driverProperties.setProperty("clientCertificateKeyStorePassword",
clientPassword);

// Get the MySQL-compatible driver to use.
mysqlDriver = environment.getMySQLDriver();

// Set the path to the server public key, if any
// Note that the property name casing is slightly different for MySQL
// and MariaDB drivers. See
// https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-security.html#cj-conn-prop_serverRSAPublicKeyFile
// and https://mariadb.com/kb/en/about-mariadb-connector-j/#infrequently-used-parameters
String publicKeyFile = environment.getMYSQLServerRSAPublicKeyFile();
if (publicKeyFile != null)
driverProperties.setProperty(
mysqlDriver == MySQLDriver.MYSQL
? "serverRSAPublicKeyFile" : "serverRsaPublicKeyFile",
publicKeyFile);

// If timezone is present, set it.
TimeZone serverTz = environment.getServerTimeZone();
if (serverTz != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,4 +443,35 @@ public boolean enforceAccessWindowsForActiveSessions() throws GuacamoleException
);
}

/**
* Returns the absolute path to the public key for the server being connected to,
* if any, or null if the configuration property is unset.
*
* @return
* The absolute path to the public key for the server being connected to.
*
* @throws GuacamoleException
* If an error occurs retrieving the configuration value.
*/
public String getMYSQLServerRSAPublicKeyFile() throws GuacamoleException {
return getProperty(MySQLGuacamoleProperties.MYSQL_SERVER_RSA_PUBLIC_KEY_FILE);
}

/**
* Returns true if the database server public key should be automatically
* retrieved from the MySQL server, or false otherwise.
*
* @return
* Whether the database server public key should be automatically
* retrieved from the MySQL server.
*
* @throws GuacamoleException
* If an error occurs retrieving the configuration value.
*/
public boolean getMYSQLAllowPublicKeyRetrieval() throws GuacamoleException {
return getProperty(
MySQLGuacamoleProperties.MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL,
false);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -302,5 +302,28 @@ private MySQLGuacamoleProperties() {}
public String getName() { return "mysql-batch-size"; }

};


/**
* The absolute path to the public key for the server being connected to, if any.
*/
public static final StringGuacamoleProperty MYSQL_SERVER_RSA_PUBLIC_KEY_FILE =
new StringGuacamoleProperty() {

@Override
public String getName() { return "mysql-server-rsa-public-key-file"; }

};

/**
* Whether or not the server public key should be automatically retreived from
* the MySQL server.
*/
public static final BooleanGuacamoleProperty MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL =
new BooleanGuacamoleProperty() {

@Override
public String getName() { return "mysql-allow-public-key-retrieval"; }

};

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,65 @@
*/
public interface Restrictable extends Attributes {

/**
* The name of the attribute that contains the absolute date and time after
* which this restrictable object may be used. If this attribute is present
* access to to this object will be denied at any time prior to the parsed
* value of this attribute, regardless of what other restrictions may be
* present to allow access to the object at certain days/times of the week
* or from certain hosts.
*/
public static final String RESTRICT_TIME_AFTER_ATTRIBUTE_NAME = "guac-restrict-time-after";

/**
* The name of the attribute that contains a list of weekdays and times (UTC)
* that this restrictable object can be used. The presence of values within
* this attribute will automatically restrict use of the object at any times
* that are not specified.
*/
public static final String RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME = "guac-restrict-time-allowed";

/**
* The name of the attribute that contains the absolute date and time before
* which use of this restrictable object may be used. If this attribute is
* present use of the object will be denied at any time after the parsed
* value of this attribute, regardless of the presence of other restrictions
* that may allow access at certain days/times of the week or from certain
* hosts.
*/
public static final String RESTRICT_TIME_BEFORE_ATTRIBUTE_NAME = "guac-restrict-time-before";

/**
* The name of the attribute that contains a list of weekdays and times (UTC)
* that this restrictable object cannot be used. Denied times will always take
* precedence over allowed times. The presence of this attribute without
* guac-restrict-time-allowed will deny access only during the times listed
* in this attribute, allowing access at all other times. The presence of
* this attribute along with the guac-restrict-time-allowed attribute will
* deny access at any times that overlap with the allowed times.
*/
public static final String RESTRICT_TIME_DENIED_ATTRIBUTE_NAME = "guac-restrict-time-denied";

/**
* The name of the attribute that contains a list of hosts from which this
* restrictable object may be used. The presence of this attribute will
* restrict use to only users accessing Guacamole from the list of hosts
* contained in the attribute, subject to further restriction by the
* guac-restrict-hosts-denied attribute.
*/
public static final String RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME = "guac-restrict-hosts-allowed";

/**
* The name of the attribute that contains a list of hosts from which this
* restrictable object may not be used. The presence of this attribute,
* absent the guac-restrict-hosts-allowed attribute, will allow use from
* all hosts except the ones listed in this attribute. The presence of this
* attribute coupled with the guac-restrict-hosts-allowed attribute will
* block access from any IPs in this list, overriding any that may be
* allowed.
*/
public static final String RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME = "guac-restrict-hosts-denied";

/**
* Return the restriction state for this restrictable object at the
* current date and time. By default returns an implicit denial.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
import inet.ipaddr.HostNameException;
import inet.ipaddr.IPAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
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.auth.restrict.form.DateTimeRestrictionField;
import org.apache.guacamole.calendar.DailyRestriction;
import org.apache.guacamole.calendar.RestrictionType;
import org.apache.guacamole.calendar.TimeRestrictionParser;
Expand All @@ -54,6 +54,67 @@ public class RestrictionVerificationService {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(RestrictionVerificationService.class);

/**
* Given the provided strings of an absolute date after which an action is
* valid and before which an action is valid, parse the strings into Date
* objects and determine if the current date and time falls within the
* provided window, returning the appropriate restriction type.
*
* @param afterTimeString
* The string that has the date and time value after which the activity
* is allowed.
*
* @param beforeTimeString
* The string that has the date and time value before which the activity
* is allowed.
*
* @return
* The RestrictionType that represents the allowed or denied state of
* the activity.
*/
private static RestrictionType allowedByDateTimeRestrictions(
String afterTimeString, String beforeTimeString) {

// Set a default restriction.
RestrictionType dateTimeRestriction = RestrictionType.IMPLICIT_ALLOW;

// Check the after string and make sure that now is after that date.
if (afterTimeString != null && !afterTimeString.isEmpty()) {
Date now = new Date();
try {
Date afterTime = DateTimeRestrictionField.parse(afterTimeString);
if (now.before(afterTime))
return RestrictionType.EXPLICIT_DENY;
}
catch (ParseException e) {
LOGGER.warn("Failed to parse date and time string: {}:", e.getMessage());
LOGGER.debug("Parse exception while parsing date and time string.", e);
return RestrictionType.IMPLICIT_DENY;
}
dateTimeRestriction = RestrictionType.EXPLICIT_ALLOW;
}

// Check the before string and make sure that now is prior to that date.
if (beforeTimeString != null && !beforeTimeString.isEmpty()) {
Date now = new Date();
try {
Date beforeTime = DateTimeRestrictionField.parse(beforeTimeString);
if (now.after(beforeTime))
return RestrictionType.EXPLICIT_DENY;
}
catch (ParseException e) {
LOGGER.warn("Failed to parse date and time string: {}:", e.getMessage());
LOGGER.debug("Parse exception while parsing date and time string.", e);
return RestrictionType.IMPLICIT_DENY;
}
dateTimeRestriction = RestrictionType.EXPLICIT_ALLOW;

}

// Return the determined RestrictionType for the given date/time strings.
return dateTimeRestriction;
}

/**
* Parse out the provided strings of allowed and denied times, verifying
* whether or not a login or connection should be allowed at the current
Expand Down Expand Up @@ -251,8 +312,8 @@ public static void verifyHostRestrictions(UserContext context,
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);
String allowedHostString = userAttributes.get(Restrictable.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
String deniedHostString = userAttributes.get(Restrictable.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
RestrictionType hostRestrictionResult = allowedByHostRestrictions(allowedHostString, deniedHostString, remoteAddress);

switch (hostRestrictionResult) {
Expand Down Expand Up @@ -284,8 +345,8 @@ public static void verifyHostRestrictions(UserContext context,
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);
String grpAllowedHostString = grpAttributes.get(Restrictable.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
String grpDeniedHostString = grpAttributes.get(Restrictable.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
RestrictionType grpRestrictionResult = allowedByHostRestrictions(grpAllowedHostString, grpDeniedHostString, remoteAddress);

// Any explicit denials are thrown immediately
Expand Down Expand Up @@ -344,8 +405,8 @@ public static 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);
String allowedHostsString = restrictable.getAttributes().get(Restrictable.RESTRICT_HOSTS_ALLOWED_ATTRIBUTE_NAME);
String deniedHostsString = restrictable.getAttributes().get(Restrictable.RESTRICT_HOSTS_DENIED_ATTRIBUTE_NAME);
RestrictionType hostRestrictionResult = allowedByHostRestrictions(allowedHostsString, deniedHostsString, remoteAddress);

// If the host is not allowed
Expand Down Expand Up @@ -393,8 +454,8 @@ public static void verifyTimeRestrictions(UserContext context,
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);
String allowedTimeString = userAttributes.get(Restrictable.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
String deniedTimeString = userAttributes.get(Restrictable.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
RestrictionType timeRestrictionResult = allowedByTimeRestrictions(allowedTimeString, deniedTimeString);

// Check the time restriction for explicit results.
Expand Down Expand Up @@ -426,8 +487,8 @@ public static void verifyTimeRestrictions(UserContext context,
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);
String grpAllowedTimeString = grpAttributes.get(Restrictable.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
String grpDeniedTimeString = grpAttributes.get(Restrictable.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
RestrictionType grpRestrictionResult = allowedByTimeRestrictions(grpAllowedTimeString, grpDeniedTimeString);

// An explicit deny results in immediate denial of the login.
Expand Down Expand Up @@ -463,6 +524,18 @@ public static void verifyTimeRestrictions(UserContext context,

}

public static void verifyDateTimeRestrictions(Restrictable restrictable) throws GuacamoleException {

String afterTimeString = restrictable.getAttributes().get(Restrictable.RESTRICT_TIME_AFTER_ATTRIBUTE_NAME);
String beforeTimeString = restrictable.getAttributes().get(Restrictable.RESTRICT_TIME_BEFORE_ATTRIBUTE_NAME);
RestrictionType dateRestriction = allowedByDateTimeRestrictions(afterTimeString, beforeTimeString);
if (!dateRestriction.isAllowed())
throw new TranslatableGuacamoleSecurityException(
"Use of this connection or connection group is not allowed at this time.",
"RESTRICT.ERROR_CONNECTION_NOT_ALLOWED_NOW"
);
}

/**
* Verify the time restrictions for the given Connection object, throwing
* an exception if the connection should not be allowed, or silently
Expand All @@ -478,8 +551,8 @@ public static void verifyTimeRestrictions(UserContext context,
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);
String allowedTimeString = restrictable.getAttributes().get(Restrictable.RESTRICT_TIME_ALLOWED_ATTRIBUTE_NAME);
String deniedTimeString = restrictable.getAttributes().get(Restrictable.RESTRICT_TIME_DENIED_ATTRIBUTE_NAME);
RestrictionType timeRestriction = allowedByTimeRestrictions(allowedTimeString, deniedTimeString);
if (!timeRestriction.isAllowed())
throw new TranslatableGuacamoleSecurityException(
Expand Down Expand Up @@ -536,6 +609,7 @@ public static void verifyLoginRestrictions(UserContext context,
*/
public static void verifyConnectionRestrictions(Restrictable restrictable,
String remoteAddress) throws GuacamoleException {
verifyDateTimeRestrictions(restrictable);
verifyTimeRestrictions(restrictable);
verifyHostRestrictions(restrictable, remoteAddress);
}
Expand Down
Loading