From d67c64bb37fabb0368cd192168bd025eb3699ad8 Mon Sep 17 00:00:00 2001 From: Robert Manner Date: Thu, 23 Jan 2020 13:59:50 +0100 Subject: [PATCH] plugins/python/pyhelpers: have a default sudo_printf function Adapted the default sudo_printf from sudoers plugin to be able to print errors before plugin open() gets called. (This is used by the multiple io plugin loading to display error for too much plugin load.) Since this makes us always have a sudo_log, I have removed the logic about whether it is available or not. --- plugins/python/pyhelpers.c | 43 ++++++++++++++++--- plugins/python/pyhelpers.h | 2 - plugins/python/python_plugin_common.c | 3 +- .../python/regress/check_python_examples.c | 5 ++- ...mple_io_plugin_command_log_multiple.stderr | 1 + plugins/python/sudo_python_module.c | 5 --- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/plugins/python/pyhelpers.c b/plugins/python/pyhelpers.c index 44acfa437..d03f06bd6 100644 --- a/plugins/python/pyhelpers.c +++ b/plugins/python/pyhelpers.c @@ -25,16 +25,45 @@ #include #include +#include "pathnames.h" -static int _sudo_printf_noop(int msg_type, const char *fmt, ...) +static int +_sudo_printf_default(int msg_type, const char *fmt, ...) { - (void) msg_type; - (void) fmt; - return 0; + FILE *fp = stdout; + FILE *ttyfp = NULL; + va_list ap; + int len; + + if (ISSET(msg_type, SUDO_CONV_PREFER_TTY)) { + /* Try writing to /dev/tty first. */ + ttyfp = fopen(_PATH_TTY, "w"); + } + + switch (msg_type & 0xff) { + case SUDO_CONV_ERROR_MSG: + fp = stderr; + /* FALLTHROUGH */ + case SUDO_CONV_INFO_MSG: + va_start(ap, fmt); + len = vfprintf(ttyfp ? ttyfp : fp, fmt, ap); + va_end(ap); + break; + default: + len = -1; + errno = EINVAL; + break; + } + + if (ttyfp != NULL) + fclose(ttyfp); + + return len; } + struct PythonContext py_ctx = { - &_sudo_printf_noop, + &_sudo_printf_default, NULL, 0, NULL @@ -45,7 +74,7 @@ int py_is_sudo_log_available(void) { debug_decl(py_is_sudo_log_available, PYTHON_DEBUG_INTERNAL); - debug_return_int(py_ctx.sudo_log != &_sudo_printf_noop); + debug_return_int(py_ctx.sudo_log != &_sudo_printf_default); } char * @@ -408,7 +437,7 @@ void py_ctx_reset() { memset(&py_ctx, 0, sizeof(py_ctx)); - py_ctx.sudo_log = &_sudo_printf_noop; + py_ctx.sudo_log = &_sudo_printf_default; } int diff --git a/plugins/python/pyhelpers.h b/plugins/python/pyhelpers.h index 23f45330c..d8b2dd122 100644 --- a/plugins/python/pyhelpers.h +++ b/plugins/python/pyhelpers.h @@ -59,8 +59,6 @@ int py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[], void py_log_last_error(const char *context_message); -int py_is_sudo_log_available(void); - char *py_create_string_rep(PyObject *py_object); char *py_join_str_list(PyObject *py_str_list, const char *separator); diff --git a/plugins/python/python_plugin_common.c b/plugins/python/python_plugin_common.c index 1ac6fec12..060ce0ce5 100644 --- a/plugins/python/python_plugin_common.c +++ b/plugins/python/python_plugin_common.c @@ -194,7 +194,8 @@ python_plugin_register_logging(sudo_conv_t conversation, if (py_ctx.sudo_conv == NULL) py_ctx.sudo_conv = conversation; - py_ctx.sudo_log = sudo_printf; + if (sudo_printf) + py_ctx.sudo_log = sudo_printf; struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files); struct sudo_conf_debug_file_list *debug_files_ptr = &debug_files; diff --git a/plugins/python/regress/check_python_examples.c b/plugins/python/regress/check_python_examples.c index 597d91245..4802b0793 100644 --- a/plugins/python/regress/check_python_examples.c +++ b/plugins/python/regress/check_python_examples.c @@ -234,7 +234,6 @@ check_example_io_plugin_command_log_multiple(void) VERIFY_PTR_NE(python_io2, NULL); VERIFY_PTR_NE(python_io2, python_io); } - VERIFY_PTR((*python_io_clone)(), NULL); // no more available // open the first plugin and let it log to tmp_dir create_io_plugin_options(data.tmp_dir); @@ -250,6 +249,10 @@ check_example_io_plugin_command_log_multiple(void) data.user_info, data.command_info, data.plugin_argc, data.plugin_argv, data.user_env, data.plugin_options), SUDO_RC_OK); + // For verifying the error message of no more plugin. It should be displayed only once. + VERIFY_PTR((*python_io_clone)(), NULL); + VERIFY_PTR((*python_io_clone)(), NULL); + // open the second plugin with another log directory VERIFY_TRUE(asprintf(&data.tmp_dir2, TEMP_PATH_TEMPLATE) >= 0); VERIFY_NOT_NULL(mkdtemp(data.tmp_dir2)); diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr index e69de29bb..f51980519 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr +++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr @@ -0,0 +1 @@ +sudo: loading more than 8 sudo python IO plugins is not supported diff --git a/plugins/python/sudo_python_module.c b/plugins/python/sudo_python_module.c index 050d70ec7..e76a3b325 100644 --- a/plugins/python/sudo_python_module.c +++ b/plugins/python/sudo_python_module.c @@ -113,11 +113,6 @@ python_sudo_log(int msg_type, PyObject *Py_UNUSED(py_self), PyObject *py_args, P if (_parse_log_function_args(py_args, py_kwargs, &args_joined, &end) != SUDO_RC_OK) goto cleanup; - if (!py_is_sudo_log_available()) { - PyErr_Format(sudo_exc_SudoException, "sudo.log: Message displaying is unavailable"); - goto cleanup; - } - rc = py_ctx.sudo_log(msg_type, "%s%s", args_joined, end); if (rc < 0) { PyErr_Format(sudo_exc_SudoException, "sudo.log: Error displaying message");