7443d56081
Signed-off-by: Karel Zak <kzak@redhat.com>
204 lines
5.7 KiB
Diff
204 lines
5.7 KiB
Diff
From 6273784aa4f40121b3963b41df0986044eeaced0 Mon Sep 17 00:00:00 2001
|
|
From: Karel Zak <kzak@redhat.com>
|
|
Date: Tue, 28 Aug 2012 16:32:28 +0200
|
|
Subject: [PATCH 200/208] su: add --group and --supp-group options
|
|
|
|
These options allow to specify alternative groups. The command
|
|
su(1) has to be executed by root. The implementation is based on
|
|
Fedora runuser(1) command.
|
|
|
|
For example:
|
|
|
|
# su --group=kzak --supp-group=uuidd -
|
|
# id
|
|
uid=0(root) gid=1000(kzak) groups=0(root),985(uuidd),1000(kzak)
|
|
|
|
non-root user:
|
|
|
|
$ su --group=kzak -
|
|
su: only root can specify alternative groups
|
|
|
|
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
---
|
|
login-utils/su.1 | 6 +++++
|
|
login-utils/su.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
2 files changed, 75 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/login-utils/su.1 b/login-utils/su.1
|
|
index 598cebd..59e1731 100644
|
|
--- a/login-utils/su.1
|
|
+++ b/login-utils/su.1
|
|
@@ -59,6 +59,12 @@ Pass
|
|
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:
|
|
diff --git a/login-utils/su.c b/login-utils/su.c
|
|
index c6b8bce..f11c757 100644
|
|
--- a/login-utils/su.c
|
|
+++ b/login-utils/su.c
|
|
@@ -110,6 +110,8 @@ static struct option const longopts[] =
|
|
{"login", no_argument, NULL, 'l'},
|
|
{"preserve-environment", no_argument, NULL, 'p'},
|
|
{"shell", required_argument, NULL, 's'},
|
|
+ {"group", required_argument, NULL, 'g'},
|
|
+ {"supp-group", required_argument, NULL, 'G'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{"version", no_argument, 0, 'V'},
|
|
{NULL, 0, NULL, 0}
|
|
@@ -424,11 +426,18 @@ modify_environment (const struct passwd *pw, const char *shell)
|
|
/* Become the user and group(s) specified by PW. */
|
|
|
|
static void
|
|
-init_groups (const struct passwd *pw)
|
|
+init_groups (const struct passwd *pw, gid_t *groups, int num_groups)
|
|
{
|
|
int retval;
|
|
+
|
|
errno = 0;
|
|
- if (initgroups (pw->pw_name, pw->pw_gid) == -1)
|
|
+
|
|
+ if (num_groups)
|
|
+ retval = setgroups (num_groups, groups);
|
|
+ else
|
|
+ retval = initgroups (pw->pw_name, pw->pw_gid);
|
|
+
|
|
+ if (retval == -1)
|
|
{
|
|
cleanup_pam (PAM_ABORT);
|
|
err (EXIT_FAILURE, _("cannot set groups"));
|
|
@@ -535,6 +544,8 @@ usage (int status)
|
|
-c, --command <command> pass a single command to the shell with -c\n\
|
|
--session-command <command> pass a single command to the shell with -c\n\
|
|
and do not create a new session\n\
|
|
+ -g --group=group specify the primary group\n\
|
|
+ -G --supp-group=group specify a supplemental group\n\
|
|
-f, --fast pass -f to the shell (for csh or tcsh)\n\
|
|
-m, --preserve-environment do not reset environment variables\n\
|
|
-p same as -m\n\
|
|
@@ -556,6 +567,19 @@ void load_config(void)
|
|
logindefs_load_file(_PATH_LOGINDEFS);
|
|
}
|
|
|
|
+/*
|
|
+ * Returns 1 if the current user is not root
|
|
+ */
|
|
+static int
|
|
+evaluate_uid(void)
|
|
+{
|
|
+ uid_t ruid = getuid();
|
|
+ uid_t euid = geteuid();
|
|
+
|
|
+ /* if we're really root and aren't running setuid */
|
|
+ return (uid_t) 0 == ruid && ruid == euid ? 0 : 1;
|
|
+}
|
|
+
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
@@ -566,6 +590,11 @@ main (int argc, char **argv)
|
|
char *shell = NULL;
|
|
struct passwd *pw;
|
|
struct passwd pw_copy;
|
|
+ struct group *gr;
|
|
+ gid_t groups[NGROUPS_MAX];
|
|
+ int num_supp_groups = 0;
|
|
+ int use_gid = 0;
|
|
+ int restricted;
|
|
|
|
setlocale (LC_ALL, "");
|
|
bindtextdomain (PACKAGE, LOCALEDIR);
|
|
@@ -575,7 +604,7 @@ main (int argc, char **argv)
|
|
simulate_login = false;
|
|
change_environment = true;
|
|
|
|
- while ((optc = getopt_long (argc, argv, "c:flmps:hV", longopts, NULL)) != -1)
|
|
+ while ((optc = getopt_long (argc, argv, "c:fg:G:lmps:hV", longopts, NULL)) != -1)
|
|
{
|
|
switch (optc)
|
|
{
|
|
@@ -592,6 +621,26 @@ main (int argc, char **argv)
|
|
fast_startup = true;
|
|
break;
|
|
|
|
+ case 'g':
|
|
+ gr = getgrnam(optarg);
|
|
+ if (!gr)
|
|
+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
|
|
+ use_gid = 1;
|
|
+ groups[0] = gr->gr_gid;
|
|
+ break;
|
|
+
|
|
+ case 'G':
|
|
+ num_supp_groups++;
|
|
+ if (num_supp_groups >= NGROUPS_MAX)
|
|
+ errx(EXIT_FAILURE,
|
|
+ _("can't specify more than %d supplemental groups"),
|
|
+ NGROUPS_MAX - 1);
|
|
+ gr = getgrnam(optarg);
|
|
+ if (!gr)
|
|
+ errx(EXIT_FAILURE, _("group %s does not exist"), optarg);
|
|
+ groups[num_supp_groups] = gr->gr_gid;
|
|
+ break;
|
|
+
|
|
case 'l':
|
|
simulate_login = true;
|
|
break;
|
|
@@ -617,6 +666,8 @@ main (int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
+ restricted = evaluate_uid ();
|
|
+
|
|
if (optind < argc && !strcmp (argv[optind], "-"))
|
|
{
|
|
simulate_login = true;
|
|
@@ -625,6 +676,9 @@ main (int argc, char **argv)
|
|
if (optind < argc)
|
|
new_user = argv[optind++];
|
|
|
|
+ if ((num_supp_groups || use_gid) && restricted)
|
|
+ errx(EXIT_FAILURE, _("only root can specify alternative groups"));
|
|
+
|
|
logindefs_load_defaults = load_config;
|
|
|
|
pw = getpwnam (new_user);
|
|
@@ -648,6 +702,17 @@ main (int argc, char **argv)
|
|
: DEFAULT_SHELL);
|
|
endpwent ();
|
|
|
|
+ if (num_supp_groups && !use_gid)
|
|
+ {
|
|
+ pw->pw_gid = groups[1];
|
|
+ memmove (groups, groups + 1, sizeof(gid_t) * num_supp_groups);
|
|
+ }
|
|
+ else if (use_gid)
|
|
+ {
|
|
+ pw->pw_gid = groups[0];
|
|
+ num_supp_groups++;
|
|
+ }
|
|
+
|
|
authenticate (pw);
|
|
|
|
if (request_same_session || !command || !pw->pw_uid)
|
|
@@ -666,7 +731,7 @@ main (int argc, char **argv)
|
|
}
|
|
shell = xstrdup (shell ? shell : pw->pw_shell);
|
|
|
|
- init_groups (pw);
|
|
+ init_groups (pw, groups, num_supp_groups);
|
|
|
|
create_watching_parent ();
|
|
/* Now we're in the child. */
|
|
--
|
|
1.7.11.7
|
|
|