version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 1
|
Line 1
|
%{ |
%{ |
/* |
/* |
* Copyright (c) 1996, 1998-2005, 2007-2011 | * Copyright (c) 1996, 1998-2005, 2007-2012 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* 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 |
Line 44
|
Line 44
|
#ifdef HAVE_UNISTD_H |
#ifdef HAVE_UNISTD_H |
# include <unistd.h> |
# include <unistd.h> |
#endif /* HAVE_UNISTD_H */ |
#endif /* HAVE_UNISTD_H */ |
|
#ifdef HAVE_INTTYPES_H |
|
# include <inttypes.h> |
|
#endif |
#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) |
#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) |
# include <alloca.h> |
# include <alloca.h> |
#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ |
#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ |
Line 52
|
Line 55
|
#include "sudoers.h" /* XXX */ |
#include "sudoers.h" /* XXX */ |
#include "parse.h" |
#include "parse.h" |
#include "toke.h" |
#include "toke.h" |
|
#include "gram.h" |
|
|
/* |
/* |
* We must define SIZE_MAX for yacc's skeleton.c. |
* We must define SIZE_MAX for yacc's skeleton.c. |
Line 70
|
Line 74
|
* Globals |
* Globals |
*/ |
*/ |
extern int sudolineno; |
extern int sudolineno; |
|
extern int last_token; |
extern char *sudoers; |
extern char *sudoers; |
static int verbose = FALSE; | bool sudoers_warnings = true; |
int parse_error = FALSE; | bool parse_error = false; |
int pedantic = FALSE; | |
int errorlineno = -1; |
int errorlineno = -1; |
char *errorfile = NULL; |
char *errorfile = NULL; |
|
|
Line 92 static struct member *new_member(char *, int);
|
Line 96 static struct member *new_member(char *, int);
|
void |
void |
yyerror(const char *s) |
yyerror(const char *s) |
{ |
{ |
|
debug_decl(yyerror, SUDO_DEBUG_PARSER) |
|
|
|
/* If we last saw a newline the error is on the preceding line. */ |
|
if (last_token == COMMENT) |
|
sudolineno--; |
|
|
/* Save the line the first error occurred on. */ |
/* Save the line the first error occurred on. */ |
if (errorlineno == -1) { |
if (errorlineno == -1) { |
errorlineno = sudolineno ? sudolineno - 1 : 0; | errorlineno = sudolineno; |
errorfile = estrdup(sudoers); |
errorfile = estrdup(sudoers); |
} |
} |
if (trace_print != NULL) { | if (sudoers_warnings && s != NULL) { |
LEXTRACE("<*> "); |
LEXTRACE("<*> "); |
} else if (verbose && s != NULL) { | #ifndef TRACELEXER |
warningx(_(">>> %s: %s near line %d <<<"), sudoers, s, | if (trace_print == NULL || trace_print == sudoers_trace_print) |
sudolineno ? sudolineno - 1 : 0); | warningx(_(">>> %s: %s near line %d <<<"), sudoers, s, sudolineno); |
| #endif |
} |
} |
parse_error = TRUE; | parse_error = true; |
| debug_return; |
} |
} |
%} |
%} |
|
|
Line 116 yyerror(const char *s)
|
Line 128 yyerror(const char *s)
|
struct sudo_command command; |
struct sudo_command command; |
struct cmndtag tag; |
struct cmndtag tag; |
struct selinux_info seinfo; |
struct selinux_info seinfo; |
|
struct solaris_privs_info privinfo; |
char *string; |
char *string; |
int tok; |
int tok; |
} |
} |
Line 154 yyerror(const char *s)
|
Line 167 yyerror(const char *s)
|
%token <tok> ERROR |
%token <tok> ERROR |
%token <tok> TYPE /* SELinux type */ |
%token <tok> TYPE /* SELinux type */ |
%token <tok> ROLE /* SELinux role */ |
%token <tok> ROLE /* SELinux role */ |
|
%token <tok> PRIVS /* Solaris privileges */ |
|
%token <tok> LIMITPRIVS /* Solaris limit privileges */ |
|
%token <tok> MYSELF /* run as myself, not another user */ |
|
|
%type <cmndspec> cmndspec |
%type <cmndspec> cmndspec |
%type <cmndspec> cmndspeclist |
%type <cmndspec> cmndspeclist |
Line 179 yyerror(const char *s)
|
Line 195 yyerror(const char *s)
|
%type <seinfo> selinux |
%type <seinfo> selinux |
%type <string> rolespec |
%type <string> rolespec |
%type <string> typespec |
%type <string> typespec |
|
%type <privinfo> solarisprivs |
|
%type <string> privsspec |
|
%type <string> limitprivsspec |
|
|
%% |
%% |
|
|
Line 236 defaults_list : defaults_entry
|
Line 255 defaults_list : defaults_entry
|
; |
; |
|
|
defaults_entry : DEFVAR { |
defaults_entry : DEFVAR { |
$$ = new_default($1, NULL, TRUE); | $$ = new_default($1, NULL, true); |
} |
} |
| '!' DEFVAR { |
| '!' DEFVAR { |
$$ = new_default($2, NULL, FALSE); | $$ = new_default($2, NULL, false); |
} |
} |
| DEFVAR '=' WORD { |
| DEFVAR '=' WORD { |
$$ = new_default($1, $3, TRUE); | $$ = new_default($1, $3, true); |
} |
} |
| DEFVAR '+' WORD { |
| DEFVAR '+' WORD { |
$$ = new_default($1, $3, '+'); |
$$ = new_default($1, $3, '+'); |
Line 260 privileges : privilege
|
Line 279 privileges : privilege
|
; |
; |
|
|
privilege : hostlist '=' cmndspeclist { |
privilege : hostlist '=' cmndspeclist { |
struct privilege *p = emalloc(sizeof(*p)); | struct privilege *p = ecalloc(1, sizeof(*p)); |
list2tq(&p->hostlist, $1); |
list2tq(&p->hostlist, $1); |
list2tq(&p->cmndlist, $3); |
list2tq(&p->cmndlist, $3); |
p->prev = p; |
p->prev = p; |
p->next = NULL; | /* p->next = NULL; */ |
$$ = p; |
$$ = p; |
} |
} |
; |
; |
|
|
ophost : host { |
ophost : host { |
$$ = $1; |
$$ = $1; |
$$->negated = FALSE; | $$->negated = false; |
} |
} |
| '!' host { |
| '!' host { |
$$ = $2; |
$$ = $2; |
$$->negated = TRUE; | $$->negated = true; |
} |
} |
; |
; |
|
|
Line 306 cmndspeclist : cmndspec
|
Line 325 cmndspeclist : cmndspec
|
if ($3->type == NULL) |
if ($3->type == NULL) |
$3->type = $3->prev->type; |
$3->type = $3->prev->type; |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
|
#ifdef HAVE_PRIV_SET |
|
/* propagate privs & limitprivs */ |
|
if ($3->privs == NULL) |
|
$3->privs = $3->prev->privs; |
|
if ($3->limitprivs == NULL) |
|
$3->limitprivs = $3->prev->limitprivs; |
|
#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 = $3->prev->tags.nopasswd; |
Line 329 cmndspeclist : cmndspec
|
Line 355 cmndspeclist : cmndspec
|
} |
} |
; |
; |
|
|
cmndspec : runasspec selinux cmndtag opcmnd { | cmndspec : runasspec selinux solarisprivs cmndtag opcmnd { |
struct cmndspec *cs = emalloc(sizeof(*cs)); | struct cmndspec *cs = ecalloc(1, sizeof(*cs)); |
if ($1 != NULL) { |
if ($1 != NULL) { |
list2tq(&cs->runasuserlist, $1->runasusers); |
list2tq(&cs->runasuserlist, $1->runasusers); |
list2tq(&cs->runasgrouplist, $1->runasgroups); |
list2tq(&cs->runasgrouplist, $1->runasgroups); |
Line 343 cmndspec : runasspec selinux cmndtag opcmnd {
|
Line 369 cmndspec : runasspec selinux cmndtag opcmnd {
|
cs->role = $2.role; |
cs->role = $2.role; |
cs->type = $2.type; |
cs->type = $2.type; |
#endif |
#endif |
cs->tags = $3; | #ifdef HAVE_PRIV_SET |
cs->cmnd = $4; | cs->privs = $3.privs; |
| cs->limitprivs = $3.limitprivs; |
| #endif |
| cs->tags = $4; |
| cs->cmnd = $5; |
cs->prev = cs; |
cs->prev = cs; |
cs->next = NULL; |
cs->next = NULL; |
/* sudo "ALL" implies the SETENV tag */ |
/* sudo "ALL" implies the SETENV tag */ |
Line 357 cmndspec : runasspec selinux cmndtag opcmnd {
|
Line 387 cmndspec : runasspec selinux cmndtag opcmnd {
|
|
|
opcmnd : cmnd { |
opcmnd : cmnd { |
$$ = $1; |
$$ = $1; |
$$->negated = FALSE; | $$->negated = false; |
} |
} |
| '!' cmnd { |
| '!' cmnd { |
$$ = $2; |
$$ = $2; |
$$->negated = TRUE; | $$->negated = true; |
} |
} |
; |
; |
|
|
Line 397 selinux : /* empty */ {
|
Line 427 selinux : /* empty */ {
|
} |
} |
; |
; |
|
|
|
privsspec : PRIVS '=' WORD { |
|
$$ = $3; |
|
} |
|
; |
|
limitprivsspec : LIMITPRIVS '=' WORD { |
|
$$ = $3; |
|
} |
|
; |
|
|
|
solarisprivs : /* empty */ { |
|
$$.privs = NULL; |
|
$$.limitprivs = NULL; |
|
} |
|
| privsspec { |
|
$$.privs = $1; |
|
$$.limitprivs = NULL; |
|
} |
|
| limitprivsspec { |
|
$$.privs = NULL; |
|
$$.limitprivs = $1; |
|
} |
|
| privsspec limitprivsspec { |
|
$$.privs = $1; |
|
$$.limitprivs = $2; |
|
} |
|
| limitprivsspec privsspec { |
|
$$.limitprivs = $1; |
|
$$.privs = $2; |
|
} |
|
|
runasspec : /* empty */ { |
runasspec : /* empty */ { |
$$ = NULL; |
$$ = NULL; |
} |
} |
Line 405 runasspec : /* empty */ {
|
Line 465 runasspec : /* empty */ {
|
} |
} |
; |
; |
|
|
runaslist : userlist { | runaslist : /* empty */ { |
$$ = emalloc(sizeof(struct runascontainer)); | $$ = ecalloc(1, sizeof(struct runascontainer)); |
| $$->runasusers = new_member(NULL, MYSELF); |
| /* $$->runasgroups = NULL; */ |
| } |
| | userlist { |
| $$ = ecalloc(1, sizeof(struct runascontainer)); |
$$->runasusers = $1; |
$$->runasusers = $1; |
$$->runasgroups = NULL; | /* $$->runasgroups = NULL; */ |
} |
} |
| userlist ':' grouplist { |
| userlist ':' grouplist { |
$$ = emalloc(sizeof(struct runascontainer)); | $$ = ecalloc(1, sizeof(struct runascontainer)); |
$$->runasusers = $1; |
$$->runasusers = $1; |
$$->runasgroups = $3; |
$$->runasgroups = $3; |
} |
} |
| ':' grouplist { |
| ':' grouplist { |
$$ = emalloc(sizeof(struct runascontainer)); | $$ = ecalloc(1, sizeof(struct runascontainer)); |
$$->runasusers = NULL; | /* $$->runasusers = NULL; */ |
$$->runasgroups = $2; |
$$->runasgroups = $2; |
} |
} |
|
| ':' { |
|
$$ = ecalloc(1, sizeof(struct runascontainer)); |
|
$$->runasusers = new_member(NULL, MYSELF); |
|
/* $$->runasgroups = NULL; */ |
|
} |
; |
; |
|
|
cmndtag : /* empty */ { |
cmndtag : /* empty */ { |
Line 427 cmndtag : /* empty */ {
|
Line 497 cmndtag : /* empty */ {
|
$$.log_input = $$.log_output = UNSPEC; |
$$.log_input = $$.log_output = UNSPEC; |
} |
} |
| cmndtag NOPASSWD { |
| cmndtag NOPASSWD { |
$$.nopasswd = TRUE; | $$.nopasswd = true; |
} |
} |
| cmndtag PASSWD { |
| cmndtag PASSWD { |
$$.nopasswd = FALSE; | $$.nopasswd = false; |
} |
} |
| cmndtag NOEXEC { |
| cmndtag NOEXEC { |
$$.noexec = TRUE; | $$.noexec = true; |
} |
} |
| cmndtag EXEC { |
| cmndtag EXEC { |
$$.noexec = FALSE; | $$.noexec = false; |
} |
} |
| cmndtag SETENV { |
| cmndtag SETENV { |
$$.setenv = TRUE; | $$.setenv = true; |
} |
} |
| cmndtag NOSETENV { |
| cmndtag NOSETENV { |
$$.setenv = FALSE; | $$.setenv = false; |
} |
} |
| cmndtag LOG_INPUT { |
| cmndtag LOG_INPUT { |
$$.log_input = TRUE; | $$.log_input = true; |
} |
} |
| cmndtag NOLOG_INPUT { |
| cmndtag NOLOG_INPUT { |
$$.log_input = FALSE; | $$.log_input = false; |
} |
} |
| cmndtag LOG_OUTPUT { |
| cmndtag LOG_OUTPUT { |
$$.log_output = TRUE; | $$.log_output = true; |
} |
} |
| cmndtag NOLOG_OUTPUT { |
| cmndtag NOLOG_OUTPUT { |
$$.log_output = FALSE; | $$.log_output = false; |
} |
} |
; |
; |
|
|
Line 465 cmnd : ALL {
|
Line 535 cmnd : ALL {
|
$$ = new_member($1, ALIAS); |
$$ = new_member($1, ALIAS); |
} |
} |
| COMMAND { |
| COMMAND { |
struct sudo_command *c = emalloc(sizeof(*c)); | struct sudo_command *c = ecalloc(1, sizeof(*c)); |
c->cmnd = $1.cmnd; |
c->cmnd = $1.cmnd; |
c->args = $1.args; |
c->args = $1.args; |
$$ = new_member((char *)c, COMMAND); |
$$ = new_member((char *)c, COMMAND); |
Line 547 userlist : opuser
|
Line 617 userlist : opuser
|
|
|
opuser : user { |
opuser : user { |
$$ = $1; |
$$ = $1; |
$$->negated = FALSE; | $$->negated = false; |
} |
} |
| '!' user { |
| '!' user { |
$$ = $2; |
$$ = $2; |
$$->negated = TRUE; | $$->negated = true; |
} |
} |
; |
; |
|
|
Line 581 grouplist : opgroup
|
Line 651 grouplist : opgroup
|
|
|
opgroup : group { |
opgroup : group { |
$$ = $1; |
$$ = $1; |
$$->negated = FALSE; | $$->negated = false; |
} |
} |
| '!' group { |
| '!' group { |
$$ = $2; |
$$ = $2; |
$$->negated = TRUE; | $$->negated = true; |
} |
} |
; |
; |
|
|
Line 605 static struct defaults *
|
Line 675 static struct defaults *
|
new_default(char *var, char *val, int op) |
new_default(char *var, char *val, int op) |
{ |
{ |
struct defaults *d; |
struct defaults *d; |
|
debug_decl(new_default, SUDO_DEBUG_PARSER) |
|
|
d = emalloc(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); |
tq_init(&d->binding); |
d->type = 0; | /* d->type = 0; */ |
d->op = op; |
d->op = op; |
d->prev = d; |
d->prev = d; |
d->next = NULL; | /* d->next = NULL; */ |
|
|
return d; | debug_return_ptr(d); |
} |
} |
|
|
static struct member * |
static struct member * |
new_member(char *name, int type) |
new_member(char *name, int type) |
{ |
{ |
struct member *m; |
struct member *m; |
|
debug_decl(new_member, SUDO_DEBUG_PARSER) |
|
|
m = emalloc(sizeof(struct member)); | m = ecalloc(1, sizeof(struct member)); |
m->name = name; |
m->name = name; |
m->type = type; |
m->type = type; |
m->prev = m; |
m->prev = m; |
m->next = NULL; | /* m->next = NULL; */ |
|
|
return m; | debug_return_ptr(m); |
} |
} |
|
|
/* |
/* |
Line 642 add_defaults(int type, struct member *bmem, struct def
|
Line 714 add_defaults(int type, struct member *bmem, struct def
|
{ |
{ |
struct defaults *d; |
struct defaults *d; |
struct member_list binding; |
struct member_list binding; |
|
debug_decl(add_defaults, SUDO_DEBUG_PARSER) |
|
|
/* |
/* |
* We can only call list2tq once on bmem as it will zero |
* We can only call list2tq once on bmem as it will zero |
Line 657 add_defaults(int type, struct member *bmem, struct def
|
Line 730 add_defaults(int type, struct member *bmem, struct def
|
d->binding = binding; |
d->binding = binding; |
} |
} |
tq_append(&defaults, defs); |
tq_append(&defaults, defs); |
|
|
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 667 static void
|
Line 742 static void
|
add_userspec(struct member *members, struct privilege *privs) |
add_userspec(struct member *members, struct privilege *privs) |
{ |
{ |
struct userspec *u; |
struct userspec *u; |
|
debug_decl(add_userspec, SUDO_DEBUG_PARSER) |
|
|
u = emalloc(sizeof(*u)); | u = ecalloc(1, sizeof(*u)); |
list2tq(&u->users, members); |
list2tq(&u->users, members); |
list2tq(&u->privileges, privs); |
list2tq(&u->privileges, privs); |
u->prev = u; |
u->prev = u; |
u->next = NULL; | /* u->next = NULL; */ |
tq_append(&userspecs, u); |
tq_append(&userspecs, u); |
|
|
|
debug_return; |
} |
} |
|
|
/* |
/* |
Line 681 add_userspec(struct member *members, struct privilege
|
Line 759 add_userspec(struct member *members, struct privilege
|
* the current sudoers file to path. |
* the current sudoers file to path. |
*/ |
*/ |
void |
void |
init_parser(const char *path, int quiet) | init_parser(const char *path, bool quiet) |
{ |
{ |
struct defaults *d; |
struct defaults *d; |
struct member *m, *binding; |
struct member *m, *binding; |
Line 689 init_parser(const char *path, int quiet)
|
Line 767 init_parser(const char *path, int quiet)
|
struct privilege *priv; |
struct privilege *priv; |
struct cmndspec *cs; |
struct cmndspec *cs; |
struct sudo_command *c; |
struct sudo_command *c; |
|
debug_decl(init_parser, SUDO_DEBUG_PARSER) |
|
|
while ((us = tq_pop(&userspecs)) != NULL) { |
while ((us = tq_pop(&userspecs)) != NULL) { |
while ((m = tq_pop(&us->users)) != NULL) { |
while ((m = tq_pop(&us->users)) != NULL) { |
Line 700 init_parser(const char *path, int quiet)
|
Line 779 init_parser(const char *path, int quiet)
|
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
char *role = NULL, *type = NULL; |
char *role = NULL, *type = NULL; |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
|
#ifdef HAVE_PRIV_SET |
|
char *privs = NULL, *limitprivs = NULL; |
|
#endif /* HAVE_PRIV_SET */ |
|
|
while ((m = tq_pop(&priv->hostlist)) != NULL) { |
while ((m = tq_pop(&priv->hostlist)) != NULL) { |
efree(m->name); |
efree(m->name); |
Line 717 init_parser(const char *path, int quiet)
|
Line 799 init_parser(const char *path, int quiet)
|
efree(cs->type); |
efree(cs->type); |
} |
} |
#endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
|
#ifdef HAVE_PRIV_SET |
|
/* Only free the first instance of privs/limitprivs. */ |
|
if (cs->privs != privs) { |
|
privs = cs->privs; |
|
efree(cs->privs); |
|
} |
|
if (cs->limitprivs != limitprivs) { |
|
limitprivs = cs->limitprivs; |
|
efree(cs->limitprivs); |
|
} |
|
#endif /* HAVE_PRIV_SET */ |
if (tq_last(&cs->runasuserlist) != runasuser) { |
if (tq_last(&cs->runasuserlist) != runasuser) { |
runasuser = tq_last(&cs->runasuserlist); |
runasuser = tq_last(&cs->runasuserlist); |
while ((m = tq_pop(&cs->runasuserlist)) != NULL) { |
while ((m = tq_pop(&cs->runasuserlist)) != NULL) { |
Line 773 init_parser(const char *path, int quiet)
|
Line 866 init_parser(const char *path, int quiet)
|
efree(sudoers); |
efree(sudoers); |
sudoers = path ? estrdup(path) : NULL; |
sudoers = path ? estrdup(path) : NULL; |
|
|
parse_error = FALSE; | parse_error = false; |
errorlineno = -1; |
errorlineno = -1; |
errorfile = NULL; | errorfile = sudoers; |
verbose = !quiet; | sudoers_warnings = !quiet; |
| |
| debug_return; |
} |
} |