Store the file/lineno for alias and userspec entries so we can

provide that info if there is an error.
This commit is contained in:
Todd C. Miller
2016-11-12 19:22:32 -07:00
parent 90995c0acf
commit 7524c231cc
10 changed files with 271 additions and 183 deletions

View File

@@ -135,34 +135,47 @@ FFIILLEESS
_/_e_t_c_/_s_u_d_o_e_r_s_._t_m_p Lock file for visudo _/_e_t_c_/_s_u_d_o_e_r_s_._t_m_p Lock file for visudo
DDIIAAGGNNOOSSTTIICCSS DDIIAAGGNNOOSSTTIICCSS
In addition to reporting _s_u_d_o_e_r_s parse errors, vviissuuddoo may produce the
following messages:
sudoers file busy, try again later. sudoers file busy, try again later.
Someone else is currently editing the _s_u_d_o_e_r_s file. Someone else is currently editing the _s_u_d_o_e_r_s file.
/etc/sudoers.tmp: Permission denied /etc/sudoers.tmp: Permission denied
You didn't run vviissuuddoo as root. You didn't run vviissuuddoo as root.
Can't find you in the passwd database you do not exist in the passwd database
Your user ID does not appear in the system passwd file. Your user ID does not appear in the system passwd database.
Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined {User,Runas,Host,Cmnd}_Alias referenced but not defined
Either you are trying to use an undeclared Either you are trying to use an undeclared
{User,Runas,Host,Cmnd}_Alias or you have a user or host name listed {User,Runas,Host,Cmnd}_Alias or you have a user or host name listed
that consists solely of uppercase letters, digits, and the that consists solely of uppercase letters, digits, and the
underscore (`_') character. In the latter case, you can ignore the underscore (`_') character. In the latter case, you can ignore the
warnings (ssuuddoo will not complain). In --ss (strict) mode these are warnings (ssuuddoo will not complain). The message is prefixed with
errors, not warnings. the path name of the _s_u_d_o_e_r_s file and the line number where the
undefined alias was used. In --ss (strict) mode these are errors,
not warnings.
Warning: unused {User,Runas,Host,Cmnd}_Alias unused {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias was defined but never The specified {User,Runas,Host,Cmnd}_Alias was defined but never
used. You may wish to comment out or remove the unused alias. used. The message is prefixed with the path name of the _s_u_d_o_e_r_s
file and the line number where the unused alias was defined. You
may wish to comment out or remove the unused alias.
Warning: cycle in {User,Runas,Host,Cmnd}_Alias cycle in {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
itself, either directly or through an alias it includes. This is itself, either directly or through an alias it includes. The
only a warning by default as ssuuddoo will ignore cycles when parsing message is prefixed with the path name of the _s_u_d_o_e_r_s file and the
the _s_u_d_o_e_r_s file. line number where the cycle was detected. This is only a warning
unless vviissuuddoo is run in --ss (strict) mode as ssuuddoo will ignore cycles
when parsing the _s_u_d_o_e_r_s file.
visudo: /etc/sudoers: input and output files must be different unknown defaults entry "name"
The _s_u_d_o_e_r_s file contains a Defaults variable not recognized by
vviissuuddoo.
/etc/sudoers: input and output files must be different
The --xx flag was used and the specified _o_u_t_p_u_t___f_i_l_e has the same The --xx flag was used and the specified _o_u_t_p_u_t___f_i_l_e has the same
path name as the _s_u_d_o_e_r_s file to export. path name as the _s_u_d_o_e_r_s file to export.
@@ -199,4 +212,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or https://www.sudo.ws/license.html for file distributed with ssuuddoo or https://www.sudo.ws/license.html for
complete details. complete details.
Sudo 1.8.18 November 20, 2015 Sudo 1.8.18 Sudo 1.8.19 November 12, 2016 Sudo 1.8.19

View File

@@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\" .\"
.TH "VISUDO" "8" "November 20, 2015" "Sudo @PACKAGE_VERSION@" "System Manager's Manual" .TH "VISUDO" "8" "November 12, 2016" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -324,6 +324,11 @@ List of who can run what
\fI@sysconfdir@/sudoers.tmp\fR \fI@sysconfdir@/sudoers.tmp\fR
Lock file for visudo Lock file for visudo
.SH "DIAGNOSTICS" .SH "DIAGNOSTICS"
In addition to reporting
\fIsudoers\fR
parse errors,
\fBvisudo\fR
may produce the following messages:
.TP 6n .TP 6n
\fRsudoers file busy, try again later.\fR \fRsudoers file busy, try again later.\fR
Someone else is currently editing the Someone else is currently editing the
@@ -335,10 +340,10 @@ You didn't run
\fBvisudo\fR \fBvisudo\fR
as root. as root.
.TP 6n .TP 6n
\fRCan't find you in the passwd database\fR \fRyou do not exist in the passwd database\fR
Your user ID does not appear in the system passwd file. Your user ID does not appear in the system passwd database.
.TP 6n .TP 6n
\fRWarning: {User,Runas,Host,Cmnd}_Alias referenced but not defined\fR \fR{User,Runas,Host,Cmnd}_Alias referenced but not defined\fR
Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
or you have a user or host name listed that consists solely of or you have a user or host name listed that consists solely of
uppercase letters, digits, and the underscore uppercase letters, digits, and the underscore
@@ -348,26 +353,47 @@ In the latter case, you can ignore the warnings
(\fBsudo\fR (\fBsudo\fR
will not complain) will not complain)
\&. \&.
The message is prefixed with the path name of the
\fIsudoers\fR
file and the line number where the undefined alias was used.
In In
\fB\-s\fR \fB\-s\fR
(strict) mode these are errors, not warnings. (strict) mode these are errors, not warnings.
.TP 6n .TP 6n
\fRWarning: unused {User,Runas,Host,Cmnd}_Alias\fR \fRunused {User,Runas,Host,Cmnd}_Alias\fR
The specified {User,Runas,Host,Cmnd}_Alias was defined but never The specified {User,Runas,Host,Cmnd}_Alias was defined but never
used. used.
The message is prefixed with the path name of the
\fIsudoers\fR
file and the line number where the unused alias was defined.
You may wish to comment out or remove the unused alias. You may wish to comment out or remove the unused alias.
.TP 6n .TP 6n
\fRWarning: cycle in {User,Runas,Host,Cmnd}_Alias\fR \fRcycle in {User,Runas,Host,Cmnd}_Alias\fR
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
itself, either directly or through an alias it includes. itself, either directly or through an alias it includes.
This is only a warning by default as The message is prefixed with the path name of the
\fIsudoers\fR
file and the line number where the cycle was detected.
This is only a warning unless
\fBvisudo\fR
is run in
\fB\-s\fR
(strict) mode as
\fBsudo\fR \fBsudo\fR
will ignore cycles when parsing will ignore cycles when parsing
the the
\fIsudoers\fR \fIsudoers\fR
file. file.
.TP 6n .TP 6n
\fRvisudo: @sysconfdir@/sudoers: input and output files must be different\fR \fRunknown defaults entry \&"name\&"\fR
The
\fIsudoers\fR
file contains a
\fRDefaults\fR
variable not recognized by
\fBvisudo\fR.
.TP 6n
\fR@sysconfdir@/sudoers: input and output files must be different\fR
The The
\fB\-x\fR \fB\-x\fR
flag was used and the specified flag was used and the specified

View File

@@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\" .\"
.Dd November 20, 2015 .Dd November 12, 2016
.Dt VISUDO @mansectsu@ .Dt VISUDO @mansectsu@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -310,6 +310,11 @@ List of who can run what
Lock file for visudo Lock file for visudo
.El .El
.Sh DIAGNOSTICS .Sh DIAGNOSTICS
In addition to reporting
.Em sudoers
parse errors,
.Nm
may produce the following messages:
.Bl -tag -width 4n .Bl -tag -width 4n
.It Li sudoers file busy, try again later. .It Li sudoers file busy, try again later.
Someone else is currently editing the Someone else is currently editing the
@@ -319,9 +324,9 @@ file.
You didn't run You didn't run
.Nm .Nm
as root. as root.
.It Li Can't find you in the passwd database .It Li you do not exist in the passwd database
Your user ID does not appear in the system passwd file. Your user ID does not appear in the system passwd database.
.It Li Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined .It Li {User,Runas,Host,Cmnd}_Alias referenced but not defined
Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
or you have a user or host name listed that consists solely of or you have a user or host name listed that consists solely of
uppercase letters, digits, and the underscore uppercase letters, digits, and the underscore
@@ -332,23 +337,43 @@ In the latter case, you can ignore the warnings
.Nm sudo .Nm sudo
will not complain will not complain
.Pc . .Pc .
The message is prefixed with the path name of the
.Em sudoers
file and the line number where the undefined alias was used.
In In
.Fl s .Fl s
(strict) mode these are errors, not warnings. (strict) mode these are errors, not warnings.
.It Li Warning: unused {User,Runas,Host,Cmnd}_Alias .It Li unused {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias was defined but never The specified {User,Runas,Host,Cmnd}_Alias was defined but never
used. used.
The message is prefixed with the path name of the
.Em sudoers
file and the line number where the unused alias was defined.
You may wish to comment out or remove the unused alias. You may wish to comment out or remove the unused alias.
.It Li Warning: cycle in {User,Runas,Host,Cmnd}_Alias .It Li cycle in {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
itself, either directly or through an alias it includes. itself, either directly or through an alias it includes.
This is only a warning by default as The message is prefixed with the path name of the
.Em sudoers
file and the line number where the cycle was detected.
This is only a warning unless
.Nm
is run in
.Fl s
(strict) mode as
.Nm sudo .Nm sudo
will ignore cycles when parsing will ignore cycles when parsing
the the
.Em sudoers .Em sudoers
file. file.
.It Li visudo: @sysconfdir@/sudoers: input and output files must be different .It Li unknown defaults entry \&"name\&"
The
.Em sudoers
file contains a
.Li Defaults
variable not recognized by
.Nm .
.It Li @sysconfdir@/sudoers: input and output files must be different
The The
.Fl x .Fl x
flag was used and the specified flag was used and the specified

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2005, 2007-2015 * Copyright (c) 2004-2005, 2007-2016
* 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
@@ -109,10 +109,11 @@ alias_put(struct alias *a)
/* /*
* Add an alias to the aliases redblack tree. * Add an alias to the aliases redblack tree.
* Note that "file" must be a reference-counted string.
* Returns NULL on success and an error string on failure. * Returns NULL on success and an error string on failure.
*/ */
const char * const char *
alias_add(char *name, int type, struct member *members) alias_add(char *name, int type, char *file, int lineno, struct member *members)
{ {
static char errbuf[512]; static char errbuf[512];
struct alias *a; struct alias *a;
@@ -126,6 +127,8 @@ alias_add(char *name, int type, struct member *members)
a->name = name; a->name = name;
a->type = type; a->type = type;
/* a->used = false; */ /* a->used = false; */
a->file = rcstr_addref(file);
a->lineno = lineno;
HLTQ_TO_TAILQ(&a->members, members, entries); HLTQ_TO_TAILQ(&a->members, members, entries);
switch (rbinsert(aliases, a, NULL)) { switch (rbinsert(aliases, a, NULL)) {
case 1: case 1:
@@ -173,6 +176,7 @@ alias_free(void *v)
debug_decl(alias_free, SUDOERS_DEBUG_ALIAS) debug_decl(alias_free, SUDOERS_DEBUG_ALIAS)
free(a->name); free(a->name);
rcstr_delref(a->file);
free_members(&a->members); free_members(&a->members);
free(a); free(a);

View File

@@ -87,6 +87,9 @@
#include "parse.h" #include "parse.h"
#include "toke.h" #include "toke.h"
/* If we last saw a newline the entry is on the preceding line. */
#define this_lineno (last_token == COMMENT ? sudolineno - 1 : sudolineno)
/* /*
* Globals * Globals
*/ */
@@ -106,7 +109,7 @@ static bool add_userspec(struct member *, struct privilege *);
static struct defaults *new_default(char *, char *, short); static struct defaults *new_default(char *, char *, short);
static struct member *new_member(char *, int); static struct member *new_member(char *, int);
static struct sudo_digest *new_digest(int, const char *); static struct sudo_digest *new_digest(int, const char *);
#line 73 "gram.y" #line 76 "gram.y"
#ifndef YYSTYPE_DEFINED #ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED #define YYSTYPE_DEFINED
typedef union { typedef union {
@@ -124,7 +127,7 @@ typedef union {
int tok; int tok;
} YYSTYPE; } YYSTYPE;
#endif /* YYSTYPE_DEFINED */ #endif /* YYSTYPE_DEFINED */
#line 127 "gram.c" #line 130 "gram.c"
#define COMMAND 257 #define COMMAND 257
#define ALIAS 258 #define ALIAS 258
#define DEFVAR 259 #define DEFVAR 259
@@ -689,19 +692,15 @@ short *yysslim;
YYSTYPE *yyvs; YYSTYPE *yyvs;
unsigned int yystacksize; unsigned int yystacksize;
int yyparse(void); int yyparse(void);
#line 849 "gram.y" #line 856 "gram.y"
void void
sudoerserror(const char *s) sudoerserror(const char *s)
{ {
debug_decl(sudoerserror, SUDOERS_DEBUG_PARSER) debug_decl(sudoerserror, SUDOERS_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; errorlineno = this_lineno;
rcstr_delref(errorfile); rcstr_delref(errorfile);
errorfile = rcstr_addref(sudoers); errorfile = rcstr_addref(sudoers);
} }
@@ -714,7 +713,7 @@ sudoerserror(const char *s)
/* Warnings are displayed in the user's locale. */ /* Warnings are displayed in the user's locale. */
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale); sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), sudolineno); sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), this_lineno);
sudoers_setlocale(oldlocale, NULL); sudoers_setlocale(oldlocale, NULL);
} }
#endif #endif
@@ -740,7 +739,7 @@ new_default(char *var, char *val, short op)
/* d->type = 0; */ /* d->type = 0; */
d->op = op; d->op = op;
/* d->binding = NULL */ /* d->binding = NULL */
d->lineno = last_token == COMMENT ? sudolineno - 1 : sudolineno; d->lineno = this_lineno;
d->file = rcstr_addref(sudoers); d->file = rcstr_addref(sudoers);
HLTQ_INIT(d, entries); HLTQ_INIT(d, entries);
@@ -847,6 +846,8 @@ add_userspec(struct member *members, struct privilege *privs)
"unable to allocate memory"); "unable to allocate memory");
debug_return_bool(false); debug_return_bool(false);
} }
u->lineno = this_lineno;
u->file = rcstr_addref(sudoers);
HLTQ_TO_TAILQ(&u->users, members, entries); HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries); HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries); TAILQ_INSERT_TAIL(&userspecs, u, entries);
@@ -887,6 +888,7 @@ init_parser(const char *path, bool quiet)
bool ret = true; bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER) debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
/* XXX - move into a free function */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) { TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) {
struct member *m, *m_next; struct member *m, *m_next;
struct privilege *priv, *priv_next; struct privilege *priv, *priv_next;
@@ -961,6 +963,7 @@ init_parser(const char *path, bool quiet)
} }
free(priv); free(priv);
} }
rcstr_delref(us->file);
free(us); free(us);
} }
TAILQ_INIT(&userspecs); TAILQ_INIT(&userspecs);
@@ -1004,7 +1007,7 @@ init_parser(const char *path, bool quiet)
debug_return_bool(ret); debug_return_bool(ret);
} }
#line 955 "gram.c" #line 958 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__) #if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void) static int yygrowstack(void)
@@ -1213,23 +1216,23 @@ yyreduce:
switch (yyn) switch (yyn)
{ {
case 1: case 1:
#line 167 "gram.y" #line 170 "gram.y"
{ ; } { ; }
break; break;
case 5: case 5:
#line 175 "gram.y" #line 178 "gram.y"
{ {
; ;
} }
break; break;
case 6: case 6:
#line 178 "gram.y" #line 181 "gram.y"
{ {
yyerrok; yyerrok;
} }
break; break;
case 7: case 7:
#line 181 "gram.y" #line 184 "gram.y"
{ {
if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) { if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
sudoerserror(N_("unable to allocate memory")); sudoerserror(N_("unable to allocate memory"));
@@ -1238,73 +1241,73 @@ case 7:
} }
break; break;
case 8: case 8:
#line 187 "gram.y"
{
;
}
break;
case 9:
#line 190 "gram.y" #line 190 "gram.y"
{ {
; ;
} }
break; break;
case 10: case 9:
#line 193 "gram.y" #line 193 "gram.y"
{ {
; ;
} }
break; break;
case 11: case 10:
#line 196 "gram.y" #line 196 "gram.y"
{ {
; ;
} }
break; break;
case 12: case 11:
#line 199 "gram.y" #line 199 "gram.y"
{
;
}
break;
case 12:
#line 202 "gram.y"
{ {
if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults)) if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
YYERROR; YYERROR;
} }
break; break;
case 13: case 13:
#line 203 "gram.y" #line 206 "gram.y"
{ {
if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults)) if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR; YYERROR;
} }
break; break;
case 14: case 14:
#line 207 "gram.y" #line 210 "gram.y"
{ {
if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults)) if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR; YYERROR;
} }
break; break;
case 15: case 15:
#line 211 "gram.y" #line 214 "gram.y"
{ {
if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults)) if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR; YYERROR;
} }
break; break;
case 16: case 16:
#line 215 "gram.y" #line 218 "gram.y"
{ {
if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults)) if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR; YYERROR;
} }
break; break;
case 18: case 18:
#line 222 "gram.y" #line 225 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries); HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
yyval.defaults = yyvsp[-2].defaults; yyval.defaults = yyvsp[-2].defaults;
} }
break; break;
case 19: case 19:
#line 228 "gram.y" #line 231 "gram.y"
{ {
yyval.defaults = new_default(yyvsp[0].string, NULL, true); yyval.defaults = new_default(yyvsp[0].string, NULL, true);
if (yyval.defaults == NULL) { if (yyval.defaults == NULL) {
@@ -1314,7 +1317,7 @@ case 19:
} }
break; break;
case 20: case 20:
#line 235 "gram.y" #line 238 "gram.y"
{ {
yyval.defaults = new_default(yyvsp[0].string, NULL, false); yyval.defaults = new_default(yyvsp[0].string, NULL, false);
if (yyval.defaults == NULL) { if (yyval.defaults == NULL) {
@@ -1324,7 +1327,7 @@ case 20:
} }
break; break;
case 21: case 21:
#line 242 "gram.y" #line 245 "gram.y"
{ {
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true); yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
if (yyval.defaults == NULL) { if (yyval.defaults == NULL) {
@@ -1334,7 +1337,7 @@ case 21:
} }
break; break;
case 22: case 22:
#line 249 "gram.y" #line 252 "gram.y"
{ {
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+'); yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
if (yyval.defaults == NULL) { if (yyval.defaults == NULL) {
@@ -1344,7 +1347,7 @@ case 22:
} }
break; break;
case 23: case 23:
#line 256 "gram.y" #line 259 "gram.y"
{ {
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-'); yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
if (yyval.defaults == NULL) { if (yyval.defaults == NULL) {
@@ -1354,14 +1357,14 @@ case 23:
} }
break; break;
case 25: case 25:
#line 266 "gram.y" #line 269 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries); HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
yyval.privilege = yyvsp[-2].privilege; yyval.privilege = yyvsp[-2].privilege;
} }
break; break;
case 26: case 26:
#line 272 "gram.y" #line 275 "gram.y"
{ {
struct privilege *p = calloc(1, sizeof(*p)); struct privilege *p = calloc(1, sizeof(*p));
if (p == NULL) { if (p == NULL) {
@@ -1375,21 +1378,21 @@ case 26:
} }
break; break;
case 27: case 27:
#line 285 "gram.y" #line 288 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 28: case 28:
#line 289 "gram.y" #line 292 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 29: case 29:
#line 295 "gram.y" #line 298 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1399,7 +1402,7 @@ case 29:
} }
break; break;
case 30: case 30:
#line 302 "gram.y" #line 305 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1409,7 +1412,7 @@ case 30:
} }
break; break;
case 31: case 31:
#line 309 "gram.y" #line 312 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, NETGROUP); yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1419,7 +1422,7 @@ case 31:
} }
break; break;
case 32: case 32:
#line 316 "gram.y" #line 319 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, NTWKADDR); yyval.member = new_member(yyvsp[0].string, NTWKADDR);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1429,7 +1432,7 @@ case 32:
} }
break; break;
case 33: case 33:
#line 323 "gram.y" #line 326 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, WORD); yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1439,7 +1442,7 @@ case 33:
} }
break; break;
case 35: case 35:
#line 333 "gram.y" #line 336 "gram.y"
{ {
struct cmndspec *prev; struct cmndspec *prev;
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries); prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
@@ -1485,7 +1488,7 @@ case 35:
} }
break; break;
case 36: case 36:
#line 378 "gram.y" #line 381 "gram.y"
{ {
struct cmndspec *cs = calloc(1, sizeof(*cs)); struct cmndspec *cs = calloc(1, sizeof(*cs));
if (cs == NULL) { if (cs == NULL) {
@@ -1534,7 +1537,7 @@ case 36:
} }
break; break;
case 37: case 37:
#line 426 "gram.y" #line 429 "gram.y"
{ {
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string); yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
if (yyval.digest == NULL) { if (yyval.digest == NULL) {
@@ -1544,7 +1547,7 @@ case 37:
} }
break; break;
case 38: case 38:
#line 433 "gram.y" #line 436 "gram.y"
{ {
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string); yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
if (yyval.digest == NULL) { if (yyval.digest == NULL) {
@@ -1554,7 +1557,7 @@ case 38:
} }
break; break;
case 39: case 39:
#line 440 "gram.y" #line 443 "gram.y"
{ {
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string); yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
if (yyval.digest == NULL) { if (yyval.digest == NULL) {
@@ -1564,7 +1567,7 @@ case 39:
} }
break; break;
case 40: case 40:
#line 447 "gram.y" #line 450 "gram.y"
{ {
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string); yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
if (yyval.digest == NULL) { if (yyval.digest == NULL) {
@@ -1574,13 +1577,13 @@ case 40:
} }
break; break;
case 41: case 41:
#line 456 "gram.y" #line 459 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
} }
break; break;
case 42: case 42:
#line 459 "gram.y" #line 462 "gram.y"
{ {
if (yyvsp[0].member->type != COMMAND) { if (yyvsp[0].member->type != COMMAND) {
sudoerserror(N_("a digest requires a path name")); sudoerserror(N_("a digest requires a path name"));
@@ -1592,127 +1595,127 @@ case 42:
} }
break; break;
case 43: case 43:
#line 470 "gram.y" #line 473 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 44: case 44:
#line 474 "gram.y" #line 477 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 45: case 45:
#line 480 "gram.y" #line 483 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 46: case 46:
#line 485 "gram.y" #line 488 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 47: case 47:
#line 490 "gram.y" #line 493 "gram.y"
{ {
yyval.seinfo.role = NULL; yyval.seinfo.role = NULL;
yyval.seinfo.type = NULL; yyval.seinfo.type = NULL;
} }
break; break;
case 48: case 48:
#line 494 "gram.y" #line 497 "gram.y"
{ {
yyval.seinfo.role = yyvsp[0].string; yyval.seinfo.role = yyvsp[0].string;
yyval.seinfo.type = NULL; yyval.seinfo.type = NULL;
} }
break; break;
case 49: case 49:
#line 498 "gram.y" #line 501 "gram.y"
{ {
yyval.seinfo.type = yyvsp[0].string; yyval.seinfo.type = yyvsp[0].string;
yyval.seinfo.role = NULL; yyval.seinfo.role = NULL;
} }
break; break;
case 50: case 50:
#line 502 "gram.y" #line 505 "gram.y"
{ {
yyval.seinfo.role = yyvsp[-1].string; yyval.seinfo.role = yyvsp[-1].string;
yyval.seinfo.type = yyvsp[0].string; yyval.seinfo.type = yyvsp[0].string;
} }
break; break;
case 51: case 51:
#line 506 "gram.y" #line 509 "gram.y"
{ {
yyval.seinfo.type = yyvsp[-1].string; yyval.seinfo.type = yyvsp[-1].string;
yyval.seinfo.role = yyvsp[0].string; yyval.seinfo.role = yyvsp[0].string;
} }
break; break;
case 52: case 52:
#line 512 "gram.y" #line 515 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 53: case 53:
#line 516 "gram.y" #line 519 "gram.y"
{ {
yyval.string = yyvsp[0].string; yyval.string = yyvsp[0].string;
} }
break; break;
case 54: case 54:
#line 521 "gram.y" #line 524 "gram.y"
{ {
yyval.privinfo.privs = NULL; yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = NULL; yyval.privinfo.limitprivs = NULL;
} }
break; break;
case 55: case 55:
#line 525 "gram.y" #line 528 "gram.y"
{ {
yyval.privinfo.privs = yyvsp[0].string; yyval.privinfo.privs = yyvsp[0].string;
yyval.privinfo.limitprivs = NULL; yyval.privinfo.limitprivs = NULL;
} }
break; break;
case 56: case 56:
#line 529 "gram.y" #line 532 "gram.y"
{ {
yyval.privinfo.privs = NULL; yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = yyvsp[0].string; yyval.privinfo.limitprivs = yyvsp[0].string;
} }
break; break;
case 57: case 57:
#line 533 "gram.y" #line 536 "gram.y"
{ {
yyval.privinfo.privs = yyvsp[-1].string; yyval.privinfo.privs = yyvsp[-1].string;
yyval.privinfo.limitprivs = yyvsp[0].string; yyval.privinfo.limitprivs = yyvsp[0].string;
} }
break; break;
case 58: case 58:
#line 537 "gram.y" #line 540 "gram.y"
{ {
yyval.privinfo.limitprivs = yyvsp[-1].string; yyval.privinfo.limitprivs = yyvsp[-1].string;
yyval.privinfo.privs = yyvsp[0].string; yyval.privinfo.privs = yyvsp[0].string;
} }
break; break;
case 59: case 59:
#line 543 "gram.y" #line 546 "gram.y"
{ {
yyval.runas = NULL; yyval.runas = NULL;
} }
break; break;
case 60: case 60:
#line 546 "gram.y" #line 549 "gram.y"
{ {
yyval.runas = yyvsp[-1].runas; yyval.runas = yyvsp[-1].runas;
} }
break; break;
case 61: case 61:
#line 551 "gram.y" #line 554 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) { if (yyval.runas != NULL) {
@@ -1730,7 +1733,7 @@ case 61:
} }
break; break;
case 62: case 62:
#line 566 "gram.y" #line 569 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1742,7 +1745,7 @@ case 62:
} }
break; break;
case 63: case 63:
#line 575 "gram.y" #line 578 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1754,7 +1757,7 @@ case 63:
} }
break; break;
case 64: case 64:
#line 584 "gram.y" #line 587 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) { if (yyval.runas == NULL) {
@@ -1766,7 +1769,7 @@ case 64:
} }
break; break;
case 65: case 65:
#line 593 "gram.y" #line 596 "gram.y"
{ {
yyval.runas = calloc(1, sizeof(struct runascontainer)); yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) { if (yyval.runas != NULL) {
@@ -1784,97 +1787,97 @@ case 65:
} }
break; break;
case 66: case 66:
#line 610 "gram.y" #line 613 "gram.y"
{ {
TAGS_INIT(yyval.tag); TAGS_INIT(yyval.tag);
} }
break; break;
case 67: case 67:
#line 613 "gram.y" #line 616 "gram.y"
{ {
yyval.tag.nopasswd = true; yyval.tag.nopasswd = true;
} }
break; break;
case 68: case 68:
#line 616 "gram.y" #line 619 "gram.y"
{ {
yyval.tag.nopasswd = false; yyval.tag.nopasswd = false;
} }
break; break;
case 69: case 69:
#line 619 "gram.y" #line 622 "gram.y"
{ {
yyval.tag.noexec = true; yyval.tag.noexec = true;
} }
break; break;
case 70: case 70:
#line 622 "gram.y" #line 625 "gram.y"
{ {
yyval.tag.noexec = false; yyval.tag.noexec = false;
} }
break; break;
case 71: case 71:
#line 625 "gram.y" #line 628 "gram.y"
{ {
yyval.tag.setenv = true; yyval.tag.setenv = true;
} }
break; break;
case 72: case 72:
#line 628 "gram.y" #line 631 "gram.y"
{ {
yyval.tag.setenv = false; yyval.tag.setenv = false;
} }
break; break;
case 73: case 73:
#line 631 "gram.y" #line 634 "gram.y"
{ {
yyval.tag.log_input = true; yyval.tag.log_input = true;
} }
break; break;
case 74: case 74:
#line 634 "gram.y" #line 637 "gram.y"
{ {
yyval.tag.log_input = false; yyval.tag.log_input = false;
} }
break; break;
case 75: case 75:
#line 637 "gram.y" #line 640 "gram.y"
{ {
yyval.tag.log_output = true; yyval.tag.log_output = true;
} }
break; break;
case 76: case 76:
#line 640 "gram.y" #line 643 "gram.y"
{ {
yyval.tag.log_output = false; yyval.tag.log_output = false;
} }
break; break;
case 77: case 77:
#line 643 "gram.y" #line 646 "gram.y"
{ {
yyval.tag.follow = true; yyval.tag.follow = true;
} }
break; break;
case 78: case 78:
#line 646 "gram.y" #line 649 "gram.y"
{ {
yyval.tag.follow = false; yyval.tag.follow = false;
} }
break; break;
case 79: case 79:
#line 649 "gram.y" #line 652 "gram.y"
{ {
yyval.tag.send_mail = true; yyval.tag.send_mail = true;
} }
break; break;
case 80: case 80:
#line 652 "gram.y" #line 655 "gram.y"
{ {
yyval.tag.send_mail = false; yyval.tag.send_mail = false;
} }
break; break;
case 81: case 81:
#line 657 "gram.y" #line 660 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1884,7 +1887,7 @@ case 81:
} }
break; break;
case 82: case 82:
#line 664 "gram.y" #line 667 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1894,7 +1897,7 @@ case 82:
} }
break; break;
case 83: case 83:
#line 671 "gram.y" #line 674 "gram.y"
{ {
struct sudo_command *c = calloc(1, sizeof(*c)); struct sudo_command *c = calloc(1, sizeof(*c));
if (c == NULL) { if (c == NULL) {
@@ -1912,82 +1915,86 @@ case 83:
} }
break; break;
case 86: case 86:
#line 692 "gram.y" #line 695 "gram.y"
{ {
const char *s; const char *s;
if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) { s = alias_add(yyvsp[-2].string, HOSTALIAS, sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
} }
break; break;
case 88: case 88:
#line 702 "gram.y" #line 706 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 91: case 91:
#line 712 "gram.y" #line 716 "gram.y"
{ {
const char *s; const char *s;
if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) { s = alias_add(yyvsp[-2].string, CMNDALIAS, sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
} }
break; break;
case 93: case 93:
#line 722 "gram.y" #line 727 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 96: case 96:
#line 732 "gram.y" #line 737 "gram.y"
{ {
const char *s; const char *s;
if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) { s = alias_add(yyvsp[-2].string, RUNASALIAS, sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
} }
break; break;
case 99: case 99:
#line 745 "gram.y" #line 751 "gram.y"
{ {
const char *s; const char *s;
if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) { s = alias_add(yyvsp[-2].string, USERALIAS, sudoers, this_lineno, yyvsp[0].member);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
} }
break; break;
case 101: case 101:
#line 755 "gram.y" #line 762 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 102: case 102:
#line 761 "gram.y" #line 768 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 103: case 103:
#line 765 "gram.y" #line 772 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 104: case 104:
#line 771 "gram.y" #line 778 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -1997,7 +2004,7 @@ case 104:
} }
break; break;
case 105: case 105:
#line 778 "gram.y" #line 785 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2007,7 +2014,7 @@ case 105:
} }
break; break;
case 106: case 106:
#line 785 "gram.y" #line 792 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, NETGROUP); yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2017,7 +2024,7 @@ case 106:
} }
break; break;
case 107: case 107:
#line 792 "gram.y" #line 799 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, USERGROUP); yyval.member = new_member(yyvsp[0].string, USERGROUP);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2027,7 +2034,7 @@ case 107:
} }
break; break;
case 108: case 108:
#line 799 "gram.y" #line 806 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, WORD); yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2037,28 +2044,28 @@ case 108:
} }
break; break;
case 110: case 110:
#line 809 "gram.y" #line 816 "gram.y"
{ {
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member; yyval.member = yyvsp[-2].member;
} }
break; break;
case 111: case 111:
#line 815 "gram.y" #line 822 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = false; yyval.member->negated = false;
} }
break; break;
case 112: case 112:
#line 819 "gram.y" #line 826 "gram.y"
{ {
yyval.member = yyvsp[0].member; yyval.member = yyvsp[0].member;
yyval.member->negated = true; yyval.member->negated = true;
} }
break; break;
case 113: case 113:
#line 825 "gram.y" #line 832 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, ALIAS); yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2068,7 +2075,7 @@ case 113:
} }
break; break;
case 114: case 114:
#line 832 "gram.y" #line 839 "gram.y"
{ {
yyval.member = new_member(NULL, ALL); yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2078,7 +2085,7 @@ case 114:
} }
break; break;
case 115: case 115:
#line 839 "gram.y" #line 846 "gram.y"
{ {
yyval.member = new_member(yyvsp[0].string, WORD); yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) { if (yyval.member == NULL) {
@@ -2087,7 +2094,7 @@ case 115:
} }
} }
break; break;
#line 2038 "gram.c" #line 2045 "gram.c"
} }
yyssp -= yym; yyssp -= yym;
yystate = *yyssp; yystate = *yyssp;

