Add struct sudoers_parser_config and pass it to init_parser().

This struct contains parser configuration such as the sudoers file
uid/gid/mode and parse flags such as verbose, strict and recovery.
This commit is contained in:
Todd C. Miller
2023-05-08 17:03:31 -06:00
parent fb9d0d79a7
commit 9d7c30c5a8
15 changed files with 604 additions and 477 deletions

View File

@@ -770,7 +770,7 @@ parse_sudoers(const char *input_file, struct cvtsudoers_config *conf)
input_file = "stdin"; input_file = "stdin";
} else if ((sudoersin = fopen(input_file, "r")) == NULL) } else if ((sudoersin = fopen(input_file, "r")) == NULL)
sudo_fatal(U_("unable to open %s"), input_file); sudo_fatal(U_("unable to open %s"), input_file);
init_parser(input_file, NULL, false, 1); init_parser(input_file, NULL, NULL);
if (sudoersparse() && !parse_error) { if (sudoersparse() && !parse_error) {
sudo_warnx(U_("failed to parse %s file, unknown error"), input_file); sudo_warnx(U_("failed to parse %s file, unknown error"), input_file);
parse_error = true; parse_error = true;

View File

@@ -73,8 +73,10 @@ sudo_file_open(struct sudo_nss *nss)
handle = malloc(sizeof(*handle)); handle = malloc(sizeof(*handle));
if (handle != NULL) { if (handle != NULL) {
handle->fp = open_sudoers(policy_path_sudoers(), &outfile, false, NULL); const char *path_sudoers = policy_path_sudoers();
handle->fp = open_sudoers(path_sudoers, &outfile, false, NULL);
if (handle->fp != NULL) { if (handle->fp != NULL) {
init_parser(NULL, path_sudoers, policy_sudoers_conf());
init_parse_tree(&handle->parse_tree, NULL, NULL, nss); init_parse_tree(&handle->parse_tree, NULL, NULL, nss);
if (outfile != NULL) { if (outfile != NULL) {
/* Update path to open sudoers file. */ /* Update path to open sudoers file. */
@@ -108,7 +110,7 @@ sudo_file_parse(const struct sudo_nss *nss)
sudoersin = handle->fp; sudoersin = handle->fp;
error = sudoersparse(); error = sudoersparse();
if (error || (parse_error && !sudoers_recovery)) { if (error || (parse_error && !sudoers_error_recovery())) {
/* unrecoverable error */ /* unrecoverable error */
debug_return_ptr(NULL); debug_return_ptr(NULL);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -48,15 +48,15 @@
/* /*
* Globals * Globals
*/ */
bool sudoers_recovery = true;
bool sudoers_strict = false;
bool parse_error = false; bool parse_error = false;
static struct sudoers_parser_config parser_conf =
SUDOERS_PARSER_CONFIG_INITIALIZER;
/* Optional logging function for parse errors. */ /* Optional logging function for parse errors. */
sudoers_logger_t sudoers_error_hook; sudoers_logger_t sudoers_error_hook;
static int alias_line, alias_column; static int alias_line, alias_column;
static int sudoers_verbose = 1;
#ifdef NO_LEAKS #ifdef NO_LEAKS
static struct parser_leak_list parser_leak_list = static struct parser_leak_list parser_leak_list =
@@ -216,17 +216,19 @@ entry : '\n' {
yyerrok; yyerrok;
} }
| include { | include {
const bool success = push_include($1, sudoers_verbose); const bool success = push_include($1,
parser_conf.verbose);
parser_leak_remove(LEAK_PTR, $1); parser_leak_remove(LEAK_PTR, $1);
free($1); free($1);
if (!success && !sudoers_recovery) if (!success && !parser_conf.recovery)
YYERROR; YYERROR;
} }
| includedir { | includedir {
const bool success = push_includedir($1, sudoers_verbose); const bool success = push_includedir($1,
parser_conf.verbose);
parser_leak_remove(LEAK_PTR, $1); parser_leak_remove(LEAK_PTR, $1);
free($1); free($1);
if (!success && !sudoers_recovery) if (!success && !parser_conf.recovery)
YYERROR; YYERROR;
} }
| userlist privileges '\n' { | userlist privileges '\n' {
@@ -1216,7 +1218,7 @@ sudoerserrorf(const char *fmt, ...)
sudoers_error_hook(sudoers, this_lineno, column, fmt, ap); sudoers_error_hook(sudoers, this_lineno, column, fmt, ap);
va_end(ap); va_end(ap);
} }
if (sudoers_verbose > 0 && fmt != NULL) { if (parser_conf.verbose > 0 && fmt != NULL) {
LEXTRACE("<*> "); LEXTRACE("<*> ");
#ifndef TRACELEXER #ifndef TRACELEXER
if (trace_print == NULL || trace_print == sudoers_trace_print) { if (trace_print == NULL || trace_print == sudoers_trace_print) {
@@ -1782,7 +1784,8 @@ free_parse_tree(struct sudoers_parse_tree *parse_tree)
* the current sudoers file to path. * the current sudoers file to path.
*/ */
bool bool
init_parser(const char *file, const char *path, bool strict, int verbose) init_parser(const char *file, const char *path,
const struct sudoers_parser_config *conf)
{ {
bool ret = true; bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER); debug_decl(init_parser, SUDOERS_DEBUG_PARSER);
@@ -1811,9 +1814,14 @@ init_parser(const char *file, const char *path, bool strict, int verbose)
sudoers_search_path = NULL; sudoers_search_path = NULL;
} }
if (conf != NULL) {
parser_conf = *conf;
} else {
const struct sudoers_parser_config def_conf =
SUDOERS_PARSER_CONFIG_INITIALIZER;
parser_conf = def_conf;
}
parse_error = false; parse_error = false;
sudoers_strict = strict;
sudoers_verbose = verbose;
debug_return_bool(ret); debug_return_bool(ret);
} }
@@ -1821,7 +1829,7 @@ init_parser(const char *file, const char *path, bool strict, int verbose)
bool bool
reset_parser(void) reset_parser(void)
{ {
return init_parser(NULL, NULL, false, 1); return init_parser(NULL, NULL, NULL);
} }
/* /*
@@ -1848,6 +1856,36 @@ init_options(struct command_options *opts)
#endif #endif
} }
uid_t
sudoers_file_uid(void)
{
return parser_conf.sudoers_uid;
}
gid_t
sudoers_file_gid(void)
{
return parser_conf.sudoers_gid;
}
mode_t
sudoers_file_mode(void)
{
return parser_conf.sudoers_mode;
}
bool
sudoers_error_recovery(void)
{
return parser_conf.recovery;
}
bool
sudoers_strict(void)
{
return parser_conf.strict;
}
bool bool
parser_leak_add(enum parser_leak_types type, void *v) parser_leak_add(enum parser_leak_types type, void *v)
{ {

View File

@@ -322,6 +322,26 @@ struct cmnd_info {
bool intercepted; bool intercepted;
}; };
/*
* Parse configuration settings, passed to init_parser().
*/
struct sudoers_parser_config {
bool strict;
bool recovery;
int verbose;
mode_t sudoers_mode;
uid_t sudoers_uid;
gid_t sudoers_gid;
};
#define SUDOERS_PARSER_CONFIG_INITIALIZER { \
false, /* strict */ \
true, /* recovery */ \
1, /* verbose level 1 */ \
SUDOERS_MODE, \
SUDOERS_UID, \
SUDOERS_GID \
}
/* /*
* The parser passes pointers to data structures that are not stored anywhere. * The parser passes pointers to data structures that are not stored anywhere.
* We add them to the leak list at allocation time and remove them from * We add them to the leak list at allocation time and remove them from
@@ -372,7 +392,7 @@ int check_aliases(struct sudoers_parse_tree *parse_tree, bool strict, bool quiet
/* gram.y */ /* gram.y */
extern struct sudoers_parse_tree parsed_policy; extern struct sudoers_parse_tree parsed_policy;
extern bool (*sudoers_error_hook)(const char *file, int line, int column, const char *fmt, va_list args); extern bool (*sudoers_error_hook)(const char *file, int line, int column, const char *fmt, va_list args);
bool init_parser(const char *file, const char *path, bool strict, int verbose); bool init_parser(const char *file, const char *path, const struct sudoers_parser_config *conf);
bool reset_parser(void); bool reset_parser(void);
void free_member(struct member *m); void free_member(struct member *m);
void free_members(struct member_list *members); void free_members(struct member_list *members);

View File

@@ -1,7 +1,7 @@
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 2010-2022 Todd C. Miller <Todd.Miller@sudo.ws> * Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +50,7 @@ struct sudoers_exec_args {
char ***info; char ***info;
}; };
static struct sudoers_parser_config parser_conf = SUDOERS_PARSER_CONFIG_INITIALIZER;
static unsigned int sudo_version; static unsigned int sudo_version;
static const char *interfaces_string; static const char *interfaces_string;
sudo_conv_t sudo_conv; sudo_conv_t sudo_conv;
@@ -95,12 +96,12 @@ parse_bool(const char *line, int varlen, int *flags, int fval)
int int
sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults) sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
{ {
struct sudoers_open_info *info = v;
const char *p, *errstr, *groups = NULL; const char *p, *errstr, *groups = NULL;
struct sudoers_open_info *info = v;
int flags = MODE_UPDATE_TICKET;
const char *remhost = NULL; const char *remhost = NULL;
unsigned char uuid[16]; unsigned char uuid[16];
char * const *cur; char * const *cur;
int flags = MODE_UPDATE_TICKET;
debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN); debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN);
#define MATCHES(s, v) \ #define MATCHES(s, v) \
@@ -124,9 +125,6 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
} }
/* Parse sudo.conf plugin args. */ /* Parse sudo.conf plugin args. */
sudoers_mode = SUDOERS_MODE;
sudoers_uid = SUDOERS_UID;
sudoers_gid = SUDOERS_GID;
if (info->plugin_args != NULL) { if (info->plugin_args != NULL) {
for (cur = info->plugin_args; *cur != NULL; cur++) { for (cur = info->plugin_args; *cur != NULL; cur++) {
if (MATCHES(*cur, "error_recovery=")) { if (MATCHES(*cur, "error_recovery=")) {
@@ -134,7 +132,7 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
if (val == -1) { if (val == -1) {
INVALID("error_recovery="); /* Not a fatal error. */ INVALID("error_recovery="); /* Not a fatal error. */
} else { } else {
sudoers_recovery = val; parser_conf.recovery = val;
} }
continue; continue;
} }
@@ -145,7 +143,7 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
} }
if (MATCHES(*cur, "sudoers_uid=")) { if (MATCHES(*cur, "sudoers_uid=")) {
p = *cur + sizeof("sudoers_uid=") - 1; p = *cur + sizeof("sudoers_uid=") - 1;
sudoers_uid = (uid_t) sudo_strtoid(p, &errstr); parser_conf.sudoers_uid = (uid_t)sudo_strtoid(p, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_warnx(U_("%s: %s"), *cur, U_(errstr)); sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
goto bad; goto bad;
@@ -154,7 +152,7 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
} }
if (MATCHES(*cur, "sudoers_gid=")) { if (MATCHES(*cur, "sudoers_gid=")) {
p = *cur + sizeof("sudoers_gid=") - 1; p = *cur + sizeof("sudoers_gid=") - 1;
sudoers_gid = (gid_t) sudo_strtoid(p, &errstr); parser_conf.sudoers_gid = (gid_t)sudo_strtoid(p, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_warnx(U_("%s: %s"), *cur, U_(errstr)); sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
goto bad; goto bad;
@@ -163,7 +161,7 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
} }
if (MATCHES(*cur, "sudoers_mode=")) { if (MATCHES(*cur, "sudoers_mode=")) {
p = *cur + sizeof("sudoers_mode=") - 1; p = *cur + sizeof("sudoers_mode=") - 1;
sudoers_mode = sudo_strtomode(p, &errstr); parser_conf.sudoers_mode = sudo_strtomode(p, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_warnx(U_("%s: %s"), *cur, U_(errstr)); sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
goto bad; goto bad;
@@ -625,6 +623,13 @@ bad:
debug_return_int(MODE_ERROR); debug_return_int(MODE_ERROR);
} }
/* Return the policy's struct sudoers_parser_config. */
const struct sudoers_parser_config *
policy_sudoers_conf(void)
{
return &parser_conf;
}
/* Return the path to the sudoers file, which may be set in the plugin args. */ /* Return the path to the sudoers file, which may be set in the plugin args. */
const char * const char *
policy_path_sudoers(void) policy_path_sudoers(void)

View File

@@ -312,7 +312,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
/* Initialize defaults and parse sudoers. */ /* Initialize defaults and parse sudoers. */
init_defaults(); init_defaults();
init_parser("sudoers", NULL, true, 1); init_parser("sudoers", NULL, NULL);
sudoersrestart(fp); sudoersrestart(fp);
sudoersparse(); sudoersparse();
reparent_parse_tree(&parse_tree); reparent_parse_tree(&parse_tree);

View File

@@ -295,7 +295,11 @@ set_perms(int perm)
} }
break; break;
case PERM_SUDOERS: case PERM_SUDOERS: {
const uid_t sudoers_uid = sudoers_file_uid();
const gid_t sudoers_gid = sudoers_file_gid();
const mode_t sudoers_mode = sudoers_file_mode();
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist); sudo_gidlist_addref(state->gidlist);
@@ -334,6 +338,7 @@ set_perms(int perm)
goto bad; goto bad;
} }
break; break;
}
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
@@ -619,7 +624,11 @@ set_perms(int perm)
} }
break; break;
case PERM_SUDOERS: case PERM_SUDOERS: {
const uid_t sudoers_uid = sudoers_file_uid();
const gid_t sudoers_gid = sudoers_file_gid();
const mode_t sudoers_mode = sudoers_file_mode();
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist); sudo_gidlist_addref(state->gidlist);
@@ -667,6 +676,7 @@ set_perms(int perm)
} }
} }
break; break;
}
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
@@ -1012,7 +1022,11 @@ set_perms(int perm)
} }
break; break;
case PERM_SUDOERS: case PERM_SUDOERS: {
const uid_t sudoers_uid = sudoers_file_uid();
const gid_t sudoers_gid = sudoers_file_gid();
const mode_t sudoers_mode = sudoers_file_mode();
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist); sudo_gidlist_addref(state->gidlist);
@@ -1047,6 +1061,7 @@ set_perms(int perm)
goto bad; goto bad;
} }
break; break;
}
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
@@ -1321,7 +1336,11 @@ set_perms(int perm)
} }
break; break;
case PERM_SUDOERS: case PERM_SUDOERS: {
const uid_t sudoers_uid = sudoers_file_uid();
const gid_t sudoers_gid = sudoers_file_gid();
const mode_t sudoers_mode = sudoers_file_mode();
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist); sudo_gidlist_addref(state->gidlist);
@@ -1355,6 +1374,7 @@ set_perms(int perm)
goto bad; goto bad;
} }
break; break;
}
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->gidlist = ostate->gidlist; state->gidlist = ostate->gidlist;

