summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-selinux8
-rw-r--r--src/Makefile.am1
-rw-r--r--src/id.c63
3 files changed, 62 insertions, 10 deletions
diff --git a/ChangeLog-selinux b/ChangeLog-selinux
index cb5f4b398..4993bd88e 100644
--- a/ChangeLog-selinux
+++ b/ChangeLog-selinux
@@ -1,3 +1,11 @@
+2007-01-13 Jim Meyering <jim@meyering.net>
+
+ id: Add SELinux support: -Z option.
+ * src/id.c (main): Apply patches from Fedora, with these changes:
+ Remove #ifdef WITH_SELINUX.
+ Use error (EXIT_FAILURE, not fprintf+exit(1).
+ * src/Makefile.am (id_LDADD): Define, so as to add $(LIB_SELINUX).
+
2007-01-06 Jim Meyering <jim@meyering.net>
stat: Add support for SELinux in the form of a %C format directive.
diff --git a/src/Makefile.am b/src/Makefile.am
index 4bc4faefb..3f65a1e37 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -73,6 +73,7 @@ __LDADD = $(LDADD) $(LIB_EACCESS)
# for clock_gettime and fdatasync
dd_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
+id_LDADD = $(LDADD) $(LIB_SELINUX)
ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
pr_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
shred_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
diff --git a/src/id.c b/src/id.c
index 7ed7167ee..cc34d2f4a 100644
--- a/src/id.c
+++ b/src/id.c
@@ -1,5 +1,5 @@
/* id -- print real and effective UIDs and GIDs
- Copyright (C) 1989-2005 Free Software Foundation, Inc.
+ Copyright (C) 1989-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include <pwd.h>
#include <grp.h>
#include <getopt.h>
+#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -37,6 +38,9 @@
int getugroups ();
+/* If nonzero, output only the SELinux context. -Z */
+static int just_context = 0;
+
static void print_user (uid_t uid);
static void print_group (gid_t gid);
static void print_group_list (const char *username);
@@ -55,8 +59,13 @@ static gid_t rgid, egid;
/* True unless errors have been encountered. */
static bool ok = true;
+/* The SELinux context. Start with a known invalid value so print_full_info
+ knows when `context' has not been set to a meaningful value. */
+static security_context_t context = NULL;
+
static struct option const longopts[] =
{
+ {"context", no_argument, NULL, 'Z'},
{"group", no_argument, NULL, 'g'},
{"groups", no_argument, NULL, 'G'},
{"name", no_argument, NULL, 'n'},
@@ -80,6 +89,7 @@ usage (int status)
Print information for USERNAME, or the current user.\n\
\n\
-a ignore, for compatibility with other versions\n\
+ -Z, --context print only the security context of the current user\n\
-g, --group print only the effective group ID\n\
-G, --groups print all group IDs\n\
-n, --name print a name instead of a number, for -ugG\n\
@@ -101,6 +111,7 @@ int
main (int argc, char **argv)
{
int optc;
+ int selinux_enabled = (is_selinux_enabled () > 0);
/* If true, output the list of all group IDs. -G */
bool just_group_list = false;
@@ -119,13 +130,22 @@ main (int argc, char **argv)
atexit (close_stdout);
- while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "agnruGZ", longopts, NULL)) != -1)
{
switch (optc)
{
case 'a':
/* Ignore -a, for compatibility with SVR4. */
break;
+
+ case 'Z':
+ /* politely decline if we're not on a selinux-enabled kernel. */
+ if (!selinux_enabled)
+ error (EXIT_FAILURE, 0, _("--context (-Z) can be used only on "
+ "an SELinux-enabled kernel"));
+ just_context = 1;
+ break;
+
case 'g':
just_group = true;
break;
@@ -148,19 +168,38 @@ main (int argc, char **argv)
}
}
- if (just_user + just_group + just_group_list > 1)
- error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
-
- if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
- error (EXIT_FAILURE, 0,
- _("cannot print only names or real IDs in default format"));
-
- if (argc - optind > 1)
+ if (1 < argc - optind)
{
error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
usage (EXIT_FAILURE);
}
+ if (argc - optind == 1 && just_context)
+ error (EXIT_FAILURE, 0,
+ _("cannot print security context when user specified"));
+
+ if (just_context && !selinux_enabled)
+ error (EXIT_FAILURE, 0, _("\
+cannot display context when selinux not enabled or when displaying the id\n\
+of a different user"));
+
+ /* If we are on a selinux-enabled kernel, get our context.
+ Otherwise, leave the context variable alone - it has
+ been initialized known invalid value; if we see this invalid
+ value later, we will know we are on a non-selinux kernel. */
+ if (selinux_enabled)
+ {
+ if (getcon (&context) && just_context)
+ error (EXIT_FAILURE, 0, _("can't get process context"));
+ }
+
+ if (just_user + just_group + just_group_list + just_context > 1)
+ error (EXIT_FAILURE, 0, _("cannot print \"only\" of more than one choice"));
+
+ if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
+ error (EXIT_FAILURE, 0,
+ _("cannot print only names or real IDs in default format"));
+
if (argc - optind == 1)
{
struct passwd *pwd = getpwnam (argv[optind]);
@@ -183,6 +222,8 @@ main (int argc, char **argv)
print_group (use_real ? rgid : egid);
else if (just_group_list)
print_group_list (argv[optind]);
+ else if (just_context)
+ fputs (context, stdout);
else
print_full_info (argv[optind]);
putchar ('\n');
@@ -385,4 +426,6 @@ print_full_info (const char *username)
free (groups);
}
#endif /* HAVE_GETGROUPS */
+ if (context != NULL)
+ printf (" context=%s", context);
}