View File

@@ -49,6 +49,9 @@
#include "parse.h" #include "parse.h"
#include "toke.h" #include "toke.h"
/* If we last saw a newline the entry is on the preceding line. */
#define this_lineno (last_token == COMMENT ? sudolineno - 1 : sudolineno)
/* /*
* Globals * Globals
*/ */
@@ -691,7 +694,8 @@ hostaliases : hostalias
hostalias : ALIAS '=' hostlist { hostalias : ALIAS '=' hostlist {
const char *s; const char *s;
if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) { s = alias_add($1, HOSTALIAS, sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
@@ -711,7 +715,8 @@ cmndaliases : cmndalias
cmndalias : ALIAS '=' cmndlist { cmndalias : ALIAS '=' cmndlist {
const char *s; const char *s;
if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) { s = alias_add($1, CMNDALIAS, sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
@@ -731,7 +736,8 @@ runasaliases : runasalias
runasalias : ALIAS '=' userlist { runasalias : ALIAS '=' userlist {
const char *s; const char *s;
if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) { s = alias_add($1, RUNASALIAS, sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
@@ -744,7 +750,8 @@ useraliases : useralias
useralias : ALIAS '=' userlist { useralias : ALIAS '=' userlist {
const char *s; const char *s;
if ((s = alias_add($1, USERALIAS, $3)) != NULL) { s = alias_add($1, USERALIAS, sudoers, this_lineno, $3);
if (s != NULL) {
sudoerserror(s); sudoerserror(s);
YYERROR; YYERROR;
} }
@@ -851,13 +858,9 @@ sudoerserror(const char *s)
{ {
debug_decl(sudoerserror, SUDOERS_DEBUG_PARSER) debug_decl(sudoerserror, SUDOERS_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; errorlineno = this_lineno;
rcstr_delref(errorfile); rcstr_delref(errorfile);
errorfile = rcstr_addref(sudoers); errorfile = rcstr_addref(sudoers);
} }
@@ -870,7 +873,7 @@ sudoerserror(const char *s)
/* Warnings are displayed in the user's locale. */ /* Warnings are displayed in the user's locale. */
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale); sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), sudolineno); sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), this_lineno);
sudoers_setlocale(oldlocale, NULL); sudoers_setlocale(oldlocale, NULL);
} }
#endif #endif
@@ -896,7 +899,7 @@ new_default(char *var, char *val, short op)
/* d->type = 0; */ /* d->type = 0; */
d->op = op; d->op = op;
/* d->binding = NULL */ /* d->binding = NULL */
d->lineno = last_token == COMMENT ? sudolineno - 1 : sudolineno; d->lineno = this_lineno;
d->file = rcstr_addref(sudoers); d->file = rcstr_addref(sudoers);
HLTQ_INIT(d, entries); HLTQ_INIT(d, entries);
@@ -1003,6 +1006,8 @@ add_userspec(struct member *members, struct privilege *privs)
"unable to allocate memory"); "unable to allocate memory");
debug_return_bool(false); debug_return_bool(false);
} }
u->lineno = this_lineno;
u->file = rcstr_addref(sudoers);
HLTQ_TO_TAILQ(&u->users, members, entries); HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries); HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries); TAILQ_INSERT_TAIL(&userspecs, u, entries);
@@ -1043,6 +1048,7 @@ init_parser(const char *path, bool quiet)
bool ret = true; bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER) debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
/* XXX - move into a free function */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) { TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) {
struct member *m, *m_next; struct member *m, *m_next;
struct privilege *priv, *priv_next; struct privilege *priv, *priv_next;
@@ -1117,6 +1123,7 @@ init_parser(const char *path, bool quiet)
} }
free(priv); free(priv);
} }
rcstr_delref(us->file);
free(us); free(us);
} }
TAILQ_INIT(&userspecs); TAILQ_INIT(&userspecs);

