Do not create RMRR entries for identity-mapped domains.
[freebsd.git] / usr.bin / id / id.c
1 /*-
2  * Copyright (c) 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #ifndef lint
31 static const char copyright[] =
32 "@(#) Copyright (c) 1991, 1993\n\
33         The Regents of the University of California.  All rights reserved.\n";
34 #endif /* not lint */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)id.c        8.2 (Berkeley) 2/16/94";
39 #endif
40 #endif /* not lint */
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include <sys/param.h>
45 #include <sys/mac.h>
46
47 #ifdef USE_BSM_AUDIT
48 #include <bsm/audit.h>
49 #endif
50
51 #include <err.h>
52 #include <errno.h>
53 #include <grp.h>
54 #include <pwd.h>
55 #include <stdint.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60
61 static void     id_print(struct passwd *, int, int, int);
62 static void     pline(struct passwd *);
63 static void     pretty(struct passwd *);
64 #ifdef USE_BSM_AUDIT
65 static void     auditid(void);
66 #endif
67 static void     group(struct passwd *, int);
68 static void     maclabel(void);
69 static void     usage(void);
70 static struct passwd *who(char *);
71
72 static int isgroups, iswhoami;
73
74 int
75 main(int argc, char *argv[])
76 {
77         struct group *gr;
78         struct passwd *pw;
79         int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
80         int Aflag, cflag;
81         int error;
82         const char *myname;
83         char loginclass[MAXLOGNAME];
84
85         Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
86         Aflag = cflag = 0;
87
88         myname = strrchr(argv[0], '/');
89         myname = (myname != NULL) ? myname + 1 : argv[0];
90         if (strcmp(myname, "groups") == 0) {
91                 isgroups = 1;
92                 Gflag = nflag = 1;
93         }
94         else if (strcmp(myname, "whoami") == 0) {
95                 iswhoami = 1;
96                 uflag = nflag = 1;
97         }
98
99         while ((ch = getopt(argc, argv,
100             (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
101                 switch(ch) {
102 #ifdef USE_BSM_AUDIT
103                 case 'A':
104                         Aflag = 1;
105                         break;
106 #endif
107                 case 'G':
108                         Gflag = 1;
109                         break;
110                 case 'M':
111                         Mflag = 1;
112                         break;
113                 case 'P':
114                         Pflag = 1;
115                         break;
116                 case 'a':
117                         break;
118                 case 'c':
119                         cflag = 1;
120                         break;
121                 case 'g':
122                         gflag = 1;
123                         break;
124                 case 'n':
125                         nflag = 1;
126                         break;
127                 case 'p':
128                         pflag = 1;
129                         break;
130                 case 'r':
131                         rflag = 1;
132                         break;
133                 case 'u':
134                         uflag = 1;
135                         break;
136                 case '?':
137                 default:
138                         usage();
139                 }
140         argc -= optind;
141         argv += optind;
142
143         if (iswhoami && argc > 0)
144                 usage();
145
146         switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
147         case 1:
148                 break;
149         case 0:
150                 if (!nflag && !rflag)
151                         break;
152                 /* FALLTHROUGH */
153         default:
154                 usage();
155         }
156
157         pw = *argv ? who(*argv) : NULL;
158
159         if (Mflag && pw != NULL)
160                 usage();
161
162 #ifdef USE_BSM_AUDIT
163         if (Aflag) {
164                 auditid();
165                 exit(0);
166         }
167 #endif
168
169         if (cflag) {
170                 error = getloginclass(loginclass, sizeof(loginclass));
171                 if (error != 0)
172                         err(1, "loginclass");
173                 (void)printf("%s\n", loginclass);
174                 exit(0);
175         }
176
177         if (gflag) {
178                 id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
179                 if (nflag && (gr = getgrgid(id)))
180                         (void)printf("%s\n", gr->gr_name);
181                 else
182                         (void)printf("%u\n", id);
183                 exit(0);
184         }
185
186         if (uflag) {
187                 id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
188                 if (nflag && (pw = getpwuid(id)))
189                         (void)printf("%s\n", pw->pw_name);
190                 else
191                         (void)printf("%u\n", id);
192                 exit(0);
193         }
194
195         if (Gflag) {
196                 group(pw, nflag);
197                 exit(0);
198         }
199
200         if (Mflag) {
201                 maclabel();
202                 exit(0);
203         }
204
205         if (Pflag) {
206                 pline(pw);
207                 exit(0);
208         }
209
210         if (pflag) {
211                 pretty(pw);
212                 exit(0);
213         }
214
215         if (pw) {
216                 id_print(pw, 1, 0, 0);
217         }
218         else {
219                 id = getuid();
220                 pw = getpwuid(id);
221                 id_print(pw, 0, 1, 1);
222         }
223         exit(0);
224 }
225
226 static void
227 pretty(struct passwd *pw)
228 {
229         struct group *gr;
230         u_int eid, rid;
231         char *login;
232
233         if (pw) {
234                 (void)printf("uid\t%s\n", pw->pw_name);
235                 (void)printf("groups\t");
236                 group(pw, 1);
237         } else {
238                 if ((login = getlogin()) == NULL)
239                         err(1, "getlogin");
240
241                 pw = getpwuid(rid = getuid());
242                 if (pw == NULL || strcmp(login, pw->pw_name))
243                         (void)printf("login\t%s\n", login);
244                 if (pw)
245                         (void)printf("uid\t%s\n", pw->pw_name);
246                 else
247                         (void)printf("uid\t%u\n", rid);
248
249                 if ((eid = geteuid()) != rid) {
250                         if ((pw = getpwuid(eid)))
251                                 (void)printf("euid\t%s\n", pw->pw_name);
252                         else
253                                 (void)printf("euid\t%u\n", eid);
254                 }
255                 if ((rid = getgid()) != (eid = getegid())) {
256                         if ((gr = getgrgid(rid)))
257                                 (void)printf("rgid\t%s\n", gr->gr_name);
258                         else
259                                 (void)printf("rgid\t%u\n", rid);
260                 }
261                 (void)printf("groups\t");
262                 group(NULL, 1);
263         }
264 }
265
266 static void
267 id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
268 {
269         struct group *gr;
270         gid_t gid, egid, lastgid;
271         uid_t uid, euid;
272         int cnt, ngroups;
273         long ngroups_max;
274         gid_t *groups;
275         const char *fmt;
276
277         if (pw != NULL) {
278                 uid = pw->pw_uid;
279                 gid = pw->pw_gid;
280         }
281         else {
282                 uid = getuid();
283                 gid = getgid();
284         }
285
286         ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
287         if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
288                 err(1, "malloc");
289
290         if (use_ggl && pw != NULL) {
291                 ngroups = ngroups_max;
292                 getgrouplist(pw->pw_name, gid, groups, &ngroups);
293         }
294         else {
295                 ngroups = getgroups(ngroups_max, groups);
296         }
297
298         if (pw != NULL)
299                 printf("uid=%u(%s)", uid, pw->pw_name);
300         else 
301                 printf("uid=%u", getuid());
302         printf(" gid=%u", gid);
303         if ((gr = getgrgid(gid)))
304                 (void)printf("(%s)", gr->gr_name);
305         if (p_euid && (euid = geteuid()) != uid) {
306                 (void)printf(" euid=%u", euid);
307                 if ((pw = getpwuid(euid)))
308                         (void)printf("(%s)", pw->pw_name);
309         }
310         if (p_egid && (egid = getegid()) != gid) {
311                 (void)printf(" egid=%u", egid);
312                 if ((gr = getgrgid(egid)))
313                         (void)printf("(%s)", gr->gr_name);
314         }
315         fmt = " groups=%u";
316         for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
317                 if (lastgid == (gid = groups[cnt]))
318                         continue;
319                 printf(fmt, gid);
320                 fmt = ",%u";
321                 if ((gr = getgrgid(gid)))
322                         printf("(%s)", gr->gr_name);
323                 lastgid = gid;
324         }
325         printf("\n");
326         free(groups);
327 }
328
329 #ifdef USE_BSM_AUDIT
330 static void
331 auditid(void)
332 {
333         auditinfo_t auditinfo;
334         auditinfo_addr_t ainfo_addr;
335         int ret, extended;
336
337         extended = 0;
338         ret = getaudit(&auditinfo);
339         if (ret < 0 && errno == E2BIG) {
340                 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0)
341                         err(1, "getaudit_addr");
342                 extended = 1;
343         } else if (ret < 0)
344                 err(1, "getaudit");
345         if (extended != 0) {
346                 (void) printf("auid=%d\n"
347                     "mask.success=0x%08x\n"
348                     "mask.failure=0x%08x\n"
349                     "asid=%d\n"
350                     "termid_addr.port=0x%08jx\n"
351                     "termid_addr.addr[0]=0x%08x\n"
352                     "termid_addr.addr[1]=0x%08x\n"
353                     "termid_addr.addr[2]=0x%08x\n"
354                     "termid_addr.addr[3]=0x%08x\n",
355                         ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success,
356                         ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid,
357                         (uintmax_t)ainfo_addr.ai_termid.at_port,
358                         ainfo_addr.ai_termid.at_addr[0],
359                         ainfo_addr.ai_termid.at_addr[1],
360                         ainfo_addr.ai_termid.at_addr[2],
361                         ainfo_addr.ai_termid.at_addr[3]);
362         } else {
363                 (void) printf("auid=%d\n"
364                     "mask.success=0x%08x\n"
365                     "mask.failure=0x%08x\n"
366                     "asid=%d\n"
367                     "termid.port=0x%08jx\n"
368                     "termid.machine=0x%08x\n",
369                         auditinfo.ai_auid, auditinfo.ai_mask.am_success,
370                         auditinfo.ai_mask.am_failure,
371                         auditinfo.ai_asid, (uintmax_t)auditinfo.ai_termid.port,
372                         auditinfo.ai_termid.machine);
373         }
374 }
375 #endif
376
377 static void
378 group(struct passwd *pw, int nflag)
379 {
380         struct group *gr;
381         int cnt, id, lastid, ngroups;
382         long ngroups_max;
383         gid_t *groups;
384         const char *fmt;
385
386         ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
387         if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL)
388                 err(1, "malloc");
389
390         if (pw) {
391                 ngroups = ngroups_max;
392                 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
393         } else {
394                 ngroups = getgroups(ngroups_max, groups);
395         }
396         fmt = nflag ? "%s" : "%u";
397         for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
398                 if (lastid == (id = groups[cnt]))
399                         continue;
400                 if (nflag) {
401                         if ((gr = getgrgid(id)))
402                                 (void)printf(fmt, gr->gr_name);
403                         else
404                                 (void)printf(*fmt == ' ' ? " %u" : "%u",
405                                     id);
406                         fmt = " %s";
407                 } else {
408                         (void)printf(fmt, id);
409                         fmt = " %u";
410                 }
411                 lastid = id;
412         }
413         (void)printf("\n");
414         free(groups);
415 }
416
417 static void
418 maclabel(void)
419 {
420         char *string;
421         mac_t label;
422         int error;
423
424         error = mac_prepare_process_label(&label);
425         if (error == -1)
426                 errx(1, "mac_prepare_type: %s", strerror(errno));
427
428         error = mac_get_proc(label);
429         if (error == -1)
430                 errx(1, "mac_get_proc: %s", strerror(errno));
431
432         error = mac_to_text(label, &string);
433         if (error == -1)
434                 errx(1, "mac_to_text: %s", strerror(errno));
435
436         (void)printf("%s\n", string);
437         mac_free(label);
438         free(string);
439 }
440
441 static struct passwd *
442 who(char *u)
443 {
444         struct passwd *pw;
445         long id;
446         char *ep;
447
448         /*
449          * Translate user argument into a pw pointer.  First, try to
450          * get it as specified.  If that fails, try it as a number.
451          */
452         if ((pw = getpwnam(u)))
453                 return(pw);
454         id = strtol(u, &ep, 10);
455         if (*u && !*ep && (pw = getpwuid(id)))
456                 return(pw);
457         errx(1, "%s: no such user", u);
458         /* NOTREACHED */
459 }
460
461 static void
462 pline(struct passwd *pw)
463 {
464
465         if (!pw) {
466                 if ((pw = getpwuid(getuid())) == NULL)
467                         err(1, "getpwuid");
468         }
469
470         (void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
471                         pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
472                         (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
473                         pw->pw_dir, pw->pw_shell);
474 }
475
476
477 static void
478 usage(void)
479 {
480
481         if (isgroups)
482                 (void)fprintf(stderr, "usage: groups [user]\n");
483         else if (iswhoami)
484                 (void)fprintf(stderr, "usage: whoami\n");
485         else
486                 (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
487                     "usage: id [user]",
488 #ifdef USE_BSM_AUDIT
489                     "       id -A\n",
490 #else
491                     "",
492 #endif
493                     "       id -G [-n] [user]",
494                     "       id -M",
495                     "       id -P [user]",
496                     "       id -c",
497                     "       id -g [-nr] [user]",
498                     "       id -p [user]",
499                     "       id -u [-nr] [user]");
500         exit(1);
501 }