|
version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.5, 2014/06/15 16:12:54
|
|
Line 1
|
Line 1
|
| %{ |
%{ |
| /* |
/* |
| * Copyright (c) 1996, 1998-2005, 2007-2012 | * Copyright (c) 1996, 1998-2005, 2007-2013 |
| * 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 25
|
Line 25
|
| #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 44
|
Line 43
|
| #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 54
|
| #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 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 88 static void add_defaults(int, struct member *, struct
|
Line 86 static void add_defaults(int, struct member *, struct
|
| static void add_userspec(struct member *, struct privilege *); |
static void add_userspec(struct member *, struct privilege *); |
| static struct defaults *new_default(char *, char *, int); |
static struct defaults *new_default(char *, char *, int); |
| static struct member *new_member(char *, int); |
static struct member *new_member(char *, int); |
| void yyerror(const char *); | static struct sudo_digest *new_digest(int, const char *); |
| |
| void | |
| 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. */ | |
| if (errorlineno == -1) { | |
| errorlineno = sudolineno; | |
| errorfile = estrdup(sudoers); | |
| } | |
| if (trace_print != NULL) { | |
| LEXTRACE("<*> "); | |
| } else if (sudoers_warnings && s != NULL) { | |
| warningx(_(">>> %s: %s near line %d <<<"), sudoers, s, sudolineno); | |
| } | |
| parse_error = true; | |
| debug_return; | |
| } | |
| %} |
%} |
| |
|
| %union { |
%union { |
|
Line 120 yyerror(const char *s)
|
Line 95 yyerror(const char *s)
|
| struct member *member; |
struct member *member; |
| struct runascontainer *runas; |
struct runascontainer *runas; |
| struct privilege *privilege; |
struct privilege *privilege; |
| |
struct sudo_digest *digest; |
| 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 135 yyerror(const char *s)
|
Line 112 yyerror(const char *s)
|
| %token <string> NETGROUP /* a netgroup (+NAME) */ |
%token <string> NETGROUP /* a netgroup (+NAME) */ |
| %token <string> USERGROUP /* a usergroup (%NAME) */ |
%token <string> USERGROUP /* a usergroup (%NAME) */ |
| %token <string> WORD /* a word */ |
%token <string> WORD /* a word */ |
| |
%token <string> DIGEST /* a SHA-2 digest */ |
| %token <tok> DEFAULTS /* Defaults entry */ |
%token <tok> DEFAULTS /* Defaults entry */ |
| %token <tok> DEFAULTS_HOST /* Host-specific defaults entry */ |
%token <tok> DEFAULTS_HOST /* Host-specific defaults entry */ |
| %token <tok> DEFAULTS_USER /* User-specific defaults entry */ |
%token <tok> DEFAULTS_USER /* User-specific defaults entry */ |
|
Line 161 yyerror(const char *s)
|
Line 139 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 */ |
| |
%token <tok> SHA224 /* sha224 digest */ |
| |
%token <tok> SHA256 /* sha256 digest */ |
| |
%token <tok> SHA384 /* sha384 digest */ |
| |
%token <tok> SHA512 /* sha512 digest */ |
| |
|
| %type <cmndspec> cmndspec |
%type <cmndspec> cmndspec |
| %type <cmndspec> cmndspeclist |
%type <cmndspec> cmndspeclist |
|
Line 168 yyerror(const char *s)
|
Line 153 yyerror(const char *s)
|
| %type <defaults> defaults_list |
%type <defaults> defaults_list |
| %type <member> cmnd |
%type <member> cmnd |
| %type <member> opcmnd |
%type <member> opcmnd |
| |
%type <member> digcmnd |
| %type <member> cmndlist |
%type <member> cmndlist |
| %type <member> host |
%type <member> host |
| %type <member> hostlist |
%type <member> hostlist |
|
Line 186 yyerror(const char *s)
|
Line 172 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 |
| |
%type <digest> digest |
| |
|
| %% |
%% |
| |
|
|
Line 237 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 261 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 305 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 |
| |
/* propagate privs & limitprivs */ |
| |
if ($3->privs == NULL) |
| |
$3->privs = prev->privs; |
| |
if ($3->limitprivs == NULL) |
| |
$3->limitprivs = 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 = 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; |
| } |
} |
| ; |
; |
| |
|
| cmndspec : runasspec selinux cmndtag opcmnd { | 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; |
| 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->prev = cs; | cs->limitprivs = $3.limitprivs; |
| cs->next = NULL; | #endif |
| | cs->tags = $4; |
| | cs->cmnd = $5; |
| | HLTQ_INIT(cs, entries); |
| /* 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 362 cmndspec : runasspec selinux cmndtag opcmnd {
|
Line 370 cmndspec : runasspec selinux cmndtag opcmnd {
|
| } |
} |
| ; |
; |
| |
|
| |
digest : SHA224 ':' DIGEST { |
| |
$$ = new_digest(SUDO_DIGEST_SHA224, $3); |
| |
} |
| |
| SHA256 ':' DIGEST { |
| |
$$ = new_digest(SUDO_DIGEST_SHA256, $3); |
| |
} |
| |
| SHA384 ':' DIGEST { |
| |
$$ = new_digest(SUDO_DIGEST_SHA384, $3); |
| |
} |
| |
| SHA512 ':' DIGEST { |
| |
$$ = new_digest(SUDO_DIGEST_SHA512, $3); |
| |
} |
| |
; |
| |
|
| |
digcmnd : opcmnd { |
| |
$$ = $1; |
| |
} |
| |
| digest opcmnd { |
| |
/* XXX - yuck */ |
| |
struct sudo_command *c = (struct sudo_command *)($2->name); |
| |
c->digest = $1; |
| |
$$ = $2; |
| |
} |
| |
; |
| |
|
| opcmnd : cmnd { |
opcmnd : cmnd { |
| $$ = $1; |
$$ = $1; |
| $$->negated = false; |
$$->negated = false; |
|
Line 404 selinux : /* empty */ {
|
Line 437 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 412 runasspec : /* empty */ {
|
Line 476 runasspec : /* empty */ {
|
| } |
} |
| ; |
; |
| |
|
| runaslist : userlist { | runaslist : /* empty */ { |
| $$ = ecalloc(1, 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; */ |
| } |
} |
|
Line 427 runaslist : userlist {
|
Line 496 runaslist : userlist {
|
| /* $$->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 486 hostaliases : hostalias
|
Line 560 hostaliases : hostalias
|
| hostalias : ALIAS '=' hostlist { |
hostalias : ALIAS '=' hostlist { |
| char *s; |
char *s; |
| if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) { |
if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) { |
| yyerror(s); | sudoerserror(s); |
| YYERROR; |
YYERROR; |
| } |
} |
| } |
} |
|
Line 494 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 506 cmndaliases : cmndalias
|
Line 580 cmndaliases : cmndalias
|
| cmndalias : ALIAS '=' cmndlist { |
cmndalias : ALIAS '=' cmndlist { |
| char *s; |
char *s; |
| if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) { |
if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) { |
| yyerror(s); | sudoerserror(s); |
| YYERROR; |
YYERROR; |
| } |
} |
| } |
} |
| ; |
; |
| |
|
| cmndlist : opcmnd | cmndlist : digcmnd |
| | cmndlist ',' opcmnd { | | cmndlist ',' digcmnd { |
| list_append($1, $3); | HLTQ_CONCAT($1, $3, entries); |
| $$ = $1; |
$$ = $1; |
| } |
} |
| ; |
; |
|
Line 526 runasaliases : runasalias
|
Line 600 runasaliases : runasalias
|
| runasalias : ALIAS '=' userlist { |
runasalias : ALIAS '=' userlist { |
| char *s; |
char *s; |
| if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) { |
if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) { |
| yyerror(s); | sudoerserror(s); |
| YYERROR; |
YYERROR; |
| } |
} |
| } |
} |
|
Line 539 useraliases : useralias
|
Line 613 useraliases : useralias
|
| useralias : ALIAS '=' userlist { |
useralias : ALIAS '=' userlist { |
| char *s; |
char *s; |
| if ((s = alias_add($1, USERALIAS, $3)) != NULL) { |
if ((s = alias_add($1, USERALIAS, $3)) != NULL) { |
| yyerror(s); | sudoerserror(s); |
| YYERROR; |
YYERROR; |
| } |
} |
| } |
} |
|
Line 547 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 581 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 608 group : ALIAS {
|
Line 682 group : ALIAS {
|
| ; |
; |
| |
|
| %% |
%% |
| |
void |
| |
sudoerserror(const char *s) |
| |
{ |
| |
debug_decl(sudoerserror, 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. */ |
| |
if (errorlineno == -1) { |
| |
errorlineno = sudolineno; |
| |
errorfile = estrdup(sudoers); |
| |
} |
| |
if (sudoers_warnings && s != NULL) { |
| |
LEXTRACE("<*> "); |
| |
#ifndef TRACELEXER |
| |
if (trace_print == NULL || trace_print == sudoers_trace_print) { |
| |
const char fmt[] = ">>> %s: %s near line %d <<<\n"; |
| |
int oldlocale; |
| |
|
| |
/* Warnings are displayed in the user's locale. */ |
| |
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale); |
| |
sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), sudolineno); |
| |
sudoers_setlocale(oldlocale, NULL); |
| |
} |
| |
#endif |
| |
} |
| |
parse_error = true; |
| |
debug_return; |
| |
} |
| |
|
| static struct defaults * |
static struct defaults * |
| new_default(char *var, char *val, int op) |
new_default(char *var, char *val, int op) |
| { |
{ |
|
Line 617 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 635 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); |
| } |
} |
| |
|
| |
struct sudo_digest * |
| |
new_digest(int digest_type, const char *digest_str) |
| |
{ |
| |
struct sudo_digest *dig; |
| |
debug_decl(new_digest, SUDO_DEBUG_PARSER) |
| |
|
| |
dig = emalloc(sizeof(*dig)); |
| |
dig->digest_type = digest_type; |
| |
dig->digest_str = estrdup(digest_str); |
| |
|
| |
debug_return_ptr(dig); |
| |
} |
| |
|
| /* |
/* |
| * Add a list of defaults structures to the defaults list. |
* Add a list of defaults structures to the defaults list. |
| * The binding, if non-NULL, specifies a list of hosts, users, or |
* The binding, if non-NULL, specifies a list of hosts, users, or |
|
Line 650 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 682 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 696 add_userspec(struct member *members, struct privilege
|
Line 817 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 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 */ |
| |
#ifdef HAVE_PRIV_SET |
| |
char *privs = NULL, *limitprivs = NULL; |
| |
#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 733 init_parser(const char *path, int quiet)
|
Line 858 init_parser(const char *path, int quiet)
|
| efree(cs->type); |
efree(cs->type); |
| } |
} |
| #endif /* HAVE_SELINUX */ |
#endif /* HAVE_SELINUX */ |
| if (tq_last(&cs->runasuserlist) != runasuser) { | #ifdef HAVE_PRIV_SET |
| runasuser = tq_last(&cs->runasuserlist); | /* Only free the first instance of privs/limitprivs. */ |
| while ((m = tq_pop(&cs->runasuserlist)) != NULL) { | if (cs->privs != privs) { |
| | privs = cs->privs; |
| | efree(cs->privs); |
| | } |
| | if (cs->limitprivs != limitprivs) { |
| | limitprivs = cs->limitprivs; |
| | efree(cs->limitprivs); |
| | } |
| | #endif /* HAVE_PRIV_SET */ |
| | /* Only free the first instance of runas user/group lists. */ |
| | if (cs->runasuserlist && cs->runasuserlist != runasuserlist) { |
| | 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 760 init_parser(const char *path, int quiet)
|
Line 900 init_parser(const char *path, int 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(); |
| |
|