4.2 Rule

The rule statement configures a GNU Rush 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 the rule.

The syntax of the rule statement is:

Configuration: rule tag

The tag argument is optional. If it is given, it supplies a tag for the rule, i.e. a (presumably unique) identifier, which is used to label this rule. Rush uses this tag in its diagnostic messages. For rules without explicit tag, Rush supplies a default tag, which is constructed by concatenating ‘#’ character and the ordinal number of rule in the configuration file, in decimal notation. Rule numbering begins from ‘1’.

The following sub-sections describe statements that can be used within a rule.

4.2.1 Conditions

These statements define conditions that are used to match the rule with the request. A rule may contain any number of conditions. All conditions are tested in order of their appearance in the rule and are tied together using boolean shortcut ‘and’ evaluation: if any of them yields false, the rest is not evaluated and control is transferred to the subsequent rule.

Rule Config: command regex

True, if the current command line matches regular expression regex.

For example:

 
command ^scp (-v )?-t /incoming/(alpha|ftp)

By default, POSIX extended regular expressions are used. This, however can be changed using regex statement (see section Regex).

Rule Config: match[n] regexp

True, if nth word from the command line matches regular expression regexp. Notice, that square brackets form part of the statement syntax. A special value ‘$’ can be used instead of n to denote the last word. Unless changed by previous regex statement (see section Regex), POSIX extended regular expressions are used.

The command line is split into words using the same rules as used in /bin/sh.

For example, the condition below yields true if the last argument is an absolute path name:

 
match[$] ^/.*
Rule Config: argc op num

Compare the number of command line arguments to num. The comparison operator is given by op, which can be one of the following: ‘=’ (or ‘==’), ‘!=’, ‘<’, ‘<=’, ‘>’, ‘>=’.

For example, the following condition matches if the number of arguments is less than 3:

 
argc < 3
Rule Config: uid op num

Compare current UID to num. The comparison operator is given by op, which can be one of the following: ‘=’ (‘==’), ‘!=’, ‘<’, ‘<=’, ‘>’, ‘>=’.

Rule Config: gid op num

Compare current GID to num. The comparison operator is given by op, which can be one of the following: ‘=’ (‘==’), ‘!=’, ‘<’, ‘<=’, ‘>’, ‘>=’.

Rule Config: user names

Argument is a whitespace-separated list of user names. This condition yields true, if the user name matches one of the listed names. String comparisons are case-sensitive.

Rule Config: group names

Argument is a whitespace-separated list of group names. This condition yields true, if the the name of any group the user is a member of matches one of listed names. String comparisons are case-sensitive.

For example, to match users from groups ‘admin’ and ‘root’:

 
group admin root

Each condition allows for a negated form, by placing an exclamation sign between the condition keyword and expression. For example:

command ^scp

True, if the command line begins with ‘scp’.

command ! ^scp

True if the command line does not begin with ‘scp’.

4.2.2 Transformations

Special actions that allow to rewrite command line are called transformations. GNU Rush supports five kinds of transformations: ‘set’, ‘transform’, ‘delete’, ‘map’. All of them operate on command line split into words. Additionally, ‘set’ and ‘transform’ can operate on the entire command line.

Rush performs word splitting using the same rules as sh. Transformation actions refer to words by their index. Three kinds of indexes are supported. First of all, a word may be referred to by its ordinal number in the command line. The command name itself has index ‘0’. For example, given the command line:

 
/bin/scp -t /upload

one gets:

Index Value
0 /bin/scp
1 -t
2 /upload

Negative indexes can also be used. They refer to words in the backward order, as illustrated in the following table:

Index Value
-1 /upload
-2 -t
-3 /bin/scp

Finally, the last word may be referred to as ‘$’, and the command name itself as ‘^’. There is a subtle difference between ‘0’ and ‘^’. The notation ‘^’ refers to the name of the program that rush will execute at the end of the matching rule, whereas the notation ‘0’ refers to the 0th argument that will be passed to that program (‘argv[0]’). Most of the time the two values coincide. Unless the rule modifies ‘^’, ‘0’th word will be used as the program name. There exist some cases when you need to explicitly set ‘^’. See section Interactive Access, for a possible use of this feature.

