version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.6, 2014/06/15 16:12:54
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 1996, 1998-2005, 2007-2012 | * Copyright (c) 1996, 1998-2005, 2007-2013 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
Line 32
|
Line 32
|
#include <config.h> |
#include <config.h> |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/time.h> |
#include <sys/time.h> |
|
#include <sys/uio.h> |
#ifndef __TANDEM |
#ifndef __TANDEM |
# include <sys/file.h> |
# include <sys/file.h> |
#endif |
#endif |
Line 67
|
Line 67
|
#include <fcntl.h> |
#include <fcntl.h> |
#include <netinet/in.h> |
#include <netinet/in.h> |
#include <arpa/inet.h> |
#include <arpa/inet.h> |
#include <netdb.h> | #ifdef TIME_WITH_SYS_TIME |
#if TIME_WITH_SYS_TIME | |
# include <time.h> |
# include <time.h> |
#endif |
#endif |
#ifdef HAVE_SETLOCALE | #ifdef HAVE_GETOPT_LONG |
# include <locale.h> | # include <getopt.h> |
#endif | # else |
| # include "compat/getopt.h" |
| #endif /* HAVE_GETOPT_LONG */ |
|
|
#include "sudoers.h" |
#include "sudoers.h" |
#include "interfaces.h" |
|
#include "parse.h" |
#include "parse.h" |
#include "redblack.h" |
#include "redblack.h" |
#include "gettext.h" |
|
#include "sudoers_version.h" |
#include "sudoers_version.h" |
#include "sudo_conf.h" |
#include "sudo_conf.h" |
#include <gram.h> |
#include <gram.h> |
|
|
struct sudoersfile { |
struct sudoersfile { |
struct sudoersfile *prev, *next; | TAILQ_ENTRY(sudoersfile) entries; |
char *path; |
char *path; |
char *tpath; |
char *tpath; |
int fd; |
int fd; |
int modified; |
int modified; |
int doedit; |
int doedit; |
}; |
}; |
TQ_DECLARE(sudoersfile) | TAILQ_HEAD(sudoersfile_list, sudoersfile); |
|
|
sudo_conv_t sudo_conv; /* NULL in non-plugin */ |
|
|
|
/* |
/* |
* Function prototypes |
* Function prototypes |
*/ |
*/ |
Line 109 static bool check_syntax(char *, bool, bool, bool);
|
Line 106 static bool check_syntax(char *, bool, bool, bool);
|
static bool edit_sudoers(struct sudoersfile *, char *, char *, int); |
static bool edit_sudoers(struct sudoersfile *, char *, char *, int); |
static bool install_sudoers(struct sudoersfile *, bool); |
static bool install_sudoers(struct sudoersfile *, bool); |
static int print_unused(void *, void *); |
static int print_unused(void *, void *); |
static void reparse_sudoers(char *, char *, bool, bool); | static bool reparse_sudoers(char *, char *, bool, bool); |
static int run_command(char *, char **); |
static int run_command(char *, char **); |
static int visudo_printf(int msg_type, const char *fmt, ...); |
|
static void setup_signals(void); |
static void setup_signals(void); |
static void help(void) __attribute__((__noreturn__)); |
static void help(void) __attribute__((__noreturn__)); |
static void usage(int); |
static void usage(int); |
|
static void visudo_cleanup(void); |
|
|
void cleanup(int); | extern bool export_sudoers(const char *, const char *, bool, bool); |
|
|
extern void yyerror(const char *); | extern void sudoerserror(const char *); |
extern void yyrestart(FILE *); | extern void sudoersrestart(FILE *); |
|
|
/* |
/* |
* External globals exported by the parser |
|
*/ |
|
extern struct rbtree *aliases; |
|
extern FILE *yyin; |
|
extern char *sudoers, *errorfile; |
|
extern int errorlineno; |
|
extern bool parse_error; |
|
/* For getopt(3) */ |
|
extern char *optarg; |
|
extern int optind; |
|
|
|
/* |
|
* Globals |
* Globals |
*/ |
*/ |
struct interface *interfaces; |
|
struct sudo_user sudo_user; |
struct sudo_user sudo_user; |
struct passwd *list_pw; |
struct passwd *list_pw; |
sudo_printf_t sudo_printf = visudo_printf; | static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist); |
static struct sudoersfile_list sudoerslist; | |
static struct rbtree *alias_freelist; |
static struct rbtree *alias_freelist; |
static bool checkonly; |
static bool checkonly; |
|
static const char short_opts[] = "cf:hqsVx:"; |
|
static struct option long_opts[] = { |
|
{ "check", no_argument, NULL, 'c' }, |
|
{ "export", required_argument, NULL, 'x' }, |
|
{ "file", required_argument, NULL, 'f' }, |
|
{ "help", no_argument, NULL, 'h' }, |
|
{ "quiet", no_argument, NULL, 'q' }, |
|
{ "strict", no_argument, NULL, 's' }, |
|
{ "version", no_argument, NULL, 'V' }, |
|
{ NULL, no_argument, NULL, '\0' }, |
|
}; |
|
|
|
__dso_public int main(int argc, char *argv[]); |
|
|
int |
int |
main(int argc, char *argv[]) |
main(int argc, char *argv[]) |
{ |
{ |
Line 151 main(int argc, char *argv[])
|
Line 147 main(int argc, char *argv[])
|
char *args, *editor, *sudoers_path; |
char *args, *editor, *sudoers_path; |
int ch, exitcode = 0; |
int ch, exitcode = 0; |
bool quiet, strict, oldperms; |
bool quiet, strict, oldperms; |
|
const char *export_path; |
debug_decl(main, SUDO_DEBUG_MAIN) |
debug_decl(main, SUDO_DEBUG_MAIN) |
|
|
#if defined(SUDO_DEVEL) && defined(__OpenBSD__) |
#if defined(SUDO_DEVEL) && defined(__OpenBSD__) |
Line 160 main(int argc, char *argv[])
|
Line 157 main(int argc, char *argv[])
|
} |
} |
#endif |
#endif |
|
|
#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) | initprogname(argc > 0 ? argv[0] : "visudo"); |
setprogname(argc > 0 ? argv[0] : "visudo"); | sudoers_initlocale(setlocale(LC_ALL, ""), def_sudoers_locale); |
#endif | |
| |
#ifdef HAVE_SETLOCALE | |
setlocale(LC_ALL, ""); | |
#endif | |
bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have visudo domain */ |
bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have visudo domain */ |
textdomain("sudoers"); |
textdomain("sudoers"); |
|
|
if (argc < 1) |
if (argc < 1) |
usage(1); |
usage(1); |
|
|
|
/* Register fatal/fatalx callback. */ |
|
fatal_callback_register(visudo_cleanup); |
|
|
/* Read sudo.conf. */ |
/* Read sudo.conf. */ |
sudo_conf_read(); | sudo_conf_read(NULL); |
|
|
/* |
/* |
* Arg handling. |
* Arg handling. |
*/ |
*/ |
checkonly = oldperms = quiet = strict = false; |
checkonly = oldperms = quiet = strict = false; |
|
export_path = NULL; |
sudoers_path = _PATH_SUDOERS; |
sudoers_path = _PATH_SUDOERS; |
while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) { | while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { |
switch (ch) { |
switch (ch) { |
case 'V': |
case 'V': |
(void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION); | (void) printf(_("%s version %s\n"), getprogname(), |
(void) printf(_("%s grammar version %d\n"), getprogname(), SUDOERS_GRAMMAR_VERSION); | PACKAGE_VERSION); |
| (void) printf(_("%s grammar version %d\n"), getprogname(), |
| SUDOERS_GRAMMAR_VERSION); |
goto done; |
goto done; |
case 'c': |
case 'c': |
checkonly++; /* check mode */ | checkonly = true; /* check mode */ |
break; |
break; |
case 'f': |
case 'f': |
sudoers_path = optarg; /* sudoers file path */ |
sudoers_path = optarg; /* sudoers file path */ |
Line 198 main(int argc, char *argv[])
|
Line 196 main(int argc, char *argv[])
|
help(); |
help(); |
break; |
break; |
case 's': |
case 's': |
strict++; /* strict mode */ | strict = true; /* strict mode */ |
break; |
break; |
case 'q': |
case 'q': |
quiet++; /* quiet mode */ | quiet = true; /* quiet mode */ |
break; |
break; |
|
case 'x': |
|
export_path = optarg; /* export mode */ |
|
break; |
default: |
default: |
usage(1); |
usage(1); |
} |
} |
Line 215 main(int argc, char *argv[])
|
Line 216 main(int argc, char *argv[])
|
sudo_setgrent(); |
sudo_setgrent(); |
|
|
/* Mock up a fake sudo_user struct. */ |
/* Mock up a fake sudo_user struct. */ |
user_cmnd = ""; | user_cmnd = user_base = ""; |
if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) |
if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) |
errorx(1, _("you do not exist in the %s database"), "passwd"); | fatalx(U_("you do not exist in the %s database"), "passwd"); |
get_hostname(); |
get_hostname(); |
|
|
/* Setup defaults data structures. */ |
/* Setup defaults data structures. */ |
Line 227 main(int argc, char *argv[])
|
Line 228 main(int argc, char *argv[])
|
exitcode = check_syntax(sudoers_path, quiet, strict, oldperms) ? 0 : 1; |
exitcode = check_syntax(sudoers_path, quiet, strict, oldperms) ? 0 : 1; |
goto done; |
goto done; |
} |
} |
|
if (export_path != NULL) { |
|
exitcode = export_sudoers(sudoers_path, export_path, quiet, strict) ? 0 : 1; |
|
goto done; |
|
} |
|
|
/* |
/* |
* Parse the existing sudoers file(s) in quiet mode to highlight any | * Parse the existing sudoers file(s) to highlight any existing |
* existing errors and to pull in editor and env_editor conf values. | * errors and to pull in editor and env_editor conf values. |
*/ |
*/ |
if ((yyin = open_sudoers(sudoers_path, true, NULL)) == NULL) { | if ((sudoersin = open_sudoers(sudoers_path, true, NULL)) == NULL) |
error(1, "%s", sudoers_path); | exit(1); |
} | init_parser(sudoers_path, false); |
init_parser(sudoers_path, 0); | sudoersparse(); |
yyparse(); | |
(void) update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER); |
(void) update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER); |
|
|
editor = get_editor(&args); |
editor = get_editor(&args); |
Line 245 main(int argc, char *argv[])
|
Line 249 main(int argc, char *argv[])
|
setup_signals(); |
setup_signals(); |
|
|
/* Edit the sudoers file(s) */ |
/* Edit the sudoers file(s) */ |
tq_foreach_fwd(&sudoerslist, sp) { | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
if (!sp->doedit) |
if (!sp->doedit) |
continue; |
continue; |
if (sp != tq_first(&sudoerslist)) { | if (sp != TAILQ_FIRST(&sudoerslist)) { |
printf(_("press return to edit %s: "), sp->path); |
printf(_("press return to edit %s: "), sp->path); |
while ((ch = getchar()) != EOF && ch != '\n') |
while ((ch = getchar()) != EOF && ch != '\n') |
continue; |
continue; |
Line 256 main(int argc, char *argv[])
|
Line 260 main(int argc, char *argv[])
|
edit_sudoers(sp, editor, args, -1); |
edit_sudoers(sp, editor, args, -1); |
} |
} |
|
|
/* Check edited files for a parse error and re-edit any that fail. */ | /* |
reparse_sudoers(editor, args, strict, quiet); | * Check edited files for a parse error, re-edit any that fail |
| * and install the edited files as needed. |
/* Install the sudoers temp files as needed. */ | */ |
tq_foreach_fwd(&sudoerslist, sp) { | if (reparse_sudoers(editor, args, strict, quiet)) { |
(void) install_sudoers(sp, oldperms); | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
| (void) install_sudoers(sp, oldperms); |
| } |
} |
} |
|
|
done: |
done: |
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode); | sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode); |
exit(exitcode); |
exit(exitcode); |
} |
} |
|
|
Line 316 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
Line 322 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
debug_decl(edit_sudoers, SUDO_DEBUG_UTIL) |
debug_decl(edit_sudoers, SUDO_DEBUG_UTIL) |
|
|
if (fstat(sp->fd, &sb) == -1) |
if (fstat(sp->fd, &sb) == -1) |
error(1, _("unable to stat %s"), sp->path); | fatal(U_("unable to stat %s"), sp->path); |
orig_size = sb.st_size; |
orig_size = sb.st_size; |
mtim_get(&sb, &orig_mtim); |
mtim_get(&sb, &orig_mtim); |
|
|
Line 325 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
Line 331 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
easprintf(&sp->tpath, "%s.tmp", sp->path); |
easprintf(&sp->tpath, "%s.tmp", sp->path); |
tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
if (tfd < 0) |
if (tfd < 0) |
error(1, "%s", sp->tpath); | fatal("%s", sp->tpath); |
|
|
/* Copy sp->path -> sp->tpath and reset the mtime. */ |
/* Copy sp->path -> sp->tpath and reset the mtime. */ |
if (orig_size != 0) { |
if (orig_size != 0) { |
(void) lseek(sp->fd, (off_t)0, SEEK_SET); |
(void) lseek(sp->fd, (off_t)0, SEEK_SET); |
while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) |
while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) |
if (write(tfd, buf, nread) != nread) |
if (write(tfd, buf, nread) != nread) |
error(1, _("write error")); | fatal(U_("write error")); |
|
|
/* Add missing newline at EOF if needed. */ |
/* Add missing newline at EOF if needed. */ |
if (nread > 0 && buf[nread - 1] != '\n') { |
if (nread > 0 && buf[nread - 1] != '\n') { |
buf[0] = '\n'; |
buf[0] = '\n'; |
if (write(tfd, buf, 1) != 1) |
if (write(tfd, buf, 1) != 1) |
error(1, _("write error")); | fatal(U_("write error")); |
} |
} |
} |
} |
(void) close(tfd); |
(void) close(tfd); |
Line 420 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
Line 426 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
* Sanity checks. |
* Sanity checks. |
*/ |
*/ |
if (stat(sp->tpath, &sb) < 0) { |
if (stat(sp->tpath, &sb) < 0) { |
warningx(_("unable to stat temporary file (%s), %s unchanged"), | warningx(U_("unable to stat temporary file (%s), %s unchanged"), |
sp->tpath, sp->path); |
sp->tpath, sp->path); |
goto done; |
goto done; |
} |
} |
if (sb.st_size == 0 && orig_size != 0) { |
if (sb.st_size == 0 && orig_size != 0) { |
warningx(_("zero length temporary file (%s), %s unchanged"), | warningx(U_("zero length temporary file (%s), %s unchanged"), |
sp->tpath, sp->path); |
sp->tpath, sp->path); |
sp->modified = true; |
sp->modified = true; |
goto done; |
goto done; |
} |
} |
} else { |
} else { |
warningx(_("editor (%s) failed, %s unchanged"), editor, sp->path); | warningx(U_("editor (%s) failed, %s unchanged"), editor, sp->path); |
goto done; |
goto done; |
} |
} |
|
|
/* Set modified bit if use changed the file. */ | /* Set modified bit if the user changed the file. */ |
modified = true; |
modified = true; |
mtim_get(&sb, &tv); |
mtim_get(&sb, &tv); |
if (orig_size == sb.st_size && timevalcmp(&orig_mtim, &tv, ==)) { | if (orig_size == sb.st_size && sudo_timevalcmp(&orig_mtim, &tv, ==)) { |
/* |
/* |
* If mtime and size match but the user spent no measurable |
* If mtime and size match but the user spent no measurable |
* time in the editor we can't tell if the file was changed. |
* time in the editor we can't tell if the file was changed. |
*/ |
*/ |
timevalsub(&tv1, &tv2); | if (sudo_timevalcmp(&tv1, &tv2, !=)) |
if (timevalisset(&tv2)) | |
modified = false; |
modified = false; |
} |
} |
|
|
Line 454 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
Line 459 edit_sudoers(struct sudoersfile *sp, char *editor, cha
|
if (modified) |
if (modified) |
sp->modified = modified; |
sp->modified = modified; |
else |
else |
warningx(_("%s unchanged"), sp->tpath); | warningx(U_("%s unchanged"), sp->tpath); |
|
|
rval = true; |
rval = true; |
done: |
done: |
Line 464 done:
|
Line 469 done:
|
/* |
/* |
* Parse sudoers after editing and re-edit any ones that caused a parse error. |
* Parse sudoers after editing and re-edit any ones that caused a parse error. |
*/ |
*/ |
static void | static bool |
reparse_sudoers(char *editor, char *args, bool strict, bool quiet) |
reparse_sudoers(char *editor, char *args, bool strict, bool quiet) |
{ |
{ |
struct sudoersfile *sp, *last; |
struct sudoersfile *sp, *last; |
Line 475 reparse_sudoers(char *editor, char *args, bool strict,
|
Line 480 reparse_sudoers(char *editor, char *args, bool strict,
|
/* |
/* |
* Parse the edited sudoers files and do sanity checking |
* Parse the edited sudoers files and do sanity checking |
*/ |
*/ |
do { | while ((sp = TAILQ_FIRST(&sudoerslist)) != NULL) { |
sp = tq_first(&sudoerslist); | last = TAILQ_LAST(&sudoerslist, sudoersfile_list); |
last = tq_last(&sudoerslist); | |
fp = fopen(sp->tpath, "r+"); |
fp = fopen(sp->tpath, "r+"); |
if (fp == NULL) |
if (fp == NULL) |
errorx(1, _("unable to re-open temporary file (%s), %s unchanged."), | fatalx(U_("unable to re-open temporary file (%s), %s unchanged."), |
sp->tpath, sp->path); |
sp->tpath, sp->path); |
|
|
/* Clean slate for each parse */ |
/* Clean slate for each parse */ |
init_defaults(); |
init_defaults(); |
init_parser(sp->path, quiet); |
init_parser(sp->path, quiet); |
|
|
/* Parse the sudoers temp file */ | /* Parse the sudoers temp file(s) */ |
yyrestart(fp); | sudoersrestart(fp); |
if (yyparse() && !parse_error) { | if (sudoersparse() && !parse_error) { |
warningx(_("unabled to parse temporary file (%s), unknown error"), | warningx(U_("unabled to parse temporary file (%s), unknown error"), |
sp->tpath); |
sp->tpath); |
parse_error = true; |
parse_error = true; |
errorfile = sp->path; |
errorfile = sp->path; |
} |
} |
fclose(yyin); | fclose(sudoersin); |
if (!parse_error) { |
if (!parse_error) { |
if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER) || | if (!check_defaults(SETDEF_ALL, quiet) || |
check_aliases(strict, quiet) != 0) { |
check_aliases(strict, quiet) != 0) { |
parse_error = true; |
parse_error = true; |
errorfile = sp->path; | errorfile = NULL; |
} |
} |
} |
} |
|
|
/* |
/* |
* Got an error, prompt the user for what to do now | * Got an error, prompt the user for what to do now. |
*/ |
*/ |
if (parse_error) { |
if (parse_error) { |
switch (whatnow()) { |
switch (whatnow()) { |
case 'Q' : parse_error = false; /* ignore parse error */ | case 'Q': |
break; | parse_error = false; /* ignore parse error */ |
case 'x' : /* XXX - should return instead of exiting */ | break; |
cleanup(0); | case 'x': |
sudo_debug_exit_int(__func__, __FILE__, | visudo_cleanup(); /* discard changes */ |
__LINE__, sudo_debug_subsys, 0); | debug_return_bool(false); |
exit(0); | case 'e': |
break; | default: |
} | /* Edit file with the parse error */ |
} | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
if (parse_error) { | if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) { |
/* Edit file with the parse error */ | edit_sudoers(sp, editor, args, errorlineno); |
tq_foreach_fwd(&sudoerslist, sp) { | if (errorfile != NULL) |
if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) { | break; |
edit_sudoers(sp, editor, args, errorlineno); | } |
break; | |
} |
} |
|
if (errorfile != NULL && sp == NULL) { |
|
fatalx(U_("internal error, unable to find %s in list!"), |
|
sudoers); |
|
} |
|
break; |
} |
} |
if (sp == NULL) { |
|
errorx(1, _("internal error, unable to find %s in list!"), |
|
sudoers); |
|
} |
|
} |
} |
|
|
/* If any new #include directives were added, edit them too. */ |
/* If any new #include directives were added, edit them too. */ |
for (sp = last->next; sp != NULL; sp = sp->next) { | for (sp = TAILQ_NEXT(last, entries); sp != NULL; sp = TAILQ_NEXT(sp, entries)) { |
printf(_("press return to edit %s: "), sp->path); |
printf(_("press return to edit %s: "), sp->path); |
while ((ch = getchar()) != EOF && ch != '\n') |
while ((ch = getchar()) != EOF && ch != '\n') |
continue; |
continue; |
edit_sudoers(sp, editor, args, errorlineno); |
edit_sudoers(sp, editor, args, errorlineno); |
} |
} |
} while (parse_error); |
|
|
|
debug_return; | /* If all sudoers files parsed OK we are done. */ |
| if (!parse_error) |
| break; |
| } |
| |
| debug_return_bool(true); |
} |
} |
|
|
/* |
/* |
Line 578 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
Line 586 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
if (oldperms) { |
if (oldperms) { |
/* Use perms of the existing file. */ |
/* Use perms of the existing file. */ |
if (fstat(sp->fd, &sb) == -1) |
if (fstat(sp->fd, &sb) == -1) |
error(1, _("unable to stat %s"), sp->path); | fatal(U_("unable to stat %s"), sp->path); |
if (chown(sp->tpath, sb.st_uid, sb.st_gid) != 0) { |
if (chown(sp->tpath, sb.st_uid, sb.st_gid) != 0) { |
warning(_("unable to set (uid, gid) of %s to (%u, %u)"), | warning(U_("unable to set (uid, gid) of %s to (%u, %u)"), |
sp->tpath, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid); |
sp->tpath, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid); |
} |
} |
if (chmod(sp->tpath, sb.st_mode & 0777) != 0) { |
if (chmod(sp->tpath, sb.st_mode & 0777) != 0) { |
warning(_("unable to change mode of %s to 0%o"), sp->tpath, | warning(U_("unable to change mode of %s to 0%o"), sp->tpath, |
(unsigned int)(sb.st_mode & 0777)); |
(unsigned int)(sb.st_mode & 0777)); |
} |
} |
} else { |
} else { |
if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { |
if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { |
warning(_("unable to set (uid, gid) of %s to (%u, %u)"), | warning(U_("unable to set (uid, gid) of %s to (%u, %u)"), |
sp->tpath, SUDOERS_UID, SUDOERS_GID); |
sp->tpath, SUDOERS_UID, SUDOERS_GID); |
goto done; |
goto done; |
} |
} |
if (chmod(sp->tpath, SUDOERS_MODE) != 0) { |
if (chmod(sp->tpath, SUDOERS_MODE) != 0) { |
warning(_("unable to change mode of %s to 0%o"), sp->tpath, | warning(U_("unable to change mode of %s to 0%o"), sp->tpath, |
SUDOERS_MODE); |
SUDOERS_MODE); |
goto done; |
goto done; |
} |
} |
Line 611 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
Line 619 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
} else { |
} else { |
if (errno == EXDEV) { |
if (errno == EXDEV) { |
char *av[4]; |
char *av[4]; |
warningx(_("%s and %s not on the same file system, using mv to rename"), | warningx(U_("%s and %s not on the same file system, using mv to rename"), |
sp->tpath, sp->path); |
sp->tpath, sp->path); |
|
|
/* Build up argument vector for the command */ |
/* Build up argument vector for the command */ |
Line 625 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
Line 633 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
|
|
/* And run it... */ |
/* And run it... */ |
if (run_command(_PATH_MV, av)) { |
if (run_command(_PATH_MV, av)) { |
warningx(_("command failed: '%s %s %s', %s unchanged"), | warningx(U_("command failed: '%s %s %s', %s unchanged"), |
_PATH_MV, sp->tpath, sp->path, sp->path); |
_PATH_MV, sp->tpath, sp->path, sp->path); |
(void) unlink(sp->tpath); |
(void) unlink(sp->tpath); |
efree(sp->tpath); |
efree(sp->tpath); |
Line 635 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
Line 643 install_sudoers(struct sudoersfile *sp, bool oldperms)
|
efree(sp->tpath); |
efree(sp->tpath); |
sp->tpath = NULL; |
sp->tpath = NULL; |
} else { |
} else { |
warning(_("error renaming %s, %s unchanged"), sp->tpath, sp->path); | warning(U_("error renaming %s, %s unchanged"), sp->tpath, sp->path); |
(void) unlink(sp->tpath); |
(void) unlink(sp->tpath); |
goto done; |
goto done; |
} |
} |
Line 647 done:
|
Line 655 done:
|
|
|
/* STUB */ |
/* STUB */ |
void |
void |
set_fqdn(void) |
|
{ |
|
return; |
|
} |
|
|
|
/* STUB */ |
|
void |
|
init_envtables(void) |
init_envtables(void) |
{ |
{ |
return; |
return; |
Line 687 group_plugin_query(const char *user, const char *group
|
Line 688 group_plugin_query(const char *user, const char *group
|
return false; |
return false; |
} |
} |
|
|
|
/* STUB */ |
|
struct interface *get_interfaces(void) |
|
{ |
|
return NULL; |
|
} |
|
|
/* |
/* |
* Assuming a parse error occurred, prompt the user for what they want |
* Assuming a parse error occurred, prompt the user for what they want |
* to do now. Returns the first letter of their choice. |
* to do now. Returns the first letter of their choice. |
Line 732 setup_signals(void)
|
Line 739 setup_signals(void)
|
/* |
/* |
* Setup signal handlers to cleanup nicely. |
* Setup signal handlers to cleanup nicely. |
*/ |
*/ |
zero_bytes(&sa, sizeof(sa)); | memset(&sa, 0, sizeof(sa)); |
sigemptyset(&sa.sa_mask); |
sigemptyset(&sa.sa_mask); |
sa.sa_flags = SA_RESTART; |
sa.sa_flags = SA_RESTART; |
sa.sa_handler = quit; |
sa.sa_handler = quit; |
Line 753 run_command(char *path, char **argv)
|
Line 760 run_command(char *path, char **argv)
|
|
|
switch (pid = sudo_debug_fork()) { |
switch (pid = sudo_debug_fork()) { |
case -1: |
case -1: |
error(1, _("unable to execute %s"), path); | fatal(U_("unable to execute %s"), path); |
break; /* NOTREACHED */ |
break; /* NOTREACHED */ |
case 0: |
case 0: |
sudo_endpwent(); |
sudo_endpwent(); |
sudo_endgrent(); |
sudo_endgrent(); |
closefrom(STDERR_FILENO + 1); |
closefrom(STDERR_FILENO + 1); |
execv(path, argv); |
execv(path, argv); |
warning(_("unable to run %s"), path); | warning(U_("unable to run %s"), path); |
_exit(127); |
_exit(127); |
break; /* NOTREACHED */ |
break; /* NOTREACHED */ |
} |
} |
Line 808 check_syntax(char *sudoers_path, bool quiet, bool stri
|
Line 815 check_syntax(char *sudoers_path, bool quiet, bool stri
|
debug_decl(check_syntax, SUDO_DEBUG_UTIL) |
debug_decl(check_syntax, SUDO_DEBUG_UTIL) |
|
|
if (strcmp(sudoers_path, "-") == 0) { |
if (strcmp(sudoers_path, "-") == 0) { |
yyin = stdin; | sudoersin = stdin; |
sudoers_path = "stdin"; |
sudoers_path = "stdin"; |
} else if ((yyin = fopen(sudoers_path, "r")) == NULL) { | } else if ((sudoersin = fopen(sudoers_path, "r")) == NULL) { |
if (!quiet) |
if (!quiet) |
warning(_("unable to open %s"), sudoers_path); | warning(U_("unable to open %s"), sudoers_path); |
goto done; |
goto done; |
} |
} |
init_parser(sudoers_path, quiet); |
init_parser(sudoers_path, quiet); |
if (yyparse() && !parse_error) { | if (sudoersparse() && !parse_error) { |
if (!quiet) |
if (!quiet) |
warningx(_("failed to parse %s file, unknown error"), sudoers_path); | warningx(U_("failed to parse %s file, unknown error"), sudoers_path); |
parse_error = true; |
parse_error = true; |
errorfile = sudoers_path; |
errorfile = sudoers_path; |
} |
} |
if (!parse_error && check_aliases(strict, quiet) != 0) { | if (!parse_error) { |
parse_error = true; | if (!check_defaults(SETDEF_ALL, quiet) || |
errorfile = sudoers_path; | check_aliases(strict, quiet) != 0) { |
| parse_error = true; |
| errorfile = NULL; |
| } |
} |
} |
ok = !parse_error; |
ok = !parse_error; |
|
|
Line 833 check_syntax(char *sudoers_path, bool quiet, bool stri
|
Line 843 check_syntax(char *sudoers_path, bool quiet, bool stri
|
if (errorlineno != -1) |
if (errorlineno != -1) |
(void) printf(_("parse error in %s near line %d\n"), |
(void) printf(_("parse error in %s near line %d\n"), |
errorfile, errorlineno); |
errorfile, errorlineno); |
else | else if (errorfile != NULL) |
(void) printf(_("parse error in %s\n"), errorfile); |
(void) printf(_("parse error in %s\n"), errorfile); |
} |
} |
} else { |
} else { |
struct sudoersfile *sp; |
struct sudoersfile *sp; |
|
|
/* Parsed OK, check mode and owner. */ |
/* Parsed OK, check mode and owner. */ |
if (oldperms || check_owner(sudoers_path, quiet)) | if (oldperms || check_owner(sudoers_path, quiet)) { |
(void) printf(_("%s: parsed OK\n"), sudoers_path); | if (!quiet) |
else | (void) printf(_("%s: parsed OK\n"), sudoers_path); |
| } else { |
ok = false; |
ok = false; |
tq_foreach_fwd(&sudoerslist, sp) { | } |
if (oldperms || check_owner(sp->path, quiet)) | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
(void) printf(_("%s: parsed OK\n"), sp->path); | if (oldperms || check_owner(sp->path, quiet)) { |
else | if (!quiet) |
| (void) printf(_("%s: parsed OK\n"), sp->path); |
| } else { |
ok = false; |
ok = false; |
|
} |
} |
} |
} |
} |
|
|
Line 874 open_sudoers(const char *path, bool doedit, bool *keep
|
Line 888 open_sudoers(const char *path, bool doedit, bool *keep
|
open_flags = O_RDWR | O_CREAT; |
open_flags = O_RDWR | O_CREAT; |
|
|
/* Check for existing entry */ |
/* Check for existing entry */ |
tq_foreach_fwd(&sudoerslist, entry) { | TAILQ_FOREACH(entry, &sudoerslist, entries) { |
if (strcmp(path, entry->path) == 0) |
if (strcmp(path, entry->path) == 0) |
break; |
break; |
} |
} |
Line 882 open_sudoers(const char *path, bool doedit, bool *keep
|
Line 896 open_sudoers(const char *path, bool doedit, bool *keep
|
entry = ecalloc(1, sizeof(*entry)); |
entry = ecalloc(1, sizeof(*entry)); |
entry->path = estrdup(path); |
entry->path = estrdup(path); |
/* entry->modified = 0; */ |
/* entry->modified = 0; */ |
entry->prev = entry; |
|
/* entry->next = NULL; */ |
|
entry->fd = open(entry->path, open_flags, SUDOERS_MODE); |
entry->fd = open(entry->path, open_flags, SUDOERS_MODE); |
/* entry->tpath = NULL; */ |
/* entry->tpath = NULL; */ |
entry->doedit = doedit; |
entry->doedit = doedit; |
Line 893 open_sudoers(const char *path, bool doedit, bool *keep
|
Line 905 open_sudoers(const char *path, bool doedit, bool *keep
|
debug_return_ptr(NULL); |
debug_return_ptr(NULL); |
} |
} |
if (!checkonly && !lock_file(entry->fd, SUDO_TLOCK)) |
if (!checkonly && !lock_file(entry->fd, SUDO_TLOCK)) |
errorx(1, _("%s busy, try again later"), entry->path); | fatalx(U_("%s busy, try again later"), entry->path); |
if ((fp = fdopen(entry->fd, "r")) == NULL) |
if ((fp = fdopen(entry->fd, "r")) == NULL) |
error(1, "%s", entry->path); | fatal("%s", entry->path); |
tq_append(&sudoerslist, entry); | TAILQ_INSERT_TAIL(&sudoerslist, entry, entries); |
} else { |
} else { |
/* Already exists, open .tmp version if there is one. */ |
/* Already exists, open .tmp version if there is one. */ |
if (entry->tpath != NULL) { |
if (entry->tpath != NULL) { |
if ((fp = fopen(entry->tpath, "r")) == NULL) |
if ((fp = fopen(entry->tpath, "r")) == NULL) |
error(1, "%s", entry->tpath); | fatal("%s", entry->tpath); |
} else { |
} else { |
if ((fp = fdopen(entry->fd, "r")) == NULL) |
if ((fp = fdopen(entry->fd, "r")) == NULL) |
error(1, "%s", entry->path); | fatal("%s", entry->path); |
rewind(fp); |
rewind(fp); |
} |
} |
} |
} |
Line 937 get_editor(char **args)
|
Line 949 get_editor(char **args)
|
} else { |
} else { |
if (def_env_editor) { |
if (def_env_editor) { |
/* If we are honoring $EDITOR this is a fatal error. */ |
/* If we are honoring $EDITOR this is a fatal error. */ |
errorx(1, _("specified editor (%s) doesn't exist"), UserEditor); | fatalx(U_("specified editor (%s) doesn't exist"), UserEditor); |
} else { |
} else { |
/* Otherwise, just ignore $EDITOR. */ |
/* Otherwise, just ignore $EDITOR. */ |
UserEditor = NULL; |
UserEditor = NULL; |
Line 960 get_editor(char **args)
|
Line 972 get_editor(char **args)
|
|
|
if (stat(UserEditor, &user_editor_sb) != 0) { |
if (stat(UserEditor, &user_editor_sb) != 0) { |
/* Should never happen since we already checked above. */ |
/* Should never happen since we already checked above. */ |
error(1, _("unable to stat editor (%s)"), UserEditor); | fatal(U_("unable to stat editor (%s)"), UserEditor); |
} |
} |
EditorPath = estrdup(def_editor); |
EditorPath = estrdup(def_editor); |
Editor = strtok(EditorPath, ":"); |
Editor = strtok(EditorPath, ":"); |
Line 1008 get_editor(char **args)
|
Line 1020 get_editor(char **args)
|
|
|
/* Bleah, none of the editors existed! */ |
/* Bleah, none of the editors existed! */ |
if (Editor == NULL || *Editor == '\0') |
if (Editor == NULL || *Editor == '\0') |
errorx(1, _("no editor found (editor path = %s)"), def_editor); | fatalx(U_("no editor found (editor path = %s)"), def_editor); |
} |
} |
*args = EditorArgs; |
*args = EditorArgs; |
debug_return_str(Editor); |
debug_return_str(Editor); |
Line 1040 get_args(char *cmnd)
|
Line 1052 get_args(char *cmnd)
|
static void |
static void |
get_hostname(void) |
get_hostname(void) |
{ |
{ |
char *p, thost[MAXHOSTNAMELEN + 1]; | char *p, thost[HOST_NAME_MAX + 1]; |
debug_decl(get_hostname, SUDO_DEBUG_UTIL) |
debug_decl(get_hostname, SUDO_DEBUG_UTIL) |
|
|
if (gethostname(thost, sizeof(thost)) != -1) { |
if (gethostname(thost, sizeof(thost)) != -1) { |
Line 1057 get_hostname(void)
|
Line 1069 get_hostname(void)
|
} else { |
} else { |
user_host = user_shost = "localhost"; |
user_host = user_shost = "localhost"; |
} |
} |
|
user_runhost = user_host; |
|
user_srunhost = user_shost; |
debug_return; |
debug_return; |
} |
} |
|
|
Line 1068 alias_remove_recursive(char *name, int type)
|
Line 1082 alias_remove_recursive(char *name, int type)
|
bool rval = true; |
bool rval = true; |
debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS) |
debug_decl(alias_remove_recursive, SUDO_DEBUG_ALIAS) |
|
|
if ((a = alias_find(name, type)) != NULL) { | if ((a = alias_remove(name, type)) != NULL) { |
tq_foreach_fwd(&a->members, m) { | TAILQ_FOREACH(m, &a->members, entries) { |
if (m->type == ALIAS) { |
if (m->type == ALIAS) { |
if (!alias_remove_recursive(m->name, type)) |
if (!alias_remove_recursive(m->name, type)) |
rval = false; |
rval = false; |
} |
} |
} |
} |
} |
|
alias_seqno++; |
|
a = alias_remove(name, type); |
|
if (a) |
|
rbinsert(alias_freelist, a); |
rbinsert(alias_freelist, a); |
|
} |
debug_return_bool(rval); |
debug_return_bool(rval); |
} |
} |
|
|
Line 1091 check_alias(char *name, int type, int strict, int quie
|
Line 1102 check_alias(char *name, int type, int strict, int quie
|
int errors = 0; |
int errors = 0; |
debug_decl(check_alias, SUDO_DEBUG_ALIAS) |
debug_decl(check_alias, SUDO_DEBUG_ALIAS) |
|
|
if ((a = alias_find(name, type)) != NULL) { | if ((a = alias_get(name, type)) != NULL) { |
/* check alias contents */ |
/* check alias contents */ |
tq_foreach_fwd(&a->members, m) { | TAILQ_FOREACH(m, &a->members, entries) { |
if (m->type == ALIAS) |
if (m->type == ALIAS) |
errors += check_alias(m->name, type, strict, quiet); |
errors += check_alias(m->name, type, strict, quiet); |
} |
} |
|
alias_put(a); |
} else { |
} else { |
if (!quiet) { |
if (!quiet) { |
char *fmt; |
|
if (errno == ELOOP) { |
if (errno == ELOOP) { |
fmt = strict ? | warningx(strict ? |
_("Error: cycle in %s_Alias `%s'") : | U_("Error: cycle in %s_Alias `%s'") : |
_("Warning: cycle in %s_Alias `%s'"); | U_("Warning: cycle in %s_Alias `%s'"), |
| type == HOSTALIAS ? "Host" : type == CMNDALIAS ? "Cmnd" : |
| type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" : |
| "Unknown", name); |
} else { |
} else { |
fmt = strict ? | warningx(strict ? |
_("Error: %s_Alias `%s' referenced but not defined") : | U_("Error: %s_Alias `%s' referenced but not defined") : |
_("Warning: %s_Alias `%s' referenced but not defined"); | U_("Warning: %s_Alias `%s' referenced but not defined"), |
| type == HOSTALIAS ? "Host" : type == CMNDALIAS ? "Cmnd" : |
| type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" : |
| "Unknown", name); |
} |
} |
warningx(fmt, |
|
type == HOSTALIAS ? "Host" : type == CMNDALIAS ? "Cmnd" : |
|
type == USERALIAS ? "User" : type == RUNASALIAS ? "Runas" : |
|
"Unknown", name); |
|
} |
} |
errors++; |
errors++; |
} |
} |
Line 1128 static int
|
Line 1141 static int
|
check_aliases(bool strict, bool quiet) |
check_aliases(bool strict, bool quiet) |
{ |
{ |
struct cmndspec *cs; |
struct cmndspec *cs; |
struct member *m, *binding; | struct member *m; |
struct privilege *priv; |
struct privilege *priv; |
struct userspec *us; |
struct userspec *us; |
struct defaults *d; |
struct defaults *d; |
Line 1138 check_aliases(bool strict, bool quiet)
|
Line 1151 check_aliases(bool strict, bool quiet)
|
alias_freelist = rbcreate(alias_compare); |
alias_freelist = rbcreate(alias_compare); |
|
|
/* Forward check. */ |
/* Forward check. */ |
tq_foreach_fwd(&userspecs, us) { | TAILQ_FOREACH(us, &userspecs, entries) { |
tq_foreach_fwd(&us->users, m) { | TAILQ_FOREACH(m, &us->users, entries) { |
if (m->type == ALIAS) { |
if (m->type == ALIAS) { |
alias_seqno++; |
|
errors += check_alias(m->name, USERALIAS, strict, quiet); |
errors += check_alias(m->name, USERALIAS, strict, quiet); |
} |
} |
} |
} |
tq_foreach_fwd(&us->privileges, priv) { | TAILQ_FOREACH(priv, &us->privileges, entries) { |
tq_foreach_fwd(&priv->hostlist, m) { | TAILQ_FOREACH(m, &priv->hostlist, entries) { |
if (m->type == ALIAS) { |
if (m->type == ALIAS) { |
alias_seqno++; |
|
errors += check_alias(m->name, HOSTALIAS, strict, quiet); |
errors += check_alias(m->name, HOSTALIAS, strict, quiet); |
} |
} |
} |
} |
tq_foreach_fwd(&priv->cmndlist, cs) { | TAILQ_FOREACH(cs, &priv->cmndlist, entries) { |
tq_foreach_fwd(&cs->runasuserlist, m) { | if (cs->runasuserlist != NULL) { |
if (m->type == ALIAS) { | TAILQ_FOREACH(m, cs->runasuserlist, entries) { |
alias_seqno++; | if (m->type == ALIAS) { |
errors += check_alias(m->name, RUNASALIAS, strict, quiet); | errors += check_alias(m->name, RUNASALIAS, strict, quiet); |
| } |
} |
} |
} |
} |
|
if (cs->runasgrouplist != NULL) { |
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) { |
|
if (m->type == ALIAS) { |
|
errors += check_alias(m->name, RUNASALIAS, strict, quiet); |
|
} |
|
} |
|
} |
if ((m = cs->cmnd)->type == ALIAS) { |
if ((m = cs->cmnd)->type == ALIAS) { |
alias_seqno++; |
|
errors += check_alias(m->name, CMNDALIAS, strict, quiet); |
errors += check_alias(m->name, CMNDALIAS, strict, quiet); |
} |
} |
} |
} |
Line 1168 check_aliases(bool strict, bool quiet)
|
Line 1186 check_aliases(bool strict, bool quiet)
|
} |
} |
|
|
/* Reverse check (destructive) */ |
/* Reverse check (destructive) */ |
tq_foreach_fwd(&userspecs, us) { | TAILQ_FOREACH(us, &userspecs, entries) { |
tq_foreach_fwd(&us->users, m) { | TAILQ_FOREACH(m, &us->users, entries) { |
if (m->type == ALIAS) { |
if (m->type == ALIAS) { |
alias_seqno++; |
|
if (!alias_remove_recursive(m->name, USERALIAS)) |
if (!alias_remove_recursive(m->name, USERALIAS)) |
errors++; |
errors++; |
} |
} |
} |
} |
tq_foreach_fwd(&us->privileges, priv) { | TAILQ_FOREACH(priv, &us->privileges, entries) { |
tq_foreach_fwd(&priv->hostlist, m) { | TAILQ_FOREACH(m, &priv->hostlist, entries) { |
if (m->type == ALIAS) { |
if (m->type == ALIAS) { |
alias_seqno++; |
|
if (!alias_remove_recursive(m->name, HOSTALIAS)) |
if (!alias_remove_recursive(m->name, HOSTALIAS)) |
errors++; |
errors++; |
} |
} |
} |
} |
tq_foreach_fwd(&priv->cmndlist, cs) { | TAILQ_FOREACH(cs, &priv->cmndlist, entries) { |
tq_foreach_fwd(&cs->runasuserlist, m) { | if (cs->runasuserlist != NULL) { |
if (m->type == ALIAS) { | TAILQ_FOREACH(m, cs->runasuserlist, entries) { |
alias_seqno++; | if (m->type == ALIAS) { |
if (!alias_remove_recursive(m->name, RUNASALIAS)) | if (!alias_remove_recursive(m->name, RUNASALIAS)) |
errors++; | errors++; |
| } |
} |
} |
} |
} |
|
if (cs->runasgrouplist != NULL) { |
|
TAILQ_FOREACH(m, cs->runasgrouplist, entries) { |
|
if (m->type == ALIAS) { |
|
if (!alias_remove_recursive(m->name, RUNASALIAS)) |
|
errors++; |
|
} |
|
} |
|
} |
if ((m = cs->cmnd)->type == ALIAS) { |
if ((m = cs->cmnd)->type == ALIAS) { |
alias_seqno++; |
|
if (!alias_remove_recursive(m->name, CMNDALIAS)) |
if (!alias_remove_recursive(m->name, CMNDALIAS)) |
errors++; |
errors++; |
} |
} |
} |
} |
} |
} |
} |
} |
tq_foreach_fwd(&defaults, d) { | TAILQ_FOREACH(d, &defaults, entries) { |
switch (d->type) { |
switch (d->type) { |
case DEFAULTS_HOST: |
case DEFAULTS_HOST: |
atype = HOSTALIAS; |
atype = HOSTALIAS; |
Line 1217 check_aliases(bool strict, bool quiet)
|
Line 1241 check_aliases(bool strict, bool quiet)
|
default: |
default: |
continue; /* not an alias */ |
continue; /* not an alias */ |
} |
} |
tq_foreach_fwd(&d->binding, binding) { | TAILQ_FOREACH(m, d->binding, entries) { |
for (m = binding; m != NULL; m = m->next) { | if (m->type == ALIAS) { |
if (m->type == ALIAS) { | if (!alias_remove_recursive(m->name, atype)) |
alias_seqno++; | errors++; |
if (!alias_remove_recursive(m->name, atype)) | |
errors++; | |
} | |
} |
} |
} |
} |
} |
} |
Line 1242 print_unused(void *v1, void *v2)
|
Line 1263 print_unused(void *v1, void *v2)
|
struct alias *a = (struct alias *)v1; |
struct alias *a = (struct alias *)v1; |
char *prefix = (char *)v2; |
char *prefix = (char *)v2; |
|
|
warningx2(_("%s: unused %s_Alias %s"), prefix, | warningx_nodebug(U_("%s: unused %s_Alias %s"), prefix, |
a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" : |
a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" : |
a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" : |
a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" : |
"Unknown", a->name); |
"Unknown", a->name); |
Line 1252 print_unused(void *v1, void *v2)
|
Line 1273 print_unused(void *v1, void *v2)
|
/* |
/* |
* Unlink any sudoers temp files that remain. |
* Unlink any sudoers temp files that remain. |
*/ |
*/ |
void | static void |
cleanup(int gotsignal) | visudo_cleanup(void) |
{ |
{ |
struct sudoersfile *sp; |
struct sudoersfile *sp; |
|
|
tq_foreach_fwd(&sudoerslist, sp) { | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
if (sp->tpath != NULL) |
if (sp->tpath != NULL) |
(void) unlink(sp->tpath); |
(void) unlink(sp->tpath); |
} |
} |
if (!gotsignal) { | sudo_endpwent(); |
sudo_endpwent(); | sudo_endgrent(); |
sudo_endgrent(); | |
} | |
} |
} |
|
|
/* |
/* |
Line 1273 cleanup(int gotsignal)
|
Line 1292 cleanup(int gotsignal)
|
static void |
static void |
quit(int signo) |
quit(int signo) |
{ |
{ |
const char *signame, *myname; | struct sudoersfile *sp; |
| struct iovec iov[4]; |
|
|
cleanup(signo); | TAILQ_FOREACH(sp, &sudoerslist, entries) { |
| if (sp->tpath != NULL) |
| (void) unlink(sp->tpath); |
| } |
| |
#define emsg " exiting due to signal: " |
#define emsg " exiting due to signal: " |
myname = getprogname(); | iov[0].iov_base = (char *)getprogname(); |
signame = strsignal(signo); | iov[0].iov_len = strlen(iov[0].iov_base); |
ignore_result(write(STDERR_FILENO, myname, strlen(myname))); | iov[1].iov_base = emsg; |
ignore_result(write(STDERR_FILENO, emsg, sizeof(emsg) - 1)); | iov[1].iov_len = sizeof(emsg) - 1; |
ignore_result(write(STDERR_FILENO, signame, strlen(signame))); | iov[2].iov_base = strsignal(signo); |
ignore_result(write(STDERR_FILENO, "\n", 1)); | iov[2].iov_len = strlen(iov[2].iov_base); |
| iov[3].iov_base = "\n"; |
| iov[3].iov_len = 1; |
| ignore_result(writev(STDERR_FILENO, iov, 4)); |
_exit(signo); |
_exit(signo); |
} |
} |
|
|
Line 1290 static void
|
Line 1317 static void
|
usage(int fatal) |
usage(int fatal) |
{ |
{ |
(void) fprintf(fatal ? stderr : stdout, |
(void) fprintf(fatal ? stderr : stdout, |
"usage: %s [-chqsV] [-f sudoers]\n", getprogname()); | "usage: %s [-chqsV] [-f sudoers] [-x file]\n", getprogname()); |
if (fatal) |
if (fatal) |
exit(1); |
exit(1); |
} |
} |
Line 1301 help(void)
|
Line 1328 help(void)
|
(void) printf(_("%s - safely edit the sudoers file\n\n"), getprogname()); |
(void) printf(_("%s - safely edit the sudoers file\n\n"), getprogname()); |
usage(0); |
usage(0); |
(void) puts(_("\nOptions:\n" |
(void) puts(_("\nOptions:\n" |
" -c check-only mode\n" | " -c, --check check-only mode\n" |
" -f sudoers specify sudoers file location\n" | " -f, --file=file specify sudoers file location\n" |
" -h display help message and exit\n" | " -h, --help display help message and exit\n" |
" -q less verbose (quiet) syntax error messages\n" | " -q, --quiet less verbose (quiet) syntax error messages\n" |
" -s strict syntax checking\n" | " -s, --strict strict syntax checking\n" |
" -V display version information and exit")); | " -V, --version display version information and exit\n" |
| " -x, --export=file export sudoers in JSON format")); |
exit(0); |
exit(0); |
} |
|
|
|
static int |
|
visudo_printf(int msg_type, const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
FILE *fp; |
|
|
|
switch (msg_type) { |
|
case SUDO_CONV_INFO_MSG: |
|
fp = stdout; |
|
break; |
|
case SUDO_CONV_ERROR_MSG: |
|
fp = stderr; |
|
break; |
|
default: |
|
errno = EINVAL; |
|
return -1; |
|
} |
|
|
|
va_start(ap, fmt); |
|
vfprintf(fp, fmt, ap); |
|
va_end(ap); |
|
|
|
return 0; |
|
} |
} |