version 1.1.1.3, 2013/10/14 07:56:34
|
version 1.1.1.4, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
.\" |
.\" |
.\" Copyright (c) 1994-1996, 1998-2005, 2007-2013 | .\" Copyright (c) 1994-1996, 1998-2005, 2007-2014 |
.\" Todd C. Miller <Todd.Miller@courtesan.com> |
.\" Todd C. Miller <Todd.Miller@courtesan.com> |
.\" |
.\" |
.\" Permission to use, copy, modify, and distribute this software for any |
.\" Permission to use, copy, modify, and distribute this software for any |
Line 19
|
Line 19
|
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force |
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force |
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. |
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. |
.\" |
.\" |
.Dd August 31, 2013 | .Dd February 15, 2014 |
.Dt SUDOERS @mansectform@ |
.Dt SUDOERS @mansectform@ |
.Os Sudo @PACKAGE_VERSION@ |
.Os Sudo @PACKAGE_VERSION@ |
.Sh NAME |
.Sh NAME |
Line 194 lookup is still done for root, not the user specified
|
Line 194 lookup is still done for root, not the user specified
|
.Ev SUDO_USER . |
.Ev SUDO_USER . |
.Pp |
.Pp |
.Em sudoers |
.Em sudoers |
uses time stamp files for credential caching. | uses per-user time stamp files for credential caching. |
Once a | Once a user has been authenticated, a record is written |
user has been authenticated, the time stamp is updated and the user | containing the uid that was used to authenticate, the |
may then use sudo without a password for a short period of time | terminal session ID, and a time stamp |
| (using a monotonic clock if one is available). |
| The user may then use |
| .Nm sudo |
| without a password for a short period of time |
.Po |
.Po |
.Li @timeout@ |
.Li @timeout@ |
minutes unless overridden by the |
minutes unless overridden by the |
Line 206 option
|
Line 210 option
|
.Pc . |
.Pc . |
By default, |
By default, |
.Em sudoers |
.Em sudoers |
uses a tty-based time stamp which means that | uses a separate record for each tty, which means that |
there is a separate time stamp for each of a user's login sessions. | a user's login sessions are authenticated separately. |
The |
The |
.Em tty_tickets |
.Em tty_tickets |
option can be disabled to force the use of a |
option can be disabled to force the use of a |
Line 344 and, as such, it is not possible for
|
Line 348 and, as such, it is not possible for
|
to preserve them. |
to preserve them. |
.Pp |
.Pp |
As a special case, if |
As a special case, if |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Fl i |
.Fl i |
option (initial login) is |
option (initial login) is |
specified, |
specified, |
Line 529 non-Unix group names and IDs (prefixed with
|
Line 533 non-Unix group names and IDs (prefixed with
|
and |
and |
.Ql %:# |
.Ql %:# |
respectively) and |
respectively) and |
.Li User_Alias Ns No es. | .Li User_Alias Ns es. |
Each list item may be prefixed with zero or more |
Each list item may be prefixed with zero or more |
.Ql \&! |
.Ql \&! |
operators. |
operators. |
Line 603 is similar to a
|
Line 607 is similar to a
|
.Li User_List |
.Li User_List |
except that instead |
except that instead |
of |
of |
.Li User_Alias Ns No es | .Li User_Alias Ns es |
it can contain |
it can contain |
.Li Runas_Alias Ns No es . | .Li Runas_Alias Ns es . |
Note that |
Note that |
user names and groups are matched as strings. |
user names and groups are matched as strings. |
In other words, two |
In other words, two |
Line 871 may be run as.
|
Line 875 may be run as.
|
A fully-specified |
A fully-specified |
.Li Runas_Spec |
.Li Runas_Spec |
consists of two |
consists of two |
.Li Runas_List Ns No s | .Li Runas_List Ns s |
(as defined above) separated by a colon |
(as defined above) separated by a colon |
.Pq Ql :\& |
.Pq Ql :\& |
and enclosed in a set of parentheses. |
and enclosed in a set of parentheses. |
Line 879 The first
|
Line 883 The first
|
.Li Runas_List |
.Li Runas_List |
indicates |
indicates |
which users the command may be run as via |
which users the command may be run as via |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Fl u |
.Fl u |
option. |
option. |
The second defines a list of groups that can be specified via |
The second defines a list of groups that can be specified via |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Fl g |
.Fl g |
option. |
option. |
If both |
If both |
.Li Runas_List Ns No s | .Li Runas_List Ns s |
are specified, the command may be run with any combination of users |
are specified, the command may be run with any combination of users |
and groups listed in their respective |
and groups listed in their respective |
.Li Runas_List Ns No s. | .Li Runas_List Ns s. |
If only the first is specified, the command may be run as any user |
If only the first is specified, the command may be run as any user |
in the list but no |
in the list but no |
.Fl g |
.Fl g |
Line 903 second is specified, the command may be run as the inv
|
Line 907 second is specified, the command may be run as the inv
|
with the group set to any listed in the |
with the group set to any listed in the |
.Li Runas_List . |
.Li Runas_List . |
If both |
If both |
.Li Runas_List Ns No s | .Li Runas_List Ns s |
are empty, the command may only be run as the invoking user. |
are empty, the command may only be run as the invoking user. |
If no |
If no |
.Li Runas_Spec |
.Li Runas_Spec |
Line 926 may run
|
Line 930 may run
|
.Pa /bin/ls , |
.Pa /bin/ls , |
.Pa /bin/kill , |
.Pa /bin/kill , |
and |
and |
.Pa /usr/bin/lprm Ns No \(em Ns but | .Pa /usr/bin/lprm Ns \(em Ns but |
only as |
only as |
.Sy operator . |
.Sy operator . |
E.g., |
E.g., |
Line 1083 and
|
Line 1087 and
|
Once a tag is set on a |
Once a tag is set on a |
.Li Cmnd , |
.Li Cmnd , |
subsequent |
subsequent |
.Li Cmnd Ns No s | .Li Cmnd Ns s |
in the |
in the |
.Li Cmnd_Spec_List , |
.Li Cmnd_Spec_List , |
inherit the tag unless it is overridden by the opposite tag (in other words, |
inherit the tag unless it is overridden by the opposite tag (in other words, |
Line 1289 it must be
|
Line 1293 it must be
|
escaped. |
escaped. |
For example: |
For example: |
.Bd -literal -offset 4n |
.Bd -literal -offset 4n |
/bin/ls [[\:alpha\:]]* | /bin/ls [[:\&alpha:\&]]* |
.Ed |
.Ed |
.Pp |
.Pp |
Would match any file name beginning with a letter. |
Would match any file name beginning with a letter. |
Line 1575 when used as part of a word (e.g.\& a user name or hos
|
Line 1579 when used as part of a word (e.g.\& a user name or hos
|
.Ql )\& , |
.Ql )\& , |
.Ql \e . |
.Ql \e . |
.Sh SUDOERS OPTIONS |
.Sh SUDOERS OPTIONS |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
behavior can be modified by |
behavior can be modified by |
.Li Default_Entry |
.Li Default_Entry |
lines, as explained earlier. |
lines, as explained earlier. |
Line 1624 This flag is
|
Line 1628 This flag is
|
by default. |
by default. |
.It closefrom_override |
.It closefrom_override |
If set, the user may use |
If set, the user may use |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Fl C |
.Fl C |
option which overrides the default starting point at which |
option which overrides the default starting point at which |
.Nm sudo |
.Nm sudo |
Line 1645 by default when
|
Line 1649 by default when
|
is compiled with |
is compiled with |
.Sy zlib |
.Sy zlib |
support. |
support. |
|
.It use_netgroups |
|
If set, netgroups (prefixed with |
|
.Ql + ) , |
|
may be used in place of a user or host. |
|
For LDAP-based sudoers, netgroup support requires an expensive |
|
substring match on the server. |
|
If netgroups are not needed, this option can be disabled to reduce the |
|
load on the LDAP server. |
|
This flag is |
|
.Em on |
|
by default. |
.It exec_background |
.It exec_background |
By default, |
By default, |
.Nm sudo |
.Nm sudo |
Line 1725 if they match a value specified in
|
Line 1740 if they match a value specified in
|
.Li editor . |
.Li editor . |
This flag is |
This flag is |
.Em @env_editor@ |
.Em @env_editor@ |
by | by default. |
default. | |
.It env_reset |
.It env_reset |
If set, |
If set, |
.Nm sudo |
.Nm sudo |
Line 1826 If the system is configured to use the
|
Line 1840 If the system is configured to use the
|
file in preference to DNS, the |
file in preference to DNS, the |
.Dq canonical |
.Dq canonical |
host name may not be fully-qualified. |
host name may not be fully-qualified. |
The order that sources are queried for hosts name resolution | The order that sources are queried for host name resolution |
is usually specified in the |
is usually specified in the |
.Pa @nsswitch_conf@ , |
.Pa @nsswitch_conf@ , |
.Pa @netsvc_conf@ , |
.Pa @netsvc_conf@ , |
Line 2209 by default.
|
Line 2223 by default.
|
.It rootpw |
.It rootpw |
If set, |
If set, |
.Nm sudo |
.Nm sudo |
will prompt for the root password instead of the password of the invoking user. | will prompt for the root password instead of the password of the invoking user |
| when running a command or editing a file. |
This flag is |
This flag is |
.Em off |
.Em off |
by default. |
by default. |
Line 2220 will prompt for the password of the user defined by th
|
Line 2235 will prompt for the password of the user defined by th
|
.Em runas_default |
.Em runas_default |
option (defaults to |
option (defaults to |
.Li @runas_default@ ) |
.Li @runas_default@ ) |
instead of the password of the invoking user. | instead of the password of the invoking user |
| when running a command or editing a file. |
This flag is |
This flag is |
.Em off |
.Em off |
by default. |
by default. |
Line 2356 by the
|
Line 2372 by the
|
.Fl u |
.Fl u |
option (defaults to |
option (defaults to |
.Li root ) |
.Li root ) |
instead of the password of the invoking user. | instead of the password of the invoking user |
In addition, the time stamp file name will include the target user's name. | when running a command or editing a file. |
Note that this flag precludes the use of a uid not listed in the passwd |
Note that this flag precludes the use of a uid not listed in the passwd |
database as an argument to the |
database as an argument to the |
.Fl u |
.Fl u |
Line 2369 by default.
|
Line 2385 by default.
|
If set, users must authenticate on a per-tty basis. |
If set, users must authenticate on a per-tty basis. |
With this flag enabled, |
With this flag enabled, |
.Nm sudo |
.Nm sudo |
will use a file named for the tty the user is | will use a separate record in the time stamp file for each tty. |
logged in on in the user's time stamp directory. | If disabled, a single record is used for all login sessions. |
If disabled, the time stamp of the directory is used instead. | |
This flag is |
This flag is |
.Em @tty_tickets@ |
.Em @tty_tickets@ |
by default. |
by default. |
Line 2622 escape sequences.
|
Line 2637 escape sequences.
|
.Pp |
.Pp |
In addition to the escape sequences, path names that end in six or |
In addition to the escape sequences, path names that end in six or |
more |
more |
.Li X Ns No s | .Li X Ns s |
will have the |
will have the |
.Li X Ns No s | .Li X Ns s |
replaced with a unique combination of digits and letters, similar to the |
replaced with a unique combination of digits and letters, similar to the |
.Xr mktemp 3 |
.Xr mktemp 3 |
function. |
function. |
Line 2638 overwritten unless
|
Line 2653 overwritten unless
|
.Em iolog_file |
.Em iolog_file |
ends in six or |
ends in six or |
more |
more |
.Li X Ns No s . | .Li X Ns s . |
| .It lecture_status_dir |
| The directory in which |
| .Nm sudo |
| stores per-user lecture status files. |
| Once a user has received the lecture, a zero-length file is |
| created in this directory so that |
| .Nm sudo |
| will not lecture the user again. |
| This directory should |
| .Em not |
| be cleared when the system reboots. |
| The default is |
| .Pa @vardir@/lectured . |
.It limitprivs |
.It limitprivs |
The default Solaris limit privileges to use when constructing a new |
The default Solaris limit privileges to use when constructing a new |
privilege set for a command. |
privilege set for a command. |
Line 2680 it will
|
Line 2708 it will
|
.Dq roll over |
.Dq roll over |
to zero, after which |
to zero, after which |
.Nm sudoers |
.Nm sudoers |
will truncate and re-use any existing I/O log pathnames. | will truncate and re-use any existing I/O log path names. |
.Pp |
.Pp |
This setting is only supported by version 1.8.7 or higher. |
This setting is only supported by version 1.8.7 or higher. |
.It noexec_file |
.It noexec_file |
Line 2818 Defaults to
|
Line 2846 Defaults to
|
The directory in which |
The directory in which |
.Nm sudo |
.Nm sudo |
stores its time stamp files. |
stores its time stamp files. |
|
This directory should be cleared when the system reboots. |
The default is |
The default is |
.Pa @timedir@ . | .Pa @rundir@/ts . |
.It timestampowner |
.It timestampowner |
The owner of the time stamp directory and the time stamps stored therein. | The owner of the lecture status directory, time stamp directory and all |
| files stored therein. |
The default is |
The default is |
.Li root . |
.Li root . |
.It type |
.It type |
Line 3120 Environment variables to be preserved in the user's en
|
Line 3150 Environment variables to be preserved in the user's en
|
.Em env_reset |
.Em env_reset |
option is in effect. |
option is in effect. |
This allows fine-grained control over the environment |
This allows fine-grained control over the environment |
.Nm sudo Ns No -spawned | .Nm sudo Ns -spawned |
processes will receive. |
processes will receive. |
The argument may be a double-quoted, space-separated list or a |
The argument may be a double-quoted, space-separated list or a |
single value without double-quotes. |
single value without double-quotes. |
Line 3298 failed attempts and the value of the
|
Line 3328 failed attempts and the value of the
|
.Em passwd_tries |
.Em passwd_tries |
option. |
option. |
.It a password is required |
.It a password is required |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Fl n |
.Fl n |
option was specified but a password was required. |
option was specified but a password was required. |
.It sorry, you are not allowed to set the following environment variables |
.It sorry, you are not allowed to set the following environment variables |
Line 3419 file) to the
|
Line 3449 file) to the
|
line in the |
line in the |
.Xr sudo.conf @mansectform@ |
.Xr sudo.conf @mansectform@ |
file. |
file. |
.It unable to open @timedir@/username/ttyname | .It unable to open @rundir@/ts/username |
.Em sudoers |
.Em sudoers |
was unable to read or create the user's time stamp file. |
was unable to read or create the user's time stamp file. |
.It unable to write to @timedir@/username/ttyname | This can happen when |
| .Em timestampowner |
| is set to a user other than root and the mode on |
| .Pa @rundir@ |
| is not searchable by group or other. |
| The default mode for |
| .Pa @rundir@ |
| is 0711. |
| .It unable to write to @rundir@/ts/username |
.Em sudoers |
.Em sudoers |
was unable to write to the user's time stamp file. |
was unable to write to the user's time stamp file. |
.It unable to mkdir to @timedir@/username | .It @rundir@/ts is owned by uid X, should be Y |
| The time stamp directory is owned by a user other than |
| .Em timestampowner . |
| This can occur when the value of |
| .Em timestampowner |
| has been changed. |
.Em sudoers |
.Em sudoers |
was unable to create the user's time stamp directory. | will ignore the time stamp directory until the owner is corrected. |
| .It @rundir@/ts is group writable |
| The time stamp directory is group-writable; it should be writable only by |
| .Em timestampowner . |
| The default mode for the time stamp directory is 0700. |
| .Em sudoers |
| will ignore the time stamp directory until the mode is corrected. |
.El |
.El |
.Ss Notes on logging via syslog |
.Ss Notes on logging via syslog |
By default, |
By default, |
Line 3506 Local groups file
|
Line 3555 Local groups file
|
List of network groups |
List of network groups |
.It Pa @iolog_dir@ |
.It Pa @iolog_dir@ |
I/O log files |
I/O log files |
.It Pa @timedir@ | .It Pa @rundir@/ts |
Directory containing time stamps for the |
Directory containing time stamps for the |
.Em sudoers |
.Em sudoers |
security policy |
security policy |
|
.It Pa @vardir@/lectured |
|
Directory containing lecture status files for the |
|
.Em sudoers |
|
security policy |
.It Pa /etc/environment |
.It Pa /etc/environment |
Initial environment for |
Initial environment for |
.Fl i |
.Fl i |
Line 3945 executes a program, that program is free to do whateve
|
Line 3998 executes a program, that program is free to do whateve
|
it pleases, including run other programs. |
it pleases, including run other programs. |
This can be a security issue since it is not uncommon for a program to |
This can be a security issue since it is not uncommon for a program to |
allow shell escapes, which lets a user bypass |
allow shell escapes, which lets a user bypass |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
access control and logging. |
access control and logging. |
Common programs that permit shell escapes include shells (obviously), |
Common programs that permit shell escapes include shells (obviously), |
editors, paginators, mail and terminal programs. |
editors, paginators, mail and terminal programs. |
Line 3971 variable (usually
|
Line 4024 variable (usually
|
.Ev LD_PRELOAD ) |
.Ev LD_PRELOAD ) |
to an alternate shared library. |
to an alternate shared library. |
On such systems, |
On such systems, |
.Nm sudo Ns No 's | .Nm sudo Ns 's |
.Em noexec |
.Em noexec |
functionality can be used to prevent a program run by |
functionality can be used to prevent a program run by |
.Nm sudo |
.Nm sudo |
Line 4034 operations (such as changing or overwriting files) tha
|
Line 4087 operations (such as changing or overwriting files) tha
|
to unintended privilege escalation. |
to unintended privilege escalation. |
In the specific case of an editor, a safer approach is to give the |
In the specific case of an editor, a safer approach is to give the |
user permission to run |
user permission to run |
.Nm sudoedit . | .Nm sudoedit |
| (see below). |
| .Ss Secure editing |
| The |
| .Em sudoers |
| plugin includes |
| .Nm sudoedit |
| support which allows users to securely edit files with the editor |
| of their choice. |
| As |
| .Nm sudoedit |
| is a built-in command, it must be specified in |
| .Em sudoers |
| without a leading path. |
| However, it may take command line arguments just as a normal command does. |
| For example, to allow user operator to edit the |
| .Dq message of the day |
| file: |
| .Bd -literal -offset indent |
| operator sudoedit /etc/motd |
| .Ed |
| .Pp |
| The operator user then runs |
| .Nm sudoedit |
| as follows: |
| .Bd -literal -offset indent |
| $ sudoedit /etc/motd |
| .Ed |
| .Pp |
| The editor will run as the operator user, not root, on a temporary copy of |
| .Pa /etc/motd . |
| After the file has been edited, |
| .Pa /etc/motd |
| will be updated with the contents of the temporary copy. |
.Ss Time stamp file checks |
.Ss Time stamp file checks |
.Em sudoers |
.Em sudoers |
will check the ownership of its time stamp directory |
will check the ownership of its time stamp directory |
.Po |
.Po |
.Pa @timedir@ | .Pa @rundir@/ts |
by default |
by default |
.Pc |
.Pc |
and ignore the directory's contents if it is not owned by root or |
and ignore the directory's contents if it is not owned by root or |
if it is writable by a user other than root. |
if it is writable by a user other than root. |
On systems that allow non-root users to give away files via | Older versions of |
.Xr chown 2 , | |
if the time stamp directory is located in a world-writable | |
directory (e.g.\&, | |
.Pa /tmp ) , | |
it is possible for a user to create the time stamp directory before | |
.Nm sudo |
.Nm sudo |
is run. | stored time stamp files in |
However, because | .Pa /tmp ; |
| this is no longer recommended as it may be possible for a user |
| to create the time stamp themselves on systems that allow |
| unprivileged users to change the ownership of files they create. |
| .Pp |
| While the time stamp directory |
| .Em should |
| be cleared at reboot time, not all systems contain a |
| .Pa /var/run |
| directory. |
| To avoid potential problems, |
.Em sudoers |
.Em sudoers |
checks the ownership and mode of the directory and its | will ignore time stamp files that date from before the machine booted |
contents, the only damage that can be done is to | on systems where the boot time is available. |
.Dq hide | |
files by putting them in the time stamp dir. | |
This is unlikely to happen since once the time stamp dir is owned by root | |
and inaccessible by any other user, the user placing files there would be | |
unable to get them back out. | |
.Pp |
.Pp |
|
Some systems with graphical desktop environments allow unprivileged |
|
users to change the system clock. |
|
Since |
.Em sudoers |
.Em sudoers |
|
relies on the system clock for time stamp validation, it may be |
|
possible on such systems for a user to run |
|
.Nm sudo |
|
for longer than |
|
.Em timestamp_timeout |
|
by setting the clock back. |
|
To combat this, |
|
.Em sudoers |
|
uses a monotonic clock (which never moves backwards) for its time stamps |
|
if the system supports it. |
|
.Pp |
|
.Em sudoers |
will not honor time stamps set far in the future. |
will not honor time stamps set far in the future. |
Time stamps with a date greater than current_time + 2 * |
Time stamps with a date greater than current_time + 2 * |
.Li TIMEOUT |
.Li TIMEOUT |
will be ignored and sudo will log and complain. | will be ignored and |
This is done to keep a user from creating his/her own time stamp with a | |
bogus date on systems that allow users to give away files if the time | |
stamp directory is located in a world-writable directory. | |
.Pp | |
On systems where the boot time is available, | |
.Em sudoers |
.Em sudoers |
will ignore time stamps that date from before the machine booted. | will log and complain. |
.Pp |
.Pp |
Since time stamp files live in the file system, they can outlive a |
Since time stamp files live in the file system, they can outlive a |
user's login session. |
user's login session. |
Line 4081 As a result, a user may be able to login, run a comman
|
Line 4177 As a result, a user may be able to login, run a comman
|
.Nm sudo |
.Nm sudo |
after authenticating, logout, login again, and run |
after authenticating, logout, login again, and run |
.Nm sudo |
.Nm sudo |
without authenticating so long as the time stamp file's modification | without authenticating so long as the record's time stamp is within |
time is within | |
.Li @timeout@ |
.Li @timeout@ |
minutes (or whatever the timeout is set to in | minutes (or whatever value the timeout is set to in |
.Em sudoers ) . |
.Em sudoers ) . |
When the |
When the |
.Em tty_tickets |
.Em tty_tickets |
option is enabled, the time stamp has per-tty granularity but still | option is enabled, the time stamp record includes the device |
| number of the terminal the user authenticated with. |
| This provides per-tty granularity but time stamp records still |
may outlive the user's session. |
may outlive the user's session. |
On Linux systems where the devpts filesystem is used, Solaris systems | The time stamp record also includes the session ID of the process |
with the devices filesystem, as well as other systems that utilize a | that last authenticated. |
devfs filesystem that monotonically increase the inode number of devices | This prevents processes in different terminal sessions from using |
as they are created (such as Mac OS X), | the same time stamp record. |
.Em sudoers | It also helps reduce the chance that a user will be able to run |
is able to determine when a tty-based time stamp file is stale and will | .Nm sudo |
ignore it. | without entering a password when logging out and back in again |
Administrators should not rely on this feature as it is not universally | on the same terminal. |
available. | |
.Sh DEBUGGING |
.Sh DEBUGGING |
Versions 1.8.4 and higher of the |
Versions 1.8.4 and higher of the |
.Nm sudoers |
.Nm sudoers |
Line 4113 The
|
Line 4209 The
|
plugin uses the same debug flag format as the |
plugin uses the same debug flag format as the |
.Nm sudo |
.Nm sudo |
front-end: |
front-end: |
.Em subsystem Ns No @ Ns Em priority . | .Em subsystem Ns @ Ns Em priority . |
.Pp |
.Pp |
The priorities used by |
The priorities used by |
.Nm sudoers , |
.Nm sudoers , |
Line 4178 for the plugin.
|
Line 4274 for the plugin.
|
pseudo-tty related code |
pseudo-tty related code |
.It Em rbtree |
.It Em rbtree |
redblack tree internals |
redblack tree internals |
|
.It Em sssd |
|
SSSD-based sudoers |
.It Em util |
.It Em util |
utility functions |
utility functions |
.El |
.El |