46
39
#ifdef HAVE_UNISTD_H
47
40
# include <unistd.h>
48
41
#endif /* HAVE_UNISTD_H */
51
#endif /* HAVE_FNMATCH */
52
#ifdef HAVE_EXTENDED_GLOB
54
#endif /* HAVE_EXTENDED_GLOB */
55
#ifdef HAVE_NETGROUP_H
56
# include <netgroup.h>
57
#endif /* HAVE_NETGROUP_H */
61
#include <netinet/in.h>
62
#include <arpa/inet.h>
66
# define NAMLEN(dirent) strlen((dirent)->d_name)
68
# define dirent direct
69
# define NAMLEN(dirent) (dirent)->d_namlen
70
# ifdef HAVE_SYS_NDIR_H
71
# include <sys/ndir.h>
73
# ifdef HAVE_SYS_DIR_H
83
#include "interfaces.h"
86
# include "emul/fnmatch.h"
87
#endif /* HAVE_FNMATCH */
88
#ifndef HAVE_EXTENDED_GLOB
89
# include "emul/glob.h"
90
#endif /* HAVE_EXTENDED_GLOB */
93
__unused static const char rcsid[] = "$Sudo: parse.c,v 1.160.2.16 2008/02/09 14:44:48 millert Exp $";
52
__unused static const char rcsid[] = "$Sudo: parse.c,v 1.238 2008/12/09 13:49:55 millert Exp $";
99
int parse_error = FALSE;
101
extern FILE *yyin, *yyout;
106
static int has_meta __P((char *));
107
void init_parser __P((void));
110
* Look up the user in the sudoers file and check to see if they are
55
/* Characters that must be quoted in sudoers */
56
#define SUDOERS_QUOTED ":\\,=#\""
58
/* sudoers nsswitch routines */
59
struct sudo_nss sudo_nss_file = {
67
sudo_file_display_cmnd,
68
sudo_file_display_defaults,
69
sudo_file_display_bound_defaults,
70
sudo_file_display_privs
77
extern char *errorfile;
78
extern int errorlineno, parse_error;
83
static void print_member __P((struct lbuf *, char *, int, int, int));
84
static int display_bound_defaults __P((int, struct lbuf *));
90
if (def_ignore_local_sudoers)
92
nss->handle = open_sudoers(_PATH_SUDOERS, NULL);
93
return(nss->handle ? 0 : -1);
100
/* Free parser data structures and close sudoers file. */
101
init_parser(NULL, 0);
102
if (nss->handle != NULL) {
111
* Parse the specified sudoers file.
115
struct sudo_nss *nss;
117
if (nss->handle == NULL)
120
init_parser(_PATH_SUDOERS, 0);
122
if (yyparse() != 0 || parse_error) {
123
log_error(NO_EXIT, "parse error in %s near line %d",
124
errorfile, errorlineno);
131
* Wrapper around update_defaults() for nsswitch code.
134
sudo_file_setdefs(nss)
135
struct sudo_nss *nss;
137
if (nss->handle == NULL)
140
if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER))
146
* Look up the user in the parsed sudoers file and check to see if they are
111
147
* allowed to run the specified command on this host as the target user.
114
sudoers_lookup(pwflag)
150
sudo_file_lookup(nss, validated, pwflag)
151
struct sudo_nss *nss;
119
/* We opened _PATH_SUDOERS in check_sudoers() so just rewind it. */
124
/* Allocate space for data structures in the parser. */
127
/* Keep more state for pseudo-commands so that listpw and verifypw work */
131
/* Need to be runas user while stat'ing things in the parser. */
132
set_perms(PERM_RUNAS);
135
/* Close the sudoers file now that we are done with it. */
136
(void) fclose(sudoers_fp);
139
if (error || parse_error) {
140
set_perms(PERM_ROOT);
141
return(VALIDATE_ERROR);
145
* Assume the worst. If the stack is empty the user was
146
* not mentioned at all.
148
if (def_authenticate)
149
error = VALIDATE_NOT_OK;
151
error = VALIDATE_NOT_OK | FLAG_NOPASS;
153
SET(error, FLAG_NO_CHECK);
155
SET(error, FLAG_NO_HOST);
157
SET(error, FLAG_NO_USER);
155
int match, host_match, runas_match, cmnd_match;
157
struct cmndtag *tags = NULL;
158
struct privilege *priv;
161
if (nss->handle == NULL)
161
165
* Only check the actual command if pwflag is not set.
162
166
* It is set for the "validate", "list" and "kill" pseudo-commands.
163
167
* Always check the host and user.
168
171
enum def_tupple pwcheck;
170
173
pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
174
nopass = (pwcheck == all) ? TRUE : FALSE;
177
SET(validated, FLAG_NO_CHECK);
178
CLR(validated, FLAG_NO_USER);
179
CLR(validated, FLAG_NO_HOST);
181
tq_foreach_fwd(&userspecs, us) {
182
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
184
tq_foreach_fwd(&us->privileges, priv) {
185
if (hostlist_matches(&priv->hostlist) != ALLOW)
187
tq_foreach_fwd(&priv->cmndlist, cs) {
188
/* Only check the command when listing another user. */
189
if (user_uid == 0 || list_pw == NULL ||
190
user_uid == list_pw->pw_uid ||
191
cmnd_matches(cs->cmnd) == ALLOW)
193
if ((pwcheck == any && cs->tags.nopasswd == TRUE) ||
194
(pwcheck == all && cs->tags.nopasswd != TRUE))
195
nopass = cs->tags.nopasswd;
199
if (match == ALLOW || user_uid == 0) {
200
/* User has an entry for this host. */
201
SET(validated, VALIDATE_OK);
202
} else if (match == DENY)
203
SET(validated, VALIDATE_NOT_OK);
172
204
if (pwcheck == always && def_authenticate)
173
nopass = FLAG_CHECK_USER;
174
else if (pwcheck == never || !def_authenticate)
175
nopass = FLAG_NOPASS;
178
if (host_matches == TRUE) {
180
if (pwcheck == any && no_passwd == TRUE)
181
nopass = FLAG_NOPASS;
182
else if (pwcheck == all && nopass != 0)
183
nopass = (no_passwd == TRUE) ? FLAG_NOPASS : 0;
188
set_perms(PERM_ROOT);
191
return(VALIDATE_OK | nopass);
195
if (host_matches == TRUE) {
196
CLR(error, FLAG_NO_HOST);
197
if (runas_matches == TRUE && cmnd_matches == TRUE) {
199
* User was granted access to cmnd on host as user.
205
SET(validated, FLAG_CHECK_USER);
206
else if (pwcheck == never || nopass == TRUE)
207
def_authenticate = FALSE;
211
/* Need to be runas user while stat'ing things. */
212
set_perms(PERM_RUNAS);
215
tq_foreach_rev(&userspecs, us) {
216
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
218
CLR(validated, FLAG_NO_USER);
219
tq_foreach_rev(&us->privileges, priv) {
220
host_match = hostlist_matches(&priv->hostlist);
221
if (host_match == ALLOW)
222
CLR(validated, FLAG_NO_HOST);
225
tq_foreach_rev(&priv->cmndlist, cs) {
226
runas_match = runaslist_matches(&cs->runasuserlist,
227
&cs->runasgrouplist);
228
if (runas_match == ALLOW) {
229
cmnd_match = cmnd_matches(cs->cmnd);
230
if (cmnd_match != UNSPEC) {
201
233
#ifdef HAVE_SELINUX
202
/* Set role and type if not specified on command line. */
203
if (user_role == NULL) {
204
if (match[top-1].role != NULL)
205
user_role = match[top-1].role;
207
user_role = def_role;
209
if (user_type == NULL) {
210
if (match[top-1].type != NULL)
211
user_type = match[top-1].type;
213
user_type = def_type;
216
set_perms(PERM_ROOT);
218
(no_passwd == TRUE ? FLAG_NOPASS : 0) |
219
(no_execve == TRUE ? FLAG_NOEXEC : 0) |
220
(setenv_ok >= TRUE ? FLAG_SETENV : 0));
221
} else if ((runas_matches == TRUE && cmnd_matches == FALSE) ||
222
(runas_matches == FALSE && cmnd_matches == TRUE)) {
224
* User was explicitly denied access to cmnd on host.
226
set_perms(PERM_ROOT);
227
return(VALIDATE_NOT_OK |
228
(no_passwd == TRUE ? FLAG_NOPASS : 0) |
229
(no_execve == TRUE ? FLAG_NOEXEC : 0) |
230
(setenv_ok >= TRUE ? FLAG_SETENV : 0));
234
/* Set role and type if not specified on command line. */
235
if (user_role == NULL)
236
user_role = cs->role ? estrdup(cs->role) : def_role;
237
if (user_type == NULL)
238
user_type = cs->type ? estrdup(cs->type) : def_type;
239
#endif /* HAVE_SELINUX */
247
if (match == ALLOW) {
248
SET(validated, VALIDATE_OK);
249
CLR(validated, VALIDATE_NOT_OK);
251
if (tags->nopasswd != UNSPEC)
252
def_authenticate = !tags->nopasswd;
253
if (tags->noexec != UNSPEC)
254
def_noexec = tags->noexec;
255
if (tags->setenv != UNSPEC)
256
def_setenv = tags->setenv;
258
} else if (match == DENY) {
259
SET(validated, VALIDATE_NOT_OK);
260
CLR(validated, VALIDATE_OK);
236
262
set_perms(PERM_ROOT);
239
* The user was neither explicitly granted nor denied access.
243
return(error | nopass);
266
#define TAG_CHANGED(t) \
267
(cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t)
270
sudo_file_append_cmnd(cs, tags, lbuf)
272
struct cmndtag *tags;
279
lbuf_append(lbuf, "ROLE=", cs->role, " ", NULL);
281
lbuf_append(lbuf, "TYPE=", cs->type, " ", NULL);
282
#endif /* HAVE_SELINUX */
283
if (TAG_CHANGED(setenv)) {
284
lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " :
286
tags->setenv = cs->tags.setenv;
288
if (TAG_CHANGED(noexec)) {
289
lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " :
291
tags->noexec = cs->tags.noexec;
293
if (TAG_CHANGED(nopasswd)) {
294
lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " :
296
tags->nopasswd = cs->tags.nopasswd;
299
print_member(lbuf, m->name, m->type, m->negated,
304
sudo_file_display_priv_short(pw, us, lbuf)
311
struct privilege *priv;
315
tq_foreach_fwd(&us->privileges, priv) {
316
tags.noexec = UNSPEC;
317
tags.setenv = UNSPEC;
318
tags.nopasswd = UNSPEC;
319
lbuf_append(lbuf, " ", NULL);
320
tq_foreach_fwd(&priv->cmndlist, cs) {
321
if (cs != tq_first(&priv->cmndlist))
322
lbuf_append(lbuf, ", ", NULL);
323
lbuf_append(lbuf, "(", NULL);
324
if (!tq_empty(&cs->runasuserlist)) {
325
tq_foreach_fwd(&cs->runasuserlist, m) {
326
if (m != tq_first(&cs->runasuserlist))
327
lbuf_append(lbuf, ", ", NULL);
328
print_member(lbuf, m->name, m->type, m->negated,
332
lbuf_append(lbuf, def_runas_default, NULL);
334
if (!tq_empty(&cs->runasgrouplist)) {
335
lbuf_append(lbuf, " : ", NULL);
336
tq_foreach_fwd(&cs->runasgrouplist, m) {
337
if (m != tq_first(&cs->runasgrouplist))
338
lbuf_append(lbuf, ", ", NULL);
339
print_member(lbuf, m->name, m->type, m->negated,
343
lbuf_append(lbuf, ") ", NULL);
344
sudo_file_append_cmnd(cs, &tags, lbuf);
347
lbuf_print(lbuf); /* forces a newline */
353
sudo_file_display_priv_long(pw, us, lbuf)
360
struct privilege *priv;
364
tq_foreach_fwd(&us->privileges, priv) {
365
tags.noexec = UNSPEC;
366
tags.setenv = UNSPEC;
367
tags.nopasswd = UNSPEC;
368
lbuf_print(lbuf); /* force a newline */
369
lbuf_append(lbuf, "Sudoers entry:", NULL);
371
tq_foreach_fwd(&priv->cmndlist, cs) {
372
lbuf_append(lbuf, " RunAsUsers: ", NULL);
373
if (!tq_empty(&cs->runasuserlist)) {
374
tq_foreach_fwd(&cs->runasuserlist, m) {
375
if (m != tq_first(&cs->runasuserlist))
376
lbuf_append(lbuf, ", ", NULL);
377
print_member(lbuf, m->name, m->type, m->negated,
381
lbuf_append(lbuf, def_runas_default, NULL);
384
if (!tq_empty(&cs->runasgrouplist)) {
385
lbuf_append(lbuf, " RunAsGroups: ", NULL);
386
tq_foreach_fwd(&cs->runasgrouplist, m) {
387
if (m != tq_first(&cs->runasgrouplist))
388
lbuf_append(lbuf, ", ", NULL);
389
print_member(lbuf, m->name, m->type, m->negated,
394
lbuf_append(lbuf, " Commands: ", NULL);
396
lbuf_append(lbuf, "\t", NULL);
397
sudo_file_append_cmnd(cs, &tags, lbuf);
406
sudo_file_display_privs(nss, pw, lbuf)
407
struct sudo_nss *nss;
414
if (nss->handle == NULL)
417
tq_foreach_fwd(&userspecs, us) {
418
/* XXX - why only check the first privilege here? */
419
if (userlist_matches(pw, &us->users) != ALLOW ||
420
hostlist_matches(&us->privileges.first->hostlist) != ALLOW)
424
nfound += sudo_file_display_priv_long(pw, us, lbuf);
426
nfound += sudo_file_display_priv_short(pw, us, lbuf);
247
* If path doesn't end in /, return TRUE iff cmnd & path name the same inode;
248
* otherwise, return TRUE if user_cmnd names one of the inodes in path.
432
* Display matching Defaults entries for the given user on this host.
251
command_matches(sudoers_cmnd, sudoers_args)
435
sudo_file_display_defaults(nss, pw, lbuf)
436
struct sudo_nss *nss;
255
struct stat sudoers_stat;
257
char **ap, *base, buf[PATH_MAX];
261
/* Check for pseudo-commands */
262
if (strchr(user_cmnd, '/') == NULL) {
264
* Return true if both sudoers_cmnd and user_cmnd are "sudoedit" AND
265
* a) there are no args in sudoers OR
266
* b) there are no args on command line and none req by sudoers OR
267
* c) there are args in sudoers and on command line and they match
269
if (strcmp(sudoers_cmnd, "sudoedit") != 0 ||
270
strcmp(user_cmnd, "sudoedit") != 0)
273
(!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
275
fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
277
safe_cmnd = estrdup(sudoers_cmnd);
284
* If sudoers_cmnd has meta characters in it, use fnmatch(3)
285
* to do the matching.
287
if (has_meta(sudoers_cmnd)) {
289
* Return true if we find a match in the glob(3) results AND
290
* a) there are no args in sudoers OR
291
* b) there are no args on command line and none required by sudoers OR
292
* c) there are args in sudoers and on command line and they match
295
* Could optimize patterns ending in "/*" to "/user_base"
297
#define GLOB_FLAGS (GLOB_NOSORT | GLOB_MARK | GLOB_BRACE | GLOB_TILDE)
298
if (glob(sudoers_cmnd, GLOB_FLAGS, NULL, &gl) != 0) {
302
/* For each glob match, compare basename, st_dev and st_ino. */
303
for (ap = gl.gl_pathv; *ap != NULL; ap++) {
304
/* only stat if basenames are the same */
305
if ((base = strrchr(*ap, '/')) != NULL)
309
if (strcmp(user_base, base) != 0 ||
310
stat(*ap, &sudoers_stat) == -1)
444
if (nss->handle == NULL)
452
tq_foreach_fwd(&defaults, d) {
455
if (hostlist_matches(&d->binding) != ALLOW)
459
if (userlist_matches(pw, &d->binding) != ALLOW)
312
if (user_stat->st_dev == sudoers_stat.st_dev &&
313
user_stat->st_ino == sudoers_stat.st_ino) {
315
safe_cmnd = estrdup(*ap);
324
(!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
326
fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
328
safe_cmnd = estrdup(user_cmnd);
333
size_t dlen = strlen(sudoers_cmnd);
337
* Check to make sure this is not a directory spec (doesn't end in '/')
339
if (sudoers_cmnd[dlen - 1] != '/') {
340
/* Only proceed if user_base and basename(sudoers_cmnd) match */
341
if ((base = strrchr(sudoers_cmnd, '/')) == NULL)
345
if (strcmp(user_base, base) != 0 ||
346
stat(sudoers_cmnd, &sudoers_stat) == -1)
350
* Return true if inode/device matches AND
351
* a) there are no args in sudoers OR
352
* b) there are no args on command line and none req by sudoers OR
353
* c) there are args in sudoers and on command line and they match
355
if (user_stat->st_dev != sudoers_stat.st_dev ||
356
user_stat->st_ino != sudoers_stat.st_ino)
359
(!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
361
fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
363
safe_cmnd = estrdup(sudoers_cmnd);
466
lbuf_append(lbuf, prefix, NULL);
467
if (d->val != NULL) {
468
lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
469
d->op == '-' ? "-=" : "=", NULL);
470
if (strpbrk(d->val, " \t") != NULL) {
471
lbuf_append(lbuf, "\"", NULL);
472
lbuf_append_quoted(lbuf, "\"", d->val, NULL);
473
lbuf_append(lbuf, "\"", NULL);
370
* Grot through sudoers_cmnd's directory entries, looking for user_base.
372
dirp = opendir(sudoers_cmnd);
376
if (strlcpy(buf, sudoers_cmnd, sizeof(buf)) >= sizeof(buf))
378
while ((dent = readdir(dirp)) != NULL) {
379
/* ignore paths > PATH_MAX (XXX - log) */
381
if (strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf))
384
/* only stat if basenames are the same */
385
if (strcmp(user_base, dent->d_name) != 0 ||
386
stat(buf, &sudoers_stat) == -1)
388
if (user_stat->st_dev == sudoers_stat.st_dev &&
389
user_stat->st_ino == sudoers_stat.st_ino) {
391
safe_cmnd = estrdup(buf);
397
return(dent != NULL);
407
struct interface *ifp;
409
struct in6_addr addr6;
415
if (inet_pton(AF_INET6, n, &addr6) > 0) {
421
addr.s_addr = inet_addr(n);
424
for (i = 0; i < num_interfaces; i++) {
425
ifp = &interfaces[i];
426
if (ifp->family != family)
430
if (ifp->addr.ip4.s_addr == addr.s_addr ||
431
(ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
437
if (memcmp(ifp->addr.ip6.s6_addr, addr6.s6_addr,
438
sizeof(addr6.s6_addr)) == 0)
440
for (j = 0; j < sizeof(addr6.s6_addr); j++) {
441
if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr6.s6_addr[j])
444
if (j == sizeof(addr6.s6_addr))
446
#endif /* HAVE_IN6_ADDR */
454
addr_matches_if_netmask(n, m)
459
struct in_addr addr, mask;
460
struct interface *ifp;
462
struct in6_addr addr6, mask6;
468
if (inet_pton(AF_INET6, n, &addr6) > 0)
474
addr.s_addr = inet_addr(n);
477
if (family == AF_INET) {
479
mask.s_addr = inet_addr(m);
482
mask.s_addr = 0xffffffff;
485
mask.s_addr = htonl(mask.s_addr);
490
if (inet_pton(AF_INET6, m, &mask6) <= 0) {
492
for (i = 0; i < 16; i++) {
494
mask6.s6_addr[i] = 0;
495
else if (i * 8 + 8 <= j)
496
mask6.s6_addr[i] = 0xff;
498
mask6.s6_addr[i] = 0xff00 >> (j - i * 8);
502
#endif /* HAVE_IN6_ADDR */
504
for (i = 0; i < num_interfaces; i++) {
505
ifp = &interfaces[i];
506
if (ifp->family != family)
510
if ((ifp->addr.ip4.s_addr & mask.s_addr) == addr.s_addr)
514
for (j = 0; j < sizeof(addr6.s6_addr); j++) {
515
if ((ifp->addr.ip6.s6_addr[j] & mask6.s6_addr[j]) != addr6.s6_addr[j])
518
if (j == sizeof(addr6.s6_addr))
520
#endif /* HAVE_IN6_ADDR */
528
* Returns TRUE if "n" is one of our ip addresses or if
529
* "n" is a network that we are on, else returns FALSE.
538
/* If there's an explicit netmask, use it. */
539
if ((m = strchr(n, '/'))) {
541
retval = addr_matches_if_netmask(n, m);
544
retval = addr_matches_if(n);
550
* Returns 0 if the hostname matches the pattern and non-zero otherwise.
553
hostname_matches(shost, lhost, pattern)
558
if (has_meta(pattern)) {
559
if (strchr(pattern, '.'))
560
return(fnmatch(pattern, lhost, FNM_CASEFOLD));
562
return(fnmatch(pattern, shost, FNM_CASEFOLD));
564
if (strchr(pattern, '.'))
565
return(strcasecmp(lhost, pattern));
567
return(strcasecmp(shost, pattern));
572
* Returns TRUE if the user/uid from sudoers matches the specified user/uid,
573
* else returns FALSE.
576
userpw_matches(sudoers_user, user, pw)
581
if (pw != NULL && *sudoers_user == '#') {
582
uid_t uid = atoi(sudoers_user + 1);
583
if (uid == pw->pw_uid)
586
return(strcmp(sudoers_user, user) == 0);
590
* Returns TRUE if the given user belongs to the named group,
591
* else returns FALSE.
592
* XXX - reduce the number of passwd/group lookups
595
usergr_matches(group, user, pw)
605
/* make sure we have a valid usergroup, sudo style */
609
/* look up user's primary gid in the passwd file */
610
if (pw == NULL && (pw = getpwnam(user)) == NULL)
614
if ((grp = getgrnam(group)) == NULL)
617
/* check against user's primary (passwd file) gid */
618
if (grp->gr_gid == pw_gid)
622
* If the user has a supplementary group vector, check it first.
624
if (strcmp(user, user_name) == 0) {
625
for (i = 0; i < user_ngroups; i++) {
626
if (grp->gr_gid == user_groups[i])
630
if (grp->gr_mem != NULL) {
631
for (cur = grp->gr_mem; *cur; cur++) {
632
if (strcmp(*cur, user) == 0)
641
* Returns TRUE if "host" and "user" belong to the netgroup "netgr",
642
* else return FALSE. Either of "host", "shost" or "user" may be NULL
643
* in which case that argument is not checked...
646
netgr_matches(netgr, host, shost, user)
653
#ifdef HAVE_GETDOMAINNAME
654
static int initialized;
657
/* make sure we have a valid netgroup, sudo style */
661
#ifdef HAVE_GETDOMAINNAME
662
/* get the domain name (if any) */
664
domain = (char *) emalloc(MAXHOSTNAMELEN);
665
if (getdomainname(domain, MAXHOSTNAMELEN) == -1 || *domain == '\0') {
671
#endif /* HAVE_GETDOMAINNAME */
674
if (innetgr(netgr, host, user, domain))
676
else if (host != shost && innetgr(netgr, shost, user, domain))
678
#endif /* HAVE_INNETGR */
684
* Returns TRUE if "s" has shell meta characters in it,
685
* else returns FALSE.
693
for (t = s; *t; t++) {
694
if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']')
475
lbuf_append_quoted(lbuf, SUDOERS_QUOTED, d->val, NULL);
477
lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
486
* Display Defaults entries that are per-runas or per-command
489
sudo_file_display_bound_defaults(nss, pw, lbuf)
490
struct sudo_nss *nss;
496
/* XXX - should only print ones that match what the user can do. */
497
nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf);
498
nfound += display_bound_defaults(DEFAULTS_CMND, lbuf);
504
* Display Defaults entries of the given type.
507
display_bound_defaults(dtype, lbuf)
512
struct member *m, *binding = NULL;
514
int atype, nfound = 0;
540
/* printf("Per-%s Defaults entries:\n", dname); */
541
tq_foreach_fwd(&defaults, d) {
542
if (d->type != dtype)
546
if (binding != tq_first(&d->binding)) {
547
binding = tq_first(&d->binding);
548
lbuf_append(lbuf, " Defaults", dsep, NULL);
549
for (m = binding; m != NULL; m = m->next) {
551
lbuf_append(lbuf, ",", NULL);
552
print_member(lbuf, m->name, m->type, m->negated, atype);
553
lbuf_append(lbuf, " ", NULL);
556
lbuf_append(lbuf, ", ", NULL);
557
if (d->val != NULL) {
558
lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
559
d->op == '-' ? "-=" : "=", d->val, NULL);
561
lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
568
sudo_file_display_cmnd(nss, pw)
569
struct sudo_nss *nss;
573
struct member *match;
574
struct privilege *priv;
577
int host_match, runas_match, cmnd_match;
579
if (nss->handle == NULL)
583
tq_foreach_rev(&userspecs, us) {
584
if (userlist_matches(pw, &us->users) != ALLOW)
587
tq_foreach_rev(&us->privileges, priv) {
588
host_match = hostlist_matches(&priv->hostlist);
589
if (host_match != ALLOW)
591
tq_foreach_rev(&priv->cmndlist, cs) {
592
runas_match = runaslist_matches(&cs->runasuserlist,
593
&cs->runasgrouplist);
594
if (runas_match == ALLOW) {
595
cmnd_match = cmnd_matches(cs->cmnd);
596
if (cmnd_match != UNSPEC) {
597
match = host_match && runas_match ?
606
if (match != NULL && !match->negated) {
607
printf("%s%s%s\n", safe_cmnd, user_args ? " " : "",
608
user_args ? user_args : "");
615
* Print the contents of a struct member to stdout
618
_print_member(lbuf, name, type, negated, alias_type)
621
int type, negated, alias_type;
625
struct sudo_command *c;
629
lbuf_append(lbuf, negated ? "!ALL" : "ALL", NULL);
632
c = (struct sudo_command *) name;
634
lbuf_append(lbuf, "!", NULL);
635
lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->cmnd, NULL);
637
lbuf_append(lbuf, " ", NULL);
638
lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->args, NULL);
642
if ((a = find_alias(name, alias_type)) != NULL) {
643
tq_foreach_fwd(&a->members, m) {
644
if (m != tq_first(&a->members))
645
lbuf_append(lbuf, ", ", NULL);
646
_print_member(lbuf, m->name, m->type,
647
negated ? !m->negated : m->negated, alias_type);
653
lbuf_append(lbuf, negated ? "!" : "", name, NULL);
659
print_member(lbuf, name, type, negated, alias_type)
662
int type, negated, alias_type;
665
_print_member(lbuf, name, type, negated, alias_type);