diff --git a/MANIFEST b/MANIFEST index 244ae236d..da3bbd67d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -161,7 +161,6 @@ lib/util/strtonum.c lib/util/sudo_conf.c lib/util/sudo_debug.c lib/util/sudo_dso.c -lib/util/sudo_printf.c lib/util/term.c lib/util/ttysize.c lib/util/util.exp.in @@ -429,6 +428,7 @@ plugins/sudoers/solaris_audit.h plugins/sudoers/sssd.c plugins/sudoers/sudo_nss.c plugins/sudoers/sudo_nss.h +plugins/sudoers/sudo_printf.c plugins/sudoers/sudoers.c plugins/sudoers/sudoers.exp plugins/sudoers/sudoers.h diff --git a/include/sudo_fatal.h b/include/sudo_fatal.h index 37dafb075..9c1c7833d 100644 --- a/include/sudo_fatal.h +++ b/include/sudo_fatal.h @@ -114,6 +114,9 @@ typedef void (*sudo_fatal_callback_t)(void); +struct sudo_conv_message; +struct sudo_conv_reply; + __dso_public int sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func); __dso_public int sudo_fatal_callback_register_v1(sudo_fatal_callback_t func); __dso_public char *sudo_warn_gettext_v1(const char *msgid) __format_arg(1); @@ -126,6 +129,7 @@ __dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) __printf0like(1, 2) __dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) __printflike(1, 2); __dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0); __dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0); +__dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const struct sudo_conv_message *msgs, struct sudo_conv_reply *replies)); #define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a)) #define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_v1((_a)) @@ -139,5 +143,6 @@ __dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printfli #define sudo_warnx_nodebug sudo_warnx_nodebug_v1 #define sudo_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b)) #define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_nodebug_v1((_a), (_b)) +#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a) #endif /* _SUDO_FATAL_H_ */ diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in index a65f86325..f495a95bb 100644 --- a/lib/util/Makefile.in +++ b/lib/util/Makefile.in @@ -98,7 +98,7 @@ SHELL = @SHELL@ LTOBJS = alloc.lo event.lo fatal.lo key_val.lo gidlist.lo lbuf.lo locking.lo \ parseln.lo progname.lo secure_path.lo setgroups.lo strtobool.lo \ strtoid.lo strtomode.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo \ - sudo_printf.lo term.lo ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@ + term.lo ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@ ATOFOO_TEST_OBJS = atofoo_test.lo locale_stub.lo @@ -494,10 +494,6 @@ sudo_debug.lo: $(srcdir)/sudo_debug.c $(incdir)/compat/stdbool.h \ sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \ $(top_builddir)/config.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_dso.c -sudo_printf.lo: $(srcdir)/sudo_printf.c $(incdir)/sudo_compat.h \ - $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \ - $(top_builddir)/config.h - $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_printf.c term.lo: $(srcdir)/term.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_debug.h $(incdir)/sudo_util.h $(top_builddir)/config.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/term.c diff --git a/lib/util/fatal.c b/lib/util/fatal.c index f337c002c..15d1f8b70 100644 --- a/lib/util/fatal.c +++ b/lib/util/fatal.c @@ -44,7 +44,8 @@ struct sudo_fatal_callback { }; SLIST_HEAD(sudo_fatal_callback_list, sudo_fatal_callback); -static struct sudo_fatal_callback_list callbacks; +static struct sudo_fatal_callback_list callbacks = SLIST_HEAD_INITIALIZER(&callbacks); +static sudo_conv_t sudo_warn_conversation; static void _warning(int errnum, const char *fmt, va_list ap); @@ -135,24 +136,44 @@ sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) static void _warning(int errnum, const char *fmt, va_list ap) { - char *str; + if (sudo_warn_conversation != NULL) { + struct sudo_conv_message msgs[6]; + int nmsgs = 0; + char *str = NULL; - sudo_evasprintf(&str, fmt, ap); - if (errnum) { - if (fmt != NULL) { - sudo_printf(SUDO_CONV_ERROR_MSG, - _("%s: %s: %s\n"), getprogname(), str, - sudo_warn_strerror(errnum)); - } else { - sudo_printf(SUDO_CONV_ERROR_MSG, - _("%s: %s\n"), getprogname(), - sudo_warn_strerror(errnum)); - } + /* Use conversation function. */ + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = getprogname(); + if (fmt != NULL) { + sudo_evasprintf(&str, fmt, ap); + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = ": "; + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = str; + } + if (errnum) { + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = ": "; + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = sudo_warn_strerror(errnum); + } + msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG; + msgs[nmsgs++].msg = "\n"; + sudo_warn_conversation(nmsgs, msgs, NULL); + sudo_efree(str); } else { - sudo_printf(SUDO_CONV_ERROR_MSG, - _("%s: %s\n"), getprogname(), str ? str : "(null)"); + /* Write to the standard error. */ + fputs(getprogname(), stderr); + if (fmt != NULL) { + fputs(": ", stderr); + vfprintf(stderr, fmt, ap); + } + if (errnum) { + fputs(": ", stderr); + fputs(sudo_warn_strerror(errnum), stderr); + } + putc('\n', stderr); } - sudo_efree(str); } /* @@ -201,3 +222,13 @@ sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func) return -1; } + +/* + * Set the conversation function to use for output insteaf of the + * standard error. If conv is NULL, switch back to standard error. + */ +void +sudo_warn_set_conversation_v1(sudo_conv_t conv) +{ + sudo_warn_conversation = conv; +} diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in index 9e308f795..4ee154930 100644 --- a/lib/util/util.exp.in +++ b/lib/util/util.exp.in @@ -1,4 +1,4 @@ -@COMPAT_EXP@_sudo_printf +@COMPAT_EXP@ initprogname sudo_conf_askpass_path_v1 sudo_conf_debug_flags_v1 @@ -70,7 +70,6 @@ sudo_lock_file_v1 sudo_new_key_val_v1 sudo_parse_gids_v1 sudo_parseln_v1 -sudo_printf sudo_secure_dir_v1 sudo_secure_file_v1 sudo_setgroups_v1 @@ -90,3 +89,4 @@ sudo_vwarn_nodebug_v1 sudo_vwarnx_nodebug_v1 sudo_warn_nodebug_v1 sudo_warnx_nodebug_v1 +sudo_warn_set_conversation_v1 diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 487314bc2..6fce1a49c 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -138,7 +138,7 @@ AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \ gram.lo match.lo match_addr.lo pwutil.lo pwutil_impl.lo \ - timestr.lo toke.lo toke_util.lo redblack.lo + redblack.lo timestr.lo toke.lo toke_util.lo SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo find_path.lo \ goodpath.lo group_plugin.lo interfaces.lo iolog.lo \ @@ -146,14 +146,15 @@ 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 = find_path.o goodpath.o locale.o visudo.o visudo_json.o +VISUDO_OBJS = find_path.o goodpath.o locale.o sudo_printf.o visudo.o \ + visudo_json.o REPLAY_OBJS = getdate.o locale.o sudoreplay.o TEST_OBJS = group_plugin.o interfaces.o locale.o net_ifs.o \ - testsudoers.o tsgetgrpw.o + sudo_printf.o testsudoers.o tsgetgrpw.o -CHECK_ADDR_OBJS = check_addr.o interfaces.o locale.o match_addr.o +CHECK_ADDR_OBJS = check_addr.o interfaces.o locale.o match_addr.o sudo_printf.o CHECK_BASE64_OBJS = check_base64.o base64.o locale.o @@ -896,6 +897,10 @@ sudo_nss.lo: $(srcdir)/sudo_nss.c $(devdir)/def_data.h \ $(srcdir)/logging.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \ $(top_builddir)/config.h $(top_builddir)/pathnames.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_nss.c +sudo_printf.o: $(srcdir)/sudo_printf.c $(incdir)/sudo_compat.h \ + $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \ + $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sudo_printf.c sudoers.lo: $(srcdir)/sudoers.c $(devdir)/def_data.h \ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \ $(incdir)/sudo_alloc.h $(incdir)/sudo_compat.h \ diff --git a/lib/util/sudo_printf.c b/plugins/sudoers/sudo_printf.c similarity index 95% rename from lib/util/sudo_printf.c rename to plugins/sudoers/sudo_printf.c index 03d5ed15f..474e0e2a4 100644 --- a/lib/util/sudo_printf.c +++ b/plugins/sudoers/sudo_printf.c @@ -33,7 +33,7 @@ #include "sudo_plugin.h" #include "sudo_debug.h" -__dso_public int +static int _sudo_printf(int msg_type, const char *fmt, ...) { va_list ap; @@ -59,4 +59,4 @@ _sudo_printf(int msg_type, const char *fmt, ...) return len; } -__dso_public sudo_printf_t sudo_printf = _sudo_printf; +sudo_printf_t sudo_printf = _sudo_printf; diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 8a3a84171..bce4fa5e3 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -104,6 +104,7 @@ uid_t timestamp_uid; char *login_style; #endif /* HAVE_BSD_AUTH_H */ int sudo_mode; +sudo_printf_t sudo_printf; static char *prev_user; static char *runas_user; diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index d04201592..e13fec60e 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -364,6 +364,7 @@ extern int long_list; extern int sudo_mode; extern uid_t timestamp_uid; extern sudo_conv_t sudo_conv; +extern sudo_printf_t sudo_printf; #endif #endif /* _SUDOERS_SUDOERS_H */ diff --git a/src/conversation.c b/src/conversation.c index b23a41874..f48deac89 100644 --- a/src/conversation.c +++ b/src/conversation.c @@ -111,3 +111,29 @@ err: return -1; } + +int +sudo_conversation_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + int len; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + va_start(ap, fmt); + len = vfprintf(stdout, fmt, ap); + va_end(ap); + break; + case SUDO_CONV_ERROR_MSG: + va_start(ap, fmt); + len = vfprintf(stderr, fmt, ap); + va_end(ap); + break; + default: + len = -1; + errno = EINVAL; + break; + } + + return len; +} diff --git a/src/sudo.c b/src/sudo.c index 164014c41..05d5214a5 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -168,6 +168,9 @@ main(int argc, char *argv[], char *envp[]) # endif #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ + /* Use conversation function for sudo_(warn|fatal)x?. */ + sudo_warn_set_conversation(sudo_conversation); + /* Make sure we are setuid root. */ sudo_check_suid(argv[0]); @@ -1085,11 +1088,13 @@ policy_open(struct plugin_container *plugin, char * const settings[], case SUDO_API_MKVERSION(1, 0): case SUDO_API_MKVERSION(1, 1): rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version, - sudo_conversation, _sudo_printf, settings, user_info, user_env); + sudo_conversation, sudo_conversation_printf, settings, + user_info, user_env); break; default: rval = plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation, - _sudo_printf, settings, user_info, user_env, plugin->options); + sudo_conversation_printf, settings, user_info, user_env, + plugin->options); } debug_return_bool(rval); @@ -1205,17 +1210,17 @@ iolog_open(struct plugin_container *plugin, char * const settings[], switch (plugin->u.generic->version) { case SUDO_API_MKVERSION(1, 0): rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version, - sudo_conversation, _sudo_printf, settings, user_info, argc, argv, - user_env); + sudo_conversation, sudo_conversation_printf, settings, + user_info, argc, argv, user_env); break; case SUDO_API_MKVERSION(1, 1): rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version, - sudo_conversation, _sudo_printf, settings, user_info, - command_info, argc, argv, user_env); + sudo_conversation, sudo_conversation_printf, settings, + user_info, command_info, argc, argv, user_env); break; default: rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation, - _sudo_printf, settings, user_info, command_info, + sudo_conversation_printf, settings, user_info, command_info, argc, argv, user_env, plugin->options); } debug_return_bool(rval); diff --git a/src/sudo_plugin_int.h b/src/sudo_plugin_int.h index a1d3e9baa..2e0fb1709 100644 --- a/src/sudo_plugin_int.h +++ b/src/sudo_plugin_int.h @@ -101,7 +101,7 @@ extern struct plugin_container_list io_plugins; int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[]); -int _sudo_printf(int msg_type, const char *fmt, ...); +int sudo_conversation_printf(int msg_type, const char *fmt, ...); bool sudo_load_plugins(struct plugin_container *policy_plugin, struct plugin_container_list *io_plugins);