diff --git a/plugins/python/Makefile.in b/plugins/python/Makefile.in index a1c2fe1e0..cab41a189 100644 --- a/plugins/python/Makefile.in +++ b/plugins/python/Makefile.in @@ -223,6 +223,11 @@ check: $(TEST_PROGS) ./check_python_examples ".libs/python_plugin.so"; \ fi +update_test_data: $(TEST_PROGS) + @if test X"$(cross_compiling)" != X"yes"; then \ + UPDATE_TESTDATA=1 ./check_python_examples ".libs/python_plugin.so"; \ + fi + check_python_examples: $(CHECK_PYTHON_EXAMPLES_OBJS) $(LIBPYTHONPLUGIN) $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PYTHON_EXAMPLES_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) diff --git a/plugins/python/pyhelpers.c b/plugins/python/pyhelpers.c index 0fec24d1b..6b235f3df 100644 --- a/plugins/python/pyhelpers.c +++ b/plugins/python/pyhelpers.c @@ -145,10 +145,9 @@ py_log_last_error(const char *context_message) char *message = py_message ? py_create_string_rep(py_message) : NULL; - py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s(%s) %s\n", + py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s%s\n", context_message ? context_message : "", context_message && *context_message ? ": " : "", - py_type ? ((PyTypeObject *)py_type)->tp_name : "None", message ? message : "(NULL)"); free(message); diff --git a/plugins/python/python_plugin_common.c b/plugins/python/python_plugin_common.c index d3e41fb56..b6e6c4edc 100644 --- a/plugins/python/python_plugin_common.c +++ b/plugins/python/python_plugin_common.c @@ -469,6 +469,7 @@ _python_plugin_get_class(const char *plugin_path, PyObject *py_module, const cha py_class = PyObject_GetAttrString(py_module, plugin_class); if (py_class == NULL) { py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to find plugin class '%s'\n", plugin_class); + PyErr_Clear(); goto cleanup; } diff --git a/plugins/python/regress/iohelpers.h b/plugins/python/regress/iohelpers.h index 1c1321bff..b2383af76 100644 --- a/plugins/python/regress/iohelpers.h +++ b/plugins/python/regress/iohelpers.h @@ -22,7 +22,6 @@ #include "config.h" #include "sudo_compat.h" -#include #include #include #include diff --git a/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log b/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log index 5d5028459..1d2918aee 100644 --- a/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log +++ b/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log @@ -1,6 +1,6 @@ sudo.debug was called with arguments: (, 'My demo purpose plugin shows this ERROR level debug message') sudo.debug was called with arguments: (, 'My demo purpose plugin shows this INFO level debug message') -LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* -LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* +LogHandler.emit was called +LogHandler.emit was called sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),) -sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\] +sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')] diff --git a/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log b/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log index fddfd973d..755b3f5c5 100644 --- a/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log +++ b/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log @@ -2,10 +2,10 @@ __init__ @ SRC_DIR/example_debugging.py:58 calls C function: sudo.debug was called with arguments: (, 'My demo purpose plugin shows this ERROR level debug message') __init__ @ SRC_DIR/example_debugging.py:63 calls C function: sudo.debug was called with arguments: (, 'My demo purpose plugin shows this INFO level debug message') -handle @ .*/logging/__init__.py:[0-9]* calls C function: -LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* -handle @ .*/logging/__init__.py:[0-9]* calls C function: -LogHandler.emit was called with arguments: (<.*sudo.LogHandler.* +handle @ logging/__init__.py calls C function: +LogHandler.emit was called +handle @ logging/__init__.py calls C function: +LogHandler.emit was called __init__ @ SRC_DIR/example_debugging.py:85 calls C function: sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),) -sudo.options_as_dict returned result: \[('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')\] +sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')] diff --git a/plugins/python/regress/testdata/check_example_debugging_plugin@info.log b/plugins/python/regress/testdata/check_example_debugging_plugin@info.log index bb2647f34..ed72f35ff 100644 --- a/plugins/python/regress/testdata/check_example_debugging_plugin@info.log +++ b/plugins/python/regress/testdata/check_example_debugging_plugin@info.log @@ -2,7 +2,7 @@ __init__ @ SRC_DIR/example_debugging.py:58 debugs: My demo purpose plugin shows this ERROR level debug message __init__ @ SRC_DIR/example_debugging.py:63 debugs: My demo purpose plugin shows this INFO level debug message -handle @ .*/logging/__init__.py:[0-9]* debugs: +handle @ logging/__init__.py debugs: Python log system shows this ERROR level debug message -handle @ .*/logging/__init__.py:[0-9]* debugs: +handle @ logging/__init__.py debugs: Python log system shows this INFO level debug message diff --git a/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log b/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log index e56ec2f3a..97a89efd8 100644 --- a/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log +++ b/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log @@ -1,2 +1,2 @@ -DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] +DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')] DebugDemoPlugin.__init__ returned result: diff --git a/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log b/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log index 829c809b9..ae39daf16 100644 --- a/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log +++ b/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log @@ -1,4 +1,4 @@ -DebugDemoPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] +DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')] DebugDemoPlugin.__init__ returned result: DebugDemoPlugin function 'log_ttyin' is not implemented DebugDemoPlugin function 'log_ttyout' is not implemented diff --git a/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log b/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log index f7f0081e0..bb2fc4f07 100644 --- a/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log +++ b/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log @@ -1,4 +1,4 @@ -.* +SudoGroupPlugin.__init__ was called with arguments: () [('args', ('ModulePath=SRC_DIR/example_group_plugin.py', 'ClassName=SudoGroupPlugin')), ('version', '1.0')] SudoGroupPlugin.__init__ returned result: SudoGroupPlugin.query was called with arguments: ('user', 'group', ('pw_name', 'pw_passwd', 1001, 101, 'pw_gecos', 'pw_dir', 'pw_shell')) SudoGroupPlugin.query returned result: RC.REJECT diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored index 01a09bc45..73fdc5d75 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored +++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored @@ -1,9 +1,9 @@ -- Plugin STARTED -- EXEC id --help -EXEC info \[ +EXEC info [ "command=/bin/id", "runas_uid=0" -\] +] STD IN some standard input STD OUT some standard output STD ERR some standard error diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored index 981e3edb4..bc60c38bd 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored +++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored @@ -1,9 +1,9 @@ -- Plugin STARTED -- EXEC id --help -EXEC info \[ +EXEC info [ "command=/bin/id", "runas_uid=0" -\] +] STD IN stdin for plugin 1 STD OUT stdout for plugin 1 STD ERR stderr for plugin 1 diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored index c47b237c7..ed3fdc845 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored +++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored @@ -1,9 +1,9 @@ -- Plugin STARTED -- EXEC whoami -EXEC info \[ +EXEC info [ "command=/bin/whoami", "runas_uid=1" -\] +] STD IN stdin for plugin 2 STD OUT stdout for plugin 2 STD ERR stderr for plugin 2 diff --git a/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored index 86c276d6e..1b99398be 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored +++ b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored @@ -1,8 +1,8 @@ -- Plugin STARTED -- EXEC cmd -EXEC info \[ +EXEC info [ "command=/usr/share/cmd", "runas_uid=0" -\] +] CLOSE Failed to execute, execve returned 1 (EPERM) -- Plugin DESTROYED -- diff --git a/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr index 8f3c4482a..1dd42a6fe 100644 --- a/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr +++ b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr @@ -1 +1 @@ -Failed to construct plugin instance: (FileNotFoundError) \[Errno 2\] No such file or directory: '/some/not/writable/directory/sudo.log' +Failed to construct plugin instance: [Errno 2] No such file or directory: '/some/not/writable/directory/sudo.log' diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log b/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log index 45a34360b..6f1479ab4 100644 --- a/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log +++ b/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log @@ -1,4 +1,4 @@ -SudoPolicyPlugin.__init__ was called with arguments: () \[('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')\] +SudoPolicyPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')] SudoPolicyPlugin.__init__ returned result: SudoPolicyPlugin.validate was called with arguments: () SudoPolicyPlugin.validate returned result: None diff --git a/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr index e2e090e3c..7ba1bc95c 100644 --- a/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr +++ b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr @@ -1 +1 @@ -Failed during loading plugin class: (ImportError) File 'SRC_DIR/example_debugging.py' must be owned by uid 0 +Failed during loading plugin class: File 'SRC_DIR/example_debugging.py' must be owned by uid 0 diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr index 4477029ba..a4c519a53 100644 --- a/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr +++ b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr @@ -1,2 +1,2 @@ Failed to find plugin class 'MispelledPluginName' -Failed during loading plugin class: (AttributeError) .* has no attribute 'MispelledPluginName' +Failed during loading plugin class diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr index 265f391f8..3087ba807 100644 --- a/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr +++ b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr @@ -1 +1 @@ -Failed during loading plugin class: ([^)]*) No module named 'wrong_path' +Failed during loading plugin class: No module named 'wrong_path' diff --git a/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout index a44aefecd..0500bec89 100644 --- a/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout +++ b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout @@ -1,61 +1,61 @@ (APPROVAL 1) Constructed: { "_id": "(APPROVAL 1)", - "plugin_options": \[ + "plugin_options": [ "ModulePath=SRC_DIR/regress/plugin_approval_test.py", "ClassName=ApprovalTestPlugin", "Id=1" - \], - "settings": \[ + ], + "settings": [ "SETTING1=VALUE1", "setting2=value2" - \], - "submit_argv": \[ + ], + "submit_argv": [ "sudo", "-u", "user", "whoami", "--help" - \], + ], "submit_optind": 3, - "user_env": \[ + "user_env": [ "USER_ENV1=VALUE1", "USER_ENV2=value2" - \], - "user_info": \[ + ], + "user_info": [ "INFO1=VALUE1", "info2=value2" - \], + ], "version": "1.17" } (APPROVAL 2) Constructed: { "_id": "(APPROVAL 2)", - "plugin_options": \[ + "plugin_options": [ "ModulePath=SRC_DIR/regress/plugin_approval_test.py", "ClassName=ApprovalTestPlugin", "Id=2" - \], - "settings": \[ + ], + "settings": [ "SETTING1=VALUE1", "setting2=value2" - \], - "submit_argv": \[ + ], + "submit_argv": [ "sudo", "-u", "user", "whoami", "--help" - \], + ], "submit_optind": 3, - "user_env": \[ + "user_env": [ "USER_ENV1=VALUE1", "USER_ENV2=value2" - \], - "user_info": \[ + ], + "user_info": [ "INFO1=VALUE1", "info2=value2" - \], + ], "version": "1.17" } (APPROVAL 1) Show version was called with arguments: (0,) diff --git a/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout b/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout index 2fd129c5b..cd5bef997 100644 --- a/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout +++ b/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout @@ -1,4 +1,4 @@ -PATH before: \[\] (should be empty) -PATH set: \['path_for_first_plugin'\] -PATH before: \[\] (should be empty) -PATH set: \['path_for_second_plugin'\] +PATH before: [] (should be empty) +PATH set: ['path_for_first_plugin'] +PATH before: [] (should be empty) +PATH set: ['path_for_second_plugin'] diff --git a/plugins/python/regress/testhelpers.c b/plugins/python/regress/testhelpers.c index ce18e464c..1a861bd91 100644 --- a/plugins/python/regress/testhelpers.c +++ b/plugins/python/regress/testhelpers.c @@ -190,7 +190,7 @@ verify_log_lines(const char *reference_path) char line[1024] = ""; char stored_str[MAX_OUTPUT] = ""; while(fgets(line, sizeof(line), file) != NULL) { - const char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning + char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning VERIFY_NOT_NULL(line_data); // malformed log line line_data += 2; @@ -198,6 +198,28 @@ verify_log_lines(const char *reference_path) if (line_end) snprintf(line_end, sizeof(line) - (line_end - line), " object>\n"); + if (strncmp(line_data, "handle @ /", sizeof("handle @ /") - 1) == 0) { + char *start = line_data + sizeof("handle @ ") - 1; + + // normalize path to logging/__init__.py + char *logging = strstr(start, "logging/"); + if (logging != NULL) { + memmove(start, logging, strlen(logging) + 1); + } + + // remove line number + char *colon = strchr(start, ':'); + if (colon != NULL) { + size_t len = strspn(colon + 1, "0123456789"); + if (len != 0) + memmove(colon, colon + len + 1, strlen(colon + len + 1) + 1); + } + } else if (strncmp(line_data, "LogHandler.emit was called ", 27) == 0) { + // LogHandler.emit argument details vary based on python version + line_data[26] = '\n'; + line_data[27] = '\0'; + } + VERIFY_TRUE(strlcat(stored_str, line_data, sizeof(stored_str)) < sizeof(stored_str)); // we have enough space in buffer } diff --git a/plugins/python/regress/testhelpers.h b/plugins/python/regress/testhelpers.h index 5bd65c10b..360b4a574 100644 --- a/plugins/python/regress/testhelpers.h +++ b/plugins/python/regress/testhelpers.h @@ -111,27 +111,10 @@ char ** create_str_array(size_t count, ...); #define VERIFY_STR(actual, expected) \ do { \ const char *actual_str = actual; \ - regex_t regex; \ - int result = 0; \ - if (!actual_str) { \ - result = -1; \ - } else if (*expected == '\0') { \ - result = strcmp(actual_str, expected); \ - } else { \ - if ((result = regcomp(®ex, expected, REG_NOSUB)) != 0) { \ - char errbuf[1024]; \ - regerror(result, ®ex, errbuf, sizeof(errbuf)); \ - fprintf(stderr, "regcomp failed at %s:%d: %s\npattern: %s\n", \ - __FILE__, __LINE__, errbuf, expected); \ - } else { \ - result = regexec(®ex, actual_str, 0, NULL, 0); \ - regfree(®ex); \ - } \ - } \ - if (result != 0) { \ - VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \ - return false; \ - } \ + if (!actual_str || strcmp(actual_str, expected) != 0) { \ + VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \ + return false; \ + } \ } while(false) #define VERIFY_STR_CONTAINS(actual, expected) \