View File

@@ -249,7 +249,6 @@ sudoers_init(void *info, sudoers_logger_t logger, char * const envp[])
} }
/* Open and parse sudoers, set global defaults. */ /* Open and parse sudoers, set global defaults. */
reset_parser();
TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) { TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
if (nss->open(nss) == -1 || (nss->parse_tree = nss->parse(nss)) == NULL) { if (nss->open(nss) == -1 || (nss->parse_tree = nss->parse(nss)) == NULL) {
TAILQ_REMOVE(snl, nss, entries); TAILQ_REMOVE(snl, nss, entries);
@@ -1300,7 +1299,8 @@ open_sudoers(const char *path, char **outfile, bool doedit, bool *keepopen)
debug_decl(open_sudoers, SUDOERS_DEBUG_PLUGIN); debug_decl(open_sudoers, SUDOERS_DEBUG_PLUGIN);
fd = sudo_open_conf_path(path, fname, sizeof(fname), open_file); fd = sudo_open_conf_path(path, fname, sizeof(fname), open_file);
error = sudo_secure_fd(fd, S_IFREG, sudoers_uid, sudoers_gid, &sb); error = sudo_secure_fd(fd, S_IFREG, sudoers_file_uid(), sudoers_file_gid(),
&sb);
switch (error) { switch (error) {
case SUDO_PATH_SECURE: case SUDO_PATH_SECURE:
/* /*
@@ -1340,7 +1340,7 @@ open_sudoers(const char *path, char **outfile, bool doedit, bool *keepopen)
case SUDO_PATH_WRONG_OWNER: case SUDO_PATH_WRONG_OWNER:
log_warningx(SLOG_PARSE_ERROR, log_warningx(SLOG_PARSE_ERROR,
N_("%s is owned by uid %u, should be %u"), fname, N_("%s is owned by uid %u, should be %u"), fname,
(unsigned int)sb.st_uid, (unsigned int)sudoers_uid); (unsigned int)sb.st_uid, (unsigned int)sudoers_file_uid());
break; break;
case SUDO_PATH_WORLD_WRITABLE: case SUDO_PATH_WORLD_WRITABLE:
log_warningx(SLOG_PARSE_ERROR, N_("%s is world writable"), fname); log_warningx(SLOG_PARSE_ERROR, N_("%s is world writable"), fname);
@@ -1348,7 +1348,7 @@ open_sudoers(const char *path, char **outfile, bool doedit, bool *keepopen)
case SUDO_PATH_GROUP_WRITABLE: case SUDO_PATH_GROUP_WRITABLE:
log_warningx(SLOG_PARSE_ERROR, log_warningx(SLOG_PARSE_ERROR,
N_("%s is owned by gid %u, should be %u"), fname, N_("%s is owned by gid %u, should be %u"), fname,
(unsigned int)sb.st_gid, (unsigned int)sudoers_gid); (unsigned int)sb.st_gid, (unsigned int)sudoers_file_gid());
break; break;
default: default:
sudo_warnx("%s: internal error, unexpected error %d", __func__, error); sudo_warnx("%s: internal error, unexpected error %d", __func__, error);

View File

@@ -324,9 +324,12 @@ int pam_prep_user(struct passwd *);
/* gram.y */ /* gram.y */
int sudoersparse(void); int sudoersparse(void);
uid_t sudoers_file_uid(void);
gid_t sudoers_file_gid(void);
mode_t sudoers_file_mode(void);
bool sudoers_error_recovery(void);
bool sudoers_strict(void);
extern bool parse_error; extern bool parse_error;
extern bool sudoers_recovery;
extern bool sudoers_strict;
/* toke.l */ /* toke.l */
YY_DECL; YY_DECL;
@@ -334,9 +337,6 @@ void sudoersrestart(FILE *);
extern FILE *sudoersin; extern FILE *sudoersin;
extern char *sudoers; extern char *sudoers;
extern char *sudoers_search_path; extern char *sudoers_search_path;
extern mode_t sudoers_mode;
extern uid_t sudoers_uid;
extern gid_t sudoers_gid;
extern int sudolineno; extern int sudolineno;
/* defaults.c */ /* defaults.c */
@@ -447,6 +447,7 @@ void sudoers_debug_deregister(void);
/* policy.c */ /* policy.c */
int sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults); int sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults);
bool sudoers_policy_store_result(bool accepted, char *argv[], char *envp[], mode_t cmnd_umask, char *iolog_path, void *v); bool sudoers_policy_store_result(bool accepted, char *argv[], char *envp[], mode_t cmnd_umask, char *iolog_path, void *v);
const struct sudoers_parser_config *policy_sudoers_conf(void);
const char *policy_path_sudoers(void); const char *policy_path_sudoers(void);
const char *policy_path_ldap_conf(void); const char *policy_path_ldap_conf(void);
const char *policy_path_ldap_secret(void); const char *policy_path_ldap_secret(void);

View File

@@ -97,6 +97,7 @@ sudo_dso_public int main(int argc, char *argv[]);
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct sudoers_parser_config parser_conf = SUDOERS_PARSER_CONFIG_INITIALIZER;
enum sudoers_formats input_format = format_sudoers; enum sudoers_formats input_format = format_sudoers;
struct cmndspec *cs; struct cmndspec *cs;
struct privilege *priv; struct privilege *priv;
@@ -106,6 +107,7 @@ main(int argc, char *argv[])
int match, host_match, runas_match, cmnd_match; int match, host_match, runas_match, cmnd_match;
int ch, dflag, exitcode = EXIT_FAILURE; int ch, dflag, exitcode = EXIT_FAILURE;
struct sudo_lbuf lbuf; struct sudo_lbuf lbuf;
id_t id;
debug_decl(main, SUDOERS_DEBUG_MAIN); debug_decl(main, SUDOERS_DEBUG_MAIN);
#if defined(SUDO_DEVEL) && defined(__OpenBSD__) #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
@@ -140,9 +142,10 @@ main(int argc, char *argv[])
dflag = 1; dflag = 1;
break; break;
case 'G': case 'G':
sudoers_gid = (gid_t)sudo_strtoid(optarg, &errstr); id = sudo_strtoid(optarg, &errstr);
if (errstr != NULL) if (errstr != NULL)
sudo_fatalx("group-ID %s: %s", optarg, errstr); sudo_fatalx("group-ID %s: %s", optarg, errstr);
parser_conf.sudoers_gid = (gid_t)id;
break; break;
case 'g': case 'g':
runas_group = optarg; runas_group = optarg;
@@ -171,9 +174,10 @@ main(int argc, char *argv[])
trace_print = testsudoers_error; trace_print = testsudoers_error;
break; break;
case 'U': case 'U':
sudoers_uid = (uid_t)sudo_strtoid(optarg, &errstr); id = sudo_strtoid(optarg, &errstr);
if (errstr != NULL) if (errstr != NULL)
sudo_fatalx("user-ID %s: %s", optarg, errstr); sudo_fatalx("user-ID %s: %s", optarg, errstr);
parser_conf.sudoers_uid = (uid_t)id;
break; break;
case 'u': case 'u':
runas_user = optarg; runas_user = optarg;
@@ -274,7 +278,9 @@ main(int argc, char *argv[])
} }
/* Initialize the parser and set sudoers filename to "sudoers". */ /* Initialize the parser and set sudoers filename to "sudoers". */
init_parser("sudoers", NULL, true, 2); parser_conf.strict = true;
parser_conf.verbose = 2;
init_parser("sudoers", NULL, &parser_conf);
/* /*
* Set runas passwd/group entries based on command line or sudoers. * Set runas passwd/group entries based on command line or sudoers.
@@ -452,7 +458,8 @@ open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
/* Report errors using the basename for consistent test output. */ /* Report errors using the basename for consistent test output. */
base = sudo_basename(file); base = sudo_basename(file);
fd = sudo_secure_open_file(file, sudoers_uid, sudoers_gid, &sb, &error); fd = sudo_secure_open_file(file, sudoers_file_uid(), sudoers_file_gid(),
&sb, &error);
if (fd != -1) { if (fd != -1) {
if ((fp = fdopen(fd, "r")) == NULL) { if ((fp = fdopen(fd, "r")) == NULL) {
sudo_warn("unable to open %s", base); sudo_warn("unable to open %s", base);
@@ -468,14 +475,14 @@ open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
break; break;
case SUDO_PATH_WRONG_OWNER: case SUDO_PATH_WRONG_OWNER:
sudo_warnx("%s should be owned by uid %u", sudo_warnx("%s should be owned by uid %u",
base, (unsigned int) sudoers_uid); base, (unsigned int) sudoers_file_uid());
break; break;
case SUDO_PATH_WORLD_WRITABLE: case SUDO_PATH_WORLD_WRITABLE:
sudo_warnx("%s is world writable", base); sudo_warnx("%s is world writable", base);
break; break;
case SUDO_PATH_GROUP_WRITABLE: case SUDO_PATH_GROUP_WRITABLE:
sudo_warnx("%s should be owned by gid %u", sudo_warnx("%s should be owned by gid %u",
base, (unsigned int) sudoers_gid); base, (unsigned int) sudoers_file_gid());
break; break;
default: default:
sudo_warnx("%s: internal error, unexpected error %d", sudo_warnx("%s: internal error, unexpected error %d",

View File

@@ -3036,7 +3036,7 @@ char *sudoerstext;
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 1996, 1998-2005, 2007-2022 * Copyright (c) 1996, 1998-2005, 2007-2023
* Todd C. Miller <Todd.Miller@sudo.ws> * Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@@ -3093,11 +3093,6 @@ char *sudoers_search_path; /* colon-separated path of sudoers files. */
const char *sudoers_errstr; /* description of last error from lexer. */ const char *sudoers_errstr; /* description of last error from lexer. */
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */ struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
/* Default sudoers mode and owner (may be set via sudo.conf) */
mode_t sudoers_mode = SUDOERS_MODE;
uid_t sudoers_uid = SUDOERS_UID;
gid_t sudoers_gid = SUDOERS_GID;
static bool continued, sawspace; static bool continued, sawspace;
static int prev_state; static int prev_state;
static int digest_type = -1; static int digest_type = -1;
@@ -3135,7 +3130,7 @@ int (*trace_print)(const char *msg) = sudoers_trace_print;
#line 3133 "toke.c" #line 3128 "toke.c"
#define INITIAL 0 #define INITIAL 0
#define GOTDEFS 1 #define GOTDEFS 1
@@ -3356,9 +3351,9 @@ YY_DECL
} }
{ {
#line 124 "toke.l" #line 119 "toke.l"
#line 3356 "toke.c" #line 3351 "toke.c"
while ( 1 ) /* loops until end-of-file is reached */ while ( 1 ) /* loops until end-of-file is reached */
{ {
@@ -3418,7 +3413,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1: case 1:
YY_RULE_SETUP YY_RULE_SETUP
#line 125 "toke.l" #line 120 "toke.l"
{ {
LEXTRACE(", "); LEXTRACE(", ");
return ','; return ',';
@@ -3426,12 +3421,12 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 2: case 2:
YY_RULE_SETUP YY_RULE_SETUP
#line 130 "toke.l" #line 125 "toke.l"
BEGIN STARTDEFS; BEGIN STARTDEFS;
YY_BREAK YY_BREAK
case 3: case 3:
YY_RULE_SETUP YY_RULE_SETUP
#line 132 "toke.l" #line 127 "toke.l"
{ {
BEGIN INDEFS; BEGIN INDEFS;
LEXTRACE("DEFVAR "); LEXTRACE("DEFVAR ");
@@ -3443,7 +3438,7 @@ YY_RULE_SETUP
case 4: case 4:
YY_RULE_SETUP YY_RULE_SETUP
#line 141 "toke.l" #line 136 "toke.l"
{ {
BEGIN STARTDEFS; BEGIN STARTDEFS;
LEXTRACE(", "); LEXTRACE(", ");
@@ -3452,7 +3447,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 5: case 5:
YY_RULE_SETUP YY_RULE_SETUP
#line 147 "toke.l" #line 142 "toke.l"
{ {
LEXTRACE("= "); LEXTRACE("= ");
return '='; return '=';
@@ -3460,7 +3455,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 6: case 6:
YY_RULE_SETUP YY_RULE_SETUP
#line 152 "toke.l" #line 147 "toke.l"
{ {
LEXTRACE("+= "); LEXTRACE("+= ");
return '+'; return '+';
@@ -3468,7 +3463,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 7: case 7:
YY_RULE_SETUP YY_RULE_SETUP
#line 157 "toke.l" #line 152 "toke.l"
{ {
LEXTRACE("-= "); LEXTRACE("-= ");
return '-'; return '-';
@@ -3476,7 +3471,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 8: case 8:
YY_RULE_SETUP YY_RULE_SETUP
#line 162 "toke.l" #line 157 "toke.l"
{ {
LEXTRACE("BEGINSTR "); LEXTRACE("BEGINSTR ");
sudoerslval.string = NULL; sudoerslval.string = NULL;
@@ -3486,7 +3481,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 9: case 9:
YY_RULE_SETUP YY_RULE_SETUP
#line 169 "toke.l" #line 164 "toke.l"
{ {
LEXTRACE("WORD(2) "); LEXTRACE("WORD(2) ");
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -3499,7 +3494,7 @@ YY_RULE_SETUP
case 10: case 10:
/* rule 10 can match eol */ /* rule 10 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 178 "toke.l" #line 173 "toke.l"
{ {
/* Line continuation char followed by newline. */ /* Line continuation char followed by newline. */
sudolineno++; sudolineno++;
@@ -3508,7 +3503,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 11: case 11:
YY_RULE_SETUP YY_RULE_SETUP
#line 184 "toke.l" #line 179 "toke.l"
{ {
LEXTRACE("ENDSTR "); LEXTRACE("ENDSTR ");
BEGIN prev_state; BEGIN prev_state;
@@ -3550,7 +3545,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 12: case 12:
YY_RULE_SETUP YY_RULE_SETUP
#line 223 "toke.l" #line 218 "toke.l"
{ {
LEXTRACE("BACKSLASH "); LEXTRACE("BACKSLASH ");
if (!append(sudoerstext, sudoersleng)) if (!append(sudoerstext, sudoersleng))
@@ -3559,7 +3554,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 13: case 13:
YY_RULE_SETUP YY_RULE_SETUP
#line 229 "toke.l" #line 224 "toke.l"
{ {
LEXTRACE("STRBODY "); LEXTRACE("STRBODY ");
if (!append(sudoerstext, sudoersleng)) if (!append(sudoerstext, sudoersleng))
@@ -3570,7 +3565,7 @@ YY_RULE_SETUP
case 14: case 14:
YY_RULE_SETUP YY_RULE_SETUP
#line 237 "toke.l" #line 232 "toke.l"
{ {
/* quoted fnmatch glob char, pass verbatim */ /* quoted fnmatch glob char, pass verbatim */
LEXTRACE("QUOTEDCHAR "); LEXTRACE("QUOTEDCHAR ");
@@ -3581,7 +3576,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 15: case 15:
YY_RULE_SETUP YY_RULE_SETUP
#line 245 "toke.l" #line 240 "toke.l"
{ {
/* quoted sudoers special char, strip backslash */ /* quoted sudoers special char, strip backslash */
LEXTRACE("QUOTEDCHAR "); LEXTRACE("QUOTEDCHAR ");
@@ -3593,7 +3588,7 @@ YY_RULE_SETUP
case 16: case 16:
/* rule 16 can match eol */ /* rule 16 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 253 "toke.l" #line 248 "toke.l"
{ {
BEGIN INITIAL; BEGIN INITIAL;
sudoersless(0); sudoersless(0);
@@ -3603,7 +3598,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 17: case 17:
YY_RULE_SETUP YY_RULE_SETUP
#line 260 "toke.l" #line 255 "toke.l"
{ {
if (sudoerslval.command.args == NULL && sudoerstext[0] == '^') { if (sudoerslval.command.args == NULL && sudoerstext[0] == '^') {
LEXTRACE("ARG REGEX "); LEXTRACE("ARG REGEX ");
@@ -3622,7 +3617,7 @@ YY_RULE_SETUP
case 18: case 18:
YY_RULE_SETUP YY_RULE_SETUP
#line 276 "toke.l" #line 271 "toke.l"
{ {
/* quoted character, pass verbatim */ /* quoted character, pass verbatim */
LEXTRACE("QUOTEDCHAR "); LEXTRACE("QUOTEDCHAR ");
@@ -3633,7 +3628,7 @@ YY_RULE_SETUP
case 19: case 19:
/* rule 19 can match eol */ /* rule 19 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 283 "toke.l" #line 278 "toke.l"
{ {
/* Let the parser attempt to recover. */ /* Let the parser attempt to recover. */
sudoersless(0); sudoersless(0);
@@ -3647,13 +3642,13 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 20: case 20:
YY_RULE_SETUP YY_RULE_SETUP
#line 294 "toke.l" #line 289 "toke.l"
{ {
if (!fill_args("$", 1, false)) if (!fill_args("$", 1, false))
yyterminate(); yyterminate();
BEGIN INITIAL; BEGIN INITIAL;
continued = false; continued = false;
if (sudoers_strict) { if (sudoers_strict()) {
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) { if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
LEXTRACE("ERROR "); LEXTRACE("ERROR ");
return ERROR; return ERROR;
@@ -3664,7 +3659,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 21: case 21:
YY_RULE_SETUP YY_RULE_SETUP
#line 308 "toke.l" #line 303 "toke.l"
{ {
if (continued) { if (continued) {
/* remove whitespace after line continuation */ /* remove whitespace after line continuation */
@@ -3683,7 +3678,7 @@ YY_RULE_SETUP
case 22: case 22:
YY_RULE_SETUP YY_RULE_SETUP
#line 324 "toke.l" #line 319 "toke.l"
{ {
/* Only return DIGEST if the length is correct. */ /* Only return DIGEST if the length is correct. */
yy_size_t digest_len = yy_size_t digest_len =
@@ -3701,7 +3696,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 23: case 23:
YY_RULE_SETUP YY_RULE_SETUP
#line 339 "toke.l" #line 334 "toke.l"
{ {
/* Only return DIGEST if the length is correct. */ /* Only return DIGEST if the length is correct. */
yy_size_t len, digest_len = yy_size_t len, digest_len =
@@ -3726,7 +3721,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 24: case 24:
YY_RULE_SETUP YY_RULE_SETUP
#line 361 "toke.l" #line 356 "toke.l"
{ {
if (continued) { if (continued) {
sudoers_errstr = N_("invalid line continuation"); sudoers_errstr = N_("invalid line continuation");
@@ -3741,7 +3736,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 25: case 25:
YY_RULE_SETUP YY_RULE_SETUP
#line 373 "toke.l" #line 368 "toke.l"
{ {
if (continued) { if (continued) {
sudoers_errstr = N_("invalid line continuation"); sudoers_errstr = N_("invalid line continuation");
@@ -3757,7 +3752,7 @@ YY_RULE_SETUP
case 26: case 26:
/* rule 26 can match eol */ /* rule 26 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 385 "toke.l" #line 380 "toke.l"
{ {
if (continued) { if (continued) {
sudoers_errstr = N_("invalid line continuation"); sudoers_errstr = N_("invalid line continuation");
@@ -3777,7 +3772,7 @@ YY_RULE_SETUP
case 27: case 27:
/* rule 27 can match eol */ /* rule 27 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 401 "toke.l" #line 396 "toke.l"
{ {
if (continued) { if (continued) {
sudoers_errstr = N_("invalid line continuation"); sudoers_errstr = N_("invalid line continuation");
@@ -3796,7 +3791,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 28: case 28:
YY_RULE_SETUP YY_RULE_SETUP
#line 417 "toke.l" #line 412 "toke.l"
{ {
char deftype; char deftype;
int n; int n;
@@ -3840,7 +3835,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 29: case 29:
YY_RULE_SETUP YY_RULE_SETUP
#line 458 "toke.l" #line 453 "toke.l"
{ {
int n; int n;
@@ -3870,7 +3865,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 30: case 30:
YY_RULE_SETUP YY_RULE_SETUP
#line 485 "toke.l" #line 480 "toke.l"
{ {
/* cmnd does not require passwd for this user */ /* cmnd does not require passwd for this user */
LEXTRACE("NOPASSWD "); LEXTRACE("NOPASSWD ");
@@ -3879,7 +3874,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 31: case 31:
YY_RULE_SETUP YY_RULE_SETUP
#line 491 "toke.l" #line 486 "toke.l"
{ {
/* cmnd requires passwd for this user */ /* cmnd requires passwd for this user */
LEXTRACE("PASSWD "); LEXTRACE("PASSWD ");
@@ -3888,7 +3883,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 32: case 32:
YY_RULE_SETUP YY_RULE_SETUP
#line 497 "toke.l" #line 492 "toke.l"
{ {
LEXTRACE("NOEXEC "); LEXTRACE("NOEXEC ");
return NOEXEC; return NOEXEC;
@@ -3896,7 +3891,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 33: case 33:
YY_RULE_SETUP YY_RULE_SETUP
#line 502 "toke.l" #line 497 "toke.l"
{ {
LEXTRACE("EXEC "); LEXTRACE("EXEC ");
return EXEC; return EXEC;
@@ -3904,7 +3899,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 34: case 34:
YY_RULE_SETUP YY_RULE_SETUP
#line 507 "toke.l" #line 502 "toke.l"
{ {
LEXTRACE("INTERCEPT "); LEXTRACE("INTERCEPT ");
return INTERCEPT; return INTERCEPT;
@@ -3912,7 +3907,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 35: case 35:
YY_RULE_SETUP YY_RULE_SETUP
#line 512 "toke.l" #line 507 "toke.l"
{ {
LEXTRACE("NOINTERCEPT "); LEXTRACE("NOINTERCEPT ");
return NOINTERCEPT; return NOINTERCEPT;
@@ -3920,7 +3915,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 36: case 36:
YY_RULE_SETUP YY_RULE_SETUP
#line 517 "toke.l" #line 512 "toke.l"
{ {
LEXTRACE("SETENV "); LEXTRACE("SETENV ");
return SETENV; return SETENV;
@@ -3928,7 +3923,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 37: case 37:
YY_RULE_SETUP YY_RULE_SETUP
#line 522 "toke.l" #line 517 "toke.l"
{ {
LEXTRACE("NOSETENV "); LEXTRACE("NOSETENV ");
return NOSETENV; return NOSETENV;
@@ -3936,7 +3931,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 38: case 38:
YY_RULE_SETUP YY_RULE_SETUP
#line 527 "toke.l" #line 522 "toke.l"
{ {
LEXTRACE("LOG_OUTPUT "); LEXTRACE("LOG_OUTPUT ");
return LOG_OUTPUT; return LOG_OUTPUT;
@@ -3944,7 +3939,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 39: case 39:
YY_RULE_SETUP YY_RULE_SETUP
#line 532 "toke.l" #line 527 "toke.l"
{ {
LEXTRACE("NOLOG_OUTPUT "); LEXTRACE("NOLOG_OUTPUT ");
return NOLOG_OUTPUT; return NOLOG_OUTPUT;
@@ -3952,7 +3947,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 40: case 40:
YY_RULE_SETUP YY_RULE_SETUP
#line 537 "toke.l" #line 532 "toke.l"
{ {
LEXTRACE("LOG_INPUT "); LEXTRACE("LOG_INPUT ");
return LOG_INPUT; return LOG_INPUT;
@@ -3960,7 +3955,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 41: case 41:
YY_RULE_SETUP YY_RULE_SETUP
#line 542 "toke.l" #line 537 "toke.l"
{ {
LEXTRACE("NOLOG_INPUT "); LEXTRACE("NOLOG_INPUT ");
return NOLOG_INPUT; return NOLOG_INPUT;
@@ -3968,7 +3963,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 42: case 42:
YY_RULE_SETUP YY_RULE_SETUP
#line 547 "toke.l" #line 542 "toke.l"
{ {
LEXTRACE("MAIL "); LEXTRACE("MAIL ");
return MAIL; return MAIL;
@@ -3976,7 +3971,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 43: case 43:
YY_RULE_SETUP YY_RULE_SETUP
#line 552 "toke.l" #line 547 "toke.l"
{ {
LEXTRACE("NOMAIL "); LEXTRACE("NOMAIL ");
return NOMAIL; return NOMAIL;
@@ -3984,7 +3979,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 44: case 44:
YY_RULE_SETUP YY_RULE_SETUP
#line 557 "toke.l" #line 552 "toke.l"
{ {
LEXTRACE("FOLLOW "); LEXTRACE("FOLLOW ");
return FOLLOWLNK; return FOLLOWLNK;
@@ -3992,7 +3987,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 45: case 45:
YY_RULE_SETUP YY_RULE_SETUP
#line 562 "toke.l" #line 557 "toke.l"
{ {
LEXTRACE("NOFOLLOW "); LEXTRACE("NOFOLLOW ");
return NOFOLLOWLNK; return NOFOLLOWLNK;
@@ -4000,7 +3995,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 46: case 46:
YY_RULE_SETUP YY_RULE_SETUP
#line 567 "toke.l" #line 562 "toke.l"
{ {
if (sudoerstext[0] == '+') if (sudoerstext[0] == '+')
sudoers_errstr = N_("empty netgroup"); sudoers_errstr = N_("empty netgroup");
@@ -4012,7 +4007,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 47: case 47:
YY_RULE_SETUP YY_RULE_SETUP
#line 576 "toke.l" #line 571 "toke.l"
{ {
/* netgroup */ /* netgroup */
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4023,7 +4018,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 48: case 48:
YY_RULE_SETUP YY_RULE_SETUP
#line 584 "toke.l" #line 579 "toke.l"
{ {
/* group */ /* group */
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4034,7 +4029,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 49: case 49:
YY_RULE_SETUP YY_RULE_SETUP
#line 592 "toke.l" #line 587 "toke.l"
{ {
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
yyterminate(); yyterminate();
@@ -4044,7 +4039,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 50: case 50:
YY_RULE_SETUP YY_RULE_SETUP
#line 599 "toke.l" #line 594 "toke.l"
{ {
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
yyterminate(); yyterminate();
@@ -4054,7 +4049,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 51: case 51:
YY_RULE_SETUP YY_RULE_SETUP
#line 606 "toke.l" #line 601 "toke.l"
{ {
if (!ipv6_valid(sudoerstext)) { if (!ipv6_valid(sudoerstext)) {
sudoers_errstr = N_("invalid IPv6 address"); sudoers_errstr = N_("invalid IPv6 address");
@@ -4069,7 +4064,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 52: case 52:
YY_RULE_SETUP YY_RULE_SETUP
#line 618 "toke.l" #line 613 "toke.l"
{ {
if (!ipv6_valid(sudoerstext)) { if (!ipv6_valid(sudoerstext)) {
sudoers_errstr = N_("invalid IPv6 address"); sudoers_errstr = N_("invalid IPv6 address");
@@ -4084,7 +4079,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 53: case 53:
YY_RULE_SETUP YY_RULE_SETUP
#line 630 "toke.l" #line 625 "toke.l"
{ {
LEXTRACE("ALL "); LEXTRACE("ALL ");
return ALL; return ALL;
@@ -4093,7 +4088,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 54: case 54:
YY_RULE_SETUP YY_RULE_SETUP
#line 636 "toke.l" #line 631 "toke.l"
{ {
LEXTRACE("CMND_TIMEOUT "); LEXTRACE("CMND_TIMEOUT ");
return CMND_TIMEOUT; return CMND_TIMEOUT;
@@ -4101,7 +4096,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 55: case 55:
YY_RULE_SETUP YY_RULE_SETUP
#line 641 "toke.l" #line 636 "toke.l"
{ {
LEXTRACE("NOTBEFORE "); LEXTRACE("NOTBEFORE ");
return NOTBEFORE; return NOTBEFORE;
@@ -4109,7 +4104,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 56: case 56:
YY_RULE_SETUP YY_RULE_SETUP
#line 646 "toke.l" #line 641 "toke.l"
{ {
LEXTRACE("NOTAFTER "); LEXTRACE("NOTAFTER ");
return NOTAFTER; return NOTAFTER;
@@ -4117,7 +4112,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 57: case 57:
YY_RULE_SETUP YY_RULE_SETUP
#line 651 "toke.l" #line 646 "toke.l"
{ {
LEXTRACE("CWD "); LEXTRACE("CWD ");
prev_state = YY_START; prev_state = YY_START;
@@ -4127,7 +4122,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 58: case 58:
YY_RULE_SETUP YY_RULE_SETUP
#line 658 "toke.l" #line 653 "toke.l"
{ {
LEXTRACE("CHROOT "); LEXTRACE("CHROOT ");
prev_state = YY_START; prev_state = YY_START;
@@ -4137,7 +4132,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 59: case 59:
YY_RULE_SETUP YY_RULE_SETUP
#line 665 "toke.l" #line 660 "toke.l"
{ {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
LEXTRACE("ROLE "); LEXTRACE("ROLE ");
@@ -4149,7 +4144,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 60: case 60:
YY_RULE_SETUP YY_RULE_SETUP
#line 674 "toke.l" #line 669 "toke.l"
{ {
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
LEXTRACE("TYPE "); LEXTRACE("TYPE ");
@@ -4161,7 +4156,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 61: case 61:
YY_RULE_SETUP YY_RULE_SETUP
#line 682 "toke.l" #line 677 "toke.l"
{ {
#ifdef HAVE_APPARMOR #ifdef HAVE_APPARMOR
LEXTRACE("APPARMOR_PROFILE "); LEXTRACE("APPARMOR_PROFILE ");
@@ -4173,7 +4168,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 62: case 62:
YY_RULE_SETUP YY_RULE_SETUP
#line 690 "toke.l" #line 685 "toke.l"
{ {
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
LEXTRACE("PRIVS "); LEXTRACE("PRIVS ");
@@ -4185,7 +4180,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 63: case 63:
YY_RULE_SETUP YY_RULE_SETUP
#line 699 "toke.l" #line 694 "toke.l"
{ {
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET
LEXTRACE("LIMITPRIVS "); LEXTRACE("LIMITPRIVS ");
@@ -4197,7 +4192,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 64: case 64:
YY_RULE_SETUP YY_RULE_SETUP
#line 708 "toke.l" #line 703 "toke.l"
{ {
got_alias: got_alias:
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4208,7 +4203,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 65: case 65:
YY_RULE_SETUP YY_RULE_SETUP
#line 716 "toke.l" #line 711 "toke.l"
{ {
/* XXX - no way to specify digest for command */ /* XXX - no way to specify digest for command */
/* no command args allowed for Defaults!/path */ /* no command args allowed for Defaults!/path */
@@ -4220,7 +4215,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 66: case 66:
YY_RULE_SETUP YY_RULE_SETUP
#line 725 "toke.l" #line 720 "toke.l"
{ {
digest_type = SUDO_DIGEST_SHA224; digest_type = SUDO_DIGEST_SHA224;
BEGIN WANTDIGEST; BEGIN WANTDIGEST;
@@ -4230,7 +4225,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 67: case 67:
YY_RULE_SETUP YY_RULE_SETUP
#line 732 "toke.l" #line 727 "toke.l"
{ {
digest_type = SUDO_DIGEST_SHA256; digest_type = SUDO_DIGEST_SHA256;
BEGIN WANTDIGEST; BEGIN WANTDIGEST;
@@ -4240,7 +4235,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 68: case 68:
YY_RULE_SETUP YY_RULE_SETUP
#line 739 "toke.l" #line 734 "toke.l"
{ {
digest_type = SUDO_DIGEST_SHA384; digest_type = SUDO_DIGEST_SHA384;
BEGIN WANTDIGEST; BEGIN WANTDIGEST;
@@ -4250,7 +4245,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 69: case 69:
YY_RULE_SETUP YY_RULE_SETUP
#line 746 "toke.l" #line 741 "toke.l"
{ {
digest_type = SUDO_DIGEST_SHA512; digest_type = SUDO_DIGEST_SHA512;
BEGIN WANTDIGEST; BEGIN WANTDIGEST;
@@ -4260,7 +4255,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 70: case 70:
YY_RULE_SETUP YY_RULE_SETUP
#line 753 "toke.l" #line 748 "toke.l"
{ {
BEGIN GOTCMND; BEGIN GOTCMND;
LEXTRACE("COMMAND "); LEXTRACE("COMMAND ");
@@ -4270,7 +4265,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 71: case 71:
YY_RULE_SETUP YY_RULE_SETUP
#line 760 "toke.l" #line 755 "toke.l"
{ {
BEGIN prev_state; BEGIN prev_state;
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4281,7 +4276,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 72: case 72:
YY_RULE_SETUP YY_RULE_SETUP
#line 768 "toke.l" #line 763 "toke.l"
{ {
/* directories can't have args... */ /* directories can't have args... */
if (sudoerstext[sudoersleng - 1] == '/') { if (sudoerstext[sudoersleng - 1] == '/') {
@@ -4298,9 +4293,9 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 73: case 73:
YY_RULE_SETUP YY_RULE_SETUP
#line 782 "toke.l" #line 777 "toke.l"
{ {
if (sudoers_strict) { if (sudoers_strict()) {
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) { if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
LEXTRACE("ERROR "); LEXTRACE("ERROR ");
return ERROR; return ERROR;
@@ -4314,7 +4309,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 74: case 74:
YY_RULE_SETUP YY_RULE_SETUP
#line 795 "toke.l" #line 790 "toke.l"
{ {
LEXTRACE("BEGINSTR "); LEXTRACE("BEGINSTR ");
sudoerslval.string = NULL; sudoerslval.string = NULL;
@@ -4324,7 +4319,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 75: case 75:
YY_RULE_SETUP YY_RULE_SETUP
#line 802 "toke.l" #line 797 "toke.l"
{ {
/* a word */ /* a word */
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4336,7 +4331,7 @@ YY_RULE_SETUP
case 76: case 76:
YY_RULE_SETUP YY_RULE_SETUP
#line 811 "toke.l" #line 806 "toke.l"
{ {
/* include file/directory */ /* include file/directory */
if (!fill(sudoerstext, sudoersleng)) if (!fill(sudoerstext, sudoersleng))
@@ -4348,7 +4343,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 77: case 77:
YY_RULE_SETUP YY_RULE_SETUP
#line 820 "toke.l" #line 815 "toke.l"
{ {
LEXTRACE("BEGINSTR "); LEXTRACE("BEGINSTR ");
sudoerslval.string = NULL; sudoerslval.string = NULL;
@@ -4359,7 +4354,7 @@ YY_RULE_SETUP
case 78: case 78:
YY_RULE_SETUP YY_RULE_SETUP
#line 828 "toke.l" #line 823 "toke.l"
{ {
LEXTRACE("( "); LEXTRACE("( ");
return '('; return '(';
@@ -4367,7 +4362,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 79: case 79:
YY_RULE_SETUP YY_RULE_SETUP
#line 833 "toke.l" #line 828 "toke.l"
{ {
LEXTRACE(") "); LEXTRACE(") ");
return ')'; return ')';
@@ -4375,7 +4370,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 80: case 80:
YY_RULE_SETUP YY_RULE_SETUP
#line 838 "toke.l" #line 833 "toke.l"
{ {
LEXTRACE(", "); LEXTRACE(", ");
return ','; return ',';
@@ -4383,7 +4378,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 81: case 81:
YY_RULE_SETUP YY_RULE_SETUP
#line 843 "toke.l" #line 838 "toke.l"
{ {
LEXTRACE("= "); LEXTRACE("= ");
return '='; return '=';
@@ -4391,7 +4386,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 82: case 82:
YY_RULE_SETUP YY_RULE_SETUP
#line 848 "toke.l" #line 843 "toke.l"
{ {
LEXTRACE(": "); LEXTRACE(": ");
return ':'; return ':';
@@ -4399,7 +4394,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 83: case 83:
YY_RULE_SETUP YY_RULE_SETUP
#line 853 "toke.l" #line 848 "toke.l"
{ {
if (sudoersleng & 1) { if (sudoersleng & 1) {
LEXTRACE("!"); LEXTRACE("!");
@@ -4410,7 +4405,7 @@ YY_RULE_SETUP
case 84: case 84:
/* rule 84 can match eol */ /* rule 84 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 860 "toke.l" #line 855 "toke.l"
{ {
if (YY_START == INSTR) { if (YY_START == INSTR) {
/* throw away old string */ /* throw away old string */
@@ -4432,7 +4427,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 85: case 85:
YY_RULE_SETUP YY_RULE_SETUP
#line 879 "toke.l" #line 874 "toke.l"
{ /* throw away space/tabs */ { /* throw away space/tabs */
sawspace = true; /* but remember for fill_args */ sawspace = true; /* but remember for fill_args */
} }
@@ -4440,7 +4435,7 @@ YY_RULE_SETUP
case 86: case 86:
/* rule 86 can match eol */ /* rule 86 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 883 "toke.l" #line 878 "toke.l"
{ {
sawspace = true; /* remember for fill_args */ sawspace = true; /* remember for fill_args */
sudolineno++; sudolineno++;
@@ -4450,7 +4445,7 @@ YY_RULE_SETUP
case 87: case 87:
/* rule 87 can match eol */ /* rule 87 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 889 "toke.l" #line 884 "toke.l"
{ {
if (sudoerstext[sudoersleng - 1] == '\n') { if (sudoerstext[sudoersleng - 1] == '\n') {
/* comment ending in a newline */ /* comment ending in a newline */
@@ -4468,7 +4463,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 88: case 88:
YY_RULE_SETUP YY_RULE_SETUP
#line 904 "toke.l" #line 899 "toke.l"
{ {
LEXTRACE("NOMATCH "); LEXTRACE("NOMATCH ");
return NOMATCH; return NOMATCH;
@@ -4484,7 +4479,7 @@ case YY_STATE_EOF(INSTR):
case YY_STATE_EOF(WANTDIGEST): case YY_STATE_EOF(WANTDIGEST):
case YY_STATE_EOF(GOTINC): case YY_STATE_EOF(GOTINC):
case YY_STATE_EOF(EXPECTPATH): case YY_STATE_EOF(EXPECTPATH):
#line 909 "toke.l" #line 904 "toke.l"
{ {
if (!pop_include()) if (!pop_include())
yyterminate(); yyterminate();
@@ -4492,10 +4487,10 @@ case YY_STATE_EOF(EXPECTPATH):
YY_BREAK YY_BREAK
case 89: case 89:
YY_RULE_SETUP YY_RULE_SETUP
#line 914 "toke.l" #line 909 "toke.l"
ECHO; ECHO;
YY_BREAK YY_BREAK
#line 4493 "toke.c" #line 4488 "toke.c"
case YY_END_OF_BUFFER: case YY_END_OF_BUFFER:
{ {
@@ -5456,7 +5451,7 @@ void sudoersfree (void * ptr )
#define YYTABLES_NAME "yytables" #define YYTABLES_NAME "yytables"
#line 914 "toke.l" #line 909 "toke.l"
struct path_list { struct path_list {
@@ -5861,7 +5856,8 @@ push_include_int(const char *opath, bool isdir, int verbose)
int count, fd, status; int count, fd, status;
fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL); fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL);
status = sudo_secure_fd(fd, S_IFDIR, sudoers_uid, sudoers_gid, &sb); status = sudo_secure_fd(fd, S_IFDIR, sudoers_file_uid(),
sudoers_file_gid(), &sb);
if (fd != -1) if (fd != -1)
close(fd); /* XXX use in read_dir_files? */ close(fd); /* XXX use in read_dir_files? */
if (status != SUDO_PATH_SECURE) { if (status != SUDO_PATH_SECURE) {
@@ -5874,7 +5870,7 @@ push_include_int(const char *opath, bool isdir, int verbose)
case SUDO_PATH_WRONG_OWNER: case SUDO_PATH_WRONG_OWNER:
sudo_warnx(U_("%s is owned by uid %u, should be %u"), sudo_warnx(U_("%s is owned by uid %u, should be %u"),
path, (unsigned int) sb.st_uid, path, (unsigned int) sb.st_uid,
(unsigned int) sudoers_uid); (unsigned int) sudoers_file_uid());
break; break;
case SUDO_PATH_WORLD_WRITABLE: case SUDO_PATH_WORLD_WRITABLE:
sudo_warnx(U_("%s is world writable"), path); sudo_warnx(U_("%s is world writable"), path);
@@ -5882,7 +5878,7 @@ push_include_int(const char *opath, bool isdir, int verbose)
case SUDO_PATH_GROUP_WRITABLE: case SUDO_PATH_GROUP_WRITABLE:
sudo_warnx(U_("%s is owned by gid %u, should be %u"), sudo_warnx(U_("%s is owned by gid %u, should be %u"),
path, (unsigned int) sb.st_gid, path, (unsigned int) sb.st_gid,
(unsigned int) sudoers_gid); (unsigned int) sudoers_file_gid());
break; break;
default: default:
break; break;

View File

@@ -2,7 +2,7 @@
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 1996, 1998-2005, 2007-2022 * Copyright (c) 1996, 1998-2005, 2007-2023
* Todd C. Miller <Todd.Miller@sudo.ws> * Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@@ -59,11 +59,6 @@ char *sudoers_search_path; /* colon-separated path of sudoers files. */
const char *sudoers_errstr; /* description of last error from lexer. */ const char *sudoers_errstr; /* description of last error from lexer. */
struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */ struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
/* Default sudoers mode and owner (may be set via sudo.conf) */
mode_t sudoers_mode = SUDOERS_MODE;
uid_t sudoers_uid = SUDOERS_UID;
gid_t sudoers_gid = SUDOERS_GID;
static bool continued, sawspace; static bool continued, sawspace;
static int prev_state; static int prev_state;
static int digest_type = -1; static int digest_type = -1;
@@ -296,7 +291,7 @@ DEFVAR [a-z_]+
yyterminate(); yyterminate();
BEGIN INITIAL; BEGIN INITIAL;
continued = false; continued = false;
if (sudoers_strict) { if (sudoers_strict()) {
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) { if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
LEXTRACE("ERROR "); LEXTRACE("ERROR ");
return ERROR; return ERROR;
@@ -780,7 +775,7 @@ sudoedit {
} /* a pathname */ } /* a pathname */
{REGEX} { {REGEX} {
if (sudoers_strict) { if (sudoers_strict()) {
if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) { if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
LEXTRACE("ERROR "); LEXTRACE("ERROR ");
return ERROR; return ERROR;
@@ -1314,7 +1309,8 @@ push_include_int(const char *opath, bool isdir, int verbose)
int count, fd, status; int count, fd, status;
fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL); fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL);
status = sudo_secure_fd(fd, S_IFDIR, sudoers_uid, sudoers_gid, &sb); status = sudo_secure_fd(fd, S_IFDIR, sudoers_file_uid(),
sudoers_file_gid(), &sb);
if (fd != -1) if (fd != -1)
close(fd); /* XXX use in read_dir_files? */ close(fd); /* XXX use in read_dir_files? */
if (status != SUDO_PATH_SECURE) { if (status != SUDO_PATH_SECURE) {
@@ -1327,7 +1323,7 @@ push_include_int(const char *opath, bool isdir, int verbose)
case SUDO_PATH_WRONG_OWNER: case SUDO_PATH_WRONG_OWNER:
sudo_warnx(U_("%s is owned by uid %u, should be %u"), sudo_warnx(U_("%s is owned by uid %u, should be %u"),
path, (unsigned int) sb.st_uid, path, (unsigned int) sb.st_uid,
(unsigned int) sudoers_uid); (unsigned int) sudoers_file_uid());
break; break;
case SUDO_PATH_WORLD_WRITABLE: case SUDO_PATH_WORLD_WRITABLE:
sudo_warnx(U_("%s is world writable"), path); sudo_warnx(U_("%s is world writable"), path);
@@ -1335,7 +1331,7 @@ push_include_int(const char *opath, bool isdir, int verbose)
case SUDO_PATH_GROUP_WRITABLE: case SUDO_PATH_GROUP_WRITABLE:
sudo_warnx(U_("%s is owned by gid %u, should be %u"), sudo_warnx(U_("%s is owned by gid %u, should be %u"),
path, (unsigned int) sb.st_gid, path, (unsigned int) sb.st_gid,
(unsigned int) sudoers_gid); (unsigned int) sudoers_file_gid());
break; break;
default: default:
break; break;

View File

@@ -151,7 +151,7 @@ fill_cmnd(const char *src, size_t len)
/* Check for sudoedit specified as a fully-qualified path. */ /* Check for sudoedit specified as a fully-qualified path. */
if ((dst = strrchr(sudoerslval.command.cmnd, '/')) != NULL) { // -V575 if ((dst = strrchr(sudoerslval.command.cmnd, '/')) != NULL) { // -V575
if (strcmp(dst, "/sudoedit") == 0) { if (strcmp(dst, "/sudoedit") == 0) {
if (sudoers_strict) { if (sudoers_strict()) {
sudoerserror( sudoerserror(
N_("sudoedit should not be specified with a path")); N_("sudoedit should not be specified with a path"));
} }

View File

@@ -111,6 +111,7 @@ struct sudo_user sudo_user;
struct passwd *list_pw; struct passwd *list_pw;
static const char *path_sudoers = _PATH_SUDOERS; static const char *path_sudoers = _PATH_SUDOERS;
static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist); static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist);
static struct sudoers_parser_config parser_conf = SUDOERS_PARSER_CONFIG_INITIALIZER;
static bool checkonly; static bool checkonly;
static bool edit_includes = true; static bool edit_includes = true;
static unsigned int errors; static unsigned int errors;
@@ -240,11 +241,11 @@ main(int argc, char *argv[])
if (fflag) { if (fflag) {
/* Looser owner/permission checks for an uninstalled sudoers file. */ /* Looser owner/permission checks for an uninstalled sudoers file. */
if (!use_owner) { if (!use_owner) {
sudoers_uid = -1; parser_conf.sudoers_uid = (uid_t)-1;
sudoers_gid = -1; parser_conf.sudoers_gid = (gid_t)-1;
} }
if (!use_perms) if (!use_perms)
SET(sudoers_mode, S_IWUSR); parser_conf.sudoers_mode |= S_IWUSR;
} else { } else {
/* Check/set owner and mode for installed sudoers file. */ /* Check/set owner and mode for installed sudoers file. */
use_owner = true; use_owner = true;
@@ -288,7 +289,9 @@ main(int argc, char *argv[])
* Parse the existing sudoers file(s) to highlight any existing * Parse the existing sudoers file(s) to highlight any existing
* errors and to pull in editor and env_editor conf values. * errors and to pull in editor and env_editor conf values.
*/ */
init_parser(NULL, path_sudoers, true, quiet ? 0 : 2); parser_conf.strict = true;
parser_conf.verbose = quiet ? 0 : 2;
init_parser(NULL, path_sudoers, &parser_conf);
if ((sudoersin = open_sudoers(path_sudoers, &sudoers, true, NULL)) == NULL) if ((sudoersin = open_sudoers(path_sudoers, &sudoers, true, NULL)) == NULL)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
@@ -651,7 +654,7 @@ reparse_sudoers(char *editor, int editor_argc, char **editor_argv,
/* Clean slate for each parse */ /* Clean slate for each parse */
if (!init_defaults()) if (!init_defaults())
sudo_fatalx("%s", U_("unable to initialize sudoers default values")); sudo_fatalx("%s", U_("unable to initialize sudoers default values"));
init_parser(sp->opath, path_sudoers, true, quiet ? 0 : 2); init_parser(sp->opath, path_sudoers, &parser_conf);
sp->errorline = -1; sp->errorline = -1;
/* Parse the sudoers temp file(s) */ /* Parse the sudoers temp file(s) */
@@ -742,19 +745,19 @@ install_sudoers(struct sudoersfile *sp, bool set_owner, bool set_mode)
(void) unlink(sp->tpath); (void) unlink(sp->tpath);
if (fstat(sp->fd, &sb) == 0) { if (fstat(sp->fd, &sb) == 0) {
if (set_owner) { if (set_owner) {
if (sb.st_uid != sudoers_uid || sb.st_gid != sudoers_gid) { if (sb.st_uid != sudoers_file_uid() || sb.st_gid != sudoers_file_gid()) {
if (chown(sp->opath, sudoers_uid, sudoers_gid) != 0) { if (chown(sp->opath, sudoers_file_uid(), sudoers_file_gid()) != 0) {
sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"), sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"),
sp->opath, (unsigned int)sudoers_uid, sp->opath, (unsigned int)sudoers_file_uid(),
(unsigned int)sudoers_gid); (unsigned int)sudoers_file_gid());
} }
} }
} }
if (set_mode) { if (set_mode) {
if ((sb.st_mode & ACCESSPERMS) != sudoers_mode) { if ((sb.st_mode & ACCESSPERMS) != sudoers_file_mode()) {
if (chmod(sp->opath, sudoers_mode) != 0) { if (chmod(sp->opath, sudoers_file_mode()) != 0) {
sudo_warn(U_("unable to change mode of %s to 0%o"), sudo_warn(U_("unable to change mode of %s to 0%o"),
sp->opath, (unsigned int)sudoers_mode); sp->opath, (unsigned int)sudoers_file_mode());
} }
} }
} }
@@ -773,10 +776,10 @@ install_sudoers(struct sudoersfile *sp, bool set_owner, bool set_mode)
sudo_fatal(U_("unable to stat %s"), sp->opath); sudo_fatal(U_("unable to stat %s"), sp->opath);
} }
if (set_owner) { if (set_owner) {
if (chown(sp->tpath, sudoers_uid, sudoers_gid) != 0) { if (chown(sp->tpath, sudoers_file_uid(), sudoers_file_gid()) != 0) {
sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"), sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"),
sp->tpath, (unsigned int)sudoers_uid, sp->tpath, (unsigned int)sudoers_file_uid(),
(unsigned int)sudoers_gid); (unsigned int)sudoers_file_gid());
goto done; goto done;
} }
} else { } else {
@@ -786,9 +789,9 @@ install_sudoers(struct sudoersfile *sp, bool set_owner, bool set_mode)
} }
} }
if (set_mode) { if (set_mode) {
if (chmod(sp->tpath, sudoers_mode) != 0) { if (chmod(sp->tpath, sudoers_file_mode()) != 0) {
sudo_warn(U_("unable to change mode of %s to 0%o"), sp->tpath, sudo_warn(U_("unable to change mode of %s to 0%o"), sp->tpath,
(unsigned int)sudoers_mode); (unsigned int)sudoers_file_mode());
goto done; goto done;
} }
} else { } else {
@@ -1022,23 +1025,23 @@ check_file(const char *path, bool quiet, bool check_owner, bool check_mode)
if (stat(path, &sb) == 0) { if (stat(path, &sb) == 0) {
if (check_owner) { if (check_owner) {
if (sb.st_uid != sudoers_uid || sb.st_gid != sudoers_gid) { if (sb.st_uid != sudoers_file_uid() || sb.st_gid != sudoers_file_gid()) {
ok = false; ok = false;
if (!quiet) { if (!quiet) {
fprintf(stderr, fprintf(stderr,
_("%s: wrong owner (uid, gid) should be (%u, %u)\n"), _("%s: wrong owner (uid, gid) should be (%u, %u)\n"),
path, (unsigned int)sudoers_uid, path, (unsigned int)sudoers_file_uid(),
(unsigned int)sudoers_gid); (unsigned int)sudoers_file_gid());
} }
} }
} }
if (check_mode) { if (check_mode) {
if ((sb.st_mode & ALLPERMS) != sudoers_mode) { if ((sb.st_mode & ALLPERMS) != sudoers_file_mode()) {
ok = false; ok = false;
if (!quiet) { if (!quiet) {
fprintf(stderr, fprintf(stderr,
_("%s: bad permissions, should be mode 0%o\n"), _("%s: bad permissions, should be mode 0%o\n"),
path, (unsigned int)sudoers_mode); path, (unsigned int)sudoers_file_mode());
} }
} }
} }
@@ -1068,7 +1071,7 @@ check_syntax(const char *path, bool quiet, bool strict, bool check_owner,
goto done; goto done;
} }
} }
init_parser(fname, path, true, quiet ? 0 : 2); init_parser(fname, path, &parser_conf);
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
if (sudoersparse() && !parse_error) { if (sudoersparse() && !parse_error) {
if (!quiet) if (!quiet)
@@ -1181,7 +1184,7 @@ new_sudoers(const char *path, bool doedit)
if (fd == -1) { if (fd == -1) {
if (!checkonly) { if (!checkonly) {
/* No sudoers file, create the destination file for editing. */ /* No sudoers file, create the destination file for editing. */
fd = open(entry->dpath, O_RDWR|O_CREAT, sudoers_mode); fd = open(entry->dpath, O_RDWR|O_CREAT, sudoers_file_mode());
} }
if (fd == -1) { if (fd == -1) {
sudo_warn("%s", entry->dpath); sudo_warn("%s", entry->dpath);
@@ -1329,6 +1332,7 @@ parse_sudoers_options(void)
for (cur = info->options; *cur != NULL; cur++) { for (cur = info->options; *cur != NULL; cur++) {
const char *errstr, *p; const char *errstr, *p;
id_t id; id_t id;
mode_t mode;
if (MATCHES(*cur, "sudoers_file=")) { if (MATCHES(*cur, "sudoers_file=")) {
path_sudoers = *cur + sizeof("sudoers_file=") - 1; path_sudoers = *cur + sizeof("sudoers_file=") - 1;
@@ -1338,21 +1342,21 @@ parse_sudoers_options(void)
p = *cur + sizeof("sudoers_uid=") - 1; p = *cur + sizeof("sudoers_uid=") - 1;
id = sudo_strtoid(p, &errstr); id = sudo_strtoid(p, &errstr);
if (errstr == NULL) if (errstr == NULL)
sudoers_uid = (uid_t) id; parser_conf.sudoers_uid = (uid_t)id;
continue; continue;
} }
if (MATCHES(*cur, "sudoers_gid=")) { if (MATCHES(*cur, "sudoers_gid=")) {
p = *cur + sizeof("sudoers_gid=") - 1; p = *cur + sizeof("sudoers_gid=") - 1;
id = sudo_strtoid(p, &errstr); id = sudo_strtoid(p, &errstr);
if (errstr == NULL) if (errstr == NULL)
sudoers_gid = (gid_t) id; parser_conf.sudoers_gid = (gid_t)id;
continue; continue;
} }
if (MATCHES(*cur, "sudoers_mode=")) { if (MATCHES(*cur, "sudoers_mode=")) {
p = *cur + sizeof("sudoers_mode=") - 1; p = *cur + sizeof("sudoers_mode=") - 1;
id = (id_t) sudo_strtomode(p, &errstr); mode = sudo_strtomode(p, &errstr);
if (errstr == NULL) if (errstr == NULL)
sudoers_mode = (mode_t) id; parser_conf.sudoers_mode = mode;
continue; continue;
} }
} }