--- embedaddon/sudo/plugins/sudoers/gram.y 2012/05/29 12:26:49 1.1.1.2 +++ embedaddon/sudo/plugins/sudoers/gram.y 2013/07/22 10:46:12 1.1.1.4 @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1996, 1998-2005, 2007-2012 + * Copyright (c) 1996, 1998-2005, 2007-2013 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -25,7 +25,6 @@ #include #include -#include #include #ifdef STDC_HEADERS # include @@ -44,6 +43,9 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ +#ifdef HAVE_INTTYPES_H +# include +#endif #if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) # include #endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ @@ -52,7 +54,6 @@ #include "sudoers.h" /* XXX */ #include "parse.h" #include "toke.h" -#include "gram.h" /* * We must define SIZE_MAX for yacc's skeleton.c. @@ -88,30 +89,7 @@ static void add_defaults(int, struct member *, struct static void add_userspec(struct member *, struct privilege *); static struct defaults *new_default(char *, char *, int); static struct member *new_member(char *, int); - void yyerror(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; -} +static struct sudo_digest *new_digest(int, const char *); %} %union { @@ -120,9 +98,11 @@ yyerror(const char *s) struct member *member; struct runascontainer *runas; struct privilege *privilege; + struct sudo_digest *digest; struct sudo_command command; struct cmndtag tag; struct selinux_info seinfo; + struct solaris_privs_info privinfo; char *string; int tok; } @@ -135,6 +115,7 @@ yyerror(const char *s) %token NETGROUP /* a netgroup (+NAME) */ %token USERGROUP /* a usergroup (%NAME) */ %token WORD /* a word */ +%token DIGEST /* a SHA-2 digest */ %token DEFAULTS /* Defaults entry */ %token DEFAULTS_HOST /* Host-specific defaults entry */ %token DEFAULTS_USER /* User-specific defaults entry */ @@ -161,6 +142,13 @@ yyerror(const char *s) %token ERROR %token TYPE /* SELinux type */ %token ROLE /* SELinux role */ +%token PRIVS /* Solaris privileges */ +%token LIMITPRIVS /* Solaris limit privileges */ +%token MYSELF /* run as myself, not another user */ +%token SHA224 /* sha224 digest */ +%token SHA256 /* sha256 digest */ +%token SHA384 /* sha384 digest */ +%token SHA512 /* sha512 digest */ %type cmndspec %type cmndspeclist @@ -168,6 +156,7 @@ yyerror(const char *s) %type defaults_list %type cmnd %type opcmnd +%type digcmnd %type cmndlist %type host %type hostlist @@ -186,6 +175,10 @@ yyerror(const char *s) %type selinux %type rolespec %type typespec +%type solarisprivs +%type privsspec +%type limitprivsspec +%type digest %% @@ -313,6 +306,13 @@ cmndspeclist : cmndspec if ($3->type == NULL) $3->type = $3->prev->type; #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 */ if ($3->tags.nopasswd == UNSPEC) $3->tags.nopasswd = $3->prev->tags.nopasswd; @@ -336,7 +336,7 @@ cmndspeclist : cmndspec } ; -cmndspec : runasspec selinux cmndtag opcmnd { +cmndspec : runasspec selinux solarisprivs cmndtag digcmnd { struct cmndspec *cs = ecalloc(1, sizeof(*cs)); if ($1 != NULL) { list2tq(&cs->runasuserlist, $1->runasusers); @@ -350,8 +350,12 @@ cmndspec : runasspec selinux cmndtag opcmnd { cs->role = $2.role; cs->type = $2.type; #endif - cs->tags = $3; - cs->cmnd = $4; +#ifdef HAVE_PRIV_SET + cs->privs = $3.privs; + cs->limitprivs = $3.limitprivs; +#endif + cs->tags = $4; + cs->cmnd = $5; cs->prev = cs; cs->next = NULL; /* sudo "ALL" implies the SETENV tag */ @@ -362,6 +366,31 @@ 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 { $$ = $1; $$->negated = false; @@ -404,6 +433,37 @@ 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 */ { $$ = NULL; } @@ -412,8 +472,13 @@ runasspec : /* empty */ { } ; -runaslist : userlist { +runaslist : /* empty */ { $$ = ecalloc(1, sizeof(struct runascontainer)); + $$->runasusers = new_member(NULL, MYSELF); + /* $$->runasgroups = NULL; */ + } + | userlist { + $$ = ecalloc(1, sizeof(struct runascontainer)); $$->runasusers = $1; /* $$->runasgroups = NULL; */ } @@ -427,6 +492,11 @@ runaslist : userlist { /* $$->runasusers = NULL; */ $$->runasgroups = $2; } + | ':' { + $$ = ecalloc(1, sizeof(struct runascontainer)); + $$->runasusers = new_member(NULL, MYSELF); + /* $$->runasgroups = NULL; */ + } ; cmndtag : /* empty */ { @@ -486,7 +556,7 @@ hostaliases : hostalias hostalias : ALIAS '=' hostlist { char *s; if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) { - yyerror(s); + sudoerserror(s); YYERROR; } } @@ -506,14 +576,14 @@ cmndaliases : cmndalias cmndalias : ALIAS '=' cmndlist { char *s; if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) { - yyerror(s); + sudoerserror(s); YYERROR; } } ; -cmndlist : opcmnd - | cmndlist ',' opcmnd { +cmndlist : digcmnd + | cmndlist ',' digcmnd { list_append($1, $3); $$ = $1; } @@ -526,7 +596,7 @@ runasaliases : runasalias runasalias : ALIAS '=' userlist { char *s; if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) { - yyerror(s); + sudoerserror(s); YYERROR; } } @@ -539,7 +609,7 @@ useraliases : useralias useralias : ALIAS '=' userlist { char *s; if ((s = alias_add($1, USERALIAS, $3)) != NULL) { - yyerror(s); + sudoerserror(s); YYERROR; } } @@ -608,6 +678,38 @@ 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 * new_default(char *var, char *val, int op) { @@ -641,6 +743,19 @@ new_member(char *name, int type) 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. * The binding, if non-NULL, specifies a list of hosts, users, or @@ -696,7 +811,7 @@ add_userspec(struct member *members, struct privilege * the current sudoers file to path. */ void -init_parser(const char *path, int quiet) +init_parser(const char *path, bool quiet) { struct defaults *d; struct member *m, *binding; @@ -716,6 +831,9 @@ init_parser(const char *path, int quiet) #ifdef HAVE_SELINUX char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ +#ifdef HAVE_PRIV_SET + char *privs = NULL, *limitprivs = NULL; +#endif /* HAVE_PRIV_SET */ while ((m = tq_pop(&priv->hostlist)) != NULL) { efree(m->name); @@ -733,6 +851,17 @@ init_parser(const char *path, int quiet) efree(cs->type); } #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) { runasuser = tq_last(&cs->runasuserlist); while ((m = tq_pop(&cs->runasuserlist)) != NULL) {