Some of the transformations implement patterns. A pattern is a string which may contain meta-variables. Before using, these meta-variables are expanded using the following rules:

Meta-variable Expansion
${user} User name
${group} Name of the user's principal group
${uid} UID
${gid} GID
${home} User's home directory
${gecos} User's GECOS field
${program} Program name (‘^’)
${command} Full command line
$0 to $9 Corresponding word from the command line
${N} Nth word (see above for the allowed values of N)

4.2.2.1 Set

The ‘set’ transformation allows to replace entire command line, or any of its arguments, with the given value.

Rule Config: set pattern

Command line is replaced with the expansion of pattern (see patterns). E.g.:

 
set /bin/echo "Command forbidden: ${command}"

As another example, the following rule uses transform to ensure that ‘/usr/bin/cvs’ binary is used:

 
rule cvs
  command ^cvs server
  set[0] /usr/bin/cvs

In versions of GNU Rush prior to 1.6, it was common to use the transform action for this purpose.

Rule Config: set[n] pattern

Replace nth argument with the expansion of pattern. Notice, that square brackets are part of the statement syntax.

See indexing, for a description of n. See patterns, for a description of pattern. E.g.:

 
set[0] /bin/echo

4.2.2.2 Delete

The ‘delete’ action deletes the given word, or range of words, from the command line. It has two forms.

Rule Config: delete[n]

Delete nth word. See indexing, for a detailed description of n and its syntax. However, see the note below.

Rule Config: delete n m

Delete words from n to m, inclusive. For example, the following action removes all arguments, except the command name:

 
delete 1 $

Neither form can be used to delete the command name, i.e. ‘[0]’ or ‘[^]’.

4.2.2.3 Transform

The transform action modifies the value of the command line, or any particular word of it, according to a sed s-expression. S-expressions are described in more detail below (see s-expression). This action has several forms.

Rule Config: transform expr

Apply expression expr to entire command line. For example, the action below adds a ‘-t’ option after the command name:

 
transform s,^[^ ]+,& -t,
Rule Config: transform pattern expr

Expand pattern as described in patterns, apply expr to the expansion, and replace the command line with the result.

Rule Config: transform[n] expr

Apply expression expr to nth word from the command line. Notice, that square brackets are part of the statement syntax. See indexing, for a detailed description of n and its syntax.

Rule Config: transform[n] pattern expr

Apply expression expr to the expanded pattern and assign the result to nth word. See patterns, for a description of patterns and their expansion. See indexing, for a detailed description of n and its syntax.

The example below replaces the 0th argument with the base name of the command, prefixed by a dash:

 
transform[0] ${^} s,.*/,-

For instance, if the command name is ‘/bin/bash’, ‘argv[0]’ will become ‘-bash’.

The transformation expression, expr, is a sed-like 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. Both regexp and replace are described in detail in The "s" Command: (sed)The "s" Command section `The `s' Command' in GNU sed.

As in sed, you can give several replace expressions, separated by a semicolon.

Supported flags are:

g

Apply the replacement to all matches to the regexp, not just the first.

i

Use case-insensitive matching

x

