blob: aa27ed39463adc682f330a488d04f1736a8dfbfe [file] [log] [blame]
Erik Andersen94f5e0b2000-05-01 19:10:52 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Mini id implementation for busybox
4 *
Erik Andersen94f5e0b2000-05-01 19:10:52 +00005 * Copyright (C) 2000 by Randolph Chung <tausq@debian.org>
6 *
Bernhard Reutner-Fischerb1629b12006-05-19 19:29:19 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Erik Andersen94f5e0b2000-05-01 19:10:52 +00008 */
9
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000010/* BB_AUDIT SUSv3 compliant. */
Eric Andersen7eb79ff2004-09-02 22:21:41 +000011/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000012 * be more similar to GNU id.
Denis Vlasenko49622d72007-03-10 16:58:49 +000013 * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000014 * Added -G option Tito Ragusa (C) 2008 for SUSv3.
Eric Andersen7eb79ff2004-09-02 22:21:41 +000015 */
Manuel Novoa III cad53642003-03-19 09:13:01 +000016
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000017#include "libbb.h"
Eric Andersen7eb79ff2004-09-02 22:21:41 +000018
Eric Andersen7eb79ff2004-09-02 22:21:41 +000019#define PRINT_REAL 1
20#define NAME_NOT_NUMBER 2
21#define JUST_USER 4
22#define JUST_GROUP 8
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000023#define JUST_ALL_GROUPS 16
Denis Vlasenko49622d72007-03-10 16:58:49 +000024#if ENABLE_SELINUX
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000025#define JUST_CONTEXT 32
Denis Vlasenko49622d72007-03-10 16:58:49 +000026#endif
Eric Andersen7eb79ff2004-09-02 22:21:41 +000027
Denis Vlasenko0d602e92008-09-14 19:31:36 +000028static int printf_full(unsigned id, const char *arg, const char *prefix)
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000029{
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000030 const char *fmt = "%s%u";
Denis Vlasenko3734b942007-07-27 11:20:10 +000031 int status = EXIT_FAILURE;
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000032
Denis Vlasenkode59c0f2006-10-05 22:50:22 +000033 if (arg) {
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000034 fmt = "%s%u(%s)";
Denis Vlasenkode59c0f2006-10-05 22:50:22 +000035 status = EXIT_SUCCESS;
Glenn L McGrathf15dfc52004-09-15 03:04:08 +000036 }
Denis Vlasenkof0ed3762006-10-26 23:21:47 +000037 printf(fmt, prefix, id, arg);
Glenn L McGrathf15dfc52004-09-15 03:04:08 +000038 return status;
Eric Andersen7eb79ff2004-09-02 22:21:41 +000039}
Manuel Novoa III cad53642003-03-19 09:13:01 +000040
Denis Vlasenko22284262008-09-18 00:56:24 +000041#if (defined(__GLIBC__) && !defined(__UCLIBC__))
42#define HAVE_getgrouplist 1
43#elif ENABLE_USE_BB_PWD_GRP
44#define HAVE_getgrouplist 1
45#else
46#define HAVE_getgrouplist 0
47#endif
48
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000049int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000050int id_main(int argc UNUSED_PARAM, char **argv)
Erik Andersen94f5e0b2000-05-01 19:10:52 +000051{
Denis Vlasenko22284262008-09-18 00:56:24 +000052 const char *username;
Eric Andersen7eb79ff2004-09-02 22:21:41 +000053 struct passwd *p;
Eric Andersen7eb79ff2004-09-02 22:21:41 +000054 uid_t uid;
55 gid_t gid;
Denis Vlasenko22284262008-09-18 00:56:24 +000056#if HAVE_getgrouplist
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000057 gid_t *groups;
Denis Vlasenko4f3209b2008-09-13 12:51:10 +000058 int n;
Denis Vlasenko22284262008-09-18 00:56:24 +000059#endif
Denis Vlasenko0d602e92008-09-14 19:31:36 +000060 unsigned flags;
Glenn L McGrathf15dfc52004-09-15 03:04:08 +000061 short status;
Denis Vlasenko49622d72007-03-10 16:58:49 +000062#if ENABLE_SELINUX
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000063 security_context_t scontext;
Denis Vlasenko49622d72007-03-10 16:58:49 +000064#endif
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000065 /* Don't allow -n -r -nr -ug -rug -nug -rnug */
Glenn L McGrathf15dfc52004-09-15 03:04:08 +000066 /* Don't allow more than one username */
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +000067 opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
68 flags = getopt32(argv, "rnugG" USE_SELINUX("Z"));
Denis Vlasenko22284262008-09-18 00:56:24 +000069 username = argv[optind];
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000070
Eric Andersen7eb79ff2004-09-02 22:21:41 +000071 /* This values could be overwritten later */
72 uid = geteuid();
73 gid = getegid();
74 if (flags & PRINT_REAL) {
75 uid = getuid();
76 gid = getgid();
Erik Andersen94f5e0b2000-05-01 19:10:52 +000077 }
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +000078
Denis Vlasenko22284262008-09-18 00:56:24 +000079 if (username) {
80#if HAVE_getgrouplist
81 int m;
82#endif
83 p = getpwnam(username);
Denis Vlasenko9a44c4f2006-12-28 05:44:47 +000084 /* xuname2uid is needed because it exits on failure */
Denis Vlasenko22284262008-09-18 00:56:24 +000085 uid = xuname2uid(username);
86 gid = p->pw_gid; /* in this case PRINT_REAL is the same */
87
88#if HAVE_getgrouplist
89 n = 16;
90 groups = NULL;
91 do {
92 m = n;
93 groups = xrealloc(groups, sizeof(groups[0]) * m);
94 getgrouplist(username, gid, groups, &n); /* GNUism? */
95 } while (n > m);
96#endif
97 } else {
98#if HAVE_getgrouplist
99 n = getgroups(0, NULL);
100 groups = xmalloc(sizeof(groups[0]) * n);
101 getgroups(n, groups);
102#endif
Erik Andersen94f5e0b2000-05-01 19:10:52 +0000103 }
104
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000105 if (flags & JUST_ALL_GROUPS) {
Denis Vlasenko22284262008-09-18 00:56:24 +0000106#if HAVE_getgrouplist
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000107 while (n--) {
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +0000108 if (flags & NAME_NOT_NUMBER)
109 printf("%s", bb_getgrgid(NULL, 0, *groups++));
110 else
Denis Vlasenko0d602e92008-09-14 19:31:36 +0000111 printf("%u", (unsigned) *groups++);
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000112 bb_putchar((n > 0) ? ' ' : '\n');
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +0000113 }
Denis Vlasenko22284262008-09-18 00:56:24 +0000114#endif
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +0000115 /* exit */
116 fflush_stdout_and_exit(EXIT_SUCCESS);
117 }
118
Denis Vlasenko49622d72007-03-10 16:58:49 +0000119 if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
Glenn L McGrathf15dfc52004-09-15 03:04:08 +0000120 /* JUST_GROUP and JUST_USER are mutually exclusive */
Denis Vlasenkode59c0f2006-10-05 22:50:22 +0000121 if (flags & NAME_NOT_NUMBER) {
Denis Vlasenko0d602e92008-09-14 19:31:36 +0000122 /* bb_getXXXid(-1) exits on failure, puts cannot segfault */
Denis Vlasenko3734b942007-07-27 11:20:10 +0000123 puts((flags & JUST_USER) ? bb_getpwuid(NULL, -1, uid) : bb_getgrgid(NULL, -1, gid));
Glenn L McGrathf15dfc52004-09-15 03:04:08 +0000124 } else {
Denis Vlasenko49622d72007-03-10 16:58:49 +0000125 if (flags & JUST_USER) {
Denis Vlasenko0d602e92008-09-14 19:31:36 +0000126 printf("%u\n", (unsigned)uid);
Denis Vlasenkoc86e0522007-03-20 11:30:28 +0000127 }
128 if (flags & JUST_GROUP) {
Denis Vlasenko0d602e92008-09-14 19:31:36 +0000129 printf("%u\n", (unsigned)gid);
Denis Vlasenkoc86e0522007-03-20 11:30:28 +0000130 }
131 }
132
Denis Vlasenko49622d72007-03-10 16:58:49 +0000133#if ENABLE_SELINUX
Denis Vlasenkoc86e0522007-03-20 11:30:28 +0000134 if (flags & JUST_CONTEXT) {
Denis Vlasenko49622d72007-03-10 16:58:49 +0000135 selinux_or_die();
Denis Vlasenko22284262008-09-18 00:56:24 +0000136 if (username) {
Denis Vlasenkoc86e0522007-03-20 11:30:28 +0000137 bb_error_msg_and_die("user name can't be passed with -Z");
138 }
139
140 if (getcon(&scontext)) {
141 bb_error_msg_and_die("can't get process context");
142 }
Denis Vlasenkofeb7ae72007-10-01 12:05:12 +0000143 puts(scontext);
Denis Vlasenkoc86e0522007-03-20 11:30:28 +0000144 }
145#endif
"Vladimir N. Oleynik"064f04e2005-10-11 14:38:01 +0000146 /* exit */
Denis Vlasenkof0ed3762006-10-26 23:21:47 +0000147 fflush_stdout_and_exit(EXIT_SUCCESS);
Eric Andersenc1b8f122001-01-25 05:12:02 +0000148 }
Glenn L McGrathf15dfc52004-09-15 03:04:08 +0000149
Eric Andersen7eb79ff2004-09-02 22:21:41 +0000150 /* Print full info like GNU id */
Denis Vlasenko3734b942007-07-27 11:20:10 +0000151 /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +0000152 status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid=");
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000153 status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid=");
Denis Vlasenko22284262008-09-18 00:56:24 +0000154#if HAVE_getgrouplist
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000155 {
156 const char *msg = " groups=";
157 while (n--) {
158 status |= printf_full(*groups, bb_getgrgid(NULL, 0, *groups), msg);
159 msg = ",";
160 groups++;
161 }
Bernhard Reutner-Fischer0ee1cb02008-09-12 09:58:11 +0000162 }
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000163 /* we leak groups vector... */
Denis Vlasenko22284262008-09-18 00:56:24 +0000164#endif
Denis Vlasenko4f3209b2008-09-13 12:51:10 +0000165
Denis Vlasenko49622d72007-03-10 16:58:49 +0000166#if ENABLE_SELINUX
Denis Vlasenkode59c0f2006-10-05 22:50:22 +0000167 if (is_selinux_enabled()) {
Denis Vlasenko7fa0fca2006-12-28 21:33:30 +0000168 security_context_t mysid;
Denis Vlasenko7fa0fca2006-12-28 21:33:30 +0000169 getcon(&mysid);
Denis Vlasenko0d602e92008-09-14 19:31:36 +0000170 printf(" context=%s", mysid ? mysid : "unknown");
171 if (mysid) /* TODO: maybe freecon(NULL) is harmless? */
Denis Vlasenko7fa0fca2006-12-28 21:33:30 +0000172 freecon(mysid);
Eric Andersen7eb79ff2004-09-02 22:21:41 +0000173 }
174#endif
Rob Landley60158cb2005-05-03 06:25:50 +0000175
Denis Vlasenko4daad902007-09-27 10:20:47 +0000176 bb_putchar('\n');
Denis Vlasenkof0ed3762006-10-26 23:21:47 +0000177 fflush_stdout_and_exit(status);
Erik Andersen94f5e0b2000-05-01 19:10:52 +0000178}