version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.5, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2004-2005, 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 2004-2005, 2007-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 19
|
Line 19
|
#include <config.h> |
#include <config.h> |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
|
#include <stdio.h> |
#include <stdio.h> |
#ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
# include <stdlib.h> |
# include <stdlib.h> |
Line 48
|
Line 47
|
#include <gram.h> |
#include <gram.h> |
|
|
/* Characters that must be quoted in sudoers */ |
/* Characters that must be quoted in sudoers */ |
#define SUDOERS_QUOTED ":\\,=#\"" | #define SUDOERS_QUOTED ":\\,=#\"" |
|
|
/* sudoers nsswitch routines */ |
/* sudoers nsswitch routines */ |
struct sudo_nss sudo_nss_file = { |
struct sudo_nss sudo_nss_file = { |
&sudo_nss_file, | { NULL, NULL }, |
NULL, | |
sudo_file_open, |
sudo_file_open, |
sudo_file_close, |
sudo_file_close, |
sudo_file_parse, |
sudo_file_parse, |
Line 66 struct sudo_nss sudo_nss_file = {
|
Line 64 struct sudo_nss sudo_nss_file = {
|
}; |
}; |
|
|
/* |
/* |
* Parser externs. |
|
*/ |
|
extern FILE *yyin; |
|
extern char *errorfile; |
|
extern int errorlineno, parse_error; |
|
|
|
/* |
|
* Local prototypes. |
* Local prototypes. |
*/ |
*/ |
static void print_member(struct lbuf *, char *, int, int, int); | static int display_bound_defaults(int dtype, struct lbuf *lbuf); |
static int display_bound_defaults(int, struct lbuf *); | static void print_member(struct lbuf *lbuf, struct member *m, int alias_type); |
| static void print_member2(struct lbuf *lbuf, struct member *m, |
| const char *separator, int alias_type); |
|
|
int |
int |
sudo_file_open(struct sudo_nss *nss) |
sudo_file_open(struct sudo_nss *nss) |
{ |
{ |
|
debug_decl(sudo_file_open, SUDO_DEBUG_NSS) |
|
|
if (def_ignore_local_sudoers) |
if (def_ignore_local_sudoers) |
return -1; | debug_return_int(-1); |
nss->handle = open_sudoers(sudoers_file, FALSE, NULL); | nss->handle = open_sudoers(sudoers_file, false, NULL); |
return nss->handle ? 0 : -1; | debug_return_int(nss->handle ? 0 : -1); |
} |
} |
|
|
int |
int |
sudo_file_close(struct sudo_nss *nss) |
sudo_file_close(struct sudo_nss *nss) |
{ |
{ |
|
debug_decl(sudo_file_close, SUDO_DEBUG_NSS) |
|
|
/* Free parser data structures and close sudoers file. */ |
/* Free parser data structures and close sudoers file. */ |
init_parser(NULL, 0); | init_parser(NULL, false); |
if (nss->handle != NULL) { |
if (nss->handle != NULL) { |
fclose(nss->handle); |
fclose(nss->handle); |
nss->handle = NULL; |
nss->handle = NULL; |
yyin = NULL; | sudoersin = NULL; |
} |
} |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 106 sudo_file_close(struct sudo_nss *nss)
|
Line 103 sudo_file_close(struct sudo_nss *nss)
|
int |
int |
sudo_file_parse(struct sudo_nss *nss) |
sudo_file_parse(struct sudo_nss *nss) |
{ |
{ |
|
debug_decl(sudo_file_close, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
return -1; | debug_return_int(-1); |
|
|
init_parser(sudoers_file, 0); | init_parser(sudoers_file, false); |
yyin = nss->handle; | sudoersin = nss->handle; |
if (yyparse() != 0 || parse_error) { | if (sudoersparse() != 0 || parse_error) { |
log_error(NO_EXIT, _("parse error in %s near line %d"), | if (errorlineno != -1) { |
errorfile, errorlineno); | log_warning(0, N_("parse error in %s near line %d"), |
return -1; | errorfile, errorlineno); |
| } else { |
| log_warning(0, N_("parse error in %s"), errorfile); |
| } |
| debug_return_int(-1); |
} |
} |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 125 sudo_file_parse(struct sudo_nss *nss)
|
Line 128 sudo_file_parse(struct sudo_nss *nss)
|
int |
int |
sudo_file_setdefs(struct sudo_nss *nss) |
sudo_file_setdefs(struct sudo_nss *nss) |
{ |
{ |
|
debug_decl(sudo_file_setdefs, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
return -1; | debug_return_int(-1); |
|
|
if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER)) |
if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER)) |
return -1; | debug_return_int(-1); |
return 0; | debug_return_int(0); |
} |
} |
|
|
/* |
/* |
Line 145 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
Line 150 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
struct cmndtag *tags = NULL; |
struct cmndtag *tags = NULL; |
struct privilege *priv; |
struct privilege *priv; |
struct userspec *us; |
struct userspec *us; |
|
struct member *matching_user; |
|
debug_decl(sudo_file_lookup, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
return validated; | debug_return_int(validated); |
|
|
/* |
/* |
* Only check the actual command if pwflag is not set. |
* Only check the actual command if pwflag is not set. |
Line 159 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
Line 166 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
enum def_tuple pwcheck; |
enum def_tuple pwcheck; |
|
|
pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; |
pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; |
nopass = (pwcheck == all) ? TRUE : FALSE; | nopass = (pwcheck == all) ? true : false; |
|
|
if (list_pw == NULL) |
if (list_pw == NULL) |
SET(validated, FLAG_NO_CHECK); |
SET(validated, FLAG_NO_CHECK); |
CLR(validated, FLAG_NO_USER); |
CLR(validated, FLAG_NO_USER); |
CLR(validated, FLAG_NO_HOST); |
CLR(validated, FLAG_NO_HOST); |
match = DENY; |
match = DENY; |
tq_foreach_fwd(&userspecs, us) { | TAILQ_FOREACH(us, &userspecs, entries) { |
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) |
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) |
continue; |
continue; |
tq_foreach_fwd(&us->privileges, priv) { | TAILQ_FOREACH(priv, &us->privileges, entries) { |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
continue; |
continue; |
tq_foreach_fwd(&priv->cmndlist, cs) { | TAILQ_FOREACH(cs, &priv->cmndlist, entries) { |
/* Only check the command when listing another user. */ |
/* Only check the command when listing another user. */ |
if (user_uid == 0 || list_pw == NULL || |
if (user_uid == 0 || list_pw == NULL || |
user_uid == list_pw->pw_uid || |
user_uid == list_pw->pw_uid || |
cmnd_matches(cs->cmnd) == ALLOW) |
cmnd_matches(cs->cmnd) == ALLOW) |
match = ALLOW; |
match = ALLOW; |
if ((pwcheck == any && cs->tags.nopasswd == TRUE) || | if ((pwcheck == any && cs->tags.nopasswd == true) || |
(pwcheck == all && cs->tags.nopasswd != TRUE)) | (pwcheck == all && cs->tags.nopasswd != true)) |
nopass = cs->tags.nopasswd; |
nopass = cs->tags.nopasswd; |
} |
} |
} |
} |
Line 191 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
Line 198 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
SET(validated, VALIDATE_NOT_OK); |
SET(validated, VALIDATE_NOT_OK); |
if (pwcheck == always && def_authenticate) |
if (pwcheck == always && def_authenticate) |
SET(validated, FLAG_CHECK_USER); |
SET(validated, FLAG_CHECK_USER); |
else if (pwcheck == never || nopass == TRUE) | else if (pwcheck == never || nopass == true) |
def_authenticate = FALSE; | def_authenticate = false; |
return validated; | debug_return_int(validated); |
} |
} |
|
|
/* Need to be runas user while stat'ing things. */ |
/* Need to be runas user while stat'ing things. */ |
set_perms(PERM_RUNAS); |
set_perms(PERM_RUNAS); |
|
|
match = UNSPEC; |
match = UNSPEC; |
tq_foreach_rev(&userspecs, us) { | TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { |
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) |
if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) |
continue; |
continue; |
CLR(validated, FLAG_NO_USER); |
CLR(validated, FLAG_NO_USER); |
tq_foreach_rev(&us->privileges, priv) { | TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { |
host_match = hostlist_matches(&priv->hostlist); |
host_match = hostlist_matches(&priv->hostlist); |
if (host_match == ALLOW) |
if (host_match == ALLOW) |
CLR(validated, FLAG_NO_HOST); |
CLR(validated, FLAG_NO_HOST); |
else |
else |
continue; |
continue; |
tq_foreach_rev(&priv->cmndlist, cs) { | TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { |
runas_match = runaslist_matches(&cs->runasuserlist, | matching_user = NULL; |
&cs->runasgrouplist); | runas_match = runaslist_matches(cs->runasuserlist, |
| cs->runasgrouplist, &matching_user, NULL); |
if (runas_match == ALLOW) { |
if (runas_match == ALLOW) { |
cmnd_match = cmnd_matches(cs->cmnd); |
cmnd_match = cmnd_matches(cs->cmnd); |
if (cmnd_match != UNSPEC) { |
if (cmnd_match != UNSPEC) { |
Line 225 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
Line 233 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
if (user_type == NULL) |
if (user_type == NULL) |
user_type = cs->type ? estrdup(cs->type) : def_type; |
user_type = cs->type ? estrdup(cs->type) : def_type; |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
|
#ifdef HAVE_PRIV_SET |
|
/* Set Solaris privilege sets */ |
|
if (runas_privs == NULL) |
|
runas_privs = cs->privs ? estrdup(cs->privs) : def_privs; |
|
if (runas_limitprivs == NULL) |
|
runas_limitprivs = cs->limitprivs ? estrdup(cs->limitprivs) : def_limitprivs; |
|
#endif /* HAVE_PRIV_SET */ |
|
/* |
|
* If user is running command as himself, |
|
* set runas_pw = sudo_user.pw. |
|
* XXX - hack, want more general solution |
|
*/ |
|
if (matching_user && matching_user->type == MYSELF) { |
|
sudo_pw_delref(runas_pw); |
|
sudo_pw_addref(sudo_user.pw); |
|
runas_pw = sudo_user.pw; |
|
} |
goto matched2; |
goto matched2; |
} |
} |
} |
} |
Line 254 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
Line 279 sudo_file_lookup(struct sudo_nss *nss, int validated,
|
def_authenticate = !tags->nopasswd; |
def_authenticate = !tags->nopasswd; |
} |
} |
restore_perms(); |
restore_perms(); |
return validated; | debug_return_int(validated); |
} |
} |
|
|
|
#define TAG_SET(tt) \ |
|
((tt) != UNSPEC && (tt) != IMPLIED) |
|
|
#define TAG_CHANGED(t) \ |
#define TAG_CHANGED(t) \ |
(cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t) | (TAG_SET(cs->tags.t) && cs->tags.t != tags->t) |
|
|
static void |
static void |
sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, |
sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, |
struct lbuf *lbuf) |
struct lbuf *lbuf) |
{ |
{ |
struct member *m; | debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS) |
|
|
|
#ifdef HAVE_PRIV_SET |
|
if (cs->privs) |
|
lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs); |
|
if (cs->limitprivs) |
|
lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs); |
|
#endif /* HAVE_PRIV_SET */ |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
if (cs->role) |
if (cs->role) |
lbuf_append(lbuf, "ROLE=%s ", cs->role); |
lbuf_append(lbuf, "ROLE=%s ", cs->role); |
Line 292 sudo_file_append_cmnd(struct cmndspec *cs, struct cmnd
|
Line 326 sudo_file_append_cmnd(struct cmndspec *cs, struct cmnd
|
lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); |
lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: "); |
tags->log_output = cs->tags.log_output; |
tags->log_output = cs->tags.log_output; |
} |
} |
m = cs->cmnd; | print_member(lbuf, cs->cmnd, CMNDALIAS); |
print_member(lbuf, m->name, m->type, m->negated, | debug_return; |
CMNDALIAS); | |
} |
} |
|
|
|
#define RUNAS_CHANGED(cs1, cs2) \ |
|
(cs1 == NULL || cs2 == NULL || \ |
|
cs1->runasuserlist != cs2->runasuserlist || \ |
|
cs1->runasgrouplist != cs2->runasgrouplist) |
|
|
static int |
static int |
sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, |
sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, |
struct lbuf *lbuf) |
struct lbuf *lbuf) |
{ |
{ |
struct cmndspec *cs; | struct cmndspec *cs, *prev_cs; |
struct member *m; |
struct member *m; |
struct privilege *priv; |
struct privilege *priv; |
struct cmndtag tags; |
struct cmndtag tags; |
int nfound = 0; |
int nfound = 0; |
|
debug_decl(sudo_file_display_priv_short, SUDO_DEBUG_NSS) |
|
|
tq_foreach_fwd(&us->privileges, priv) { | /* gcc -Wuninitialized false positive */ |
| tags.noexec = UNSPEC; |
| tags.setenv = UNSPEC; |
| tags.nopasswd = UNSPEC; |
| tags.log_input = UNSPEC; |
| tags.log_output = UNSPEC; |
| TAILQ_FOREACH(priv, &us->privileges, entries) { |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
continue; |
continue; |
tags.noexec = UNSPEC; | prev_cs = NULL; |
tags.setenv = UNSPEC; | TAILQ_FOREACH(cs, &priv->cmndlist, entries) { |
tags.nopasswd = UNSPEC; | if (RUNAS_CHANGED(cs, prev_cs)) { |
tags.log_input = UNSPEC; | if (cs != TAILQ_FIRST(&priv->cmndlist)) |
tags.log_output = UNSPEC; | lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, " "); | lbuf_append(lbuf, " ("); |
tq_foreach_fwd(&priv->cmndlist, cs) { | if (cs->runasuserlist != NULL) { |
if (cs != tq_first(&priv->cmndlist)) | TAILQ_FOREACH(m, cs->runasuserlist, entries) { |
lbuf_append(lbuf, ", "); | if (m != TAILQ_FIRST(cs->runasuserlist)) |
lbuf_append(lbuf, "("); | lbuf_append(lbuf, ", "); |
if (!tq_empty(&cs->runasuserlist)) { | print_member(lbuf, m, RUNASALIAS); |
tq_foreach_fwd(&cs->runasuserlist, m) { | } |
if (m != tq_first(&cs->runasuserlist)) | } else if (cs->runasgrouplist == NULL) { |
lbuf_append(lbuf, ", "); | lbuf_append(lbuf, "%s", def_runas_default); |
print_member(lbuf, m->name, m->type, m->negated, | } else { |
RUNASALIAS); | lbuf_append(lbuf, "%s", pw->pw_name); |
} |
} |
} else if (tq_empty(&cs->runasgrouplist)) { | if (cs->runasgrouplist != NULL) { |
lbuf_append(lbuf, "%s", def_runas_default); | lbuf_append(lbuf, " : "); |
} else { | TAILQ_FOREACH(m, cs->runasgrouplist, entries) { |
lbuf_append(lbuf, "%s", pw->pw_name); | if (m != TAILQ_FIRST(cs->runasgrouplist)) |
} | lbuf_append(lbuf, ", "); |
if (!tq_empty(&cs->runasgrouplist)) { | print_member(lbuf, m, RUNASALIAS); |
lbuf_append(lbuf, " : "); | } |
tq_foreach_fwd(&cs->runasgrouplist, m) { | |
if (m != tq_first(&cs->runasgrouplist)) | |
lbuf_append(lbuf, ", "); | |
print_member(lbuf, m->name, m->type, m->negated, | |
RUNASALIAS); | |
} |
} |
|
lbuf_append(lbuf, ") "); |
|
tags.noexec = UNSPEC; |
|
tags.setenv = UNSPEC; |
|
tags.nopasswd = UNSPEC; |
|
tags.log_input = UNSPEC; |
|
tags.log_output = UNSPEC; |
|
} else if (cs != TAILQ_FIRST(&priv->cmndlist)) { |
|
lbuf_append(lbuf, ", "); |
} |
} |
lbuf_append(lbuf, ") "); |
|
sudo_file_append_cmnd(cs, &tags, lbuf); |
sudo_file_append_cmnd(cs, &tags, lbuf); |
|
prev_cs = cs; |
nfound++; |
nfound++; |
} |
} |
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, "\n"); |
} |
} |
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
|
#define TAGS_CHANGED(ot, nt) \ |
|
((TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \ |
|
(TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \ |
|
(TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \ |
|
(TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \ |
|
(TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output)) |
|
|
|
/* |
|
* Compare the current cmndspec with the previous one to determine |
|
* whether we need to start a new long entry for "sudo -ll". |
|
* Returns true if we should start a new long entry, else false. |
|
*/ |
|
static bool |
|
new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs) |
|
{ |
|
if (prev_cs == NULL) |
|
return true; |
|
if (RUNAS_CHANGED(cs, prev_cs) || TAGS_CHANGED(cs->tags, prev_cs->tags)) |
|
return true; |
|
#ifdef HAVE_PRIV_SET |
|
if (cs->privs && (!prev_cs->privs || strcmp(cs->privs, prev_cs->privs) != 0)) |
|
return true; |
|
if (cs->limitprivs && (!prev_cs->limitprivs || strcmp(cs->limitprivs, prev_cs->limitprivs) != 0)) |
|
return true; |
|
#endif /* HAVE_PRIV_SET */ |
|
#ifdef HAVE_SELINUX |
|
if (cs->role && (!prev_cs->role || strcmp(cs->role, prev_cs->role) != 0)) |
|
return true; |
|
if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0)) |
|
return true; |
|
#endif /* HAVE_SELINUX */ |
|
return false; |
|
} |
|
|
static int |
static int |
sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, |
sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, |
struct lbuf *lbuf) |
struct lbuf *lbuf) |
{ |
{ |
struct cmndspec *cs; | struct cmndspec *cs, *prev_cs; |
struct member *m; |
struct member *m; |
struct privilege *priv; |
struct privilege *priv; |
struct cmndtag tags; | int nfound = 0, olen; |
int nfound = 0; | debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS) |
|
|
tq_foreach_fwd(&us->privileges, priv) { | TAILQ_FOREACH(priv, &us->privileges, entries) { |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
if (hostlist_matches(&priv->hostlist) != ALLOW) |
continue; |
continue; |
tags.noexec = UNSPEC; | prev_cs = NULL; |
tags.setenv = UNSPEC; | TAILQ_FOREACH(cs, &priv->cmndlist, entries) { |
tags.nopasswd = UNSPEC; | if (new_long_entry(cs, prev_cs)) { |
tags.log_input = UNSPEC; | lbuf_append(lbuf, _("\nSudoers entry:\n")); |
tags.log_output = UNSPEC; | lbuf_append(lbuf, _(" RunAsUsers: ")); |
lbuf_append(lbuf, _("\nSudoers entry:\n")); | if (cs->runasuserlist != NULL) { |
tq_foreach_fwd(&priv->cmndlist, cs) { | TAILQ_FOREACH(m, cs->runasuserlist, entries) { |
lbuf_append(lbuf, _(" RunAsUsers: ")); | if (m != TAILQ_FIRST(cs->runasuserlist)) |
if (!tq_empty(&cs->runasuserlist)) { | lbuf_append(lbuf, ", "); |
tq_foreach_fwd(&cs->runasuserlist, m) { | print_member(lbuf, m, RUNASALIAS); |
if (m != tq_first(&cs->runasuserlist)) | } |
lbuf_append(lbuf, ", "); | } else if (cs->runasgrouplist == NULL) { |
print_member(lbuf, m->name, m->type, m->negated, | lbuf_append(lbuf, "%s", def_runas_default); |
RUNASALIAS); | } else { |
| lbuf_append(lbuf, "%s", pw->pw_name); |
} |
} |
} else if (tq_empty(&cs->runasgrouplist)) { |
|
lbuf_append(lbuf, "%s", def_runas_default); |
|
} else { |
|
lbuf_append(lbuf, "%s", pw->pw_name); |
|
} |
|
lbuf_append(lbuf, "\n"); |
|
if (!tq_empty(&cs->runasgrouplist)) { |
|
lbuf_append(lbuf, _(" RunAsGroups: ")); |
|
tq_foreach_fwd(&cs->runasgrouplist, m) { |
|
if (m != tq_first(&cs->runasgrouplist)) |
|
lbuf_append(lbuf, ", "); |
|
print_member(lbuf, m->name, m->type, m->negated, |
|
RUNASALIAS); |
|
} |
|
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, "\n"); |
|
if (cs->runasgrouplist != NULL) { |
|
lbuf_append(lbuf, _(" RunAsGroups: ")); |
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) { |
|
if (m != TAILQ_FIRST(cs->runasgrouplist)) |
|
lbuf_append(lbuf, ", "); |
|
print_member(lbuf, m, RUNASALIAS); |
|
} |
|
lbuf_append(lbuf, "\n"); |
|
} |
|
olen = lbuf->len; |
|
lbuf_append(lbuf, _(" Options: ")); |
|
if (TAG_SET(cs->tags.setenv)) |
|
lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!"); |
|
if (TAG_SET(cs->tags.noexec)) |
|
lbuf_append(lbuf, "%snoexec, ", cs->tags.noexec ? "" : "!"); |
|
if (TAG_SET(cs->tags.nopasswd)) |
|
lbuf_append(lbuf, "%sauthenticate, ", cs->tags.nopasswd ? "!" : ""); |
|
if (TAG_SET(cs->tags.log_input)) |
|
lbuf_append(lbuf, "%slog_input, ", cs->tags.log_input ? "" : "!"); |
|
if (TAG_SET(cs->tags.log_output)) |
|
lbuf_append(lbuf, "%slog_output, ", cs->tags.log_output ? "" : "!"); |
|
if (lbuf->buf[lbuf->len - 2] == ',') { |
|
lbuf->len -= 2; /* remove trailing ", " */ |
|
lbuf_append(lbuf, "\n"); |
|
} else { |
|
lbuf->len = olen; /* no options */ |
|
} |
|
#ifdef HAVE_PRIV_SET |
|
if (cs->privs) |
|
lbuf_append(lbuf, " Privs: %s\n", cs->privs); |
|
if (cs->limitprivs) |
|
lbuf_append(lbuf, " Limitprivs: %s\n", cs->limitprivs); |
|
#endif /* HAVE_PRIV_SET */ |
|
#ifdef HAVE_SELINUX |
|
if (cs->role) |
|
lbuf_append(lbuf, " Role: %s\n", cs->role); |
|
if (cs->type) |
|
lbuf_append(lbuf, " Type: %s\n", cs->type); |
|
#endif /* HAVE_SELINUX */ |
|
lbuf_append(lbuf, _(" Commands:\n")); |
} |
} |
lbuf_append(lbuf, _(" Commands:\n\t")); | lbuf_append(lbuf, "\t"); |
sudo_file_append_cmnd(cs, &tags, lbuf); | print_member2(lbuf, cs->cmnd, "\n\t", CMNDALIAS); |
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, "\n"); |
|
prev_cs = cs; |
nfound++; |
nfound++; |
} |
} |
} |
} |
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
int |
int |
Line 409 sudo_file_display_privs(struct sudo_nss *nss, struct p
|
Line 519 sudo_file_display_privs(struct sudo_nss *nss, struct p
|
{ |
{ |
struct userspec *us; |
struct userspec *us; |
int nfound = 0; |
int nfound = 0; |
|
debug_decl(sudo_file_display_priv, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
goto done; |
goto done; |
|
|
tq_foreach_fwd(&userspecs, us) { | TAILQ_FOREACH(us, &userspecs, entries) { |
if (userlist_matches(pw, &us->users) != ALLOW) |
if (userlist_matches(pw, &us->users) != ALLOW) |
continue; |
continue; |
|
|
Line 423 sudo_file_display_privs(struct sudo_nss *nss, struct p
|
Line 534 sudo_file_display_privs(struct sudo_nss *nss, struct p
|
nfound += sudo_file_display_priv_short(pw, us, lbuf); |
nfound += sudo_file_display_priv_short(pw, us, lbuf); |
} |
} |
done: |
done: |
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
/* |
/* |
Line 436 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
Line 547 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
struct defaults *d; |
struct defaults *d; |
char *prefix; |
char *prefix; |
int nfound = 0; |
int nfound = 0; |
|
debug_decl(sudo_file_display_defaults, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
goto done; |
goto done; |
Line 445 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
Line 557 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
else |
else |
prefix = ", "; |
prefix = ", "; |
|
|
tq_foreach_fwd(&defaults, d) { | TAILQ_FOREACH(d, &defaults, entries) { |
switch (d->type) { |
switch (d->type) { |
case DEFAULTS_HOST: |
case DEFAULTS_HOST: |
if (hostlist_matches(&d->binding) != ALLOW) | if (hostlist_matches(d->binding) != ALLOW) |
continue; |
continue; |
break; |
break; |
case DEFAULTS_USER: |
case DEFAULTS_USER: |
if (userlist_matches(pw, &d->binding) != ALLOW) | if (userlist_matches(pw, d->binding) != ALLOW) |
continue; |
continue; |
break; |
break; |
case DEFAULTS_RUNAS: |
case DEFAULTS_RUNAS: |
Line 470 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
Line 582 sudo_file_display_defaults(struct sudo_nss *nss, struc
|
lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); |
lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); |
} else |
} else |
lbuf_append(lbuf, "%s%s%s", prefix, |
lbuf_append(lbuf, "%s%s%s", prefix, |
d->op == FALSE ? "!" : "", d->var); | d->op == false ? "!" : "", d->var); |
prefix = ", "; |
prefix = ", "; |
nfound++; |
nfound++; |
} |
} |
done: |
done: |
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
/* |
/* |
Line 486 sudo_file_display_bound_defaults(struct sudo_nss *nss,
|
Line 598 sudo_file_display_bound_defaults(struct sudo_nss *nss,
|
struct lbuf *lbuf) |
struct lbuf *lbuf) |
{ |
{ |
int nfound = 0; |
int nfound = 0; |
|
debug_decl(sudo_file_display_bound_defaults, SUDO_DEBUG_NSS) |
|
|
/* XXX - should only print ones that match what the user can do. */ |
/* XXX - should only print ones that match what the user can do. */ |
nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf); |
nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf); |
nfound += display_bound_defaults(DEFAULTS_CMND, lbuf); |
nfound += display_bound_defaults(DEFAULTS_CMND, lbuf); |
|
|
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
/* |
/* |
Line 501 static int
|
Line 614 static int
|
display_bound_defaults(int dtype, struct lbuf *lbuf) |
display_bound_defaults(int dtype, struct lbuf *lbuf) |
{ |
{ |
struct defaults *d; |
struct defaults *d; |
struct member *m, *binding = NULL; | struct member_list *binding = NULL; |
| struct member *m; |
char *dsep; |
char *dsep; |
int atype, nfound = 0; |
int atype, nfound = 0; |
|
debug_decl(display_bound_defaults, SUDO_DEBUG_NSS) |
|
|
switch (dtype) { |
switch (dtype) { |
case DEFAULTS_HOST: |
case DEFAULTS_HOST: |
Line 523 display_bound_defaults(int dtype, struct lbuf *lbuf)
|
Line 638 display_bound_defaults(int dtype, struct lbuf *lbuf)
|
dsep = "!"; |
dsep = "!"; |
break; |
break; |
default: |
default: |
return -1; | debug_return_int(-1); |
} |
} |
tq_foreach_fwd(&defaults, d) { | TAILQ_FOREACH(d, &defaults, entries) { |
if (d->type != dtype) |
if (d->type != dtype) |
continue; |
continue; |
|
|
nfound++; |
nfound++; |
if (binding != tq_first(&d->binding)) { | if (binding != d->binding) { |
binding = tq_first(&d->binding); | binding = d->binding; |
if (nfound != 1) |
if (nfound != 1) |
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, "\n"); |
lbuf_append(lbuf, " Defaults%s", dsep); |
lbuf_append(lbuf, " Defaults%s", dsep); |
for (m = binding; m != NULL; m = m->next) { | TAILQ_FOREACH(m, binding, entries) { |
if (m != binding) | if (m != TAILQ_FIRST(binding)) |
lbuf_append(lbuf, ","); |
lbuf_append(lbuf, ","); |
print_member(lbuf, m->name, m->type, m->negated, atype); | print_member(lbuf, m, atype); |
lbuf_append(lbuf, " "); |
lbuf_append(lbuf, " "); |
} |
} |
} else |
} else |
Line 547 display_bound_defaults(int dtype, struct lbuf *lbuf)
|
Line 662 display_bound_defaults(int dtype, struct lbuf *lbuf)
|
lbuf_append(lbuf, "%s%s%s", d->var, d->op == '+' ? "+=" : |
lbuf_append(lbuf, "%s%s%s", d->var, d->op == '+' ? "+=" : |
d->op == '-' ? "-=" : "=", d->val); |
d->op == '-' ? "-=" : "=", d->val); |
} else |
} else |
lbuf_append(lbuf, "%s%s", d->op == FALSE ? "!" : "", d->var); | lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var); |
} |
} |
|
|
return nfound; | debug_return_int(nfound); |
} |
} |
|
|
int |
int |
Line 562 sudo_file_display_cmnd(struct sudo_nss *nss, struct pa
|
Line 677 sudo_file_display_cmnd(struct sudo_nss *nss, struct pa
|
struct userspec *us; |
struct userspec *us; |
int rval = 1; |
int rval = 1; |
int host_match, runas_match, cmnd_match; |
int host_match, runas_match, cmnd_match; |
|
debug_decl(sudo_file_display_cmnd, SUDO_DEBUG_NSS) |
|
|
if (nss->handle == NULL) |
if (nss->handle == NULL) |
goto done; |
goto done; |
|
|
match = NULL; |
match = NULL; |
tq_foreach_rev(&userspecs, us) { | TAILQ_FOREACH_REVERSE(us, &userspecs, userspec_list, entries) { |
if (userlist_matches(pw, &us->users) != ALLOW) |
if (userlist_matches(pw, &us->users) != ALLOW) |
continue; |
continue; |
|
|
tq_foreach_rev(&us->privileges, priv) { | TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) { |
host_match = hostlist_matches(&priv->hostlist); |
host_match = hostlist_matches(&priv->hostlist); |
if (host_match != ALLOW) |
if (host_match != ALLOW) |
continue; |
continue; |
tq_foreach_rev(&priv->cmndlist, cs) { | TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) { |
runas_match = runaslist_matches(&cs->runasuserlist, | runas_match = runaslist_matches(cs->runasuserlist, |
&cs->runasgrouplist); | cs->runasgrouplist, NULL, NULL); |
if (runas_match == ALLOW) { |
if (runas_match == ALLOW) { |
cmnd_match = cmnd_matches(cs->cmnd); |
cmnd_match = cmnd_matches(cs->cmnd); |
if (cmnd_match != UNSPEC) { |
if (cmnd_match != UNSPEC) { |
match = host_match && runas_match ? cs->cmnd : NULL; | if (cmnd_match == ALLOW) |
| match = cs->cmnd; |
goto matched; |
goto matched; |
} |
} |
} |
} |
Line 595 sudo_file_display_cmnd(struct sudo_nss *nss, struct pa
|
Line 712 sudo_file_display_cmnd(struct sudo_nss *nss, struct pa
|
rval = 0; |
rval = 0; |
} |
} |
done: |
done: |
return rval; | debug_return_int(rval); |
} |
} |
|
|
/* |
/* |
Line 603 done:
|
Line 720 done:
|
*/ |
*/ |
static void |
static void |
_print_member(struct lbuf *lbuf, char *name, int type, int negated, |
_print_member(struct lbuf *lbuf, char *name, int type, int negated, |
int alias_type) | const char *separator, int alias_type) |
{ |
{ |
struct alias *a; |
struct alias *a; |
struct member *m; |
struct member *m; |
struct sudo_command *c; |
struct sudo_command *c; |
|
debug_decl(_print_member, SUDO_DEBUG_NSS) |
|
|
switch (type) { |
switch (type) { |
case ALL: |
case ALL: |
lbuf_append(lbuf, "%sALL", negated ? "!" : ""); |
lbuf_append(lbuf, "%sALL", negated ? "!" : ""); |
break; |
break; |
|
case MYSELF: |
|
lbuf_append(lbuf, "%s%s", negated ? "!" : "", user_name); |
|
break; |
case COMMAND: |
case COMMAND: |
c = (struct sudo_command *) name; |
c = (struct sudo_command *) name; |
if (negated) |
if (negated) |
Line 624 _print_member(struct lbuf *lbuf, char *name, int type,
|
Line 745 _print_member(struct lbuf *lbuf, char *name, int type,
|
} |
} |
break; |
break; |
case ALIAS: |
case ALIAS: |
if ((a = alias_find(name, alias_type)) != NULL) { | if ((a = alias_get(name, alias_type)) != NULL) { |
tq_foreach_fwd(&a->members, m) { | TAILQ_FOREACH(m, &a->members, entries) { |
if (m != tq_first(&a->members)) | if (m != TAILQ_FIRST(&a->members)) |
lbuf_append(lbuf, ", "); | lbuf_append(lbuf, "%s", separator); |
_print_member(lbuf, m->name, m->type, |
_print_member(lbuf, m->name, m->type, |
negated ? !m->negated : m->negated, alias_type); | negated ? !m->negated : m->negated, separator, |
| alias_type); |
} |
} |
|
alias_put(a); |
break; |
break; |
} |
} |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
Line 638 _print_member(struct lbuf *lbuf, char *name, int type,
|
Line 761 _print_member(struct lbuf *lbuf, char *name, int type,
|
lbuf_append(lbuf, "%s%s", negated ? "!" : "", name); |
lbuf_append(lbuf, "%s%s", negated ? "!" : "", name); |
break; |
break; |
} |
} |
|
debug_return; |
} |
} |
|
|
static void |
static void |
print_member(struct lbuf *lbuf, char *name, int type, int negated, | print_member(struct lbuf *lbuf, struct member *m, int alias_type) |
| { |
| _print_member(lbuf, m->name, m->type, m->negated, ", ", alias_type); |
| } |
| |
| static void |
| print_member2(struct lbuf *lbuf, struct member *m, const char *separator, |
int alias_type) |
int alias_type) |
{ |
{ |
alias_seqno++; | _print_member(lbuf, m->name, m->type, m->negated, separator, alias_type); |
_print_member(lbuf, name, type, negated, alias_type); | |
} |
} |