RUSH.RC(5) | Rush User Reference | RUSH.RC(5) |
rush.rc - configuration rules for remote user shell
The file /etc/rush.rc contains a set of rules that the rush(8) shell uses in order to determine whether the user is allowed to execute the requested command and to set up the environment for its execution.
Empty lines are ignored. Lines beginning with a pound sign are comments and are ignored as well.
Except for comments and empty lines, each line of the configuration file consists of the keyword and optional value, and constitutes a statement. Exceedingly long lines may be split across multiple physical lines, by ending each line with a backslash immediately followed by a newline. Statements fall into two major classes: section and regular statements. A section statement serves as a container for one or more regular statements that pursue the same goal, thus playing the role of a chapter in a book. A regular statement modifies a certain aspect of the program's behavior.
The overall file structure is as follows:
rush 2.0 global
keyword value
... rule A
keyword value
...
rule B
keyword value
...
A configuration file must begin with a rush statement indicating the version of the syntax this file uses. Current versions of rush implement syntax version 2.0. In the absence of the initial rush statement, the program will treat the configuration file as written in legacy configuration syntax (see http://www.gnu.org.ua/software/rush/manual/1.x for details).
There are two section statements: global and rule. The global section contains statements configuring the behavior of the program in general. There can be as many global statements in the configuration as you consider necessary, each of them affecting the material up to the next global statement, or end of the file, whichever occurs first.
Examples of statements that can be used in a global section are: debug, which sets the debug verbosity level, message, which configures error messages, etc. See the global section for the full list.
One or more rule statements constitute the core of the configuration. Each rule statement provides a recipe for serving a specific class of input commands. When rush is invoked with a specific command, it will scan the configuration file looking for a rule that matches the requested command line. If such a rule is found, it will be applied. Commands that don't match any rule will be rejected.
A rule statement may be followed by a tag, an arbitrary sequence of non-whitespace characters serving as a label for this rule. This sequence will be used in diagnostic messages to identify this rule. In the absence of user-supplied tag, the default one will be generated, consisting of the # symbol followed by the ordinal number of the rule in the configuration file (started with 1).
To match a particular command, each rule should contain the match statement. Its argument is a conditional expression that can contain comparison and boolean operators. The operands can refer to the command line using shell-like variables: $command to refer to the entire command line, $#, referring to the number of arguments in the command line (the command itself being counted as one of the arguments), $0 meaning the command name, and $1, $2, etc., referring to the particular command line arguments (arguments past the ninth one can be accessed as, e.g. ${10}). For example, the following rule:
rule
match $command == "ls"
will match only the ls command without arguments.
The ~ (tilde) operator denotes regular expression matching. For example, the following rule matches ls command, optionally preceded with any path prefix:
rule
match $0 ~ "^(.*/)?ls$"
Match expressions can contain terms of arbitrary complexity. Consider the following example:
rule
match $0 ~ "^(.*/)?ls$" && $# == 2 \
&& $1 !~ "^(/|/etc)$"
This rule will match any ls command having exactly one argument, unless that argument is / or /etc. Notice the use of the !~ operator to denote the negated regular expression matching, and the use of backslash to split a single expression across two physical lines.
Variables are referenced using the same syntax as in shell. For example, ${1:-/bin} expands to the value of the first parameter, if it is supplied, or to the string "/bin" otherwise. For details. see the section REFERENCE: VARIABLE EXPANSION.
Although important, the match statement is not mandatory in a rule statement. If it is absent, the rule will match any command line. This is normally used in fall-through rules. A fall-through rule applies modifications to the command environment. After applying such rule, the scanning resumes at the rule that follows it. Fall-through rules are marked with the fall-through statement.
A rule can modify the command line and environment in which it will be executed. The set statement is provided for altering the command line or its parts. It takes three arguments: the variable name or index, the operator and the value. For example, the statement:
set command = "/bin/sftp-server -u 002"
replaces the entire command line. To replace particular arguments, use the [N] syntax, where N is the index of the argument in the command line. For example, to set the first argument:
set [1] = "/tmp"
The part to the right of the equals sign can contain a transformation, i.e. a string followed by the ~ operand and a s-expression of the form s/regexp/replacement/[flags]. Parenthesized groups in regexp can be referred to in replacement using the backreference construct \N, where N is the 1-based ordinal number of the group. For example, the following statement sets the second argument to the directory part of the first one:
set [2] = "$1" ~ "s/(.*)\\//\\1/"
Two points are worth noticing. First, the left operand of ~ undergoes variable expansion. Secondly, the right-hand side operand is quoted and therefore each backslash in it has to be escaped.
The special operator =~ is used if the resulted value is assigned to the same variable that served as its argument. For example, the two statements below are equivalent:
set [1] =~ "s/(.*)\\//\\1/" set [1] = "$1" ~ "s/(.*)\\//\\1/"
Parenthesized groups matched by the most recent set statement remain available for use in the statements that follow it in the rule. To refer to the group from the recent matching, use the following construct: %N. For example, the following two statements set the first argument to the directory part, and second argument to the base name of the original $1 value:
set [1] =~ "s/(.*)\\/(.*)/\\1/" set [2] = %2
The set statement operates not only on positional arguments and built-in variables, but also on arbitrary user-defined variables. A user-defined variable springs into existence when it first appears as a left-hand side argument to the set statement. The name of the variable must follow the usual rules for variable names: it must begin with an alphabetical character or underscore and contain only letters, digits and underscores. References to user-defined variables follow the same syntax as for built-in ones.
The following example uses temporary variable temp to swap two arguments:
set temp = $1 set [1] = $2 set [2] = $temp
Variable definitions can be removed using the unset statement. It takes variable name or positional argument index as its argument:
unset temp
When index is given, the corresponding positional argument is removed and all arguments to the right of it are shifted one position left to occupy the released slot. For example, given the command line
scp -d -v -t /incoming
the statement
unset 1
will reduce it to
scp -v -t /incoming
The delete statement provides a generalization of unset for positional arguments. It takes one or two argument indexes as arguments. When used with one index, it provides the same functionality as unset. When two indices are given, it deletes all arguments between those indices (inclusive). For example, the statement
delete 1 2
will change the command line from the above example to
scp -t /incoming
Using negative indices, one can indicate arguments counting from right to left. Thus, the following will delete all arguments starting from the third:
delete 3 -1
Whereas delete and unset remove arguments at given positions, the remopt statement allows you to remove specific command line options from the command line. This is useful to ensure no potentially harmful options can be passed by the user. The statement takes one or two arguments. First argument supplies the short option letter. For example, the following removes all occurrences of the -A option:
remopt A
If there is a long-option equivalent, it can be supplied as the second argument. For example, if --all is an alias for -A, the above statement would be rewritten as:
remopt A all
Notice, that the initial dash or double-dash is omitted from both the short and long option designation.
When looking for long option in the command line, remopt will recognize its possible abbreviations. In the example above, eventual occurrences of --al will be removed as well.
If the option takes an argument, follow the first argument by a colon. For example, to remove occurrences of the options -r along with its arguments write
remopt r:
The long option equivalent can be specified as well, e.g.:
remopt r: root
This will recognize all possible ways of option usage in the command line, such as: -r ARG, -rARG, --root=ARG, or --root ARG. -afr ARG In each case, both the option and its argument will be removed, so that the modified command line will remain valid. Short option appearing in a cluster will be recognized, .e.g -afr ARG will be replaced by -af. Finally, if the option takes an optional argument, follow its short letter by two colons, as in:
remopt r:: root
Arguments can also be inserted at arbitrary positions. The insert statement is provided for this purpose. Its syntax is similar to set:
insert [N] = value
and
insert [N] = value ~ s/regex/replace/
where N is the position where to insert the new argument. All arguments starting from Nth will be shifted one position to the right, and the value will be stored in the Nth slot. In the second form, the value to be inserted is computed by applying the replacement expression to value.
A statement consists of a keyword and arguments, separated by any amount of whitespace. Arguments can be one of the following:
During backslash interpretation, the escape sequences are recognized and replaced as per table below:
Sequence Replaced with \a Audible bell character (ASCII 7) \b Backspace character (ASCII 8) \f Form-feed character (ASCII 12) \n Newline character (ASCII 10) \r Carriage return character (ASCII 13) \t Horizontal tabulation character (ASCII 9) \v Vertical tabulation character (ASCII 11) \\ A single backslash \" A double-quote. \% Percent sign
In addition, the sequence \newline is removed from the string. This allows one to split long strings over several physical lines.
During the backreference interpretation, references to parenthesized groups in regular expression are replaced with the actual content of the corresponding group in the most recently matched string. A reference is %{N} where N is a decimal number. If N is one digit, curly braces can be omitted: %N If the % character resulted from previous backslash interpretation, no backreference interpretation occurs.
Strings used in the left-hand side of a comparison expression are subject to variable expansion. This is discussed later.
Reference Meaning ${VAR:-WORD} Use Default Values ${VAR:=WORD} Assign Default Values ${VAR:?WORD} Display Error if Null or Unset ${VAR:+WORD} Use Alternate Value
where WORD stands for any valid token as described in this section. See the section REFERENCE: VARIABLE EXPANSION, for a detailed discussion of these forms and their meaning.
&& Boolean AND || Boolean OR ! Boolean negation == Equality (string or numeric) != Inequality (string or numeric) < Less than <= Less than or equal to > Greater than >= Greater than or equal to ~ Regexp matching !~ Negated regexp matching in Membership in set of strings group Membership in UNIX group = Assignment =~ Regular expression substitution
Most statements in the configuration file undergo variable expansion prior to their use. During variable expansion, references to variables in the string are replaced with their actual values. A variable reference has two basic forms:
$V ${V}
where V is either the name of the variable (request, environment, or user-defined), or the index of the positional variable. The notation in curly braces serves several purposes. First, it is obligatory if V is an index of the positional variable that is negative or greater than 9. Secondly, it should be used if the variable reference is immediately followed by an alphanumeric symbol, which will otherwise be considered part of it (as in ${home}dir). Finally, this form allows for specifying the action to take if the variable is undefined or expands to an empty value.
The following special forms are recognized:
There are three global statements, two of which can contain multiple substatements:
Introduces global settings. This statement is followed by one or more substatements. Global settings end at the nearest rule statement that follows. They remain in effect until the next global statement is encountered which alters them.
The following statements may appear in this section.
Any of the following values can be used as a synonym for true: yes, on, t, 1.
The following values can be used as synonyms for false: no, off, nil, 0.
"You are not permitted to execute this command."
"You are not permitted to execute this command."
"Local configuration error occurred."
"A system error occurred while attempting to execute command."
Each of the above keywords can be prefixed by no, which reverses its meaning. The special keyword none disables all checks.
Defines a rule. This is a block statement, which means that all statements located between it and the next rule statement (or end of file, whichever occurs first) modify the definition of that rule.
The syntax is:
rule TAG
Optional TAG argument supplies the identifier for that rule. It is used in diagnostic messages. If tag is missing, rush will supply a default one, which is constructed by concatenating the # character and the ordinal number of rule in the configuration file, in decimal notation. Rule numbering starts from 1.
A rule can contain the following statements:
A simple expression is either a comparison or a membership test. A comparison has the general syntax
lhs op rhs
where lhs and rhs are operands and op is the operation. The lhs is either a string (quoted or unquoted), or a variable reference. The rhs is a string or number. Prior to evaluating simple expression, its LHS undergoes variable expansion. In contrast, the RHS operand is always treated verbatim.
The comparison operator OP is one of the following:
== Equality (string or numeric) != Inequality (string or numeric) < Less than <= Less than or equal to > Greater than >= Greater than or equal to ~ Regexp matching !~ Negated regexp matching
Two membership tests are available. The in test has the form
LHS in ( STRING ... )
and evaluates to true if LHS matches one of the strings in parentheses. LHS undergoes variable expansion and backreference interpretation prior to comparison.
The group test has the following syntax:
group GRP
It returns true if the requesting user is a member of the group GRP. Several groups can be given in parentheses:
group (GRP ...)
in which case the test return true if the user is a member of at least one of the mentioned groups.
Compound boolean expression combine one or more expressions using logical operators
&& Boolean AND || Boolean OR ! Boolean negation
set NAME = $NAME ~ S-EXPR
i.e. it applies the search-and-replace expression S-EXPR to the current value of the variable NAME and stores the resulting string as its new value.
set [N] = $N ~ S-EXPR
The S-EXPR, is a sed replace expression of the form:
s/REGEXP/REPLACE/[FLAGS]
where REGEXP is a regular expression, REPLACE is a replacement for each part of the input that matches REGEXP and optional FLAGS are flag letters that control the substitution. Both REGEXP and REPLACE are described in sed(1).
As in sed, you can give several replace expressions, separated by semicolons.
The supported FLAGS are:
Notice, that the POSIX standard does not specify what should happen when you mix the g and NUMBER modifiers. Rush follows the GNU sed implementation in this regard, so the interaction is defined to be: ignore matches before the NUMBERth, and then match and replace all matches from the NUMBERth on.
Also notice, that usually S-EXPR is a quoted string, and as such it is subject to backslash interpretation. It is therefore important to properly escape backslashes, especially in the REPLACE part. E.g.
set bindir = $program ~ "s/(.*)\\//\\1/"
The map file consists of records, separated by newline characters. Each record, in turn, consists of fields, separated by characters listed in the DELIM argument. If it contains a space character, then fields may be delimited by any amount of whitespace characters (spaces and/or tabulations). Otherwise, exactly one character delimits fields. Fields within a record are numbered starting from 1.
The map action operates as follows. First, variable expansion and backreference interpretation is performed on the KEY argument. The result will be used as actual lookup key. Then, FILE is scanned for a record whose KNth field matches the lookup key. If such a record is found, the value of its VNth field is assigned to the variable. Otherwise, if DEFAULT is supplied, it is assigned to the variable. Otherwise, the variable remains unchanged.
The following statements modify command execution environment:
Argument is a whitespace delimited list of variables to retain. Each element in the list can be either a variable name, or a shell-style globbing pattern, in which case all variables matching that pattern will be retained, or a variable name followed by an equals sign and a value, in which case it will be retained only if its actual value equals the supplied one. For example, to retain only variables with names beginning with 'LC_':
keepenv "LC_*"
For example, to modify the 'PATH' value:
setenv PATH = "$PATH:/opt/bin"
The following statements are system actions. They provide interface to the operating system.
If some limit cannot be set, execution of the rule aborts. In particular, the L limit can be regarded as a condition, rather than an action. Setting limit L5 succeeds only if no more than 5 rush instances are simultaneously running for the same user. This can be used to limit the number of simultaneously open sessions.
The use of L resource automatically enables forked mode. See the subsection Accounting and forked mode for details.
Fall-through rules are often used to set default values for subsequent rules.
GNU rush is able to operate in two modes, which we call default and forked. When operating in the default mode, the process image of rush itself is overwritten by the command being executed. Thus, when it comes to launching the requested command, the running instance of rush ceases to exist.
There is also another operation mode, which we call forked mode. When running in this mode, rush executes the requested command in a subprocess, and remains in memory supervising its execution. Once the command terminates, rush exits.
One advantage of the forked mode is that it allows you to keep accounting, i.e. to note who is doing what and to keep a history of invocations. The accounting, in turn, can be used to limit simultaneous executions of commands, as requested by the L command to limit statement (see above).
Rush can be configured to send a notification over INET or UNIX sockets, after completing user request. It is done using the following statement:
Allowed formats for URL are:
The notification protocol is based on TCPMUX (RFC 1078). After establishing connection, rush sends the rule tag followed by a CRLF pair. The rule tag acts as a service name. The remote party replies with a single character indicating positive (+) or negative (-) acknowledgment, optionally followed by a message of explanation, and terminated with a CRLF.
If positive acknowledgment is received, rush sends a single line, consisting of the user name and the executed command line, separated by a single space character. The line is terminated with a CRLF.
After sending this line, rush closes the connection.
The post-process notification feature can be used to schedule execution of some actions after certain rules.
exit 2 TEXT
In both cases the TEXT argument can be either a quoted string, or an identifier.
If it is a quoted string, it is subject to backreference interpretation and variable expansion.
If TEXT is an identifier, it must be the name of a predefined error message (see the list in the discussion of the message statement in global section, above).
Sometimes it may be necessary to allow some group of users limited access to interactive shells. GNU rush contains provisions for such usage. When it is invoked without '-c' it assumes interactive usage. In this case only rules explicitly marked as interactive are considered, the rest of rules is ignored.
Unless command line transformations are applied, interactive rule finishes by executing /bin/sh. The first word in the command line (argv[0]) is normally set to the base name of the command being executed prefixed by a minus character.
An example
rule login
interactive true
group rshell
map program /etc/rush.shell : ${user} 1 2
set [0] = ${program} ~ "s|^.*/||;s,^,-r," rule nologin
interactive true
exit You don't have interactive access to this machine.
The login rule will match interactive user requests if the user is a member of the group rshell. It looks up the shell to use for this in the file /etc/rush.shell. This map file consists of two fields, separated by a colon. If the shell is found, its base name, prefixed with -r, will be used as argv[0] (this indicates a restricted login shell). Otherwise, the trap rule nologin will be matched, which will output the given diagnostics message and terminate rush.
The following statement allow you to provide translations (localizations) for the messages in your rush configuration:
An example:
rule l10n
locale "pl_PL"
text-domain "rush-config"
fall-through
The include statement forces inclusion of the named file in that file location:
The statement is evaluated when parsing the configuration file, which means that FILE undergoes only tilde expansion: the two characters ~/ appearing at the beginning of file name are replaced with the full path name of the current user's home directory.
If FILE is a directory, that directory is searched for a file whose name coincides with the current user name. If such a file is found, it is included.
In any case, if the named file does not exist, no error is reported, and parsing of the configuration file continues.
Before including the file rush checks if it is secure, using the criteria set in the include-security statement. See its description in the global section, above.
The include statement can be used only within a rule. The included file may not contain rule and global statements.
Sergey Poznyakoff
Report bugs to <bug-rush@gnu.org.ua>.
Copyright © 2016-2019 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it. There is NO
WARRANTY, to the extent permitted by law.
July 1, 2019 | RUSH.RC |