runuser: new command (derived from su(1))
This command is based on su(1), the differences: - based on Fedora runuser su(1) patch - not installed with suid rights - allowed for root users only - don't ask for password - uses PAM session, for example: $ cat /etc/pam.d/runuser auth sufficient pam_rootok.so session optional pam_keyinit.so revoke session required pam_limits.so session required pam_unix.so $ cat /etc/pam.d/runuser-l auth include runuser session optional pam_keyinit.so force revoke session include runuser Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
cf1a99dacc
commit
7ec6adb1cc
|
@ -138,6 +138,7 @@ tests/run.sh.trs
|
||||||
/resizepart
|
/resizepart
|
||||||
/rev
|
/rev
|
||||||
/rtcwake
|
/rtcwake
|
||||||
|
/runuser
|
||||||
/sample-mkfs
|
/sample-mkfs
|
||||||
/sample-partitions
|
/sample-partitions
|
||||||
/sample-superblocks
|
/sample-superblocks
|
||||||
|
|
|
@ -1154,6 +1154,15 @@ UL_REQUIRES_HAVE([su], [security_pam_misc_h], [PAM header file])
|
||||||
AM_CONDITIONAL(BUILD_SU, test "x$build_su" = xyes)
|
AM_CONDITIONAL(BUILD_SU, test "x$build_su" = xyes)
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([runuser],
|
||||||
|
AS_HELP_STRING([--disable-runuser], [do not build runuser]),
|
||||||
|
[], enable_runuser=yes
|
||||||
|
)
|
||||||
|
UL_BUILD_INIT([runuser])
|
||||||
|
UL_REQUIRES_HAVE([runuser], [security_pam_misc_h], [PAM header file])
|
||||||
|
AM_CONDITIONAL(BUILD_RUNUSER, test "x$build_runuser" = xyes)
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([schedutils],
|
AC_ARG_ENABLE([schedutils],
|
||||||
AS_HELP_STRING([--disable-schedutils], [do not build chrt, ionice, teskset]),
|
AS_HELP_STRING([--disable-schedutils], [do not build chrt, ionice, teskset]),
|
||||||
[], enable_schedutils=yes
|
[], enable_schedutils=yes
|
||||||
|
|
|
@ -92,6 +92,19 @@ su_LDADD = $(LDADD) -lpam -lpam_misc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
if BUILD_RUNUSER
|
||||||
|
bin_PROGRAMS += runuser
|
||||||
|
dist_man_MANS += login-utils/runuser.1
|
||||||
|
runuser_SOURCES = \
|
||||||
|
login-utils/runuser.c \
|
||||||
|
login-utils/su-common.c \
|
||||||
|
login-utils/su-common.h \
|
||||||
|
login-utils/logindefs.c \
|
||||||
|
login-utils/logindefs.h
|
||||||
|
runuser_LDADD = $(LDADD) -lpam -lpam_misc
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
if BUILD_NEWGRP
|
if BUILD_NEWGRP
|
||||||
usrbin_exec_PROGRAMS += newgrp
|
usrbin_exec_PROGRAMS += newgrp
|
||||||
dist_man_MANS += login-utils/newgrp.1
|
dist_man_MANS += login-utils/newgrp.1
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
.TH RUNUSER "1" "August 2012" "util-linux" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
runuser \- run a command with substitute user and group ID
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B runuser
|
||||||
|
[options...] [\-] [user [args...]]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B runuser
|
||||||
|
allows to run commands with substitute user and group ID.
|
||||||
|
The difference between the commands
|
||||||
|
.B runuser
|
||||||
|
and
|
||||||
|
.B su
|
||||||
|
is that
|
||||||
|
.B runuser
|
||||||
|
does not ask for password, because it may be executed by root user only.
|
||||||
|
The command
|
||||||
|
.B runuser
|
||||||
|
does not have to be installed with suid permissions.
|
||||||
|
.PP
|
||||||
|
When called without arguments
|
||||||
|
.B runuser
|
||||||
|
defaults to running an interactive shell as
|
||||||
|
.IR root .
|
||||||
|
.PP
|
||||||
|
For backward compatibility
|
||||||
|
.B runuser
|
||||||
|
defaults to not change the current directory and to only set the
|
||||||
|
environment variables
|
||||||
|
.B HOME
|
||||||
|
and
|
||||||
|
.B SHELL
|
||||||
|
(plus
|
||||||
|
.B USER
|
||||||
|
and
|
||||||
|
.B LOGNAME
|
||||||
|
if the target
|
||||||
|
.I user
|
||||||
|
is not root). It is recommended to always use the
|
||||||
|
.B \-\-login
|
||||||
|
option (instead it's shortcut
|
||||||
|
.BR \- )
|
||||||
|
to avoid side effects caused by mixing environments.
|
||||||
|
.PP
|
||||||
|
This version of
|
||||||
|
.B runuser
|
||||||
|
uses PAM for session management.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
\fB\-c\fR \fIcommand\fR, \fB\-\-command\fR=\fIcommand\fR
|
||||||
|
Pass
|
||||||
|
.I command
|
||||||
|
to the shell with the
|
||||||
|
.B \-c
|
||||||
|
option.
|
||||||
|
.TP
|
||||||
|
\fB\-\-session\-command\fR=\fIcommand\fR
|
||||||
|
Same as
|
||||||
|
.B \-c
|
||||||
|
but do not create a new session (discouraged).
|
||||||
|
.TP
|
||||||
|
\fB\-f\fR, \fB\-\-fast\fR
|
||||||
|
Pass
|
||||||
|
.B \-f
|
||||||
|
to the shell which may or may not be useful depending on the
|
||||||
|
shell.
|
||||||
|
.TP
|
||||||
|
\fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR
|
||||||
|
specify the primary group, this option is allowed for root user only
|
||||||
|
.TP
|
||||||
|
\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR
|
||||||
|
specify a supplemental group, this option is allowed for root user only
|
||||||
|
.TP
|
||||||
|
\fB\-\fR, \fB\-l\fR, \fB\-\-login\fR
|
||||||
|
Starts the shell as login shell with an environment similar to a real
|
||||||
|
login:
|
||||||
|
.RS 10
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
clears all environment variables except for
|
||||||
|
.B TERM
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
initializes the environment variables
|
||||||
|
.BR HOME ,
|
||||||
|
.BR SHELL ,
|
||||||
|
.BR USER ,
|
||||||
|
.BR LOGNAME ,
|
||||||
|
.B PATH
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
changes to the target user's home directory
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
sets argv[0] of the shell to
|
||||||
|
.RB ' \- '
|
||||||
|
in order to make the shell a login shell
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
\fB\-m\fR, \fB\-p\fR, \fB\-\-preserve-environment\fR
|
||||||
|
Preserves the whole environment, ie does not set
|
||||||
|
.BR HOME ,
|
||||||
|
.BR SHELL ,
|
||||||
|
.B USER
|
||||||
|
nor
|
||||||
|
.BR LOGNAME .
|
||||||
|
.TP
|
||||||
|
\fB\-s\fR \fISHELL\fR, \fB\-\-shell\fR=\fISHELL\fR
|
||||||
|
Runs the specified shell instead of the default. The shell to run is
|
||||||
|
selected according to the following rules in order:
|
||||||
|
.RS 10
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
the shell specified with
|
||||||
|
.B \-\-shell
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
The shell specified in the environment variable
|
||||||
|
.B SHELL
|
||||||
|
if the
|
||||||
|
.B \-\-preserve-environment
|
||||||
|
option is used.
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
the shell listed in the passwd entry of the target user
|
||||||
|
.TP
|
||||||
|
o
|
||||||
|
/bin/sh
|
||||||
|
.RE
|
||||||
|
.IP
|
||||||
|
If the target user has a restricted shell (i.e. not listed in
|
||||||
|
/etc/shells) the
|
||||||
|
.B \-\-shell
|
||||||
|
option and the
|
||||||
|
.B SHELL
|
||||||
|
environment variables are ignored unless the calling user is root.
|
||||||
|
.TP
|
||||||
|
\fB\-\-help\fR
|
||||||
|
Display help text and exit.
|
||||||
|
.TP
|
||||||
|
\fB\-\-version\fR
|
||||||
|
Display version information and exit.
|
||||||
|
.SH CONFIG FILES
|
||||||
|
.B runuser
|
||||||
|
reads the
|
||||||
|
.I /etc/default/runuser
|
||||||
|
and
|
||||||
|
.I /etc/login.defs
|
||||||
|
configuration files. The following configuration items are relevant
|
||||||
|
for
|
||||||
|
.BR runuser :
|
||||||
|
.PP
|
||||||
|
.B ENV_PATH
|
||||||
|
(string)
|
||||||
|
.RS 4
|
||||||
|
Defines the PATH environment variable for a regular user. The
|
||||||
|
default value is
|
||||||
|
.IR /usr/local/bin:\:/bin:\:/usr/bin .
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B ENV_ROOTPATH
|
||||||
|
(string)
|
||||||
|
.br
|
||||||
|
.B ENV_SUPATH
|
||||||
|
(string)
|
||||||
|
.RS 4
|
||||||
|
Defines the PATH environment variable for root. The default value is
|
||||||
|
.IR /usr/local/sbin:\:/usr/local/bin:\:/sbin:\:/bin:\:/usr/sbin:\:/usr/bin .
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B ALWAYS_SET_PATH
|
||||||
|
(boolean)
|
||||||
|
.RS 4
|
||||||
|
If set to
|
||||||
|
.I yes
|
||||||
|
and \-\-login and \-\-preserve\-environment were not specified
|
||||||
|
.B runuser
|
||||||
|
initializes
|
||||||
|
.BR PATH .
|
||||||
|
.RE
|
||||||
|
.SH EXIT STATUS
|
||||||
|
.B runuser
|
||||||
|
normally returns the exit status of the command it executed. If the
|
||||||
|
command was killed by a signal,
|
||||||
|
.B runuser
|
||||||
|
returns the number of the signal plus 128.
|
||||||
|
.PP
|
||||||
|
Exit status generated by
|
||||||
|
.B runuser
|
||||||
|
itself:
|
||||||
|
.RS 10
|
||||||
|
.TP
|
||||||
|
1
|
||||||
|
Generic error before executing the requested command
|
||||||
|
.TP
|
||||||
|
126
|
||||||
|
The requested command could not be executed
|
||||||
|
.TP
|
||||||
|
127
|
||||||
|
The requested command could was not found
|
||||||
|
.RE
|
||||||
|
.SH FILES
|
||||||
|
.PD 0
|
||||||
|
.TP 17
|
||||||
|
/etc/pam.d/runuser
|
||||||
|
default PAM configuration file
|
||||||
|
.TP
|
||||||
|
/etc/pam.d/runuser-l
|
||||||
|
PAM configuration file if \-\-login is specified
|
||||||
|
.TP
|
||||||
|
/etc/default/runuser
|
||||||
|
runuser specific logindef config file
|
||||||
|
.TP
|
||||||
|
/etc/login.defs
|
||||||
|
global logindef config file
|
||||||
|
.PD 1
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR pam (8),
|
||||||
|
.BR shells (5),
|
||||||
|
.BR login.defs (5),
|
||||||
|
.BR su (1)
|
||||||
|
.SH AUTHOR
|
||||||
|
Derived from coreutils' su which was based on an implemenation from
|
||||||
|
David MacKenzie and Fedora runuser command from Dan Walsh.
|
||||||
|
.SH AVAILABILITY
|
||||||
|
The runuser command is part of the util-linux package and is
|
||||||
|
available from
|
||||||
|
.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
|
||||||
|
Linux Kernel Archive
|
||||||
|
.UE .
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "su-common.h"
|
||||||
|
|
||||||
|
int main(int argv, char **argc)
|
||||||
|
{
|
||||||
|
return su_main(argv, argc, RUNUSER_MODE);
|
||||||
|
}
|
|
@ -65,8 +65,14 @@ enum
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
|
|
||||||
/* name of the pam configuration files. separate configs for su and su - */
|
/* name of the pam configuration files. separate configs for su and su - */
|
||||||
#define PAM_SERVICE_NAME "su"
|
#define PAM_SRVNAME_SU "su"
|
||||||
#define PAM_SERVICE_NAME_L "su-l"
|
#define PAM_SRVNAME_SU_L "su-l"
|
||||||
|
|
||||||
|
#define PAM_SRVNAME_RUNUSER "runuser"
|
||||||
|
#define PAM_SRVNAME_RUNUSER_L "runuser-l"
|
||||||
|
|
||||||
|
#define _PATH_LOGINDEFS_SU "/etc/defaults/su"
|
||||||
|
#define _PATH_LOGINDEFS_RUNUSER "/etc/defaults/runuser"
|
||||||
|
|
||||||
#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
|
#define is_pam_failure(_rc) ((_rc) != PAM_SUCCESS)
|
||||||
|
|
||||||
|
@ -106,6 +112,8 @@ static bool _pam_cred_established;
|
||||||
static sig_atomic_t volatile caught_signal = false;
|
static sig_atomic_t volatile caught_signal = false;
|
||||||
static pam_handle_t *pamh = NULL;
|
static pam_handle_t *pamh = NULL;
|
||||||
|
|
||||||
|
static int restricted = 1; /* zero for root user */
|
||||||
|
|
||||||
static struct option const longopts[] =
|
static struct option const longopts[] =
|
||||||
{
|
{
|
||||||
{"command", required_argument, NULL, 'c'},
|
{"command", required_argument, NULL, 'c'},
|
||||||
|
@ -146,7 +154,8 @@ log_su (struct passwd const *pw, bool successful)
|
||||||
|
|
||||||
openlog (program_invocation_short_name, 0 , LOG_AUTH);
|
openlog (program_invocation_short_name, 0 , LOG_AUTH);
|
||||||
syslog (LOG_NOTICE, "%s(to %s) %s on %s",
|
syslog (LOG_NOTICE, "%s(to %s) %s on %s",
|
||||||
successful ? "" : "FAILED SU ",
|
successful ? "" :
|
||||||
|
su_mode == RUNUSER_MODE ? "FAILED RUNUSER " : "FAILED SU ",
|
||||||
new_user, old_user, tty);
|
new_user, old_user, tty);
|
||||||
closelog ();
|
closelog ();
|
||||||
}
|
}
|
||||||
|
@ -315,11 +324,19 @@ static void
|
||||||
authenticate (const struct passwd *pw)
|
authenticate (const struct passwd *pw)
|
||||||
{
|
{
|
||||||
const struct passwd *lpw;
|
const struct passwd *lpw;
|
||||||
const char *cp;
|
const char *cp, *srvname = NULL;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
|
switch (su_mode) {
|
||||||
pw->pw_name, &conv, &pamh);
|
case SU_MODE:
|
||||||
|
srvname = simulate_login ? PAM_SRVNAME_SU_L : PAM_SRVNAME_SU;
|
||||||
|
break;
|
||||||
|
case RUNUSER_MODE:
|
||||||
|
srvname = simulate_login ? PAM_SRVNAME_RUNUSER_L : PAM_SRVNAME_RUNUSER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = pam_start (srvname, pw->pw_name, &conv, &pamh);
|
||||||
if (is_pam_failure(retval))
|
if (is_pam_failure(retval))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -344,6 +361,17 @@ authenticate (const struct passwd *pw)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (su_mode == RUNUSER_MODE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is the only difference between runuser(1) and su(1). The command
|
||||||
|
* runuser(1) does not required authentication, because user is root.
|
||||||
|
*/
|
||||||
|
if (restricted)
|
||||||
|
errx(EXIT_FAILURE, _("may not be used by non-root users"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
retval = pam_authenticate (pamh, 0);
|
retval = pam_authenticate (pamh, 0);
|
||||||
if (is_pam_failure(retval))
|
if (is_pam_failure(retval))
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -691,7 +719,15 @@ usage (int status)
|
||||||
static
|
static
|
||||||
void load_config(void)
|
void load_config(void)
|
||||||
{
|
{
|
||||||
logindefs_load_file("/etc/default/su");
|
switch (su_mode) {
|
||||||
|
case SU_MODE:
|
||||||
|
logindefs_load_file(_PATH_LOGINDEFS_SU);
|
||||||
|
break;
|
||||||
|
case RUNUSER_MODE:
|
||||||
|
logindefs_load_file(_PATH_LOGINDEFS_RUNUSER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
logindefs_load_file(_PATH_LOGINDEFS);
|
logindefs_load_file(_PATH_LOGINDEFS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +758,6 @@ su_main (int argc, char **argv, int mode)
|
||||||
gid_t groups[NGROUPS_MAX];
|
gid_t groups[NGROUPS_MAX];
|
||||||
int num_supp_groups = 0;
|
int num_supp_groups = 0;
|
||||||
int use_gid = 0;
|
int use_gid = 0;
|
||||||
int restricted;
|
|
||||||
|
|
||||||
setlocale (LC_ALL, "");
|
setlocale (LC_ALL, "");
|
||||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||||
|
|
Loading…
Reference in New Issue