View File

@@ -159,6 +159,8 @@ struct userspec {
TAILQ_ENTRY(userspec) entries; TAILQ_ENTRY(userspec) entries;
struct member_list users; /* list of users */ struct member_list users; /* list of users */
struct privilege_list privileges; /* list of privileges */ struct privilege_list privileges; /* list of privileges */
int lineno;
char *file;
}; };
/* /*
@@ -209,7 +211,9 @@ struct runascontainer {
struct alias { struct alias {
char *name; /* alias name */ char *name; /* alias name */
unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */ unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */
bool used; /* "used" flag for cycle detection */ short used; /* "used" flag for cycle detection */
int lineno; /* line number of alias entry */
char *file; /* file the alias entry was in */
struct member_list members; /* list of alias members */ struct member_list members; /* list of alias members */
}; };
@@ -236,7 +240,7 @@ extern struct defaults_list defaults;
/* alias.c */ /* alias.c */
bool no_aliases(void); bool no_aliases(void);
const char *alias_add(char *name, int type, struct member *members); const char *alias_add(char *name, int type, char *file, int lineno, struct member *members);
int alias_compare(const void *a1, const void *a2); int alias_compare(const void *a1, const void *a2);
struct alias *alias_get(char *name, int type); struct alias *alias_get(char *name, int type);
struct alias *alias_remove(char *name, int type); struct alias *alias_remove(char *name, int type);

