1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <string.h>
30 #include <libintl.h>
31 #include <locale.h>
32 #include <deflt.h>
33 #include <user_attr.h>
34 #include <prof_attr.h>
35 #include <exec_attr.h>
36 #include <auth_attr.h>
37
38
39 #define EXIT_OK 0
40 #define EXIT_FATAL 1
41 #define EXIT_NON_FATAL 2
42
43 #define TMP_BUF_LEN 2048 /* size of temp string buffer */
44
45 #define PRINT_DEFAULT 0x0000
46 #define PRINT_NAME 0x0010
47 #define PRINT_LONG 0x0020
48
49 #ifndef TEXT_DOMAIN /* Should be defined by cc -D */
50 #define TEXT_DOMAIN "SYS_TEST"
51 #endif
52
53 static void usage();
54 static int show_profs(char *, int);
55 static void print_profs_long(execattr_t *);
56 static void print_profile_privs(kva_t *);
57
58 static char *progname = "profiles";
59
60 int
main(int argc,char * argv[])61 main(int argc, char *argv[])
62 {
63 extern int optind;
64 int c;
65 int status = EXIT_OK;
66 int print_flag = PRINT_DEFAULT;
67
68 (void) setlocale(LC_ALL, "");
69 (void) textdomain(TEXT_DOMAIN);
70
71 while ((c = getopt(argc, argv, "l")) != EOF) {
72 switch (c) {
73 case 'l':
74 print_flag |= PRINT_LONG;
75 break;
76 default:
77 usage();
78 return (EXIT_FATAL);
79 }
80 }
81 argc -= optind;
82 argv += optind;
83
84 if (*argv == NULL) {
85 status = show_profs(NULL, print_flag);
86 } else {
87 do {
88 (void) printf("%s:\n", *argv);
89 status = show_profs((char *)*argv,
90 (print_flag | PRINT_NAME));
91 if (status == EXIT_FATAL) {
92 break;
93 }
94 if (argv[1] != NULL) {
95 /* seperate users with empty line */
96 (void) printf("\n");
97 }
98 } while (*++argv);
99 }
100 status = (status == EXIT_OK) ? status : EXIT_FATAL;
101
102 return (status);
103 }
104
105 static int
show_profs_callback(const char * prof,kva_t * pa,void * pflag,void * vcnt)106 show_profs_callback(const char *prof, kva_t *pa, void *pflag, void *vcnt)
107 {
108 char *indent = "";
109 const int *print_flag = pflag;
110 int *pcnt = vcnt;
111
112 (*pcnt)++;
113
114 if ((*print_flag) & PRINT_NAME) {
115 indent = " ";
116 }
117
118 (void) printf("%s%s", indent, prof);
119 print_profile_privs(pa);
120 (void) printf("\n");
121
122 return (0);
123 }
124
125 static int
show_profs(char * username,int print_flag)126 show_profs(char *username, int print_flag)
127 {
128 int status = EXIT_OK;
129 struct passwd *pw;
130 execattr_t *exec;
131
132 if (username == NULL) {
133 if ((pw = getpwuid(getuid())) == NULL) {
134 status = EXIT_NON_FATAL;
135 (void) fprintf(stderr, "%s: ", progname);
136 (void) fprintf(stderr, gettext("No passwd entry\n"));
137 return (status);
138 }
139 username = pw->pw_name;
140 } else if (getpwnam(username) == NULL) {
141 status = EXIT_NON_FATAL;
142 (void) fprintf(stderr, "%s: %s: ", progname, username);
143 (void) fprintf(stderr, gettext("No such user\n"));
144 return (status);
145 }
146
147 if (print_flag & PRINT_LONG) {
148 exec = getexecuser(username, KV_COMMAND, NULL,
149 GET_ALL|__SEARCH_ALL_POLS);
150 if (exec != NULL) {
151 print_profs_long(exec);
152 free_execattr(exec);
153 } else {
154 status = EXIT_NON_FATAL;
155 }
156 } else {
157 int cnt = 0;
158 (void) _enum_profs(username, show_profs_callback, &print_flag,
159 &cnt);
160
161 if (cnt == 0)
162 status = EXIT_NON_FATAL;
163 }
164
165 if (status == EXIT_NON_FATAL) {
166 (void) fprintf(stderr, "%s: %s: ", progname, username);
167 (void) fprintf(stderr, gettext("No profiles\n"));
168 }
169
170 return (status);
171 }
172
173 /*
174 * print extended profile information.
175 *
176 * output is "pretty printed" like
177 * [6spaces]Profile Name1[ possible profile privileges]
178 * [10spaces ]execname1 [skip to ATTR_COL]exec1 attributes1
179 * [ spaces to ATTR_COL ]exec1 attributes2
180 * [10spaces ]execname2 [skip to ATTR_COL]exec2 attributes1
181 * [ spaces to ATTR_COL ]exec2 attributes2
182 * [6spaces]Profile Name2[ possible profile privileges]
183 * etc
184 */
185 /*
186 * ATTR_COL is based on
187 * 10 leading spaces +
188 * 25 positions for the executable +
189 * 1 space seperating the execname from the attributes
190 * so attribute printing starts at column 37 (36 whitespaces)
191 *
192 * 25 spaces for the execname seems reasonable since currently
193 * less than 3% of the shipped exec_attr would overflow this
194 */
195 #define ATTR_COL 37
196
197 static void
print_profs_long(execattr_t * exec)198 print_profs_long(execattr_t *exec)
199 {
200 char *curprofile;
201 int len;
202 kv_t *kv_pair;
203 char *key;
204 char *val;
205 int i;
206
207 for (curprofile = ""; exec != NULL; exec = exec->next) {
208 /* print profile name if it is a new one */
209 if (strcmp(curprofile, exec->name) != 0) {
210 profattr_t *pa;
211 curprofile = exec->name;
212
213 (void) printf(" %s", curprofile);
214
215 pa = getprofnam(curprofile);
216 if (pa != NULL) {
217 print_profile_privs(pa->attr);
218 free_profattr(pa);
219 }
220 (void) printf("\n");
221 }
222 len = printf(" %s ", exec->id);
223
224 if ((exec->attr == NULL || exec->attr->data == NULL)) {
225 (void) printf("\n");
226 continue;
227 }
228
229 /*
230 * if printing the name of the executable got us past the
231 * ATTR_COLth column, skip to ATTR_COL on a new line to
232 * print the attribues.
233 * else, just skip to ATTR_COL column.
234 */
235 if (len >= ATTR_COL)
236 (void) printf("\n%*s", ATTR_COL, " ");
237 else
238 (void) printf("%*s", ATTR_COL-len, " ");
239 len = ATTR_COL;
240
241 /* print all attributes of this profile */
242 kv_pair = exec->attr->data;
243 for (i = 0; i < exec->attr->length; i++) {
244 key = kv_pair[i].key;
245 val = kv_pair[i].value;
246 if (key == NULL || val == NULL)
247 break;
248 /* align subsequent attributes on the same column */
249 if (i > 0)
250 (void) printf("%*s", len, " ");
251 (void) printf("%s=%s\n", key, val);
252 }
253 }
254 }
255
256 static void
usage()257 usage()
258 {
259 (void) fprintf(stderr,
260 gettext(" usage: profiles [-l] [user1 user2 ...]\n"));
261 }
262
263 static void
print_profile_privs(kva_t * attr)264 print_profile_privs(kva_t *attr)
265 {
266 char *privs;
267
268 if (attr) {
269 privs = kva_match(attr, PROFATTR_PRIVS_KW);
270 if (privs)
271 (void) printf(" privs=%s", privs);
272 }
273 }
274