regexp is an extended regular expression (see Extended regular expressions: (sed)Extended regexps section `Extended regular expressions' in GNU sed).

number

Only replace the numberth match of the regexp.

Note: 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.

Any delimiter can be used in lieue of ‘/’, the only requirement being that it be used consistently throughout the expression. For example, the following two expressions are equivalent:

 
transform s/one/two/
transform s,one,two,

Changing delimiters is often useful when the regex contains slashes. For instance, it is more convenient to write s,/,-, than s/\//-/.

For example, the following rule uses transform to ensure that ‘/usr/bin/cvs’ binary is used:

 
rule cvs
  command ^cvs server
  transform[0] s|.*|/usr/bin/cvs|

The same effect can be achieved with a set statement, as shown in set-command.

As a more complex example, consider the following rule:

 
rule svn
  command ^svnserve -t
  transform s|-r *[^ ]*||;s|^svnserve |/usr/bin/svnserve -r /svnroot |

This transform expression first removes all occurrences of ‘-r’ option and its arguments from the command line, and then adds its own ‘-r’ option and replaces ‘svnserve’ with the full program file name.

4.2.2.4 Map

The ‘map’ statement uses file lookup to find a new value for the command line word.

Rule Config: map[n] file delim pattern   kn vn
Rule Config: map[n] file delim pattern   kn vn default

Arguments are:

n

Argument index, as in indexing.

file

Name of the map file. It must begin with ‘/’ or ‘~/’. Before using, the file permissions and ownership are checked using the procedure described in security checks.

delim

A string containing allowed field delimiters.

pattern

The value of the lookup key. Before using, it is expanded as described in patterns.

kn

Number of the key field in file. Fields are numbered starting from 1.

vn

Number of the value field.

default

If supplied, this value is used as a replacement value, when the key was not found in file.

The map file consists of records, separated by newline characters (in other words, a record occupies one line). Each record consists of fields, separated by delimiters, given in delim argument. If delim contains a space character, then fields may be delimited by any amount of whitespace characters (spaces and/or tabulations). Otherwise, exactly one delimiter delimits fields.

Fields are numbered starting from 1.

The map action works as follows:

  1. The pattern argument is expanded as described in patterns and the resulting value is used as lookup key.
  2. The file is scanned for a record whose knth field matches the lookup key.
  3. If such a record is found, the value of its vnth field is assigned to the nth command line word (see indexing, for a description of n).
  4. Otherwise, if default is supplied, it becomes the new value of the nth word.
  5. Otherwise, the nth word remains unchanged.

For example, suppose that the file ‘/etc/passwd.rush’ has the same syntax as the system ‘passwd’ file (see Password File: (passwd(5))passwd section `passwd' in passwd(5) man page). Then, the following statement will replace ‘argv[0]’ with the value of ‘shell’ field, using the current user name as a key:

 
map[0] /etc/passwd.rush : ${user} 1 7

See also Interactive Access, for another example of using this statement.

4.2.3 System Actions

System actions provide an interface to the operating system.

Rule Config: umask mask

Set the umask. The mask must be an octal value not greater than ‘0777’. The default umask is ‘022’.

Rule Config: chroot dir

Change the root directory to that specified in dir. This directory will be used for file names beginning with ‘/’. A tilde (‘~’) in the beginning of dir is replaced with the user's home directory.

The directory dir must be properly set up to execute the commands. For example, the following rule defines execution of sftp-server in an environment, chrooted to the user's home directory:

 
rule sftp
  command ^.*/sftp-server
  set[0] bin/sftp-server
  chroot ~

For this to work, each user's home must contain the directory ‘bin’ with a copy of ‘sftp-server’ in it, as well as all directories and files that are needed for executing it, in particular ‘lib’.

Rule Config: chdir dir

Change to the directory dir. The argument is subject to tilde-expansion (see chroot, above). If both chdir and chroot are specified, then chroot is executed first.

Rule Config: limits res

Impose limits on system resources, as defined by res. The argument consists of commands, optionally separated by any amount of whitespace. A command is a single command letter followed by a number, that specifies the limit. The command letters are case-insensitive and coincide with those used by the shell ulimit utility:

Command The limit it sets
A max address space (KB)
C max core file size (KB)
D max data size (KB)
F maximum file size (KB)
M max locked-in-memory address space (KB)
N max number of open files
R max resident set size (KB)
S max stack size (KB)
T max CPU time (MIN)
U max number of processes
L max number of logins for this user (see below)
P process priority -20..20 (negative = high priority)

For example:

 
limits T10 R20 U16 P20

If some limit cannot be set, execution of the rule aborts. In particular, ‘L’ limit can be regarded as a condition, rather than action. The setting limit Ln succeeds only if no more than n 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 section Accounting and Forked Mode, for more information about it.

4.2.4 Environment

The env action allows to modify the environment in which the program will be executed.

Rule Config: env args

Modify the environment.

Its argument is a whitespace-delimited list of specifiers. The following specifiers are understood:

- (a dash)

Clear the environment. This is understood only when used as a first word in args.

-name

Unset the environment variable name.

-name=val

Unset the environment variable name only if its value is val.

name

Retain the environment variable name.

name=value

Define environment variable name to have given value.

name+=value

Retain variable name and append value to its existing value. If no such variable is present in the environment, it is created and value is assigned to it. However, if value begins with a punctuation character, this character is removed from it before the assignment. This is convenient for using this construct with environment variables like PATH, e.g.:

 
PATH+=:/sbin

In this example, if PATH exists, ‘:/sbin’ will be appended to it. Otherwise, it will be created and ‘/sbin’ will be assigned to it.

name=+value

Retain variable name and prepend value to its existing value. If no such variable is present in the environment, it is created and value is assigned to it. However, if value ends with a punctuation character, this character is removed from it before assignment.

4.2.5 Fall-through

A fall-through rule is a special rule that does not execute the requested command. When a matching fall-through rule is encountered, rush evaluates it and continues scanning its configuration for the next matching rule. Any transformation and env actions found in a fall-through rule take effect immediately, which means that subsequent rules will see modified command line and environment. Execution of any other actions found in the fall-through rule is delayed until a usual rule is found.

A fall-through rule is declared using the following statement:

Rule Config: fall-through

Declare a fall-through rule.

Usually this statement is placed as the last statement in a rule, e.g.:

 
rule default
  umask 002
  env - HOME USERNAME PATH
  fall-through

Fall-through rules provide a way to set default values for subsequent rules. For example, any rules that follow the ‘default’ rule shown above, will inherit the umask and environment set there.

One can also use fall-through rules to “normalize” command lines. For example, consider this rule:

 
rule default
  transform[0] s|.*/||;
  fall-through

It will remove all path components from the first command line argument. As a result, all subsequent rules may expect a bare binary name as the first argument.

Yet another common use for such rules is to enable accounting (see the next subsection), or set resource limits for the rest of rules:

 
rule default
  limit l1
  fall-through

4.2.6 Accounting and Forked Mode

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 to run 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 (logins, in GNU Rush terminology), as requested by ‘L’ command to limit statement (see L limit).

The forked mode is enabled on a per-rule basis, for rules that contain either ‘L’ command in the limit statement, or ‘acct on’ command:

Rule Config: acct bool

Turn accounting mode on or off, depending on bool. The argument can be one of the following: ‘yes’, ‘on’, ‘t’, ‘true’, or ‘1’, to enable accounting, and ‘no’, ‘off’, ‘nil’, ‘false’, ‘0’, to disable it.

Notice, that there is no need in explicit acct on command, if you use limit L.

The notion ‘rule contains’, used above, means that either the rule in question contains that statement, or inherits it from one of the above fall-through rules (see section Fall-through). In fact, in most cases the accounting should affect all rules, therefore we suggest to enable it in a fall-through rule at the beginning of the configuration file, e.g.:

 
rule default
  acct on
  fall-through 

If the need be, you can disable it for some of the subsequent rules by placing acct off in it. Notice, that this will disable accounting only, the forked mode will remain in action. To disable it as well and enforce default mode for a given rule, use fork off statement:

Rule Config: fork bool

Enable or disable forked mode. This statement is mainly designed as a way of disabling the forked mode for a given rule.

Once the accounting enabled, you can view the list of currently logged in users using rushwho command (see section The rushwho utility.) and view the history of last logins using rushlast command (see section The rushlast utility.).

4.2.7 Post-process Notification

Rush can be configured to send a notification over INET or UNIX sockets, after completing user request. It is done using the post-socket statement:

Rule Config: post-socket url

Notify URL about completing the user request. This statement implies forked mode (see section Accounting and Forked Mode).

Allowed formats for url are:

inet://hostname[:port]

Connect to remote host hostname using TCP/IP. Hostname is the host name or IP address of the remote machine. Optional port specifies the port number to connect to. It can be either a decimal port number or a service name from ‘/etc/services’. If port is absent, ‘tcpmux’ (port 1) is assumed.

unix://filename
local://filename

Connect to a UNIX socket filename.

For example:

 
rule default
  post-socket inet://localhost

The GNU Rush 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, immediately followed by an optional message of explanation, 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.

See section Notification, for an example of how to use this feature.

4.2.8 Exit rule

An exit rule does not execute any commands. Instead, it writes the supplied error message to the specified file descriptor and exits immediately. An exit rule is defined using the following statement:

Rule Config: exit fd message
Rule Config: exit message

Write textual message message to a file descriptor, given by the optional argument fd. If fd is absent, ‘2’ (standard error) is used.

The message argument is subject to backslash interpretation (see backslash-interpretation).

For example (note the use of line continuation character):

 
exit \
    \r\nYou are not allowed to execute that command.\r\n\
    \r\nIf you think this is wrong, ask <foo@bar.com> for assistance.\r\n

If message begins with a ‘@’ sign, the remaining characters are treated as the name of a predefined error message (see section Error Messages). The corresponding message text is retrieved and used instead of message. For example:

 
  exit @nologin-message

If the characters after ‘@’ do not correspond to any predefefined error message name, an error of type ‘config-error’ is signalled and rush exits.

If you need to begin your exit message with a ‘@’ sign, duplicate it, as in this example:

 
  exit @@Special error message

This example will produce ‘@Special error message’.

Exit actions are useful for writing trap rules, i.e. the rules that are intended to trap incorrect or prohibited command lines and to return customized reply messages in such cases. Consider the following rule:

 
rule git
  command ^git-.+
  match[1] ^/sources/[^ ]+\.git$
  transform s|.*|/usr/bin/git-shell -c "&"|

It allows to use only those Git repositories that are located under ‘/sources’ directory(6). If a user tries to access a repository outside this root, he will be returned a default error message, saying ‘You are not permitted to execute this command’ (see section usage-error). You can, however, provide a more convenient message in this case. To do so, place the following after the ‘git’ rule:

 
rule git-trap
  command ^git-.+
  exit fatal: Use of this repository is prohibited.

This rule will trap all git invocations that do not match the ‘git’ rule.

4.2.9 Localization

GNU Rush is internationalized, which means that it is able to produce log and diagnostic messages in any language, if a corresponding translation file is provided. This file is called a localization or domain file. To find an appropriate localization file, rush uses the following parameters:

locale

Locale name is a string that describes the language, territory and optionally, the character set to use. It consists of the language (ISO 639) and country (ISO 3166) codes, separated by an underscore character, e.g. ‘en_US’ or ‘pl_PL’. If a character set is specified, its name follows the country code and is separated from it by a ‘@’ character.

There are two special locale names: ‘C’ or ‘POSIX’ mean to use the default POSIX locale, and ‘""’ (an empty string), means to use the value of the environment variable LC_ALL as the locale name.

locale_dir

Directory where localization files are located. If not specified, a predefined set of directories is searched for the matching file.

domain

Text domain defines the base name of the localization file.

Given these parameters, the name of the full pathname of the localization file is defined as:

 
locale_dir/locale/LC_MESSAGES/domain.mo

GNU Rush produces three kinds of messages:

diagnostics

These are diagnostics messages that GNU Rush produces to its log output (syslog, unless in test mode).

error messages

Messages sent to the remote party when rush is not able to execute the request (see section Error Messages).

exit messages

These are messages sent to the remote party by exit rules (see section Exit rule).

These messages use different domain names (and may use different locale directories). The diagnostics and error messages use textual domain ‘rush’. The corresponding locale directory is defined at compile time and defaults to ‘prefix/share/locale’, where prefix stands for the installation prefix, which is ‘/usr/local’, by default.

GNU Rush is shipped with several localization files, which are installed by default. As of version 1.6, these files cover the following locales:

C
POSIX

This is default domain, it is always supported and does not require any special handling. It is roughly equivalent to ‘en_US’ (English).

pl

Polish messages.

uk

Ukrainian messages.

If the localization you need is not in this list, visit http://translationproject.org/domain/rush.html. If it is not there either, consider writing it (see (gettext)Translators section `Translators' in GNU gettext utilities, for a detailed instructions on how to do that).

Exit messages use custom domain files. It is responsibility of the system administrator to provide and install such files.

4.2.9.1 Localization Directives

The following configuration directives control localization. They are available for use in rule statements:

Configuration: locale name

Sets the locale name. To specify empty locale, use ‘""’ as name (recall that empty locale name means use the value of the environment variable LC_ALL as locale name).

Configuration: locale-dir name

Sets the name of the locale directory.

Configuration: text-domain name

Sets the textual domain name.

The following configuration fragment illustrates their use:

 
rule l10n
  locale pl_PL
  text-domain rush-config
  fall-through

Different users may have different localization preferences. See per-user l10n, for a description of how to implement this.

4.2.9.2 Writing Your Localization

You need to write a localization file for your configuration script if it implements exit rules (see section Exit rule) and changes user locale (see section locale).

Preparing localization consists of three stages: extracting exit messages and forming a PO file, editing this file, compiling and installing it. The discussion below describes these stages in detail.

  1. Creating a ‘po’ file.

    A PO (Portable Object) file is a plain text file, containing original messages and their translations for a particular language. See The Format of PO Files: (gettext)PO Files section `PO Files' in GNU gettext utilities, for a description of its format.

    The script rush-po.awk serves for extracting messages from the configuration file and forming a PO file. This script is installed in the ‘prefix/share/rush’ directory(7), where prefix stands for your installation prefix.

    Supposing the package is installed in the default prefix, the following command will create a PO file from your configuration file:

     
      awk -f /usr/local/share/rush/rush-po.awk \
             /usr/local/etc/rush.rc > myconf.po
    

    Please note, that rush-po.awk does not handle include directives (see section Include). If your configuration file uses these directives, you need to specify each include file in the rush-po.awk command line, e.g.:

     
      awk -f /usr/local/share/rush/rush-po.awk \
             /usr/local/etc/rush.rc /home/*/.rush > myconf.po
    
  2. Editing the PO file

    Open the created PO file with your favorite editor and supply message translations after msgstr keywords. Although you can use any editor, capable of handling plain text files, we recommend to use GNU Emacs, which provides a special po-mode. See PO Files and PO Mode Basics: (gettext)Basics section `Basics' in GNU gettext utilities, for guidelines on editing PO files and using the po-mode.

  3. Compiling the PO file

    When ready, the PO file needs be compiled into a MO (Message Object) file, which is directly readable by rush. This is done using msgfmt utility from GNU gettext:

     
      msgfmt -o myconf.mo myconf.po
    

    See (gettext)msgfmt Invocation section `msgfmt Invocation' in GNU gettext utilities, for a detailed description of the msgfmt utility.

    After creating the MO file, copy it into appropriate directory. It is important that the installed MO file uses the naming scheme described in localization file naming.

Footnotes

(6)

See section git, for a better way to handle Git accesses.

(7)

To be precise, it is installed in ‘dataroot/rush’, where dataroot is a directory for read-only architecture-independent data, which is set by the ‘--datarootdir’ option to configure. Unless that option is used, this directory defaults to ‘prefix/share/rush