View File

@@ -1 +1 @@
visudo: Error: cycle in User_Alias "FOO" visudo: stdin:1 cycle in User_Alias "FOO"

View File

@@ -1,2 +1,2 @@
visudo: Warning: unused User_Alias "A" visudo: stdin:1 unused User_Alias "A"
visudo: Warning: unused User_Alias "B" visudo: stdin:2 unused User_Alias "B"

View File

@@ -89,7 +89,7 @@ TAILQ_HEAD(sudoersfile_list, sudoersfile);
static void quit(int); static void quit(int);
static void get_hostname(void); static void get_hostname(void);
static int whatnow(void); static int whatnow(void);
static int check_aliases(bool, bool); static int check_aliases(bool strict, bool quiet);
static char *get_editor(int *editor_argc, char ***editor_argv); static char *get_editor(int *editor_argc, char ***editor_argv);
static bool check_syntax(const char *, bool, bool, bool); static bool check_syntax(const char *, bool, bool, bool);
static bool edit_sudoers(struct sudoersfile *, char *, int, char **, int); static bool edit_sudoers(struct sudoersfile *, char *, int, char **, int);
@@ -1114,7 +1114,7 @@ alias_type_to_string(int alias_type)
} }
static int static int
check_alias(char *name, int type, int strict, int quiet) check_alias(char *name, int type, char *file, int lineno, bool quiet)
{ {
struct member *m; struct member *m;
struct alias *a; struct alias *a;
@@ -1124,22 +1124,19 @@ check_alias(char *name, int type, int strict, int quiet)
if ((a = alias_get(name, type)) != NULL) { if ((a = alias_get(name, type)) != NULL) {
/* check alias contents */ /* check alias contents */
TAILQ_FOREACH(m, &a->members, entries) { TAILQ_FOREACH(m, &a->members, entries) {
if (m->type == ALIAS) if (m->type != ALIAS)
errors += check_alias(m->name, type, strict, quiet); continue;
errors += check_alias(m->name, type, a->file, a->lineno, quiet);
} }
alias_put(a); alias_put(a);
} else { } else {
if (!quiet) { if (!quiet) {
if (errno == ELOOP) { if (errno == ELOOP) {
sudo_warnx(strict ? sudo_warnx(U_("%s:%d cycle in %s \"%s\""),
U_("Error: cycle in %s \"%s\"") : file, lineno, alias_type_to_string(type), name);
U_("Warning: cycle in %s \"%s\""),
alias_type_to_string(type), name);
} else { } else {
sudo_warnx(strict ? sudo_warnx(U_("%s:%d %s \"%s\" referenced but not defined"),
U_("Error: %s \"%s\" referenced but not defined") : file, lineno, alias_type_to_string(type), name);
U_("Warning: %s \"%s\" referenced but not defined"),
alias_type_to_string(type), name);
} }
} }
errors++; errors++;
@@ -1173,32 +1170,37 @@ check_aliases(bool strict, bool quiet)
TAILQ_FOREACH(us, &userspecs, entries) { TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) { TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
errors += check_alias(m->name, USERALIAS, strict, quiet); errors += check_alias(m->name, USERALIAS,
us->file, us->lineno, quiet);
} }
} }
TAILQ_FOREACH(priv, &us->privileges, entries) { TAILQ_FOREACH(priv, &us->privileges, entries) {
TAILQ_FOREACH(m, &priv->hostlist, entries) { TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
errors += check_alias(m->name, HOSTALIAS, strict, quiet); errors += check_alias(m->name, HOSTALIAS,
us->file, us->lineno, quiet);
} }
} }
TAILQ_FOREACH(cs, &priv->cmndlist, entries) { TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (cs->runasuserlist != NULL) { if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) { TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
errors += check_alias(m->name, RUNASALIAS, strict, quiet); errors += check_alias(m->name, RUNASALIAS,
us->file, us->lineno, quiet);
} }
} }
} }
if (cs->runasgrouplist != NULL) { if (cs->runasgrouplist != NULL) {
TAILQ_FOREACH(m, cs->runasgrouplist, entries) { TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m->type == ALIAS) { if (m->type == ALIAS) {
errors += check_alias(m->name, RUNASALIAS, strict, quiet); errors += check_alias(m->name, RUNASALIAS,
us->file, us->lineno, quiet);
} }
} }
} }
if ((m = cs->cmnd)->type == ALIAS) { if ((m = cs->cmnd)->type == ALIAS) {
errors += check_alias(m->name, CMNDALIAS, strict, quiet); errors += check_alias(m->name, CMNDALIAS,
us->file, us->lineno, quiet);
} }
} }
} }
@@ -1281,8 +1283,8 @@ print_unused(void *v1, void *v2)
{ {
struct alias *a = (struct alias *)v1; struct alias *a = (struct alias *)v1;
sudo_warnx_nodebug(U_("Warning: unused %s \"%s\""), sudo_warnx_nodebug(U_("%s:%d unused %s \"%s\""),
alias_type_to_string(a->type), a->name); a->file, a->lineno, alias_type_to_string(a->type), a->name);
return 0; return 0;
} }