mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 09:57:41 +00:00
Add support for @include and @includedir
These are less confusing than #include and #includedir when the hash character is also the comment character. This commit also adds real parsing of include directives as opposed to the pure lexer approach used previously. As a result, it is now possible to include files with spaces by either using a double-quoted string or escaping the space characters with a backslash.
This commit is contained in:
parent
c63ba01e0e
commit
741c6f274e
6
MANIFEST
6
MANIFEST
@ -809,6 +809,10 @@ plugins/sudoers/regress/sudoers/test9.toke.ok
|
|||||||
plugins/sudoers/regress/testsudoers/group
|
plugins/sudoers/regress/testsudoers/group
|
||||||
plugins/sudoers/regress/testsudoers/test1.out.ok
|
plugins/sudoers/regress/testsudoers/test1.out.ok
|
||||||
plugins/sudoers/regress/testsudoers/test1.sh
|
plugins/sudoers/regress/testsudoers/test1.sh
|
||||||
|
plugins/sudoers/regress/testsudoers/test10.out.ok
|
||||||
|
plugins/sudoers/regress/testsudoers/test10.sh
|
||||||
|
plugins/sudoers/regress/testsudoers/test11.out.ok
|
||||||
|
plugins/sudoers/regress/testsudoers/test11.sh
|
||||||
plugins/sudoers/regress/testsudoers/test2.inc
|
plugins/sudoers/regress/testsudoers/test2.inc
|
||||||
plugins/sudoers/regress/testsudoers/test2.out.ok
|
plugins/sudoers/regress/testsudoers/test2.out.ok
|
||||||
plugins/sudoers/regress/testsudoers/test2.sh
|
plugins/sudoers/regress/testsudoers/test2.sh
|
||||||
@ -824,6 +828,8 @@ plugins/sudoers/regress/testsudoers/test7.out.ok
|
|||||||
plugins/sudoers/regress/testsudoers/test7.sh
|
plugins/sudoers/regress/testsudoers/test7.sh
|
||||||
plugins/sudoers/regress/testsudoers/test8.out.ok
|
plugins/sudoers/regress/testsudoers/test8.out.ok
|
||||||
plugins/sudoers/regress/testsudoers/test8.sh
|
plugins/sudoers/regress/testsudoers/test8.sh
|
||||||
|
plugins/sudoers/regress/testsudoers/test9.out.ok
|
||||||
|
plugins/sudoers/regress/testsudoers/test9.sh
|
||||||
plugins/sudoers/regress/visudo/test1.out.ok
|
plugins/sudoers/regress/visudo/test1.out.ok
|
||||||
plugins/sudoers/regress/visudo/test1.sh
|
plugins/sudoers/regress/visudo/test1.sh
|
||||||
plugins/sudoers/regress/visudo/test10.out.ok
|
plugins/sudoers/regress/visudo/test10.out.ok
|
||||||
|
5
NEWS
5
NEWS
@ -19,6 +19,11 @@ What's new in Sudo 1.9.1
|
|||||||
option to allow replaying a session that is still in progress,
|
option to allow replaying a session that is still in progress,
|
||||||
similar to "tail -f".
|
similar to "tail -f".
|
||||||
|
|
||||||
|
* The @include and @includedir directives can be used in sudoers
|
||||||
|
instead of #include and #includedir. In addition, include paths
|
||||||
|
may now have embedded white space by either using a double-quoted
|
||||||
|
string or escaping the space characters with a backslash.
|
||||||
|
|
||||||
What's new in Sudo 1.9.0
|
What's new in Sudo 1.9.0
|
||||||
|
|
||||||
* Fixed a test failure in the strsig_test regress test on FreeBSD.
|
* Fixed a test failure in the strsig_test regress test on FreeBSD.
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.TH "SUDOERS" "@mansectform@" "April 30, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
.TH "SUDOERS" "@mansectform@" "May 19, 2020" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||||
.nh
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@ -1864,12 +1864,17 @@ It is possible to include other
|
|||||||
files from within the
|
files from within the
|
||||||
\fIsudoers\fR
|
\fIsudoers\fR
|
||||||
file currently being parsed using the
|
file currently being parsed using the
|
||||||
|
\fR@include\fR
|
||||||
|
and
|
||||||
|
\fR@includedir\fR
|
||||||
|
directives.
|
||||||
|
For compatibility with sudo versions prior to 1.9.1,
|
||||||
\fR#include\fR
|
\fR#include\fR
|
||||||
and
|
and
|
||||||
\fR#includedir\fR
|
\fR#includedir\fR
|
||||||
directives.
|
are also accepted.
|
||||||
.PP
|
.PP
|
||||||
This can be used, for example, to keep a site-wide
|
An include file can be used, for example, to keep a site-wide
|
||||||
\fIsudoers\fR
|
\fIsudoers\fR
|
||||||
file in addition to a local, per-machine file.
|
file in addition to a local, per-machine file.
|
||||||
For the sake of this example the site-wide
|
For the sake of this example the site-wide
|
||||||
@ -1882,13 +1887,12 @@ To include
|
|||||||
\fI/etc/sudoers.local\fR
|
\fI/etc/sudoers.local\fR
|
||||||
from within
|
from within
|
||||||
\fI/etc/sudoers\fR
|
\fI/etc/sudoers\fR
|
||||||
we would use the
|
one would use the following line in
|
||||||
following line in
|
|
||||||
\fI/etc/sudoers\fR:
|
\fI/etc/sudoers\fR:
|
||||||
.nf
|
.nf
|
||||||
.sp
|
.sp
|
||||||
.RS 4n
|
.RS 4n
|
||||||
#include /etc/sudoers.local
|
@include /etc/sudoers.local
|
||||||
.RE
|
.RE
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
@ -1907,6 +1911,16 @@ Files that are included may themselves include other files.
|
|||||||
A hard limit of 128 nested include files is enforced to prevent include
|
A hard limit of 128 nested include files is enforced to prevent include
|
||||||
file loops.
|
file loops.
|
||||||
.PP
|
.PP
|
||||||
|
The path to the include file may contain white space if it is
|
||||||
|
escaped with a backslash
|
||||||
|
(\(oq\e\(cq).
|
||||||
|
Alternately, the entire path may be enclosed in double quotes
|
||||||
|
(\&""),
|
||||||
|
in which case no escaping is necessary.
|
||||||
|
To include a literal backslash in the path,
|
||||||
|
\(oq\e\e\(cq
|
||||||
|
should be used.
|
||||||
|
.PP
|
||||||
If the path to the include file is not fully-qualified (does not
|
If the path to the include file is not fully-qualified (does not
|
||||||
begin with a
|
begin with a
|
||||||
\(oq/\(cq),
|
\(oq/\(cq),
|
||||||
@ -1918,7 +1932,7 @@ contains the line:
|
|||||||
.nf
|
.nf
|
||||||
.sp
|
.sp
|
||||||
.RS 4n
|
.RS 4n
|
||||||
\fR#include sudoers.local\fR
|
\fR@include sudoers.local\fR
|
||||||
.RE
|
.RE
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
@ -1934,7 +1948,7 @@ then
|
|||||||
.nf
|
.nf
|
||||||
.sp
|
.sp
|
||||||
.RS 4n
|
.RS 4n
|
||||||
#include /etc/sudoers.%h
|
@include /etc/sudoers.%h
|
||||||
.RE
|
.RE
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
@ -1944,7 +1958,7 @@ to include the file
|
|||||||
\fI/etc/sudoers.xerxes\fR.
|
\fI/etc/sudoers.xerxes\fR.
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
\fR#includedir\fR
|
\fR@includedir\fR
|
||||||
directive can be used to create a
|
directive can be used to create a
|
||||||
\fIsudoers.d\fR
|
\fIsudoers.d\fR
|
||||||
directory that the system package manager can drop
|
directory that the system package manager can drop
|
||||||
@ -1954,7 +1968,7 @@ For example, given:
|
|||||||
.nf
|
.nf
|
||||||
.sp
|
.sp
|
||||||
.RS 4n
|
.RS 4n
|
||||||
#includedir /etc/sudoers.d
|
@includedir /etc/sudoers.d
|
||||||
.RE
|
.RE
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
@ -1981,14 +1995,14 @@ Using a consistent number of leading zeroes in the file names can be used
|
|||||||
to avoid such problems.
|
to avoid such problems.
|
||||||
After parsing the files in the directory, control returns to the
|
After parsing the files in the directory, control returns to the
|
||||||
file that contained the
|
file that contained the
|
||||||
\fR#includedir\fR
|
\fR@includedir\fR
|
||||||
directive.
|
directive.
|
||||||
.PP
|
.PP
|
||||||
Note that unlike files included via
|
Note that unlike files included via
|
||||||
\fR#include\fR,
|
\fR@include\fR,
|
||||||
\fBvisudo\fR
|
\fBvisudo\fR
|
||||||
will not edit the files in a
|
will not edit the files in a
|
||||||
\fR#includedir\fR
|
\fR@includedir\fR
|
||||||
directory unless one of them contains a syntax error.
|
directory unless one of them contains a syntax error.
|
||||||
It is still possible to run
|
It is still possible to run
|
||||||
\fBvisudo\fR
|
\fBvisudo\fR
|
||||||
@ -4105,7 +4119,7 @@ Entries in this file should either be of the form
|
|||||||
\(lq\fRVARIABLE=value\fR\(rq
|
\(lq\fRVARIABLE=value\fR\(rq
|
||||||
or
|
or
|
||||||
\(lq\fRexport VARIABLE=value\fR\(rq.
|
\(lq\fRexport VARIABLE=value\fR\(rq.
|
||||||
The value may optionally be surrounded by single or double quotes.
|
The value may optionally be enclosed in single or double quotes.
|
||||||
Variables in this file are only added if the variable does not already
|
Variables in this file are only added if the variable does not already
|
||||||
exist in the environment.
|
exist in the environment.
|
||||||
This file is considered to be part of the security policy,
|
This file is considered to be part of the security policy,
|
||||||
@ -4332,7 +4346,7 @@ Entries in this file should either be of the form
|
|||||||
\(lq\fRVARIABLE=value\fR\(rq
|
\(lq\fRVARIABLE=value\fR\(rq
|
||||||
or
|
or
|
||||||
\(lq\fRexport VARIABLE=value\fR\(rq.
|
\(lq\fRexport VARIABLE=value\fR\(rq.
|
||||||
The value may optionally be surrounded by single or double quotes.
|
The value may optionally be enclosed in single or double quotes.
|
||||||
Variables in this file are only added if the variable does not already
|
Variables in this file are only added if the variable does not already
|
||||||
exist in the environment.
|
exist in the environment.
|
||||||
Unlike
|
Unlike
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.Dd April 30, 2020
|
.Dd May 19, 2020
|
||||||
.Dt SUDOERS @mansectform@
|
.Dt SUDOERS @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1753,12 +1753,17 @@ It is possible to include other
|
|||||||
files from within the
|
files from within the
|
||||||
.Em sudoers
|
.Em sudoers
|
||||||
file currently being parsed using the
|
file currently being parsed using the
|
||||||
|
.Li @include
|
||||||
|
and
|
||||||
|
.Li @includedir
|
||||||
|
directives.
|
||||||
|
For compatibility with sudo versions prior to 1.9.1,
|
||||||
.Li #include
|
.Li #include
|
||||||
and
|
and
|
||||||
.Li #includedir
|
.Li #includedir
|
||||||
directives.
|
are also accepted.
|
||||||
.Pp
|
.Pp
|
||||||
This can be used, for example, to keep a site-wide
|
An include file can be used, for example, to keep a site-wide
|
||||||
.Em sudoers
|
.Em sudoers
|
||||||
file in addition to a local, per-machine file.
|
file in addition to a local, per-machine file.
|
||||||
For the sake of this example the site-wide
|
For the sake of this example the site-wide
|
||||||
@ -1771,11 +1776,10 @@ To include
|
|||||||
.Pa /etc/sudoers.local
|
.Pa /etc/sudoers.local
|
||||||
from within
|
from within
|
||||||
.Pa /etc/sudoers
|
.Pa /etc/sudoers
|
||||||
we would use the
|
one would use the following line in
|
||||||
following line in
|
|
||||||
.Pa /etc/sudoers :
|
.Pa /etc/sudoers :
|
||||||
.Bd -literal -offset 4n
|
.Bd -literal -offset 4n
|
||||||
#include /etc/sudoers.local
|
@include /etc/sudoers.local
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
When
|
When
|
||||||
@ -1793,6 +1797,16 @@ Files that are included may themselves include other files.
|
|||||||
A hard limit of 128 nested include files is enforced to prevent include
|
A hard limit of 128 nested include files is enforced to prevent include
|
||||||
file loops.
|
file loops.
|
||||||
.Pp
|
.Pp
|
||||||
|
The path to the include file may contain white space if it is
|
||||||
|
escaped with a backslash
|
||||||
|
.Pq Ql \e .
|
||||||
|
Alternately, the entire path may be enclosed in double quotes
|
||||||
|
.Pq \&"" ,
|
||||||
|
in which case no escaping is necessary.
|
||||||
|
To include a literal backslash in the path,
|
||||||
|
.Ql \e\e
|
||||||
|
should be used.
|
||||||
|
.Pp
|
||||||
If the path to the include file is not fully-qualified (does not
|
If the path to the include file is not fully-qualified (does not
|
||||||
begin with a
|
begin with a
|
||||||
.Ql / ) ,
|
.Ql / ) ,
|
||||||
@ -1802,7 +1816,7 @@ For example, if
|
|||||||
.Pa /etc/sudoers
|
.Pa /etc/sudoers
|
||||||
contains the line:
|
contains the line:
|
||||||
.Bd -literal -offset 4n
|
.Bd -literal -offset 4n
|
||||||
.Li #include sudoers.local
|
.Li @include sudoers.local
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
the file that will be included is
|
the file that will be included is
|
||||||
@ -1815,7 +1829,7 @@ In other words, if the machine's host name is
|
|||||||
.Dq xerxes ,
|
.Dq xerxes ,
|
||||||
then
|
then
|
||||||
.Bd -literal -offset 4n
|
.Bd -literal -offset 4n
|
||||||
#include /etc/sudoers.%h
|
@include /etc/sudoers.%h
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
will cause
|
will cause
|
||||||
@ -1824,7 +1838,7 @@ to include the file
|
|||||||
.Pa /etc/sudoers.xerxes .
|
.Pa /etc/sudoers.xerxes .
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Li #includedir
|
.Li @includedir
|
||||||
directive can be used to create a
|
directive can be used to create a
|
||||||
.Pa sudoers.d
|
.Pa sudoers.d
|
||||||
directory that the system package manager can drop
|
directory that the system package manager can drop
|
||||||
@ -1832,7 +1846,7 @@ directory that the system package manager can drop
|
|||||||
file rules into as part of package installation.
|
file rules into as part of package installation.
|
||||||
For example, given:
|
For example, given:
|
||||||
.Bd -literal -offset 4n
|
.Bd -literal -offset 4n
|
||||||
#includedir /etc/sudoers.d
|
@includedir /etc/sudoers.d
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.Nm sudo
|
.Nm sudo
|
||||||
@ -1858,14 +1872,14 @@ Using a consistent number of leading zeroes in the file names can be used
|
|||||||
to avoid such problems.
|
to avoid such problems.
|
||||||
After parsing the files in the directory, control returns to the
|
After parsing the files in the directory, control returns to the
|
||||||
file that contained the
|
file that contained the
|
||||||
.Li #includedir
|
.Li @includedir
|
||||||
directive.
|
directive.
|
||||||
.Pp
|
.Pp
|
||||||
Note that unlike files included via
|
Note that unlike files included via
|
||||||
.Li #include ,
|
.Li @include ,
|
||||||
.Nm visudo
|
.Nm visudo
|
||||||
will not edit the files in a
|
will not edit the files in a
|
||||||
.Li #includedir
|
.Li @includedir
|
||||||
directory unless one of them contains a syntax error.
|
directory unless one of them contains a syntax error.
|
||||||
It is still possible to run
|
It is still possible to run
|
||||||
.Nm visudo
|
.Nm visudo
|
||||||
@ -3849,7 +3863,7 @@ Entries in this file should either be of the form
|
|||||||
.Dq Li VARIABLE=value
|
.Dq Li VARIABLE=value
|
||||||
or
|
or
|
||||||
.Dq Li export VARIABLE=value .
|
.Dq Li export VARIABLE=value .
|
||||||
The value may optionally be surrounded by single or double quotes.
|
The value may optionally be enclosed in single or double quotes.
|
||||||
Variables in this file are only added if the variable does not already
|
Variables in this file are only added if the variable does not already
|
||||||
exist in the environment.
|
exist in the environment.
|
||||||
This file is considered to be part of the security policy,
|
This file is considered to be part of the security policy,
|
||||||
@ -4045,7 +4059,7 @@ Entries in this file should either be of the form
|
|||||||
.Dq Li VARIABLE=value
|
.Dq Li VARIABLE=value
|
||||||
or
|
or
|
||||||
.Dq Li export VARIABLE=value .
|
.Dq Li export VARIABLE=value .
|
||||||
The value may optionally be surrounded by single or double quotes.
|
The value may optionally be enclosed in single or double quotes.
|
||||||
Variables in this file are only added if the variable does not already
|
Variables in this file are only added if the variable does not already
|
||||||
exist in the environment.
|
exist in the environment.
|
||||||
Unlike
|
Unlike
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,44 +6,46 @@
|
|||||||
#define USERGROUP 262
|
#define USERGROUP 262
|
||||||
#define WORD 263
|
#define WORD 263
|
||||||
#define DIGEST 264
|
#define DIGEST 264
|
||||||
#define DEFAULTS 265
|
#define INCLUDE 265
|
||||||
#define DEFAULTS_HOST 266
|
#define INCLUDEDIR 266
|
||||||
#define DEFAULTS_USER 267
|
#define DEFAULTS 267
|
||||||
#define DEFAULTS_RUNAS 268
|
#define DEFAULTS_HOST 268
|
||||||
#define DEFAULTS_CMND 269
|
#define DEFAULTS_USER 269
|
||||||
#define NOPASSWD 270
|
#define DEFAULTS_RUNAS 270
|
||||||
#define PASSWD 271
|
#define DEFAULTS_CMND 271
|
||||||
#define NOEXEC 272
|
#define NOPASSWD 272
|
||||||
#define EXEC 273
|
#define PASSWD 273
|
||||||
#define SETENV 274
|
#define NOEXEC 274
|
||||||
#define NOSETENV 275
|
#define EXEC 275
|
||||||
#define LOG_INPUT 276
|
#define SETENV 276
|
||||||
#define NOLOG_INPUT 277
|
#define NOSETENV 277
|
||||||
#define LOG_OUTPUT 278
|
#define LOG_INPUT 278
|
||||||
#define NOLOG_OUTPUT 279
|
#define NOLOG_INPUT 279
|
||||||
#define MAIL 280
|
#define LOG_OUTPUT 280
|
||||||
#define NOMAIL 281
|
#define NOLOG_OUTPUT 281
|
||||||
#define FOLLOWLNK 282
|
#define MAIL 282
|
||||||
#define NOFOLLOWLNK 283
|
#define NOMAIL 283
|
||||||
#define ALL 284
|
#define FOLLOWLNK 284
|
||||||
#define COMMENT 285
|
#define NOFOLLOWLNK 285
|
||||||
#define HOSTALIAS 286
|
#define ALL 286
|
||||||
#define CMNDALIAS 287
|
#define COMMENT 287
|
||||||
#define USERALIAS 288
|
#define HOSTALIAS 288
|
||||||
#define RUNASALIAS 289
|
#define CMNDALIAS 289
|
||||||
#define ERROR 290
|
#define USERALIAS 290
|
||||||
#define TYPE 291
|
#define RUNASALIAS 291
|
||||||
#define ROLE 292
|
#define ERROR 292
|
||||||
#define PRIVS 293
|
#define TYPE 293
|
||||||
#define LIMITPRIVS 294
|
#define ROLE 294
|
||||||
#define CMND_TIMEOUT 295
|
#define PRIVS 295
|
||||||
#define NOTBEFORE 296
|
#define LIMITPRIVS 296
|
||||||
#define NOTAFTER 297
|
#define CMND_TIMEOUT 297
|
||||||
#define MYSELF 298
|
#define NOTBEFORE 298
|
||||||
#define SHA224_TOK 299
|
#define NOTAFTER 299
|
||||||
#define SHA256_TOK 300
|
#define MYSELF 300
|
||||||
#define SHA384_TOK 301
|
#define SHA224_TOK 301
|
||||||
#define SHA512_TOK 302
|
#define SHA256_TOK 302
|
||||||
|
#define SHA384_TOK 303
|
||||||
|
#define SHA512_TOK 304
|
||||||
#ifndef YYSTYPE_DEFINED
|
#ifndef YYSTYPE_DEFINED
|
||||||
#define YYSTYPE_DEFINED
|
#define YYSTYPE_DEFINED
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -92,6 +92,8 @@ static struct command_digest *new_digest(int, char *);
|
|||||||
%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 <string> DIGEST /* a SHA-2 digest */
|
||||||
|
%token <tok> INCLUDE /* @include */
|
||||||
|
%token <tok> INCLUDEDIR /* @includedir */
|
||||||
%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 */
|
||||||
@ -182,6 +184,20 @@ entry : COMMENT {
|
|||||||
| error COMMENT {
|
| error COMMENT {
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
|
| INCLUDE WORD {
|
||||||
|
if (!push_include($2, false)) {
|
||||||
|
free($2);
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
| INCLUDEDIR WORD {
|
||||||
|
if (!push_include($2, true)) {
|
||||||
|
free($2);
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
| userlist privileges {
|
| userlist privileges {
|
||||||
if (!add_userspec($1, $2)) {
|
if (!add_userspec($1, $2)) {
|
||||||
sudoerserror(N_("unable to allocate memory"));
|
sudoerserror(N_("unable to allocate memory"));
|
||||||
|
51
plugins/sudoers/regress/testsudoers/test10.out.ok
Normal file
51
plugins/sudoers/regress/testsudoers/test10.out.ok
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
Testing @include of a path with escaped white space
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing @include of a double-quoted path with white space
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #include of a path with escaped white space
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #include of a double-quoted path with white space
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
44
plugins/sudoers/regress/testsudoers/test10.sh
Executable file
44
plugins/sudoers/regress/testsudoers/test10.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Test @include of a file with embedded white space
|
||||||
|
#
|
||||||
|
|
||||||
|
# Create test file
|
||||||
|
TESTDIR="`pwd`/regress/testsudoers"
|
||||||
|
cat >"$TESTDIR/test 10.inc" <<EOF
|
||||||
|
root ALL = ALL
|
||||||
|
EOF
|
||||||
|
|
||||||
|
MYUID=`\ls -lnd "$TESTDIR/test 10.inc" | awk '{print $3}'`
|
||||||
|
MYGID=`\ls -lnd "$TESTDIR/test 10.inc" | awk '{print $4}'`
|
||||||
|
exec 2>&1
|
||||||
|
|
||||||
|
echo "Testing @include of a path with escaped white space"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
@include $TESTDIR/test\ 10.inc
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing @include of a double-quoted path with white space"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
@include "$TESTDIR/test 10.inc"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #include of a path with escaped white space"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
#include $TESTDIR/test\ 10.inc
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #include of a double-quoted path with white space"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
#include "$TESTDIR/test 10.inc"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
rm -f "$TESTDIR/test 10.inc"
|
||||||
|
exit 0
|
27
plugins/sudoers/regress/testsudoers/test11.out.ok
Normal file
27
plugins/sudoers/regress/testsudoers/test11.out.ok
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Testing @include with garbage after the path name
|
||||||
|
|
||||||
|
>>> sudoers: syntax error near line 1 <<<
|
||||||
|
Parse error in sudoers near line 1.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #include with garbage after the path name
|
||||||
|
|
||||||
|
>>> sudoers: syntax error near line 1 <<<
|
||||||
|
Parse error in sudoers near line 1.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
26
plugins/sudoers/regress/testsudoers/test11.sh
Executable file
26
plugins/sudoers/regress/testsudoers/test11.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Test @include with garbage after the path name
|
||||||
|
#
|
||||||
|
|
||||||
|
# Avoid warnings about memory leaks when there is a syntax error
|
||||||
|
ASAN_OPTIONS=detect_leaks=0; export ASAN_OPTIONS
|
||||||
|
|
||||||
|
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
||||||
|
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
||||||
|
exec 2>&1
|
||||||
|
|
||||||
|
echo "Testing @include with garbage after the path name"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
|
@include $TESTDIR/test2.inc womp womp
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #include with garbage after the path name"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
|
#include $TESTDIR/test2.inc womp womp
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exit 0
|
@ -1,3 +1,18 @@
|
|||||||
|
Testing @include
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #include
|
||||||
|
|
||||||
Parses OK.
|
Parses OK.
|
||||||
|
|
||||||
Entries for user root:
|
Entries for user root:
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Test #include facility
|
# Test @include facility
|
||||||
#
|
#
|
||||||
|
|
||||||
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
||||||
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
||||||
|
echo "Testing @include"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
|
@include $TESTDIR/test2.inc
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #include"
|
||||||
|
echo ""
|
||||||
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
#include $TESTDIR/test2.inc
|
#include $TESTDIR/test2.inc
|
||||||
EOF
|
EOF
|
||||||
|
@ -1,3 +1,44 @@
|
|||||||
|
Testing @includedir of an unquoted path
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing @includedir of a double-quoted path
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #includedir of an unquoted path
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #includedir of a double-quoted path
|
||||||
|
|
||||||
Parses OK.
|
Parses OK.
|
||||||
|
|
||||||
Entries for user root:
|
Entries for user root:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Test #include facility
|
# Test @includedir facility
|
||||||
#
|
#
|
||||||
|
|
||||||
parentdir="`echo $0 | sed 's:/[^/]*$::'`"
|
parentdir="`echo $0 | sed 's:/[^/]*$::'`"
|
||||||
@ -15,9 +15,35 @@ if [ -d "$parentdir" ]; then
|
|||||||
MYUID=`\ls -lnd $TESTDIR/test3.d | awk '{print $3}'`
|
MYUID=`\ls -lnd $TESTDIR/test3.d | awk '{print $3}'`
|
||||||
MYGID=`\ls -lnd $TESTDIR/test3.d | awk '{print $4}'`
|
MYGID=`\ls -lnd $TESTDIR/test3.d | awk '{print $4}'`
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
||||||
|
echo "Testing @includedir of an unquoted path"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
@includedir $TESTDIR/test3.d
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing @includedir of a double-quoted path"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
@includedir "$TESTDIR/test3.d"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #includedir of an unquoted path"
|
||||||
|
echo ""
|
||||||
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
#includedir $TESTDIR/test3.d
|
#includedir $TESTDIR/test3.d
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #includedir of a double-quoted path"
|
||||||
|
echo ""
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<-EOF
|
||||||
|
#includedir "$TESTDIR/test3.d"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
rm -rf "${parentdir}/test3.d"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ ASAN_OPTIONS=detect_leaks=0; export ASAN_OPTIONS
|
|||||||
|
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
./testsudoers -U 1 root id <<EOF
|
./testsudoers -U 1 root id <<EOF
|
||||||
#include $TESTDIR/test2.inc
|
@include $TESTDIR/test2.inc
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -19,13 +19,13 @@ exec 2>&1
|
|||||||
# Test world writable
|
# Test world writable
|
||||||
chmod 666 $TESTFILE
|
chmod 666 $TESTFILE
|
||||||
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
#include $TESTFILE
|
@include $TESTFILE
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Test group writable
|
# Test group writable
|
||||||
chmod 664 $TESTFILE
|
chmod 664 $TESTFILE
|
||||||
./testsudoers -U $MYUID -G -2 root id <<EOF
|
./testsudoers -U $MYUID -G -2 root id <<EOF
|
||||||
#include $TESTFILE
|
@include $TESTFILE
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
rm -f $TESTFILE
|
rm -f $TESTFILE
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
Testing @include without a newline
|
||||||
|
|
||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
||||||
|
|
||||||
|
Testing #include without a newline
|
||||||
|
|
||||||
Parses OK.
|
Parses OK.
|
||||||
|
|
||||||
Entries for user root:
|
Entries for user root:
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Test #include facility w/o a final newline.
|
# Test @include facility w/o a final newline.
|
||||||
# Same as test2.sh but missing the final newline.
|
# Same as test2.sh but missing the final newline.
|
||||||
#
|
#
|
||||||
|
|
||||||
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
||||||
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
||||||
|
echo "Testing @include without a newline"
|
||||||
|
echo ""
|
||||||
|
printf "@include $TESTDIR/test2.inc" | \
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing #include without a newline"
|
||||||
|
echo ""
|
||||||
printf "#include $TESTDIR/test2.inc" | \
|
printf "#include $TESTDIR/test2.inc" | \
|
||||||
./testsudoers -U $MYUID -G $MYGID root id
|
./testsudoers -U $MYUID -G $MYGID root id
|
||||||
|
|
||||||
|
10
plugins/sudoers/regress/testsudoers/test9.out.ok
Normal file
10
plugins/sudoers/regress/testsudoers/test9.out.ok
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Parses OK.
|
||||||
|
|
||||||
|
Entries for user root:
|
||||||
|
|
||||||
|
ALL = ALL
|
||||||
|
host matched
|
||||||
|
runas matched
|
||||||
|
cmnd allowed
|
||||||
|
|
||||||
|
Command allowed
|
13
plugins/sudoers/regress/testsudoers/test9.sh
Executable file
13
plugins/sudoers/regress/testsudoers/test9.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Test #include facility
|
||||||
|
#
|
||||||
|
|
||||||
|
MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
|
||||||
|
MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
|
||||||
|
exec 2>&1
|
||||||
|
./testsudoers -U $MYUID -G $MYGID root id <<EOF
|
||||||
|
#include $TESTDIR/test2.inc
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exit 0
|
@ -68,11 +68,12 @@
|
|||||||
* 45 sudo 1.8.15, added FOLLOW/NOFOLLOW tags as well as sudoedit_follow and sudoedit_checkdir Defaults.
|
* 45 sudo 1.8.15, added FOLLOW/NOFOLLOW tags as well as sudoedit_follow and sudoedit_checkdir Defaults.
|
||||||
* 46 sudo 1.8.20, added TIMEOUT, NOTBEFORE and NOTAFTER options.
|
* 46 sudo 1.8.20, added TIMEOUT, NOTBEFORE and NOTAFTER options.
|
||||||
* 47 sudo 1.9.0, Cmd_Alias treated as Cmnd_Alias, support for multiple digests per command and for ALL.
|
* 47 sudo 1.9.0, Cmd_Alias treated as Cmnd_Alias, support for multiple digests per command and for ALL.
|
||||||
|
* 48 sudo 1.9.1, @include and @includedir, include path escaping/quoting.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SUDOERS_VERSION_H
|
#ifndef SUDOERS_VERSION_H
|
||||||
#define SUDOERS_VERSION_H
|
#define SUDOERS_VERSION_H
|
||||||
|
|
||||||
#define SUDOERS_GRAMMAR_VERSION 47
|
#define SUDOERS_GRAMMAR_VERSION 48
|
||||||
|
|
||||||
#endif /* SUDOERS_VERSION_H */
|
#endif /* SUDOERS_VERSION_H */
|
||||||
|
@ -450,12 +450,14 @@ open_sudoers(const char *sudoers, bool doedit, bool *keepopen)
|
|||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char *sudoers_base;
|
const char *sudoers_base;
|
||||||
debug_decl(open_sudoers, SUDOERS_DEBUG_UTIL);
|
debug_decl(open_sudoers, SUDOERS_DEBUG_UTIL);
|
||||||
|
|
||||||
sudoers_base = strrchr(sudoers, '/');
|
sudoers_base = strrchr(sudoers, '/');
|
||||||
if (sudoers_base != NULL)
|
if (sudoers_base != NULL)
|
||||||
sudoers_base++;
|
sudoers_base++;
|
||||||
|
else
|
||||||
|
sudoers_base = sudoers;
|
||||||
|
|
||||||
switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
|
switch (sudo_secure_file(sudoers, sudoers_uid, sudoers_gid, &sb)) {
|
||||||
case SUDO_PATH_SECURE:
|
case SUDO_PATH_SECURE:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,8 +24,9 @@ bool fill_args(const char *, size_t, int);
|
|||||||
bool fill_cmnd(const char *, size_t);
|
bool fill_cmnd(const char *, size_t);
|
||||||
bool fill_txt(const char *, size_t, size_t);
|
bool fill_txt(const char *, size_t, size_t);
|
||||||
bool ipv6_valid(const char *s);
|
bool ipv6_valid(const char *s);
|
||||||
int sudoers_trace_print(const char *msg);
|
int sudoers_trace_print(const char *);
|
||||||
void sudoerserror(const char *);
|
void sudoerserror(const char *);
|
||||||
|
bool push_include(const char *, bool);
|
||||||
|
|
||||||
#ifndef FLEX_SCANNER
|
#ifndef FLEX_SCANNER
|
||||||
extern int (*trace_print)(const char *msg);
|
extern int (*trace_print)(const char *msg);
|
||||||
|
@ -64,9 +64,7 @@ static bool continued, sawspace;
|
|||||||
static int prev_state;
|
static int prev_state;
|
||||||
static int digest_type = -1;
|
static int digest_type = -1;
|
||||||
|
|
||||||
static bool push_include_int(char *, bool);
|
|
||||||
static bool pop_include(void);
|
static bool pop_include(void);
|
||||||
static char *parse_include_int(const char *, bool);
|
|
||||||
|
|
||||||
int (*trace_print)(const char *msg) = sudoers_trace_print;
|
int (*trace_print)(const char *msg) = sudoers_trace_print;
|
||||||
|
|
||||||
@ -76,11 +74,6 @@ int (*trace_print)(const char *msg) = sudoers_trace_print;
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ECHO ignore_result(fwrite(sudoerstext, sudoersleng, 1, sudoersout))
|
#define ECHO ignore_result(fwrite(sudoerstext, sudoersleng, 1, sudoersout))
|
||||||
|
|
||||||
#define parse_include(_p) (parse_include_int((_p), false))
|
|
||||||
#define parse_includedir(_p) (parse_include_int((_p), true))
|
|
||||||
#define push_include(_p) (push_include_int((_p), false))
|
|
||||||
#define push_includedir(_p) (push_include_int((_p), true))
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
HEX16 [0-9A-Fa-f]{1,4}
|
HEX16 [0-9A-Fa-f]{1,4}
|
||||||
@ -106,6 +99,7 @@ DEFVAR [a-z_]+
|
|||||||
%x INDEFS
|
%x INDEFS
|
||||||
%x INSTR
|
%x INSTR
|
||||||
%s WANTDIGEST
|
%s WANTDIGEST
|
||||||
|
%x GOTINC
|
||||||
|
|
||||||
%%
|
%%
|
||||||
<GOTDEFS>[[:blank:]]*,[[:blank:]]* {
|
<GOTDEFS>[[:blank:]]*,[[:blank:]]* {
|
||||||
@ -280,43 +274,54 @@ DEFVAR [a-z_]+
|
|||||||
yyless(sudoersleng);
|
yyless(sudoersleng);
|
||||||
} /* base64 digest */
|
} /* base64 digest */
|
||||||
|
|
||||||
<INITIAL>^#include[[:blank:]]+.*(\r\n|\n)? {
|
<INITIAL>@include {
|
||||||
char *path;
|
|
||||||
|
|
||||||
if (continued) {
|
if (continued) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
LEXRETURN(ERROR);
|
LEXRETURN(ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((path = parse_include(sudoerstext)) == NULL)
|
BEGIN GOTINC;
|
||||||
yyterminate();
|
LEXTRACE("INCLUDE ");
|
||||||
|
LEXRETURN(INCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
LEXTRACE("INCLUDE\n");
|
<INITIAL>@includedir {
|
||||||
|
if (continued) {
|
||||||
|
LEXTRACE("ERROR ");
|
||||||
|
LEXRETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Push current buffer and switch to include file */
|
BEGIN GOTINC;
|
||||||
if (!push_include(path))
|
LEXTRACE("INCLUDEDIR ");
|
||||||
yyterminate();
|
LEXRETURN(INCLUDEDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
<INITIAL>^#include[[:blank:]]+.*(\r\n|\n)? {
|
||||||
|
if (continued) {
|
||||||
|
LEXTRACE("ERROR ");
|
||||||
|
LEXRETURN(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only consume #include */
|
||||||
|
yyless(sizeof("#include") - 1);
|
||||||
|
|
||||||
|
BEGIN GOTINC;
|
||||||
|
LEXTRACE("INCLUDE ");
|
||||||
|
LEXRETURN(INCLUDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>^#includedir[[:blank:]]+.*(\r\n|\n)? {
|
<INITIAL>^#includedir[[:blank:]]+.*(\r\n|\n)? {
|
||||||
char *path;
|
|
||||||
|
|
||||||
if (continued) {
|
if (continued) {
|
||||||
LEXTRACE("ERROR ");
|
LEXTRACE("ERROR ");
|
||||||
LEXRETURN(ERROR);
|
LEXRETURN(ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((path = parse_includedir(sudoerstext)) == NULL)
|
/* only consume #includedir */
|
||||||
yyterminate();
|
yyless(sizeof("#includedir") - 1);
|
||||||
|
|
||||||
LEXTRACE("INCLUDEDIR\n");
|
BEGIN GOTINC;
|
||||||
|
LEXTRACE("INCLUDEDIR ");
|
||||||
/*
|
LEXRETURN(INCLUDEDIR);
|
||||||
* Push current buffer and switch to include file,
|
|
||||||
* ignoring missing or empty directories.
|
|
||||||
*/
|
|
||||||
if (!push_includedir(path))
|
|
||||||
yyterminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>^[[:blank:]]*Defaults([:@>\!][[:blank:]]*\!*\"?({ID}|{WORD}))? {
|
<INITIAL>^[[:blank:]]*Defaults([:@>\!][[:blank:]]*\!*\"?({ID}|{WORD}))? {
|
||||||
@ -638,7 +643,7 @@ sudoedit {
|
|||||||
}
|
}
|
||||||
} /* a pathname */
|
} /* a pathname */
|
||||||
|
|
||||||
<INITIAL,GOTDEFS>\" {
|
<INITIAL,GOTDEFS>\" {
|
||||||
LEXTRACE("BEGINSTR ");
|
LEXTRACE("BEGINSTR ");
|
||||||
sudoerslval.string = NULL;
|
sudoerslval.string = NULL;
|
||||||
prev_state = YY_START;
|
prev_state = YY_START;
|
||||||
@ -653,6 +658,24 @@ sudoedit {
|
|||||||
LEXRETURN(WORD);
|
LEXRETURN(WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<GOTINC>{
|
||||||
|
[^\"[:space:]]([^[:space:]]|\\[[:blank:]])* {
|
||||||
|
/* include file/directory */
|
||||||
|
if (!fill(sudoerstext, sudoersleng))
|
||||||
|
yyterminate();
|
||||||
|
BEGIN INITIAL;
|
||||||
|
LEXTRACE("WORD(6) ");
|
||||||
|
LEXRETURN(WORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
\" {
|
||||||
|
LEXTRACE("BEGINSTR ");
|
||||||
|
sudoerslval.string = NULL;
|
||||||
|
prev_state = INITIAL;
|
||||||
|
BEGIN INSTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
\( {
|
\( {
|
||||||
LEXTRACE("( ");
|
LEXTRACE("( ");
|
||||||
LEXRETURN('(');
|
LEXRETURN('(');
|
||||||
@ -914,18 +937,91 @@ init_lexer(void)
|
|||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand any embedded %h (host) escapes in the given path and makes
|
||||||
|
* a relative path fully-qualified based on the current sudoers file.
|
||||||
|
* Returns a reference-counted string.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
expand_include(const char *opath, size_t olen)
|
||||||
|
{
|
||||||
|
const char *cp, *ep;
|
||||||
|
char *path, *pp;
|
||||||
|
int dirlen = 0, len;
|
||||||
|
size_t shost_len = 0;
|
||||||
|
bool subst = false;
|
||||||
|
debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
|
||||||
|
|
||||||
|
/* Strip double quotes if present. */
|
||||||
|
if (*opath == '"') {
|
||||||
|
opath++;
|
||||||
|
olen -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Relative paths are located in the same dir as the sudoers file. */
|
||||||
|
if (*opath != '/') {
|
||||||
|
char *dirend = strrchr(sudoers, '/');
|
||||||
|
if (dirend != NULL)
|
||||||
|
dirlen = (int)(dirend - sudoers) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = olen;
|
||||||
|
for (cp = opath, ep = opath + olen; cp < ep; cp++) {
|
||||||
|
if (cp[0] == '%' && cp[1] == 'h') {
|
||||||
|
shost_len = strlen(user_shost);
|
||||||
|
len += shost_len - 2;
|
||||||
|
subst = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make a copy of the fully-qualified path and return it. */
|
||||||
|
path = pp = rcstr_alloc(len + dirlen);
|
||||||
|
if (path == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
sudoerserror(NULL);
|
||||||
|
debug_return_str(NULL);
|
||||||
|
}
|
||||||
|
if (dirlen) {
|
||||||
|
memcpy(path, sudoers, dirlen);
|
||||||
|
pp += dirlen;
|
||||||
|
}
|
||||||
|
if (subst) {
|
||||||
|
/* substitute for %h */
|
||||||
|
cp = opath;
|
||||||
|
while (cp < ep) {
|
||||||
|
if (cp[0] == '%' && cp[1] == 'h') {
|
||||||
|
memcpy(pp, user_shost, shost_len);
|
||||||
|
pp += shost_len;
|
||||||
|
cp += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*pp++ = *cp++;
|
||||||
|
}
|
||||||
|
*pp = '\0';
|
||||||
|
} else {
|
||||||
|
memcpy(pp, opath, len);
|
||||||
|
pp[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_return_str(path);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open an include file (or file from a directory), push the old
|
* Open an include file (or file from a directory), push the old
|
||||||
* sudoers file buffer and switch to the new one.
|
* sudoers file buffer and switch to the new one.
|
||||||
* A missing or insecure include dir is simply ignored.
|
* A missing or insecure include dir is simply ignored.
|
||||||
* Returns false on error, else true.
|
* Returns false on error, else true.
|
||||||
*/
|
*/
|
||||||
static bool
|
bool
|
||||||
push_include_int(char *path, bool isdir)
|
push_include(const char *opath, bool isdir)
|
||||||
{
|
{
|
||||||
struct path_list *pl;
|
struct path_list *pl;
|
||||||
|
char *path;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
debug_decl(push_include_int, SUDOERS_DEBUG_PARSER);
|
debug_decl(push_include, SUDOERS_DEBUG_PARSER);
|
||||||
|
|
||||||
|
if ((path = expand_include(opath, strlen(opath))) == NULL)
|
||||||
|
debug_return_bool(false);
|
||||||
|
|
||||||
/* push current state onto stack */
|
/* push current state onto stack */
|
||||||
if (idepth >= istacksize) {
|
if (idepth >= istacksize) {
|
||||||
@ -1065,72 +1161,6 @@ pop_include(void)
|
|||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
parse_include_int(const char *base, bool isdir)
|
|
||||||
{
|
|
||||||
const char *cp, *ep;
|
|
||||||
char *path, *pp;
|
|
||||||
int dirlen = 0, len = 0, subst = 0;
|
|
||||||
size_t shost_len = 0;
|
|
||||||
debug_decl(parse_include, SUDOERS_DEBUG_PARSER);
|
|
||||||
|
|
||||||
/* Pull out path from #include line. */
|
|
||||||
cp = base + (isdir ? sizeof("#includedir") : sizeof("#include"));
|
|
||||||
while (isblank((unsigned char) *cp))
|
|
||||||
cp++;
|
|
||||||
ep = cp;
|
|
||||||
while (*ep != '\0' && !isspace((unsigned char) *ep)) {
|
|
||||||
if (ep[0] == '%' && ep[1] == 'h') {
|
|
||||||
shost_len = strlen(user_shost);
|
|
||||||
len += shost_len - 2;
|
|
||||||
subst = 1;
|
|
||||||
}
|
|
||||||
ep++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Relative paths are located in the same dir as the sudoers file. */
|
|
||||||
if (*cp != '/') {
|
|
||||||
char *dirend = strrchr(sudoers, '/');
|
|
||||||
if (dirend != NULL)
|
|
||||||
dirlen = (int)(dirend - sudoers) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a copy of the fully-qualified path and return it. */
|
|
||||||
len += (int)(ep - cp);
|
|
||||||
path = pp = rcstr_alloc(len + dirlen);
|
|
||||||
if (path == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
sudoerserror(NULL);
|
|
||||||
debug_return_str(NULL);
|
|
||||||
}
|
|
||||||
if (dirlen) {
|
|
||||||
memcpy(path, sudoers, dirlen);
|
|
||||||
pp += dirlen;
|
|
||||||
}
|
|
||||||
if (subst) {
|
|
||||||
/* substitute for %h */
|
|
||||||
while (cp < ep) {
|
|
||||||
if (cp[0] == '%' && cp[1] == 'h') {
|
|
||||||
memcpy(pp, user_shost, shost_len);
|
|
||||||
pp += shost_len;
|
|
||||||
cp += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*pp++ = *cp++;
|
|
||||||
}
|
|
||||||
*pp = '\0';
|
|
||||||
} else {
|
|
||||||
memcpy(pp, cp, len);
|
|
||||||
pp[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push any excess characters (e.g. comment, newline) back to the lexer */
|
|
||||||
if (*ep != '\0')
|
|
||||||
yyless((int)(ep - base));
|
|
||||||
|
|
||||||
debug_return_str(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TRACELEXER
|
#ifdef TRACELEXER
|
||||||
int
|
int
|
||||||
sudoers_trace_print(const char *msg)
|
sudoers_trace_print(const char *msg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user