The sudoers file is composed of two types of entries: aliases
(basically variables) and user specifications (which specify who
may run what).
When multiple entries match for a user, they are applied in order.
Where there are multiple matches, the last match is used (which is
not necessarily the most specific match).
The sudoers file grammar will be described below in Extended
Backus-Naur Form (EBNF). Don't despair if you are unfamiliar with
EBNF; it is fairly simple, and the definitions below are annotated.
Quick guide to EBNF
EBNF is a concise and exact way of describing the grammar of a
language. Each EBNF definition is made up of production rules.
E.g.,
symbol ::= definition | alternate1 | alternate2 ...
Each production rule references others and thus makes up a grammar
for the language. EBNF also contains the following operators,
which many readers will recognize from regular expressions. Do
not, however, confuse them with 'wildcard' characters, which have
different meanings.
? Means that the preceding symbol (or group of symbols) is
optional. That is, it may appear once or not at all.
* Means that the preceding symbol (or group of symbols) may
appear zero or more times.
+ Means that the preceding symbol (or group of symbols) may
appear one or more times.
Parentheses may be used to group symbols together. For clarity, we
will use single quotes ('') to designate what is a verbatim
character string (as opposed to a symbol name).
Aliases
There are four kinds of aliases: User_Alias, Runas_Alias,
Host_Alias and Cmnd_Alias. Beginning with sudo
1.9.0, Cmd_Alias
may be used in place of Cmnd_Alias if desired.
Alias ::= 'User_Alias' User_Alias_Spec (':' User_Alias_Spec)* |
'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
'Host_Alias' Host_Alias_Spec (':' Host_Alias_Spec)* |
'Cmnd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
'Cmd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
User_Alias ::= NAME
User_Alias_Spec ::= User_Alias '=' User_List
Runas_Alias ::= NAME
Runas_Alias_Spec ::= Runas_Alias '=' Runas_List
Host_Alias ::= NAME
Host_Alias_Spec ::= Host_Alias '=' Host_List
Cmnd_Alias ::= NAME
Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
NAME ::= [A-Z]([A-Z][0-9]_)*
Each alias definition is of the form
Alias_Type NAME = item1, item2, ...
where Alias_Type is one of User_Alias, Runas_Alias, Host_Alias, or
Cmnd_Alias. A NAME is a string of uppercase letters, numbers, and
underscore characters ('_'). A NAME must
start with an uppercase
letter. It is possible to put several alias definitions of the
same type on a single line, joined by a colon (':'). E.g.,
Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
It is a syntax error to redefine an existing alias. It is possible
to use the same name for aliases of different types, but this is
not recommended.
The definitions of what constitutes a valid alias member follow.
User_List ::= User |
User ',' User_List
User ::= '!'* user name |
'!'* #uid |
'!'* %group |
'!'* %#gid |
'!'* +netgroup |
'!'* %:nonunix_group |
'!'* %:#nonunix_gid |
'!'* User_Alias
A User_List is made up of one or more user names, user-IDs
(prefixed with '#'), system group names and IDs (prefixed with '%'
and '%#' respectively), netgroups (prefixed with '+'), non-Unix
group names and IDs (prefixed with '%:' and '%:#' respectively) and
User_Aliases. Each list item may be prefixed with zero or more '!'
operators. An odd number of '!' operators negate the value of the
item; an even number just cancel each other out. User netgroups
are matched using the user and domain members only; the host member
is not used when matching.
A user name, uid, group, gid, netgroup, nonunix_group or
nonunix_gid may be enclosed in double quotes to avoid the need for
escaping special characters. Alternately, special characters may
be specified in escaped hex mode, e.g., \x20 for space. When using
double quotes, any prefix characters must be included inside the
quotes.
The actual nonunix_group and nonunix_gid syntax depends on the
underlying group provider plugin. For instance, the QAS AD plugin
supports the following formats:
•
Group in the same domain: "%:Group Name"
•
Group in any domain: "%:Group Name@FULLY.QUALIFIED.DOMAIN"
•
Group SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
See GROUP PROVIDER PLUGINS for more information.
Note that quotes around group names are optional. Unquoted strings
must use a backslash ('\') to escape spaces and special characters.
See Other special characters and reserved words for a list of
characters that need to be escaped.
Runas_List ::= Runas_Member |
Runas_Member ',' Runas_List
Runas_Member ::= '!'* user name |
'!'* #uid |
'!'* %group |
'!'* %#gid |
'!'* %:nonunix_group |
'!'* %:#nonunix_gid |
'!'* +netgroup |
'!'* Runas_Alias
A Runas_List is similar to a User_List except that instead of
User_Aliases it can contain Runas_Aliases. Note that user names
and groups are matched as strings. In other words, two users
(groups) with the same user (group) ID are considered to be
distinct. If you wish to match all user names with the same user-
ID (e.g., root and toor), you can use a user-ID instead of a name
(#0 in the example given). Note that the user-ID or group-ID
specified in a Runas_Member need not be listed in the password or
group database.
Host_List ::= Host |
Host ',' Host_List
Host ::= '!'* host name |
'!'* ip_addr |
'!'* network(/netmask)? |
'!'* +netgroup |
'!'* Host_Alias
A Host_List is made up of one or more host names, IP addresses,
network numbers, netgroups (prefixed with '+') and other aliases.
Again, the value of an item may be negated with the '!' operator.
Host netgroups are matched using the host (both qualified and
unqualified) and domain members only; the user member is not used
when matching. If you specify a network number without a netmask,
sudo
will query each of the local host's network interfaces and, if
the network number corresponds to one of the hosts's network
interfaces, will use the netmask of that interface. The netmask
may be specified either in standard IP address notation (e.g.,
255.255.255.0 or ffff:ffff:ffff:ffff::), or CIDR notation (number
of bits, e.g., 24 or 64). A host name may include shell-style
wildcards (see the Wildcards section below), but unless the host
name command on your machine returns the fully qualified host name,
you'll need to use the fqdn flag for wildcards to be useful. Note
that sudo
only inspects actual network interfaces; this means that
IP address 127.0.0.1 (localhost) will never match. Also, the host
name 'localhost' will only match if that is the actual host name,
which is usually only the case for non-networked systems.
digest ::= [A-Fa-f0-9]+ |
[A-Za-z0-9\+/=]+
Digest_Spec ::= "sha224" ':' digest |
"sha256" ':' digest |
"sha384" ':' digest |
"sha512" ':' digest
Digest_List ::= Digest_Spec |
Digest_Spec ',' Digest_List
Cmnd_List ::= Cmnd |
Cmnd ',' Cmnd_List
command name ::= file name |
file name args |
file name '""'
Edit_Spec ::= "sudoedit" file name+
Cmnd ::= Digest_List? '!'* command name |
'!'* directory |
'!'* Edit_Spec |
'!'* Cmnd_Alias
A Cmnd_List is a list of one or more command names, directories,
and other aliases. A command name is a fully qualified file name
which may include shell-style wildcards (see the Wildcards section
below). A simple file name allows the user to run the command with
any arguments they wish. However, you may also specify command
line arguments (including wildcards). Alternately, you can specify
"" to indicate that the command may only be run without
command
line arguments. A directory is a fully qualified path name ending
in a '/'. When you specify a directory in a Cmnd_List, the user
will be able to run any file within that directory (but not in any
sub-directories therein).
If a Cmnd has associated command line arguments, then the arguments
in the Cmnd must match exactly those given by the user on the
command line (or match the wildcards if there are any). Note that
the following characters must be escaped with a '\' if they are
used in command arguments: ',', ':', '=', '\'. The built-in
command 'sudoedit' is used to permit a user to run sudo
with the -e
option (or as sudoedit
). It may take command line arguments just
as a normal command does. Note that 'sudoedit' is a command built
into sudo
itself and must be specified in the sudoers file without
a leading path. If a leading path is present, for example
/usr/bin/sudoedit, the path name will be silently converted to
'sudoedit'. A fully-qualified path for sudoedit
is treated as an
error by visudo
.
A command name may be preceded by a Digest_List, a comma-separated
list of one or more Digest_Spec entries. If a Digest_List is
present, the command will only match successfully if it can be
verified using one of the SHA-2 digests in the list. Starting with
version 1.9.0, the ALL
reserved word can be used in conjunction
with a Digest_List. The following digest formats are supported:
sha224, sha256, sha384 and sha512. The string may be specified in
either hex or base64 format (base64 is more compact). There are
several utilities capable of generating SHA-2 digests in hex format
such as openssl, shasum, sha224sum, sha256sum, sha384sum,
sha512sum.
For example, using openssl:
$ openssl dgst -sha224 /bin/ls
SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
It is also possible to use openssl to generate base64 output:
$ openssl dgst -binary -sha224 /bin/ls | openssl base64
EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
Warning, if the user has write access to the command itself
(directly or via a sudo
command), it may be possible for the user
to replace the command after the digest check has been performed
but before the command is executed. A similar race condition
exists on systems that lack the fexecve
() system call when the
directory in which the command is located is writable by the user.
See the description of the fdexec setting for more information on
how sudo
executes commands that have an associated digest.
Command digests are only supported by version 1.8.7 or higher.
Defaults
Certain configuration options may be changed from their default
values at run-time via one or more Default_Entry lines. These may
affect all users on any host, all users on a specific host, a
specific user, a specific command, or commands being run as a
specific user. Note that per-command entries may not include
command line arguments. If you need to specify arguments, define a
Cmnd_Alias and reference that instead.
Default_Type ::= 'Defaults' |
'Defaults' '@' Host_List |
'Defaults' ':' User_List |
'Defaults' '!' Cmnd_List |
'Defaults' '>' Runas_List
Default_Entry ::= Default_Type Parameter_List
Parameter_List ::= Parameter |
Parameter ',' Parameter_List
Parameter ::= Parameter '=' Value |
Parameter '+=' Value |
Parameter '-=' Value |
'!'* Parameter
Parameters may be flags
, integer
values, strings
, or lists
. Flags
are implicitly boolean and can be turned off via the '!' operator.
Some integer, string and list parameters may also be used in a
boolean context to disable them. Values may be enclosed in double
quotes ("") when they contain multiple words. Special characters
may be escaped with a backslash ('\').
To include a literal backslash character in a command line argument
you must escape the backslash twice. For example, to match '\n' as
part of a command line argument, you must use '\\\\n' in the
sudoers file. This is due to there being two levels of escaping,
one in the sudoers parser itself and another when command line
arguments are matched by the fnmatch(3) function.
Lists have two additional assignment operators, += and -=. These
operators are used to add to and delete from a list respectively.
It is not an error to use the -= operator to remove an element that
does not exist in a list.
Defaults entries are parsed in the following order: generic, host,
user and runas Defaults first, then command defaults. If there are
multiple Defaults settings of the same type, the last matching
setting is used. The following Defaults settings are parsed before
all others since they may affect subsequent entries: fqdn,
group_plugin, runas_default, sudoers_locale.
See SUDOERS OPTIONS for a list of supported Defaults parameters.
User specification
User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
(':' Host_List '=' Cmnd_Spec_List)*
Cmnd_Spec_List ::= Cmnd_Spec |
Cmnd_Spec ',' Cmnd_Spec_List
Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd
Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
Option_Spec ::= (Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
Timeout_Spec ::= 'TIMEOUT=timeout'
Chdir_Spec ::= 'CWD=directory'
Chroot_Spec ::= 'CHROOT=directory'
Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'INTERCEPT:' |
'NOINTERCEPT:' | 'PASSWD:' | 'NOPASSWD:' | 'SETENV:' |
'NOSETENV:')
A user specification
determines which commands a user may run (and
as what user) on specified hosts. By default, commands are run as
root
, but this can be changed on a per-command basis.
The basic structure of a user specification is 'who where =
(as_whom) what'. Let's break that down into its constituent parts:
Runas_Spec
A Runas_Spec determines the user and/or the group that a command
may be run as. A fully-specified Runas_Spec consists of two
Runas_Lists (as defined above) separated by a colon (':') and
enclosed in a set of parentheses. The first Runas_List indicates
which users the command may be run as via the -u
option. The
second defines a list of groups that may be specified via the -g
option (in addition to any of the target user's groups). If both
Runas_Lists are specified, the command may be run with any
combination of users and groups listed in their respective
Runas_Lists. If only the first is specified, the command may be run
as any user in the list and, optionally, with any group the target
user belongs to. If the first Runas_List is empty but the second
is specified, the command may be run as the invoking user with the
group set to any listed in the Runas_List. If both Runas_Lists are
empty, the command may only be run as the invoking user and the
group, if specified, must be one that the invoking user is a member
of. If no Runas_Spec is specified, the command may only be run as
root
and the group, if specified, must be one that root
is a member
of.
A Runas_Spec sets the default for the commands that follow it.
What this means is that for the entry:
dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
The user dgb
may run /bin/ls, /bin/kill, and /usr/bin/lprm on the
host boulder—but only as operator
. E.g.,
$ sudo -u operator /bin/ls
It is also possible to override a Runas_Spec later on in an entry.
If we modify the entry like so:
dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
Then user dgb
is now allowed to run /bin/ls as operator
, but
/bin/kill and /usr/bin/lprm as root
.
We can extend this to allow dgb
to run /bin/ls with either the user
or group set to operator
:
dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill,\
/usr/bin/lprm
Note that while the group portion of the Runas_Spec permits the
user to run as command with that group, it does not force the user
to do so. If no group is specified on the command line, the
command will run with the group listed in the target user's
password database entry. The following would all be permitted by
the sudoers entry above:
$ sudo -u operator /bin/ls
$ sudo -u operator -g operator /bin/ls
$ sudo -g operator /bin/ls
In the following example, user tcm
may run commands that access a
modem device file with the dialer group.
tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu,\
/usr/local/bin/minicom
Note that in this example only the group will be set, the command
still runs as user tcm
. E.g.
$ sudo -g dialer /usr/bin/cu
Multiple users and groups may be present in a Runas_Spec, in which
case the user may select any combination of users and groups via
the -u
and -g
options. In this example:
alan ALL = (root, bin : operator, system) ALL
user alan
may run any command as either user root or bin,
optionally setting the group to operator or system.
Option_Spec
A Cmnd may have zero or more options associated with it. Options
may consist of start and/or end dates and command timeouts. Once
an option is set for a Cmnd, subsequent Cmnds in the
Cmnd_Spec_List, inherit that option unless it is overridden by
another option. Note that the option names are reserved words in
sudoers. This means that none of the valid option names (see
below) can be used when declaring an alias.
Date_Spec
sudoers
rules can be specified with a start and end date via the
NOTBEFORE and NOTAFTER settings. The time stamp must be specified
in Generalized Time as defined by RFC 4517. The format is
effectively yyyymmddHHMMSSZ where the minutes and seconds are
optional. The 'Z' suffix indicates that the time stamp is in
Coordinated Universal Time (UTC). It is also possible to specify a
timezone offset from UTC in hours and minutes instead of a 'Z'.
For example, '-0500' would correspond to Eastern Standard time in
the US. As an extension, if no 'Z' or timezone offset is
specified, local time will be used.
The following are all valid time stamps:
20170214083000Z
2017021408Z
20160315220000-0500
20151201235900
Timeout_Spec
A command may have a timeout associated with it. If the timeout
expires before the command has exited, the command will be
terminated. The timeout may be specified in combinations of days,
hours, minutes and seconds with a single-letter case-insensitive
suffix that indicates the unit of time. For example, a timeout of
7 days, 8 hours, 30 minutes and 10 seconds would be written as
7d8h30m10s. If a number is specified without a unit, seconds are
assumed. Any of the days, minutes, hours or seconds may be
omitted. The order must be from largest to smallest unit and a
unit may not be specified more than once.
The following are all valid timeout values: 7d8h30m10s, 14d, 8h30m,
600s, 3600. The following are invalid timeout values: 12m2w1d,
30s10m4h, 1d2d3h.
This setting is only supported by version 1.8.20 or higher.
Chdir_Spec
The working directory that the command will be run in can be
specified using the CWD setting. The directory must be a fully-
qualified path name beginning with a '/' or '~' character, or the
special value '*'. A value of '*' indicates that the user may
specify the working directory by running sudo
with the -D
option.
By default, commands are run from the invoking user's current
working directory, unless the -i
option is given. Path names of
the form ~user/path/name are interpreted as being relative to the
named user's home directory. If the user name is omitted, the path
will be relative to the runas user's home directory.
This setting is only supported by version 1.9.3 or higher.
Chroot_Spec
The root directory that the command will be run in can be specified
using the CHROOT setting. The directory must be a fully-qualified
path name beginning with a '/' or '~' character, or the special
value '*'. A value of '*' indicates that the user may specify the
root directory by running sudo
with the -R
option. This setting
can be used to run the command in a chroot(2) 'sandbox' similar to
the chroot(8) utility. Path names of the form ~user/path/name are
interpreted as being relative to the named user's home directory.
If the user name is omitted, the path will be relative to the runas
user's home directory.
This setting is only supported by version 1.9.3 or higher.
Tag_Spec
A command may have zero or more tags associated with it. The
following tag values are supported: EXEC, NOEXEC, FOLLOW, NOFOLLOW,
LOG_INPUT, NOLOG_INPUT, LOG_OUTPUT, NOLOG_OUTPUT, MAIL, NOMAIL,
INTERCEPT, NOINTERCEPT, PASSWD, NOPASSWD, SETENV, and NOSETENV.
Once a tag is set on a Cmnd, subsequent Cmnds in the
Cmnd_Spec_List, inherit the tag unless it is overridden by the
opposite tag (in other words, PASSWD overrides NOPASSWD and NOEXEC
overrides EXEC).
EXEC and NOEXEC
If sudo
has been compiled with noexec support and the underlying
operating system supports it, the NOEXEC tag can be used to
prevent a dynamically-linked executable from running further
commands itself.
In the following example, user aaron
may run /usr/bin/more and
/usr/bin/vi but shell escapes will be disabled.
aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
See the Preventing shell escapes section below for more details
on how NOEXEC works and whether or not it will work on your
system.
FOLLOW and NOFOLLOW Starting with version 1.8.15, sudoedit
will not
open a file that is a symbolic link unless the sudoedit_follow
flag is enabled. The FOLLOW and NOFOLLOW tags override the value
of sudoedit_follow and can be used to permit (or deny) the
editing of symbolic links on a per-command basis. These tags are
only effective for the sudoedit command and are ignored for all
other commands.
LOG_INPUT and NOLOG_INPUT
These tags override the value of the log_input flag on a per-
command basis. For more information, see the description of
log_input in the SUDOERS OPTIONS section below.
LOG_OUTPUT and NOLOG_OUTPUT
These tags override the value of the log_output flag on a per-
command basis. For more information, see the description of
log_output in the SUDOERS OPTIONS section below.
MAIL and NOMAIL
These tags provide fine-grained control over whether mail will be
sent when a user runs a command by overriding the value of the
mail_all_cmnds flag on a per-command basis. They have no effect
when sudo
is run with the -l
or -v
options. A NOMAIL tag will
also override the mail_always and mail_no_perms options. For
more information, see the descriptions of mail_all_cmnds,
mail_always, and mail_no_perms in the SUDOERS OPTIONS section
below.
PASSWD and NOPASSWD
By default, sudo
requires that a user authenticate him or herself
before running a command. This behavior can be modified via the
NOPASSWD tag. Like a Runas_Spec, the NOPASSWD tag sets a default
for the commands that follow it in the Cmnd_Spec_List.
Conversely, the PASSWD tag can be used to reverse things. For
example:
ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
would allow the user ray
to run /bin/kill, /bin/ls, and
/usr/bin/lprm as root
on the machine 'rushmore' without
authenticating himself. If we only want ray
to be able to run
/bin/kill without a password the entry would be:
ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
Note, however, that the PASSWD tag has no effect on users who are
in the group specified by the exempt_group setting.
By default, if the NOPASSWD tag is applied to any of a user's
entries for the current host, the user will be able to run 'sudo
-l' without a password. Additionally, a user may only run 'sudo
-v' without a password if all of the user's entries for the
current host have the NOPASSWD tag. This behavior may be
overridden via the verifypw and listpw options.
SETENV and NOSETENV
These tags override the value of the setenv flag on a per-command
basis. Note that if SETENV has been set for a command, the user
may disable the env_reset flag from the command line via the -E
option. Additionally, environment variables set on the command
line are not subject to the restrictions imposed by env_check,
env_delete, or env_keep. As such, only trusted users should be
allowed to set variables in this manner. If the command matched
is ALL
, the SETENV tag is implied for that command; this default
may be overridden by use of the NOSETENV tag.
INTERCEPT and NOINTERCEPT
If sudo
has been compiled with intercept support and the
underlying operating system supports it, the INTERCEPT tag can be
used to cause programs spawned by a command to be validated
against sudoers and logged just like they would be if run through
sudo
directly. This is useful in conjunction with commands that
allow shell escapes such as editors, shells and paginators.
In the following example, user chuck
may run any command on the
machine 'research' in intercept mode.
chuck research = INTERCEPT: ALL
See the Preventing shell escapes section below for more details
on how INTERCEPT works and whether or not it will work on your
system.
Wildcards
sudo
allows shell-style wildcards (aka meta or glob characters) to
be used in host names, path names and command line arguments in the
sudoers file. Wildcard matching is done via the glob(3) and
fnmatch(3) functions as specified by IEEE Std 1003.1 ('POSIX.1').
* Matches any set of zero or more characters (including
white space).
? Matches any single character (including white space).
[...] Matches any character in the specified range.
[!...] Matches any character not in the specified range.
\x For any character 'x', evaluates to 'x'. This is used to
escape special characters such as: '*', '?', '[', and
']'.
Note that these are not regular expressions.
Unlike a regular
expression there is no way to match one or more characters within a
range.
Character classes may be used if your system's glob(3) and
fnmatch(3) functions support them. However, because the ':'
character has special meaning in sudoers, it must be escaped. For
example:
/bin/ls [[\:alpha\:]]*
Would match any file name beginning with a letter.
Note that a forward slash ('/') will not be matched by wildcards
used in the file name portion of the command. This is to make a
path like:
/usr/bin/*
match /usr/bin/who but not /usr/bin/X11/xterm.
When matching the command line arguments, however, a slash does get
matched by wildcards since command line arguments may contain
arbitrary strings and not just path names.
Wildcards in command line arguments should be used with care.
Command line arguments are matched as a single, concatenated
string. This mean a wildcard character such as '?' or '*' will
match across word boundaries, which may be unexpected. For
example, while a sudoers entry like:
%operator ALL = /bin/cat /var/log/messages*
will allow command like:
$ sudo cat /var/log/messages.1
It will also allow:
$ sudo cat /var/log/messages /etc/shadow
which is probably not what was intended. In most cases it is
better to do command line processing outside of the sudoers file in
a scripting language.
Exceptions to wildcard rules
The following exceptions apply to the above rules:
"" If the empty string "" is the only command line argument
in the sudoers file entry it means that command is not
allowed to be run with any arguments.
sudoedit Command line arguments to the sudoedit built-in command
should always be path names, so a forward slash ('/')
will not be matched by a wildcard.
Including other files from within sudoers
It is possible to include other sudoers files from within the
sudoers file currently being parsed using the @include and
@includedir directives. For compatibility with sudo versions prior
to 1.9.1, #include and #includedir are also accepted.
An include file can be used, for example, to keep a site-wide
sudoers file in addition to a local, per-machine file. For the
sake of this example the site-wide sudoers file will be
/etc/sudoers and the per-machine one will be /etc/sudoers.local.
To include /etc/sudoers.local from within /etc/sudoers one would
use the following line in /etc/sudoers:
@include /etc/sudoers.local
When sudo
reaches this line it will suspend processing of the
current file (/etc/sudoers) and switch to /etc/sudoers.local. Upon
reaching the end of /etc/sudoers.local, the rest of /etc/sudoers
will be processed. Files that are included may themselves include
other files. A hard limit of 128 nested include files is enforced
to prevent include file loops.
The path to the include file may contain white space if it is
escaped with a backslash ('\'). Alternately, the entire path may
be enclosed in double quotes (""), in which case no escaping is
necessary. To include a literal backslash in the path, '\\' should
be used.
If the path to the include file is not fully-qualified (does not
begin with a '/'), it must be located in the same directory as the
sudoers file it was included from. For example, if /etc/sudoers
contains the line:
@include sudoers.local
the file that will be included is /etc/sudoers.local.
The file name may also include the %h escape, signifying the short
form of the host name. In other words, if the machine's host name
is 'xerxes', then
@include /etc/sudoers.%h
will cause sudo
to include the file /etc/sudoers.xerxes.
The @includedir directive can be used to create a sudoers.d
directory that the system package manager can drop sudoers file
rules into as part of package installation. For example, given:
@includedir /etc/sudoers.d
sudo
will suspend processing of the current file and read each file
in /etc/sudoers.d, skipping file names that end in '~' or contain a
'.' character to avoid causing problems with package manager or
editor temporary/backup files. Files are parsed in sorted lexical
order. That is, /etc/sudoers.d/01_first will be parsed before
/etc/sudoers.d/10_second. Be aware that because the sorting is
lexical, not numeric, /etc/sudoers.d/1_whoops would be loaded after
/etc/sudoers.d/10_second. Using a consistent number of leading
zeroes in the file names can be used to avoid such problems. After
parsing the files in the directory, control returns to the file
that contained the @includedir directive.
Note that unlike files included via @include, visudo
will not edit
the files in a @includedir directory unless one of them contains a
syntax error. It is still possible to run visudo
with the -f
flag
to edit the files directly, but this will not catch the
redefinition of an alias that is also present in a different file.
Other special characters and reserved words
The pound sign ('#') is used to indicate a comment (unless it is
part of a #include directive or unless it occurs in the context of
a user name and is followed by one or more digits, in which case it
is treated as a user-ID). Both the comment character and any text
after it, up to the end of the line, are ignored.
The reserved word ALL
is a built-in alias that always causes a
match to succeed. It can be used wherever one might otherwise use
a Cmnd_Alias, User_Alias, Runas_Alias, or Host_Alias. Attempting
to define an alias named ALL
will result in a syntax error. Please
note that using ALL
can be dangerous since in a command context, it
allows the user to run any command on the system.
The following option names permitted in an Option_Spec are also
considered reserved words: CHROOT, TIMEOUT, CWD, NOTBEFORE and
NOTAFTER. Attempting to define an alias with the same name as one
of the options will result in a syntax error.
An exclamation point ('!') can be used as a logical not operator in
a list or alias as well as in front of a Cmnd. This allows one to
exclude certain values. For the '!' operator to be effective,
there must be something for it to exclude. For example, to match
all users except for root one would use:
ALL,!root
If the ALL
, is omitted, as in:
!root
it would explicitly deny root but not match any other users. This
is different from a true 'negation' operator.
Note, however, that using a '!' in conjunction with the built-in
ALL
alias to allow a user to run 'all but a few' commands rarely
works as intended (see SECURITY NOTES below).
Long lines can be continued with a backslash ('\') as the last
character on the line.
White space between elements in a list as well as special syntactic
characters in a User Specification ('=', ':', '(', ')') is
optional.
The following characters must be escaped with a backslash ('\')
when used as part of a word (e.g., a user name or host name): '!',
'=', ':', ',', '(', ')', '\'.