version 1.1.1.4, 2013/07/22 10:46:12
|
version 1.1.1.5, 2014/06/15 16:12:54
|
Line 71
|
Line 71
|
/* |
/* |
* Globals |
* Globals |
*/ |
*/ |
extern int sudolineno; |
|
extern int last_token; |
|
extern char *sudoers; |
|
bool sudoers_warnings = true; |
bool sudoers_warnings = true; |
bool parse_error = false; |
bool parse_error = false; |
int errorlineno = -1; |
int errorlineno = -1; |
char *errorfile = NULL; | const char *errorfile = NULL; |
|
|
struct defaults_list defaults; | struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults); |
struct userspec_list userspecs; | struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs); |
|
|
/* |
/* |
* Local protoypes |
* Local protoypes |
Line 230 entry : COMMENT {
|
Line 227 entry : COMMENT {
|
|
|
defaults_list : defaults_entry |
defaults_list : defaults_entry |
| defaults_list ',' defaults_entry { |
| defaults_list ',' defaults_entry { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
Line 254 defaults_entry : DEFVAR {
|
Line 251 defaults_entry : DEFVAR {
|
|
|
privileges : privilege |
privileges : privilege |
| privileges ':' privilege { |
| privileges ':' privilege { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
|
|
privilege : hostlist '=' cmndspeclist { |
privilege : hostlist '=' cmndspeclist { |
struct privilege *p = ecalloc(1, sizeof(*p)); |
struct privilege *p = ecalloc(1, sizeof(*p)); |
list2tq(&p->hostlist, $1); | HLTQ_TO_TAILQ(&p->hostlist, $1, entries); |
list2tq(&p->cmndlist, $3); | HLTQ_TO_TAILQ(&p->cmndlist, $3, entries); |
p->prev = p; | HLTQ_INIT(p, entries); |
/* p->next = NULL; */ | |
$$ = p; |
$$ = p; |
} |
} |
; |
; |
Line 298 host : ALIAS {
|
Line 294 host : ALIAS {
|
|
|
cmndspeclist : cmndspec |
cmndspeclist : cmndspec |
| cmndspeclist ',' cmndspec { |
| cmndspeclist ',' cmndspec { |
list_append($1, $3); | struct cmndspec *prev; |
| prev = HLTQ_LAST($1, cmndspec, entries); |
| HLTQ_CONCAT($1, $3, entries); |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
/* propagate role and type */ |
/* propagate role and type */ |
if ($3->role == NULL) |
if ($3->role == NULL) |
$3->role = $3->prev->role; | $3->role = prev->role; |
if ($3->type == NULL) |
if ($3->type == NULL) |
$3->type = $3->prev->type; | $3->type = prev->type; |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
#ifdef HAVE_PRIV_SET |
#ifdef HAVE_PRIV_SET |
/* propagate privs & limitprivs */ |
/* propagate privs & limitprivs */ |
if ($3->privs == NULL) |
if ($3->privs == NULL) |
$3->privs = $3->prev->privs; | $3->privs = prev->privs; |
if ($3->limitprivs == NULL) |
if ($3->limitprivs == NULL) |
$3->limitprivs = $3->prev->limitprivs; | $3->limitprivs = prev->limitprivs; |
#endif /* HAVE_PRIV_SET */ |
#endif /* HAVE_PRIV_SET */ |
/* propagate tags and runas list */ |
/* propagate tags and runas list */ |
if ($3->tags.nopasswd == UNSPEC) |
if ($3->tags.nopasswd == UNSPEC) |
$3->tags.nopasswd = $3->prev->tags.nopasswd; | $3->tags.nopasswd = prev->tags.nopasswd; |
if ($3->tags.noexec == UNSPEC) |
if ($3->tags.noexec == UNSPEC) |
$3->tags.noexec = $3->prev->tags.noexec; | $3->tags.noexec = prev->tags.noexec; |
if ($3->tags.setenv == UNSPEC && |
if ($3->tags.setenv == UNSPEC && |
$3->prev->tags.setenv != IMPLIED) | prev->tags.setenv != IMPLIED) |
$3->tags.setenv = $3->prev->tags.setenv; | $3->tags.setenv = prev->tags.setenv; |
if ($3->tags.log_input == UNSPEC) |
if ($3->tags.log_input == UNSPEC) |
$3->tags.log_input = $3->prev->tags.log_input; | $3->tags.log_input = prev->tags.log_input; |
if ($3->tags.log_output == UNSPEC) |
if ($3->tags.log_output == UNSPEC) |
$3->tags.log_output = $3->prev->tags.log_output; | $3->tags.log_output = prev->tags.log_output; |
if ((tq_empty(&$3->runasuserlist) && | if (($3->runasuserlist == NULL && |
tq_empty(&$3->runasgrouplist)) && | $3->runasgrouplist == NULL) && |
(!tq_empty(&$3->prev->runasuserlist) || | (prev->runasuserlist != NULL || |
!tq_empty(&$3->prev->runasgrouplist))) { | prev->runasgrouplist != NULL)) { |
$3->runasuserlist = $3->prev->runasuserlist; | $3->runasuserlist = prev->runasuserlist; |
$3->runasgrouplist = $3->prev->runasgrouplist; | $3->runasgrouplist = prev->runasgrouplist; |
} |
} |
$$ = $1; |
$$ = $1; |
} |
} |
Line 339 cmndspeclist : cmndspec
|
Line 337 cmndspeclist : cmndspec
|
cmndspec : runasspec selinux solarisprivs cmndtag digcmnd { |
cmndspec : runasspec selinux solarisprivs cmndtag digcmnd { |
struct cmndspec *cs = ecalloc(1, sizeof(*cs)); |
struct cmndspec *cs = ecalloc(1, sizeof(*cs)); |
if ($1 != NULL) { |
if ($1 != NULL) { |
list2tq(&cs->runasuserlist, $1->runasusers); | if ($1->runasusers != NULL) { |
list2tq(&cs->runasgrouplist, $1->runasgroups); | cs->runasuserlist = |
| emalloc(sizeof(*cs->runasuserlist)); |
| HLTQ_TO_TAILQ(cs->runasuserlist, |
| $1->runasusers, entries); |
| } |
| if ($1->runasgroups != NULL) { |
| cs->runasgrouplist = |
| emalloc(sizeof(*cs->runasgrouplist)); |
| HLTQ_TO_TAILQ(cs->runasgrouplist, |
| $1->runasgroups, entries); |
| } |
efree($1); |
efree($1); |
} else { |
|
tq_init(&cs->runasuserlist); |
|
tq_init(&cs->runasgrouplist); |
|
} |
} |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
cs->role = $2.role; |
cs->role = $2.role; |
Line 356 cmndspec : runasspec selinux solarisprivs cmndtag digc
|
Line 361 cmndspec : runasspec selinux solarisprivs cmndtag digc
|
#endif |
#endif |
cs->tags = $4; |
cs->tags = $4; |
cs->cmnd = $5; |
cs->cmnd = $5; |
cs->prev = cs; | HLTQ_INIT(cs, entries); |
cs->next = NULL; | |
/* sudo "ALL" implies the SETENV tag */ |
/* sudo "ALL" implies the SETENV tag */ |
if (cs->cmnd->type == ALL && !cs->cmnd->negated && |
if (cs->cmnd->type == ALL && !cs->cmnd->negated && |
cs->tags.setenv == UNSPEC) |
cs->tags.setenv == UNSPEC) |
Line 564 hostalias : ALIAS '=' hostlist {
|
Line 568 hostalias : ALIAS '=' hostlist {
|
|
|
hostlist : ophost |
hostlist : ophost |
| hostlist ',' ophost { |
| hostlist ',' ophost { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
Line 584 cmndalias : ALIAS '=' cmndlist {
|
Line 588 cmndalias : ALIAS '=' cmndlist {
|
|
|
cmndlist : digcmnd |
cmndlist : digcmnd |
| cmndlist ',' digcmnd { |
| cmndlist ',' digcmnd { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
Line 617 useralias : ALIAS '=' userlist {
|
Line 621 useralias : ALIAS '=' userlist {
|
|
|
userlist : opuser |
userlist : opuser |
| userlist ',' opuser { |
| userlist ',' opuser { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
Line 651 user : ALIAS {
|
Line 655 user : ALIAS {
|
|
|
grouplist : opgroup |
grouplist : opgroup |
| grouplist ',' opgroup { |
| grouplist ',' opgroup { |
list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
$$ = $1; |
$$ = $1; |
} |
} |
; |
; |
Line 719 new_default(char *var, char *val, int op)
|
Line 723 new_default(char *var, char *val, int op)
|
d = ecalloc(1, sizeof(struct defaults)); |
d = ecalloc(1, sizeof(struct defaults)); |
d->var = var; |
d->var = var; |
d->val = val; |
d->val = val; |
tq_init(&d->binding); |
|
/* d->type = 0; */ |
/* d->type = 0; */ |
d->op = op; |
d->op = op; |
d->prev = d; | /* d->binding = NULL */ |
/* d->next = NULL; */ | HLTQ_INIT(d, entries); |
|
|
debug_return_ptr(d); |
debug_return_ptr(d); |
} |
} |
Line 737 new_member(char *name, int type)
|
Line 740 new_member(char *name, int type)
|
m = ecalloc(1, sizeof(struct member)); |
m = ecalloc(1, sizeof(struct member)); |
m->name = name; |
m->name = name; |
m->type = type; |
m->type = type; |
m->prev = m; | HLTQ_INIT(m, entries); |
/* m->next = NULL; */ | |
|
|
debug_return_ptr(m); |
debug_return_ptr(m); |
} |
} |
Line 765 static void
|
Line 767 static void
|
add_defaults(int type, struct member *bmem, struct defaults *defs) |
add_defaults(int type, struct member *bmem, struct defaults *defs) |
{ |
{ |
struct defaults *d; |
struct defaults *d; |
struct member_list binding; | struct member_list *binding; |
debug_decl(add_defaults, SUDO_DEBUG_PARSER) |
debug_decl(add_defaults, SUDO_DEBUG_PARSER) |
|
|
/* | if (defs != NULL) { |
* We can only call list2tq once on bmem as it will zero | /* |
* out the prev pointer when it consumes bmem. | * We use a single binding for each entry in defs. |
*/ | */ |
list2tq(&binding, bmem); | binding = emalloc(sizeof(*binding)); |
| if (bmem != NULL) |
| HLTQ_TO_TAILQ(binding, bmem, entries); |
| else |
| TAILQ_INIT(binding); |
|
|
/* | /* |
* Set type and binding (who it applies to) for new entries. | * Set type and binding (who it applies to) for new entries. |
*/ | * Then add to the global defaults list. |
for (d = defs; d != NULL; d = d->next) { | */ |
d->type = type; | HLTQ_FOREACH(d, defs, entries) { |
d->binding = binding; | d->type = type; |
| d->binding = binding; |
| } |
| TAILQ_CONCAT_HLTQ(&defaults, defs, entries); |
} |
} |
tq_append(&defaults, defs); |
|
|
|
debug_return; |
debug_return; |
} |
} |
|
|
/* |
/* |
* Allocate a new struct userspec, populate it, and insert it at the |
* Allocate a new struct userspec, populate it, and insert it at the |
* and of the userspecs list. | * end of the userspecs list. |
*/ |
*/ |
static void |
static void |
add_userspec(struct member *members, struct privilege *privs) |
add_userspec(struct member *members, struct privilege *privs) |
Line 797 add_userspec(struct member *members, struct privilege
|
Line 805 add_userspec(struct member *members, struct privilege
|
debug_decl(add_userspec, SUDO_DEBUG_PARSER) |
debug_decl(add_userspec, SUDO_DEBUG_PARSER) |
|
|
u = ecalloc(1, sizeof(*u)); |
u = ecalloc(1, sizeof(*u)); |
list2tq(&u->users, members); | HLTQ_TO_TAILQ(&u->users, members, entries); |
list2tq(&u->privileges, privs); | HLTQ_TO_TAILQ(&u->privileges, privs, entries); |
u->prev = u; | TAILQ_INSERT_TAIL(&userspecs, u, entries); |
/* u->next = NULL; */ | |
tq_append(&userspecs, u); | |
|
|
debug_return; |
debug_return; |
} |
} |
Line 813 add_userspec(struct member *members, struct privilege
|
Line 819 add_userspec(struct member *members, struct privilege
|
void |
void |
init_parser(const char *path, bool quiet) |
init_parser(const char *path, bool quiet) |
{ |
{ |
struct defaults *d; | struct member_list *binding; |
struct member *m, *binding; | struct defaults *d, *d_next; |
struct userspec *us; | struct userspec *us, *us_next; |
struct privilege *priv; | |
struct cmndspec *cs; | |
struct sudo_command *c; | |
debug_decl(init_parser, SUDO_DEBUG_PARSER) |
debug_decl(init_parser, SUDO_DEBUG_PARSER) |
|
|
while ((us = tq_pop(&userspecs)) != NULL) { | TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) { |
while ((m = tq_pop(&us->users)) != NULL) { | struct member *m, *m_next; |
| struct privilege *priv, *priv_next; |
| |
| TAILQ_FOREACH_SAFE(m, &us->users, entries, m_next) { |
efree(m->name); |
efree(m->name); |
efree(m); |
efree(m); |
} |
} |
while ((priv = tq_pop(&us->privileges)) != NULL) { | TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, priv_next) { |
struct member *runasuser = NULL, *runasgroup = NULL; | struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; |
| struct cmndspec *cs, *cs_next; |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
char *role = NULL, *type = NULL; |
char *role = NULL, *type = NULL; |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
Line 835 init_parser(const char *path, bool quiet)
|
Line 842 init_parser(const char *path, bool quiet)
|
char *privs = NULL, *limitprivs = NULL; |
char *privs = NULL, *limitprivs = NULL; |
#endif /* HAVE_PRIV_SET */ |
#endif /* HAVE_PRIV_SET */ |
|
|
while ((m = tq_pop(&priv->hostlist)) != NULL) { | TAILQ_FOREACH_SAFE(m, &priv->hostlist, entries, m_next) { |
efree(m->name); |
efree(m->name); |
efree(m); |
efree(m); |
} |
} |
while ((cs = tq_pop(&priv->cmndlist)) != NULL) { | TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, cs_next) { |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
/* Only free the first instance of a role/type. */ |
/* Only free the first instance of a role/type. */ |
if (cs->role != role) { |
if (cs->role != role) { |
Line 862 init_parser(const char *path, bool quiet)
|
Line 869 init_parser(const char *path, bool quiet)
|
efree(cs->limitprivs); |
efree(cs->limitprivs); |
} |
} |
#endif /* HAVE_PRIV_SET */ |
#endif /* HAVE_PRIV_SET */ |
if (tq_last(&cs->runasuserlist) != runasuser) { | /* Only free the first instance of runas user/group lists. */ |
runasuser = tq_last(&cs->runasuserlist); | if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { |
while ((m = tq_pop(&cs->runasuserlist)) != NULL) { | runasuserlist = cs->runasuserlist; |
| TAILQ_FOREACH_SAFE(m, runasuserlist, entries, m_next) { |
efree(m->name); |
efree(m->name); |
efree(m); |
efree(m); |
} |
} |
|
efree(runasuserlist); |
} |
} |
if (tq_last(&cs->runasgrouplist) != runasgroup) { | if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) { |
runasgroup = tq_last(&cs->runasgrouplist); | runasgrouplist = cs->runasgrouplist; |
while ((m = tq_pop(&cs->runasgrouplist)) != NULL) { | TAILQ_FOREACH_SAFE(m, runasgrouplist, entries, m_next) { |
efree(m->name); |
efree(m->name); |
efree(m); |
efree(m); |
} |
} |
|
efree(runasgrouplist); |
} |
} |
if (cs->cmnd->type == COMMAND) { |
if (cs->cmnd->type == COMMAND) { |
c = (struct sudo_command *) cs->cmnd->name; | struct sudo_command *c = |
| (struct sudo_command *) cs->cmnd->name; |
efree(c->cmnd); |
efree(c->cmnd); |
efree(c->args); |
efree(c->args); |
} |
} |
Line 889 init_parser(const char *path, bool quiet)
|
Line 900 init_parser(const char *path, bool quiet)
|
} |
} |
efree(us); |
efree(us); |
} |
} |
tq_init(&userspecs); | TAILQ_INIT(&userspecs); |
|
|
binding = NULL; |
binding = NULL; |
while ((d = tq_pop(&defaults)) != NULL) { | TAILQ_FOREACH_SAFE(d, &defaults, entries, d_next) { |
if (tq_last(&d->binding) != binding) { | if (d->binding != binding) { |
binding = tq_last(&d->binding); | struct member *m, *m_next; |
while ((m = tq_pop(&d->binding)) != NULL) { | |
| binding = d->binding; |
| TAILQ_FOREACH_SAFE(m, d->binding, entries, m_next) { |
if (m->type == COMMAND) { |
if (m->type == COMMAND) { |
c = (struct sudo_command *) m->name; | struct sudo_command *c = |
| (struct sudo_command *) m->name; |
efree(c->cmnd); |
efree(c->cmnd); |
efree(c->args); |
efree(c->args); |
} |
} |
efree(m->name); |
efree(m->name); |
efree(m); |
efree(m); |
} |
} |
|
efree(d->binding); |
} |
} |
efree(d->var); |
efree(d->var); |
efree(d->val); |
efree(d->val); |
efree(d); |
efree(d); |
} |
} |
tq_init(&defaults); | TAILQ_INIT(&defaults); |
|
|
init_aliases(); |
init_aliases(); |
|
|