From 90147bb6056df4af190fde87405dd6d13c1d8119 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sun, 25 Nov 2012 09:33:52 -0500 Subject: [PATCH] Allow sudoers programs (visudo, sudoreplay, visudo) to use plugin_error.c instead of the error.c from the front-end. This means sudoers_setlocale() needs to be independent of the sudo_user struct and the defaults table. The sudoers locale is now updated via a callback. --- plugins/sudoers/Makefile.in | 25 +++++++++++-------------- plugins/sudoers/locale.c | 27 ++++++++++++++++++++++----- plugins/sudoers/logging.h | 1 + plugins/sudoers/sudoers.c | 17 ++++++++++++++++- plugins/sudoers/sudoers.h | 2 -- plugins/sudoers/sudoreplay.c | 9 +++++---- plugins/sudoers/testsudoers.c | 6 +++--- plugins/sudoers/visudo.c | 10 +++++----- 8 files changed, 63 insertions(+), 34 deletions(-) diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 9999d8da4..3157b9e8c 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -133,23 +133,23 @@ SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo find_path.lo \ policy.lo prompt.lo set_perms.lo sudo_nss.lo sudoers.lo \ timestamp.lo @SUDOERS_OBJS@ -VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o +VISUDO_OBJS = find_path.o goodpath.o locale.o plugin_error.o visudo.o -REPLAY_OBJS = getdate.o sudoreplay.o error.o +REPLAY_OBJS = getdate.o locale.o plugin_error.o sudoreplay.o -TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o error.o group_plugin.o \ - net_ifs.o +TEST_OBJS = group_plugin.o interfaces.o locale.o net_ifs.o plugin_error.o \ + testsudoers.o tsgetgrpw.o -CHECK_ADDR_OBJS = check_addr.o match_addr.o interfaces.o error.o +CHECK_ADDR_OBJS = check_addr.o interfaces.o locale.o match_addr.o plugin_error.o -CHECK_FILL_OBJS = check_fill.o toke_util.o error.o +CHECK_FILL_OBJS = check_fill.o locale.o plugin_error.o toke_util.o -CHECK_IOLOG_PATH_OBJS = check_iolog_path.o error.o iolog_path.o pwutil.o \ - pwutil_impl.o redblack.o +CHECK_IOLOG_PATH_OBJS = check_iolog_path.o iolog_path.o locale.o \ + plugin_error.o pwutil.o pwutil_impl.o redblack.o -CHECK_SYMBOLS_OBJS = check_symbols.o error.o +CHECK_SYMBOLS_OBJS = check_symbols.o locale.o plugin_error.o -CHECK_WRAP_OBJS = check_wrap.o logwrap.o error.o +CHECK_WRAP_OBJS = check_wrap.o locale.o logwrap.o plugin_error.o LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/ @@ -508,10 +508,6 @@ env.lo: $(srcdir)/env.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(DEFS) $(srcdir)/env.c -error.o: $(top_srcdir)/src/error.c $(top_builddir)/config.h \ - $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \ - $(incdir)/gettext.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(DEFS) $(top_srcdir)/src/error.c find_path.lo: $(srcdir)/find_path.c $(top_builddir)/config.h \ $(srcdir)/sudoers.h $(top_srcdir)/compat/stdbool.h \ $(top_builddir)/pathnames.h $(incdir)/missing.h \ @@ -684,6 +680,7 @@ plugin_error.lo: $(srcdir)/plugin_error.c $(top_builddir)/config.h \ $(incdir)/alloc.h $(incdir)/error.h $(srcdir)/logging.h \ $(incdir)/sudo_plugin.h $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(DEFS) $(srcdir)/plugin_error.c +plugin_error.o: plugin_error.lo policy.lo: $(srcdir)/policy.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \ diff --git a/plugins/sudoers/locale.c b/plugins/sudoers/locale.c index d0b72dcb9..4244b2f52 100644 --- a/plugins/sudoers/locale.c +++ b/plugins/sudoers/locale.c @@ -36,6 +36,8 @@ #include "sudoers.h" static int current_locale = SUDOERS_LOCALE_USER; +static char *user_locale; +static char *sudoers_locale; int sudoers_getlocale(void) @@ -43,6 +45,19 @@ sudoers_getlocale(void) return current_locale; } +void +sudoers_initlocale(const char *ulocale, const char *slocale) +{ + if (ulocale != NULL) { + efree(user_locale); + user_locale = estrdup(ulocale); + } + if (slocale != NULL) { + efree(sudoers_locale); + sudoers_locale = estrdup(slocale); + } +} + /* * Set locale to user or sudoers value. * Returns true on success and false on failure, @@ -61,6 +76,8 @@ sudoers_setlocale(int newlocale, int *prevlocale) if (current_locale != SUDOERS_LOCALE_USER) { current_locale = SUDOERS_LOCALE_USER; res = setlocale(LC_ALL, user_locale ? user_locale : ""); + if (res != NULL && user_locale == NULL) + user_locale = estrdup(setlocale(LC_ALL, NULL)); } break; case SUDOERS_LOCALE_SUDOERS: @@ -68,11 +85,11 @@ sudoers_setlocale(int newlocale, int *prevlocale) *prevlocale = current_locale; if (current_locale != SUDOERS_LOCALE_SUDOERS) { current_locale = SUDOERS_LOCALE_SUDOERS; - res = setlocale(LC_ALL, def_sudoers_locale); - if (res == NULL) { - if (strcmp(def_sudoers_locale, "C") != 0) { - efree(def_sudoers_locale); - def_sudoers_locale = estrdup("C"); + res = setlocale(LC_ALL, sudoers_locale ? sudoers_locale : "C"); + if (res == NULL && sudoers_locale != NULL) { + if (strcmp(sudoers_locale, "C") != 0) { + efree(sudoers_locale); + sudoers_locale = estrdup("C"); res = setlocale(LC_ALL, "C"); } } diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h index f89a1ed26..e3f4efd8b 100644 --- a/plugins/sudoers/logging.h +++ b/plugins/sudoers/logging.h @@ -68,6 +68,7 @@ void log_denial(int status, bool inform_user); void log_failure(int status, int flags); void log_error(int flags, const char *fmt, ...) __printflike(2, 3); void log_fatal(int flags, const char *fmt, ...) __printflike(2, 3) __attribute__((__noreturn__)); +void sudoers_initlocale(const char *ulocale, const char *slocale); void writeln_wrap(FILE *fp, char *line, size_t len, size_t maxlen); #endif /* _LOGGING_H */ diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 314fc05eb..7184a3b13 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -85,6 +85,7 @@ */ static char *find_editor(int nfiles, char **files, char ***argv_out); static int cb_runas_default(const char *); +static int cb_sudoers_locale(const char *); static int set_cmnd(void); static void create_admin_success_flag(void); static void init_vars(char * const *); @@ -548,7 +549,7 @@ init_vars(char * const envp[]) (void) tzset(); /* set the timezone if applicable */ #endif /* HAVE_TZSET */ - user_locale = estrdup(setlocale(LC_ALL, NULL)); + sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale); for (ep = envp; *ep; ep++) { /* XXX - don't fill in if empty string */ @@ -600,6 +601,9 @@ init_vars(char * const envp[]) /* Set runas callback. */ sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default; + /* Set locale callback. */ + sudo_defs_table[I_SUDOERS_LOCALE].callback = cb_sudoers_locale; + /* It is now safe to use log_fatal() and set_perms() */ debug_return; } @@ -897,6 +901,17 @@ cb_runas_default(const char *user) return true; } +/* +/* + * Callback for sudoers_locale sudoers setting. + */ +static int +cb_sudoers_locale(const char *locale) +{ + sudoers_initlocale(NULL, locale); + return true; +} + /* * Cleanup hook for error()/errorx() */ diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index a6572d573..8f2300210 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -88,7 +88,6 @@ struct sudo_user { #endif const char *cwd; char *iolog_file; - char *locale; GETGROUPS_T *gids; int ngids; int closefrom; @@ -182,7 +181,6 @@ struct sudo_user { #define user_tty (sudo_user.tty) #define user_ttypath (sudo_user.ttypath) #define user_cwd (sudo_user.cwd) -#define user_locale (sudo_user.locale) #define user_cmnd (sudo_user.cmnd) #define user_args (sudo_user.cmnd_args) #define user_base (sudo_user.cmnd_base) diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c index 81c2c2c7b..4f715cdc8 100644 --- a/plugins/sudoers/sudoreplay.c +++ b/plugins/sudoers/sudoreplay.c @@ -95,6 +95,7 @@ #include "alloc.h" #include "error.h" #include "gettext.h" +#include "logging.h" #include "sudo_plugin.h" #include "sudo_conf.h" #include "sudo_debug.h" @@ -201,7 +202,7 @@ extern char *get_timestr(time_t, int); extern int term_raw(int, int); extern int term_restore(int, int); extern void get_ttysize(int *rowp, int *colp); -void cleanup(int); +void sudoers_cleanup(int); static int list_sessions(int, char **, const char *, const char *, const char *); static int parse_expr(struct search_node **, char **); @@ -263,7 +264,7 @@ main(int argc, char *argv[]) setprogname(argc > 0 ? argv[0] : "sudoreplay"); #endif - setlocale(LC_ALL, ""); + sudoers_setlocale(SUDOERS_LOCALE_USER, NULL); decimal = localeconv()->decimal_point; bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have sudoreplay domain */ textdomain("sudoers"); @@ -377,7 +378,7 @@ main(int argc, char *argv[]) memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESETHAND; - sa.sa_handler = cleanup; + sa.sa_handler = sudoers_cleanup; (void) sigaction(SIGINT, &sa, NULL); (void) sigaction(SIGKILL, &sa, NULL); (void) sigaction(SIGTERM, &sa, NULL); @@ -1207,7 +1208,7 @@ help(void) * Cleanup hook for error()/errorx() */ void -cleanup(int signo) +sudoers_cleanup(int signo) { term_restore(STDIN_FILENO, 0); if (signo) diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 81498b011..ba503925c 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -78,7 +78,7 @@ void print_defaults(void); void print_privilege(struct privilege *); void print_userspecs(void); void usage(void) __attribute__((__noreturn__)); -void cleanup(int); +void sudoers_cleanup(int); static void set_runaspw(const char *); static void set_runasgr(const char *); static int cb_runas_default(const char *); @@ -148,7 +148,7 @@ main(int argc, char *argv[]) setprogname(argc > 0 ? argv[0] : "testsudoers"); #endif - setlocale(LC_ALL, ""); + sudoers_setlocale(SUDOERS_LOCALE_USER, NULL); bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have own domain */ textdomain("sudoers"); @@ -469,7 +469,7 @@ restore_perms(void) } void -cleanup(int gotsignal) +sudoers_cleanup(int gotsignal) { if (!gotsignal) { sudo_endpwent(); diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index f7893c031..45015050e 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -112,7 +112,7 @@ static void setup_signals(void); static void help(void) __attribute__((__noreturn__)); static void usage(int); -void cleanup(int); +void sudoers_cleanup(int); extern void sudoerserror(const char *); extern void sudoersrestart(FILE *); @@ -161,7 +161,7 @@ main(int argc, char *argv[]) setprogname(argc > 0 ? argv[0] : "visudo"); #endif - setlocale(LC_ALL, ""); + sudoers_setlocale(SUDOERS_LOCALE_USER, NULL); bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have visudo domain */ textdomain("sudoers"); @@ -510,7 +510,7 @@ reparse_sudoers(char *editor, char *args, bool strict, bool quiet) case 'Q' : parse_error = false; /* ignore parse error */ break; case 'x' : /* XXX - should return instead of exiting */ - cleanup(0); + sudoers_cleanup(0); sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 0); exit(0); @@ -1254,7 +1254,7 @@ print_unused(void *v1, void *v2) * Unlink any sudoers temp files that remain. */ void -cleanup(int gotsignal) +sudoers_cleanup(int gotsignal) { struct sudoersfile *sp; @@ -1276,7 +1276,7 @@ quit(int signo) { const char *signame, *myname; - cleanup(signo); + sudoers_cleanup(signo); #define emsg " exiting due to signal: " myname = getprogname(); signame = strsignal(signo); -- 2.40.0