Annotation of embedaddon/sudo/plugins/sudoers/parse.c, revision 1.1.1.5
1.1 misho 1: /*
1.1.1.4 misho 2: * Copyright (c) 2004-2005, 2007-2013 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 misho 3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
16: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17: */
18:
19: #include <config.h>
20:
21: #include <sys/types.h>
22: #include <stdio.h>
23: #ifdef STDC_HEADERS
24: # include <stdlib.h>
25: # include <stddef.h>
26: #else
27: # ifdef HAVE_STDLIB_H
28: # include <stdlib.h>
29: # endif
30: #endif /* STDC_HEADERS */
31: #ifdef HAVE_STRING_H
32: # include <string.h>
33: #endif /* HAVE_STRING_H */
34: #ifdef HAVE_STRINGS_H
35: # include <strings.h>
36: #endif /* HAVE_STRINGS_H */
37: #ifdef HAVE_UNISTD_H
38: # include <unistd.h>
39: #endif /* HAVE_UNISTD_H */
40: #include <ctype.h>
41: #include <pwd.h>
42: #include <grp.h>
43:
44: #include "sudoers.h"
45: #include "parse.h"
46: #include "lbuf.h"
47: #include <gram.h>
48:
49: /* Characters that must be quoted in sudoers */
1.1.1.4 misho 50: #define SUDOERS_QUOTED ":\\,=#\""
1.1 misho 51:
52: /* sudoers nsswitch routines */
53: struct sudo_nss sudo_nss_file = {
1.1.1.5 ! misho 54: { NULL, NULL },
1.1 misho 55: sudo_file_open,
56: sudo_file_close,
57: sudo_file_parse,
58: sudo_file_setdefs,
59: sudo_file_lookup,
60: sudo_file_display_cmnd,
61: sudo_file_display_defaults,
62: sudo_file_display_bound_defaults,
63: sudo_file_display_privs
64: };
65:
66: /*
67: * Local prototypes.
68: */
1.1.1.4 misho 69: static int display_bound_defaults(int dtype, struct lbuf *lbuf);
70: static void print_member(struct lbuf *lbuf, struct member *m, int alias_type);
71: static void print_member2(struct lbuf *lbuf, struct member *m,
72: const char *separator, int alias_type);
1.1 misho 73:
74: int
75: sudo_file_open(struct sudo_nss *nss)
76: {
1.1.1.2 misho 77: debug_decl(sudo_file_open, SUDO_DEBUG_NSS)
78:
1.1 misho 79: if (def_ignore_local_sudoers)
1.1.1.2 misho 80: debug_return_int(-1);
81: nss->handle = open_sudoers(sudoers_file, false, NULL);
82: debug_return_int(nss->handle ? 0 : -1);
1.1 misho 83: }
84:
85: int
86: sudo_file_close(struct sudo_nss *nss)
87: {
1.1.1.2 misho 88: debug_decl(sudo_file_close, SUDO_DEBUG_NSS)
89:
1.1 misho 90: /* Free parser data structures and close sudoers file. */
1.1.1.3 misho 91: init_parser(NULL, false);
1.1 misho 92: if (nss->handle != NULL) {
93: fclose(nss->handle);
94: nss->handle = NULL;
1.1.1.4 misho 95: sudoersin = NULL;
1.1 misho 96: }
1.1.1.2 misho 97: debug_return_int(0);
1.1 misho 98: }
99:
100: /*
101: * Parse the specified sudoers file.
102: */
103: int
104: sudo_file_parse(struct sudo_nss *nss)
105: {
1.1.1.2 misho 106: debug_decl(sudo_file_close, SUDO_DEBUG_NSS)
107:
1.1 misho 108: if (nss->handle == NULL)
1.1.1.2 misho 109: debug_return_int(-1);
1.1 misho 110:
1.1.1.3 misho 111: init_parser(sudoers_file, false);
1.1.1.4 misho 112: sudoersin = nss->handle;
113: if (sudoersparse() != 0 || parse_error) {
1.1.1.2 misho 114: if (errorlineno != -1) {
1.1.1.4 misho 115: log_warning(0, N_("parse error in %s near line %d"),
1.1.1.2 misho 116: errorfile, errorlineno);
117: } else {
1.1.1.4 misho 118: log_warning(0, N_("parse error in %s"), errorfile);
1.1.1.2 misho 119: }
120: debug_return_int(-1);
1.1 misho 121: }
1.1.1.2 misho 122: debug_return_int(0);
1.1 misho 123: }
124:
125: /*
126: * Wrapper around update_defaults() for nsswitch code.
127: */
128: int
129: sudo_file_setdefs(struct sudo_nss *nss)
130: {
1.1.1.2 misho 131: debug_decl(sudo_file_setdefs, SUDO_DEBUG_NSS)
132:
1.1 misho 133: if (nss->handle == NULL)
1.1.1.2 misho 134: debug_return_int(-1);
1.1 misho 135:
136: if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER))
1.1.1.2 misho 137: debug_return_int(-1);
138: debug_return_int(0);
1.1 misho 139: }
140:
141: /*
142: * Look up the user in the parsed sudoers file and check to see if they are
143: * allowed to run the specified command on this host as the target user.
144: */
145: int
146: sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag)
147: {
148: int match, host_match, runas_match, cmnd_match;
149: struct cmndspec *cs;
150: struct cmndtag *tags = NULL;
151: struct privilege *priv;
152: struct userspec *us;
1.1.1.3 misho 153: struct member *matching_user;
1.1.1.2 misho 154: debug_decl(sudo_file_lookup, SUDO_DEBUG_NSS)
1.1 misho 155:
156: if (nss->handle == NULL)
1.1.1.2 misho 157: debug_return_int(validated);
1.1 misho 158:
159: /*
160: * Only check the actual command if pwflag is not set.
161: * It is set for the "validate", "list" and "kill" pseudo-commands.
162: * Always check the host and user.
163: */
164: if (pwflag) {
165: int nopass;
166: enum def_tuple pwcheck;
167:
168: pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
1.1.1.2 misho 169: nopass = (pwcheck == all) ? true : false;
1.1 misho 170:
171: if (list_pw == NULL)
172: SET(validated, FLAG_NO_CHECK);
173: CLR(validated, FLAG_NO_USER);
174: CLR(validated, FLAG_NO_HOST);
175: match = DENY;
1.1.1.5 ! misho 176: TAILQ_FOREACH(us, &userspecs, entries) {
1.1 misho 177: if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
178: continue;
1.1.1.5 ! misho 179: TAILQ_FOREACH(priv, &us->privileges, entries) {
1.1 misho 180: if (hostlist_matches(&priv->hostlist) != ALLOW)
181: continue;
1.1.1.5 ! misho 182: TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
1.1 misho 183: /* Only check the command when listing another user. */
184: if (user_uid == 0 || list_pw == NULL ||
185: user_uid == list_pw->pw_uid ||
186: cmnd_matches(cs->cmnd) == ALLOW)
187: match = ALLOW;
1.1.1.2 misho 188: if ((pwcheck == any && cs->tags.nopasswd == true) ||
189: (pwcheck == all && cs->tags.nopasswd != true))
1.1 misho 190: nopass = cs->tags.nopasswd;
191: }
192: }
193: }
194: if (match == ALLOW || user_uid == 0) {
195: /* User has an entry for this host. */
196: SET(validated, VALIDATE_OK);
197: } else if (match == DENY)
198: SET(validated, VALIDATE_NOT_OK);
199: if (pwcheck == always && def_authenticate)
200: SET(validated, FLAG_CHECK_USER);
1.1.1.2 misho 201: else if (pwcheck == never || nopass == true)
202: def_authenticate = false;
203: debug_return_int(validated);
1.1 misho 204: }
205:
206: /* Need to be runas user while stat'ing things. */
207: set_perms(PERM_RUNAS);
208:
209: match = UNSPEC;
1.1.1.5 ! misho 210: TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
1.1 misho 211: if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
212: continue;
213: CLR(validated, FLAG_NO_USER);
1.1.1.5 ! misho 214: TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
1.1 misho 215: host_match = hostlist_matches(&priv->hostlist);
216: if (host_match == ALLOW)
217: CLR(validated, FLAG_NO_HOST);
218: else
219: continue;
1.1.1.5 ! misho 220: TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
1.1.1.3 misho 221: matching_user = NULL;
1.1.1.5 ! misho 222: runas_match = runaslist_matches(cs->runasuserlist,
! 223: cs->runasgrouplist, &matching_user, NULL);
1.1 misho 224: if (runas_match == ALLOW) {
225: cmnd_match = cmnd_matches(cs->cmnd);
226: if (cmnd_match != UNSPEC) {
227: match = cmnd_match;
228: tags = &cs->tags;
229: #ifdef HAVE_SELINUX
230: /* Set role and type if not specified on command line. */
231: if (user_role == NULL)
232: user_role = cs->role ? estrdup(cs->role) : def_role;
233: if (user_type == NULL)
234: user_type = cs->type ? estrdup(cs->type) : def_type;
235: #endif /* HAVE_SELINUX */
1.1.1.3 misho 236: #ifdef HAVE_PRIV_SET
237: /* Set Solaris privilege sets */
238: if (runas_privs == NULL)
239: runas_privs = cs->privs ? estrdup(cs->privs) : def_privs;
240: if (runas_limitprivs == NULL)
241: runas_limitprivs = cs->limitprivs ? estrdup(cs->limitprivs) : def_limitprivs;
242: #endif /* HAVE_PRIV_SET */
243: /*
244: * If user is running command as himself,
245: * set runas_pw = sudo_user.pw.
246: * XXX - hack, want more general solution
247: */
248: if (matching_user && matching_user->type == MYSELF) {
249: sudo_pw_delref(runas_pw);
250: sudo_pw_addref(sudo_user.pw);
251: runas_pw = sudo_user.pw;
252: }
1.1 misho 253: goto matched2;
254: }
255: }
256: }
257: }
258: }
259: matched2:
260: if (match == ALLOW) {
261: SET(validated, VALIDATE_OK);
262: CLR(validated, VALIDATE_NOT_OK);
263: if (tags != NULL) {
264: if (tags->nopasswd != UNSPEC)
265: def_authenticate = !tags->nopasswd;
266: if (tags->noexec != UNSPEC)
267: def_noexec = tags->noexec;
268: if (tags->setenv != UNSPEC)
269: def_setenv = tags->setenv;
270: if (tags->log_input != UNSPEC)
271: def_log_input = tags->log_input;
272: if (tags->log_output != UNSPEC)
273: def_log_output = tags->log_output;
274: }
275: } else if (match == DENY) {
276: SET(validated, VALIDATE_NOT_OK);
277: CLR(validated, VALIDATE_OK);
278: if (tags != NULL && tags->nopasswd != UNSPEC)
279: def_authenticate = !tags->nopasswd;
280: }
281: restore_perms();
1.1.1.2 misho 282: debug_return_int(validated);
1.1 misho 283: }
284:
1.1.1.4 misho 285: #define TAG_SET(tt) \
286: ((tt) != UNSPEC && (tt) != IMPLIED)
287:
1.1 misho 288: #define TAG_CHANGED(t) \
1.1.1.4 misho 289: (TAG_SET(cs->tags.t) && cs->tags.t != tags->t)
1.1 misho 290:
291: static void
292: sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
293: struct lbuf *lbuf)
294: {
1.1.1.2 misho 295: debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)
1.1 misho 296:
1.1.1.3 misho 297: #ifdef HAVE_PRIV_SET
298: if (cs->privs)
299: lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs);
300: if (cs->limitprivs)
301: lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs);
302: #endif /* HAVE_PRIV_SET */
1.1 misho 303: #ifdef HAVE_SELINUX
304: if (cs->role)
305: lbuf_append(lbuf, "ROLE=%s ", cs->role);
306: if (cs->type)
307: lbuf_append(lbuf, "TYPE=%s ", cs->type);
308: #endif /* HAVE_SELINUX */
309: if (TAG_CHANGED(setenv)) {
310: lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : "NOSETENV: ");
311: tags->setenv = cs->tags.setenv;
312: }
313: if (TAG_CHANGED(noexec)) {
314: lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : "EXEC: ");
315: tags->noexec = cs->tags.noexec;
316: }
317: if (TAG_CHANGED(nopasswd)) {
318: lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: ");
319: tags->nopasswd = cs->tags.nopasswd;
320: }
321: if (TAG_CHANGED(log_input)) {
322: lbuf_append(lbuf, cs->tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: ");
323: tags->log_input = cs->tags.log_input;
324: }
325: if (TAG_CHANGED(log_output)) {
326: lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");
327: tags->log_output = cs->tags.log_output;
328: }
1.1.1.4 misho 329: print_member(lbuf, cs->cmnd, CMNDALIAS);
1.1.1.2 misho 330: debug_return;
1.1 misho 331: }
332:
1.1.1.4 misho 333: #define RUNAS_CHANGED(cs1, cs2) \
334: (cs1 == NULL || cs2 == NULL || \
1.1.1.5 ! misho 335: cs1->runasuserlist != cs2->runasuserlist || \
! 336: cs1->runasgrouplist != cs2->runasgrouplist)
1.1.1.4 misho 337:
1.1 misho 338: static int
339: sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
340: struct lbuf *lbuf)
341: {
1.1.1.4 misho 342: struct cmndspec *cs, *prev_cs;
1.1 misho 343: struct member *m;
344: struct privilege *priv;
345: struct cmndtag tags;
346: int nfound = 0;
1.1.1.2 misho 347: debug_decl(sudo_file_display_priv_short, SUDO_DEBUG_NSS)
1.1 misho 348:
1.1.1.4 misho 349: /* gcc -Wuninitialized false positive */
350: tags.noexec = UNSPEC;
351: tags.setenv = UNSPEC;
352: tags.nopasswd = UNSPEC;
353: tags.log_input = UNSPEC;
354: tags.log_output = UNSPEC;
1.1.1.5 ! misho 355: TAILQ_FOREACH(priv, &us->privileges, entries) {
1.1 misho 356: if (hostlist_matches(&priv->hostlist) != ALLOW)
357: continue;
1.1.1.4 misho 358: prev_cs = NULL;
1.1.1.5 ! misho 359: TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
1.1.1.4 misho 360: if (RUNAS_CHANGED(cs, prev_cs)) {
1.1.1.5 ! misho 361: if (cs != TAILQ_FIRST(&priv->cmndlist))
1.1.1.4 misho 362: lbuf_append(lbuf, "\n");
363: lbuf_append(lbuf, " (");
1.1.1.5 ! misho 364: if (cs->runasuserlist != NULL) {
! 365: TAILQ_FOREACH(m, cs->runasuserlist, entries) {
! 366: if (m != TAILQ_FIRST(cs->runasuserlist))
1.1.1.4 misho 367: lbuf_append(lbuf, ", ");
368: print_member(lbuf, m, RUNASALIAS);
369: }
1.1.1.5 ! misho 370: } else if (cs->runasgrouplist == NULL) {
1.1.1.4 misho 371: lbuf_append(lbuf, "%s", def_runas_default);
372: } else {
373: lbuf_append(lbuf, "%s", pw->pw_name);
1.1 misho 374: }
1.1.1.5 ! misho 375: if (cs->runasgrouplist != NULL) {
1.1.1.4 misho 376: lbuf_append(lbuf, " : ");
1.1.1.5 ! misho 377: TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
! 378: if (m != TAILQ_FIRST(cs->runasgrouplist))
1.1.1.4 misho 379: lbuf_append(lbuf, ", ");
380: print_member(lbuf, m, RUNASALIAS);
381: }
1.1 misho 382: }
1.1.1.4 misho 383: lbuf_append(lbuf, ") ");
384: tags.noexec = UNSPEC;
385: tags.setenv = UNSPEC;
386: tags.nopasswd = UNSPEC;
387: tags.log_input = UNSPEC;
388: tags.log_output = UNSPEC;
1.1.1.5 ! misho 389: } else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
1.1.1.4 misho 390: lbuf_append(lbuf, ", ");
1.1 misho 391: }
392: sudo_file_append_cmnd(cs, &tags, lbuf);
1.1.1.4 misho 393: prev_cs = cs;
1.1 misho 394: nfound++;
395: }
396: lbuf_append(lbuf, "\n");
397: }
1.1.1.2 misho 398: debug_return_int(nfound);
1.1 misho 399: }
400:
1.1.1.4 misho 401: #define TAGS_CHANGED(ot, nt) \
402: ((TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
403: (TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \
404: (TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \
405: (TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \
406: (TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output))
407:
408: /*
409: * Compare the current cmndspec with the previous one to determine
410: * whether we need to start a new long entry for "sudo -ll".
411: * Returns true if we should start a new long entry, else false.
412: */
413: static bool
414: new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
415: {
416: if (prev_cs == NULL)
417: return true;
418: if (RUNAS_CHANGED(cs, prev_cs) || TAGS_CHANGED(cs->tags, prev_cs->tags))
419: return true;
420: #ifdef HAVE_PRIV_SET
421: if (cs->privs && (!prev_cs->privs || strcmp(cs->privs, prev_cs->privs) != 0))
422: return true;
423: if (cs->limitprivs && (!prev_cs->limitprivs || strcmp(cs->limitprivs, prev_cs->limitprivs) != 0))
424: return true;
425: #endif /* HAVE_PRIV_SET */
426: #ifdef HAVE_SELINUX
427: if (cs->role && (!prev_cs->role || strcmp(cs->role, prev_cs->role) != 0))
428: return true;
429: if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0))
430: return true;
431: #endif /* HAVE_SELINUX */
432: return false;
433: }
434:
1.1 misho 435: static int
436: sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
437: struct lbuf *lbuf)
438: {
1.1.1.4 misho 439: struct cmndspec *cs, *prev_cs;
1.1 misho 440: struct member *m;
441: struct privilege *priv;
1.1.1.4 misho 442: int nfound = 0, olen;
1.1.1.2 misho 443: debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
1.1 misho 444:
1.1.1.5 ! misho 445: TAILQ_FOREACH(priv, &us->privileges, entries) {
1.1 misho 446: if (hostlist_matches(&priv->hostlist) != ALLOW)
447: continue;
1.1.1.4 misho 448: prev_cs = NULL;
1.1.1.5 ! misho 449: TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
1.1.1.4 misho 450: if (new_long_entry(cs, prev_cs)) {
451: lbuf_append(lbuf, _("\nSudoers entry:\n"));
452: lbuf_append(lbuf, _(" RunAsUsers: "));
1.1.1.5 ! misho 453: if (cs->runasuserlist != NULL) {
! 454: TAILQ_FOREACH(m, cs->runasuserlist, entries) {
! 455: if (m != TAILQ_FIRST(cs->runasuserlist))
1.1.1.4 misho 456: lbuf_append(lbuf, ", ");
457: print_member(lbuf, m, RUNASALIAS);
458: }
1.1.1.5 ! misho 459: } else if (cs->runasgrouplist == NULL) {
1.1.1.4 misho 460: lbuf_append(lbuf, "%s", def_runas_default);
461: } else {
462: lbuf_append(lbuf, "%s", pw->pw_name);
1.1 misho 463: }
464: lbuf_append(lbuf, "\n");
1.1.1.5 ! misho 465: if (cs->runasgrouplist != NULL) {
1.1.1.4 misho 466: lbuf_append(lbuf, _(" RunAsGroups: "));
1.1.1.5 ! misho 467: TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
! 468: if (m != TAILQ_FIRST(cs->runasgrouplist))
1.1.1.4 misho 469: lbuf_append(lbuf, ", ");
470: print_member(lbuf, m, RUNASALIAS);
471: }
472: lbuf_append(lbuf, "\n");
473: }
474: olen = lbuf->len;
475: lbuf_append(lbuf, _(" Options: "));
476: if (TAG_SET(cs->tags.setenv))
477: lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!");
478: if (TAG_SET(cs->tags.noexec))
479: lbuf_append(lbuf, "%snoexec, ", cs->tags.noexec ? "" : "!");
480: if (TAG_SET(cs->tags.nopasswd))
481: lbuf_append(lbuf, "%sauthenticate, ", cs->tags.nopasswd ? "!" : "");
482: if (TAG_SET(cs->tags.log_input))
483: lbuf_append(lbuf, "%slog_input, ", cs->tags.log_input ? "" : "!");
484: if (TAG_SET(cs->tags.log_output))
485: lbuf_append(lbuf, "%slog_output, ", cs->tags.log_output ? "" : "!");
486: if (lbuf->buf[lbuf->len - 2] == ',') {
487: lbuf->len -= 2; /* remove trailing ", " */
488: lbuf_append(lbuf, "\n");
489: } else {
490: lbuf->len = olen; /* no options */
491: }
492: #ifdef HAVE_PRIV_SET
493: if (cs->privs)
494: lbuf_append(lbuf, " Privs: %s\n", cs->privs);
495: if (cs->limitprivs)
496: lbuf_append(lbuf, " Limitprivs: %s\n", cs->limitprivs);
497: #endif /* HAVE_PRIV_SET */
498: #ifdef HAVE_SELINUX
499: if (cs->role)
500: lbuf_append(lbuf, " Role: %s\n", cs->role);
501: if (cs->type)
502: lbuf_append(lbuf, " Type: %s\n", cs->type);
503: #endif /* HAVE_SELINUX */
504: lbuf_append(lbuf, _(" Commands:\n"));
1.1 misho 505: }
1.1.1.4 misho 506: lbuf_append(lbuf, "\t");
507: print_member2(lbuf, cs->cmnd, "\n\t", CMNDALIAS);
1.1 misho 508: lbuf_append(lbuf, "\n");
1.1.1.4 misho 509: prev_cs = cs;
1.1 misho 510: nfound++;
511: }
512: }
1.1.1.2 misho 513: debug_return_int(nfound);
1.1 misho 514: }
515:
516: int
517: sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw,
518: struct lbuf *lbuf)
519: {
520: struct userspec *us;
521: int nfound = 0;
1.1.1.2 misho 522: debug_decl(sudo_file_display_priv, SUDO_DEBUG_NSS)
1.1 misho 523:
524: if (nss->handle == NULL)
525: goto done;
526:
1.1.1.5 ! misho 527: TAILQ_FOREACH(us, &userspecs, entries) {
1.1 misho 528: if (userlist_matches(pw, &us->users) != ALLOW)
529: continue;
530:
531: if (long_list)
532: nfound += sudo_file_display_priv_long(pw, us, lbuf);
533: else
534: nfound += sudo_file_display_priv_short(pw, us, lbuf);
535: }
536: done:
1.1.1.2 misho 537: debug_return_int(nfound);
1.1 misho 538: }
539:
540: /*
541: * Display matching Defaults entries for the given user on this host.
542: */
543: int
544: sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw,
545: struct lbuf *lbuf)
546: {
547: struct defaults *d;
548: char *prefix;
549: int nfound = 0;
1.1.1.2 misho 550: debug_decl(sudo_file_display_defaults, SUDO_DEBUG_NSS)
1.1 misho 551:
552: if (nss->handle == NULL)
553: goto done;
554:
555: if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
556: prefix = " ";
557: else
558: prefix = ", ";
559:
1.1.1.5 ! misho 560: TAILQ_FOREACH(d, &defaults, entries) {
1.1 misho 561: switch (d->type) {
562: case DEFAULTS_HOST:
1.1.1.5 ! misho 563: if (hostlist_matches(d->binding) != ALLOW)
1.1 misho 564: continue;
565: break;
566: case DEFAULTS_USER:
1.1.1.5 ! misho 567: if (userlist_matches(pw, d->binding) != ALLOW)
1.1 misho 568: continue;
569: break;
570: case DEFAULTS_RUNAS:
571: case DEFAULTS_CMND:
572: continue;
573: }
574: if (d->val != NULL) {
575: lbuf_append(lbuf, "%s%s%s", prefix, d->var,
576: d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=");
577: if (strpbrk(d->val, " \t") != NULL) {
578: lbuf_append(lbuf, "\"");
579: lbuf_append_quoted(lbuf, "\"", "%s", d->val);
580: lbuf_append(lbuf, "\"");
581: } else
582: lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val);
583: } else
584: lbuf_append(lbuf, "%s%s%s", prefix,
1.1.1.2 misho 585: d->op == false ? "!" : "", d->var);
1.1 misho 586: prefix = ", ";
587: nfound++;
588: }
589: done:
1.1.1.2 misho 590: debug_return_int(nfound);
1.1 misho 591: }
592:
593: /*
594: * Display Defaults entries that are per-runas or per-command
595: */
596: int
597: sudo_file_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw,
598: struct lbuf *lbuf)
599: {
600: int nfound = 0;
1.1.1.2 misho 601: debug_decl(sudo_file_display_bound_defaults, SUDO_DEBUG_NSS)
1.1 misho 602:
603: /* XXX - should only print ones that match what the user can do. */
604: nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf);
605: nfound += display_bound_defaults(DEFAULTS_CMND, lbuf);
606:
1.1.1.2 misho 607: debug_return_int(nfound);
1.1 misho 608: }
609:
610: /*
611: * Display Defaults entries of the given type.
612: */
613: static int
614: display_bound_defaults(int dtype, struct lbuf *lbuf)
615: {
616: struct defaults *d;
1.1.1.5 ! misho 617: struct member_list *binding = NULL;
! 618: struct member *m;
1.1 misho 619: char *dsep;
620: int atype, nfound = 0;
1.1.1.2 misho 621: debug_decl(display_bound_defaults, SUDO_DEBUG_NSS)
1.1 misho 622:
623: switch (dtype) {
624: case DEFAULTS_HOST:
625: atype = HOSTALIAS;
626: dsep = "@";
627: break;
628: case DEFAULTS_USER:
629: atype = USERALIAS;
630: dsep = ":";
631: break;
632: case DEFAULTS_RUNAS:
633: atype = RUNASALIAS;
634: dsep = ">";
635: break;
636: case DEFAULTS_CMND:
637: atype = CMNDALIAS;
638: dsep = "!";
639: break;
640: default:
1.1.1.2 misho 641: debug_return_int(-1);
1.1 misho 642: }
1.1.1.5 ! misho 643: TAILQ_FOREACH(d, &defaults, entries) {
1.1 misho 644: if (d->type != dtype)
645: continue;
646:
647: nfound++;
1.1.1.5 ! misho 648: if (binding != d->binding) {
! 649: binding = d->binding;
1.1 misho 650: if (nfound != 1)
651: lbuf_append(lbuf, "\n");
652: lbuf_append(lbuf, " Defaults%s", dsep);
1.1.1.5 ! misho 653: TAILQ_FOREACH(m, binding, entries) {
! 654: if (m != TAILQ_FIRST(binding))
1.1 misho 655: lbuf_append(lbuf, ",");
1.1.1.4 misho 656: print_member(lbuf, m, atype);
1.1 misho 657: lbuf_append(lbuf, " ");
658: }
659: } else
660: lbuf_append(lbuf, ", ");
661: if (d->val != NULL) {
662: lbuf_append(lbuf, "%s%s%s", d->var, d->op == '+' ? "+=" :
663: d->op == '-' ? "-=" : "=", d->val);
664: } else
1.1.1.2 misho 665: lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var);
1.1 misho 666: }
667:
1.1.1.2 misho 668: debug_return_int(nfound);
1.1 misho 669: }
670:
671: int
672: sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
673: {
674: struct cmndspec *cs;
675: struct member *match;
676: struct privilege *priv;
677: struct userspec *us;
678: int rval = 1;
679: int host_match, runas_match, cmnd_match;
1.1.1.2 misho 680: debug_decl(sudo_file_display_cmnd, SUDO_DEBUG_NSS)
1.1 misho 681:
682: if (nss->handle == NULL)
683: goto done;
684:
685: match = NULL;
1.1.1.5 ! misho 686: TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) {
1.1 misho 687: if (userlist_matches(pw, &us->users) != ALLOW)
688: continue;
689:
1.1.1.5 ! misho 690: TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
1.1 misho 691: host_match = hostlist_matches(&priv->hostlist);
692: if (host_match != ALLOW)
693: continue;
1.1.1.5 ! misho 694: TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
! 695: runas_match = runaslist_matches(cs->runasuserlist,
! 696: cs->runasgrouplist, NULL, NULL);
1.1 misho 697: if (runas_match == ALLOW) {
698: cmnd_match = cmnd_matches(cs->cmnd);
699: if (cmnd_match != UNSPEC) {
1.1.1.5 ! misho 700: if (cmnd_match == ALLOW)
! 701: match = cs->cmnd;
1.1 misho 702: goto matched;
703: }
704: }
705: }
706: }
707: }
708: matched:
709: if (match != NULL && !match->negated) {
710: sudo_printf(SUDO_CONV_INFO_MSG, "%s%s%s\n",
711: safe_cmnd, user_args ? " " : "", user_args ? user_args : "");
712: rval = 0;
713: }
714: done:
1.1.1.2 misho 715: debug_return_int(rval);
1.1 misho 716: }
717:
718: /*
719: * Print the contents of a struct member to stdout
720: */
721: static void
722: _print_member(struct lbuf *lbuf, char *name, int type, int negated,
1.1.1.4 misho 723: const char *separator, int alias_type)
1.1 misho 724: {
725: struct alias *a;
726: struct member *m;
727: struct sudo_command *c;
1.1.1.2 misho 728: debug_decl(_print_member, SUDO_DEBUG_NSS)
1.1 misho 729:
730: switch (type) {
731: case ALL:
732: lbuf_append(lbuf, "%sALL", negated ? "!" : "");
733: break;
1.1.1.3 misho 734: case MYSELF:
735: lbuf_append(lbuf, "%s%s", negated ? "!" : "", user_name);
736: break;
1.1 misho 737: case COMMAND:
738: c = (struct sudo_command *) name;
739: if (negated)
740: lbuf_append(lbuf, "!");
741: lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->cmnd);
742: if (c->args) {
743: lbuf_append(lbuf, " ");
744: lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args);
745: }
746: break;
747: case ALIAS:
1.1.1.4 misho 748: if ((a = alias_get(name, alias_type)) != NULL) {
1.1.1.5 ! misho 749: TAILQ_FOREACH(m, &a->members, entries) {
! 750: if (m != TAILQ_FIRST(&a->members))
1.1.1.4 misho 751: lbuf_append(lbuf, "%s", separator);
1.1 misho 752: _print_member(lbuf, m->name, m->type,
1.1.1.4 misho 753: negated ? !m->negated : m->negated, separator,
754: alias_type);
1.1 misho 755: }
1.1.1.4 misho 756: alias_put(a);
1.1 misho 757: break;
758: }
759: /* FALLTHROUGH */
760: default:
761: lbuf_append(lbuf, "%s%s", negated ? "!" : "", name);
762: break;
763: }
1.1.1.2 misho 764: debug_return;
1.1 misho 765: }
766:
767: static void
1.1.1.4 misho 768: print_member(struct lbuf *lbuf, struct member *m, int alias_type)
769: {
770: _print_member(lbuf, m->name, m->type, m->negated, ", ", alias_type);
771: }
772:
773: static void
774: print_member2(struct lbuf *lbuf, struct member *m, const char *separator,
1.1 misho 775: int alias_type)
776: {
1.1.1.4 misho 777: _print_member(lbuf, m->name, m->type, m->negated, separator, alias_type);
1.1 misho 778: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>