util-linux/0202-runuser-new-command-de...

451 lines
11 KiB
Diff

From d8c2f623ab9d9e7da1490244cb8c77c3017545dc Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 29 Aug 2012 17:34:26 +0200
Subject: [PATCH 202/208] 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>
---
.gitignore | 1 +
configure.ac | 9 ++
login-utils/Makemodule.am | 13 +++
login-utils/runuser.1 | 230 ++++++++++++++++++++++++++++++++++++++++++++++
login-utils/runuser.c | 7 ++
login-utils/su-common.c | 51 ++++++++--
6 files changed, 303 insertions(+), 8 deletions(-)
create mode 100644 login-utils/runuser.1
create mode 100644 login-utils/runuser.c
#diff --git a/.gitignore b/.gitignore
#index fbc5636..5be008f 100644
#--- a/.gitignore
#+++ b/.gitignore
#@@ -138,6 +138,7 @@ tests/run.sh.trs
# /resizepart
# /rev
# /rtcwake
#+/runuser
# /sample-mkfs
# /sample-partitions
# /sample-superblocks
diff --git a/configure.ac b/configure.ac
index 87e85fa..83ef6ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1149,6 +1149,15 @@ UL_REQUIRES_HAVE([su], [security_pam_misc_h], [PAM header file])
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],
AS_HELP_STRING([--disable-schedutils], [do not build chrt, ionice, teskset]),
[], enable_schedutils=yes
diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
index b918f00..e26d9a7 100644
--- a/login-utils/Makemodule.am
+++ b/login-utils/Makemodule.am
@@ -93,6 +93,19 @@ su_LDADD = $(LDADD) -lpam -lpam_misc
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
usrbin_exec_PROGRAMS += newgrp
dist_man_MANS += login-utils/newgrp.1
diff --git a/login-utils/runuser.1 b/login-utils/runuser.1
new file mode 100644
index 0000000..66ad1c4
--- /dev/null
+++ b/login-utils/runuser.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 .
diff --git a/login-utils/runuser.c b/login-utils/runuser.c
new file mode 100644
index 0000000..d4f37f4
--- /dev/null
+++ b/login-utils/runuser.c
@@ -0,0 +1,7 @@
+
+#include "su-common.h"
+
+int main(int argc, char **argv)
+{
+ return su_main(argc, argv, RUNUSER_MODE);
+}
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index f1f46aa..770f455 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -65,8 +65,14 @@ enum
#include "env.h"
/* name of the pam configuration files. separate configs for su and su - */
-#define PAM_SERVICE_NAME "su"
-#define PAM_SERVICE_NAME_L "su-l"
+#define PAM_SRVNAME_SU "su"
+#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)
@@ -106,6 +112,8 @@ static bool _pam_cred_established;
static sig_atomic_t volatile caught_signal = false;
static pam_handle_t *pamh = NULL;
+static int restricted = 1; /* zero for root user */
+
static struct option const longopts[] =
{
{"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);
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);
closelog ();
}
@@ -315,11 +324,19 @@ static void
authenticate (const struct passwd *pw)
{
const struct passwd *lpw;
- const char *cp;
+ const char *cp, *srvname = NULL;
int retval;
- retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME,
- pw->pw_name, &conv, &pamh);
+ switch (su_mode) {
+ 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))
goto done;
@@ -344,6 +361,17 @@ authenticate (const struct passwd *pw)
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);
if (is_pam_failure(retval))
goto done;
@@ -567,7 +595,15 @@ usage (int status)
static
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);
}
@@ -598,7 +634,6 @@ su_main (int argc, char **argv, int mode)
gid_t groups[NGROUPS_MAX];
int num_supp_groups = 0;
int use_gid = 0;
- int restricted;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
--
1.7.11.7