451 lines
11 KiB
Diff
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
|
||
|
|