erni - run commands and services as users with no shell
erni -u <user[:group1,group2,...,groupN] >> [-f <file] >> [-d] > [-c <dir] >> [-m <mask] >> [-h] > [-v] > [-V] > -E <command >>
Flags ``-u'' and ``-E'' are required, unless a configuration file is used, in which case flag ``-f'' is required.
erni permits root to run programs as user accounts that have no login shell.
The ever-familiar
su - {user} -c {command}
often seen in system init scripts, has a limitation: while the password for
the account may be disabled, {user}
must still have a valid login shell.
In turn, the presence of the login shell provides another avenue through which the account may be misused. This is of special concern for daemon accounts, which are used as placeholders to own processes and files (e.g. database or web daemons) and may thus have access to priveleged information.
erni completely bypasses the login shell, and instead uses system calls (such as setuid() and setgid()) to ``become'' the specified user within the current process space.
This means one may eliminate such accounts' login shells (that is, set them to /bin/false in the password tables) if using erni to execute processes on those accounts' behalf.
this need not limit erni's usage to system init scripts, however. It is just as useful to run ordinary commands through erni, such as calling an interactive SQL tool as the database admin account.
The command to execute is resolved using the current user's (that is, root's) search path. The target user's $PATH is not searched.
erni must be run as root.
The command has an embedded check, and will exit immediately if called as a nonroot user.
Given this, the erni binary may be installed with restrictive permissions, such as mode 500 and ownership 0:0.
erni may optionally chroot to a given directory as the specified user.
Please see the FLAGS and EXAMPLES section of this document for more information.
Since erni performs no sort of login, the target user account's login files (such as .profile or .cshrc) are not read, nor does the process change to the user's home directory before executing.
erni further limits execution by disabling all environment variables before performing the final setuid() call to assume the user's identity. This includes variables that may be required for execution, such as LD_LIBRARY_PATH or LD_PRELOAD.
Depending on the situation, this can be a help or a hinderance. If special environment variables are required, one suggestion would be to have erni run a wrapper script as the target user. The variables may then be specified within that script.
If the user in question is purely a daemon/placeholder account, one may further limit exposure by disabling the user's home directory (i.e. replace the entry in the password tables with /dev/null). Of course, if the user in question requires permanent file space, or if the commands executed require a home directory (e.g. a tool loads a database password from ${HOME}/.db_name/db_password), this is not an option.
Handling of group memberships is described in detail in the FLAGS section of this document. The short version is: leave the group parameter blank to load all of the user's groups; specify a comma-separated list if you require that a limited set of group memberships be granted to the process.
erni supports a configuration file, in lieu of specifying all options on the commandline.
Please note, however, that variable and glob expansion is performed by the calling shell and not erni; as such, any use of erni that relies on such expansion requires that values be passed on the commandline.
erni supports mixed use of commandline and config file; but values specified in the config file override those on the commandline. This can lead to confusion if values are set in both places. As such, it is recommended that either commandline or config file, not both, be used for a given erni run.
The config file consists of a set of key=value
pairs, one per line. The
names of the keys are listed in the FLAGS section of this document.
Run process as user user, with group memberships group1, group2, through groupN.
Specification of groups is optional; if none are provided on the commandline or in the config file, erni will resolve all of the user's group memberships using the system's name service switch (e.g. /etc/group, or NIS/YP, LDAP, or whatever mechanism is used). Note that this can timeout or be slow if the system is heavily loaded and/or the service used to resolve groups is unreachable.
The first group listed will be the user's primary group.
The maximum number of group memberships (primary + auxiliary) is system-dependent and determined at compile time. Hence, if the maximum number of group memberships changes between revisions of your operating system, you are encouraged to build erni for each such revision.
Both user and group names may be specified as numeric UIDs/GIDs.
Specification of an invalid user/group will cause erni to fail.
Execute command as the target user.
If specified in the config file, variable and glob expansion will not be performed; if such expansion is required, one may either use the commandline in lieu of the config file or have erni call a wrapper script which sets variables as needed.
This must be the last flag on the command line. All arguments following this flag are considered the command to run as the target user.
Run process with the specified umask.
This flag is optional; the default value it set at compile time. Unless
the source code is manually changed this default is somewhat restrictive
(027
) but should be suitable for most usage.
The fork()
call is delayed until the last possible moment: right
before the call to exec(). (This happens after the call to
chroot(), if it was requested.)
Users would otherwise risk losing Erni-related error messages (such as incorrect commandline flags) because stdout/stderr is redirected to /dev/null in the child process.
perform a chroot(2)
to the specified directory before execution
Display a brief help message and exit.
Print program version and exit.
Show debug messages during execution. This is useful for debugging, and should be included in any bug reports.
/tools/bin/wrapper.sh
as the user someuser
and umask
022
:
erni -u someuser -m 022 -E /tools/bin/wrapper.sh
Since no group memberships are specified, erni will load someuser's
default groups.
sql_tool
as user db_admin
, with group memberships
dba
and group2
:
erni -u db_admin:dba,group2 -E sql_tool
Please note, sql_tool
will be found based on the $PATH of the user
calling erni (always root), not the target user under which the
command is executed (db_admin
in this case).
Also note, the compiled-in default umask is used since it is specified on the commandline.
erni, in its present form, was designed and written by QM <qm -at- brandxdev.net>.
erni's core functionality is based on the runas
tool included in
the Titan security package.
The official erni website is
http://www.brandxdev.net/
None have been found... yet.
THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Use erni at your own risk.