plugins/python/regress: add a testcase for multiple io plugin loading
to verify 2 python plugins can work next to each other.
This commit is contained in:

committed by
Todd C. Miller

parent
3128cc97ca
commit
2eeda38f95
@@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
#include "sudo_dso.h"
|
#include "sudo_dso.h"
|
||||||
|
|
||||||
static struct io_plugin *python_io = NULL;
|
static void *python_plugin_handle = NULL;
|
||||||
|
static struct io_plugin *python_io;
|
||||||
static struct policy_plugin *python_policy = NULL;
|
static struct policy_plugin *python_policy = NULL;
|
||||||
static struct sudoers_group_plugin *group_plugin = NULL;
|
static struct sudoers_group_plugin *group_plugin = NULL;
|
||||||
|
|
||||||
@@ -143,6 +144,9 @@ cleanup(int success)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VERIFY_TRUE(rmdir_recursive(data.tmp_dir));
|
VERIFY_TRUE(rmdir_recursive(data.tmp_dir));
|
||||||
|
if (data.tmp_dir2) {
|
||||||
|
VERIFY_TRUE(rmdir_recursive(data.tmp_dir2));
|
||||||
|
}
|
||||||
|
|
||||||
free(data.settings);
|
free(data.settings);
|
||||||
free(data.user_info);
|
free(data.user_info);
|
||||||
@@ -214,6 +218,82 @@ check_example_io_plugin_command_log(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct io_plugin * (io_clone_func)(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
check_example_io_plugin_command_log_multiple(void)
|
||||||
|
{
|
||||||
|
// verify multiple python io plugin symbols are available
|
||||||
|
io_clone_func *python_io_clone = (io_clone_func *)sudo_dso_findsym(python_plugin_handle, "python_io_clone");
|
||||||
|
VERIFY_PTR_NE(python_io_clone, NULL);
|
||||||
|
|
||||||
|
struct io_plugin *python_io2 = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; ++i) {
|
||||||
|
python_io2 = (*python_io_clone)();
|
||||||
|
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);
|
||||||
|
|
||||||
|
free(data.plugin_argv);
|
||||||
|
data.plugin_argc = 2;
|
||||||
|
data.plugin_argv = create_str_array(3, "id", "--help", NULL);
|
||||||
|
|
||||||
|
free(data.command_info);
|
||||||
|
data.command_info = create_str_array(3, "command=/bin/id", "runas_uid=0", NULL);
|
||||||
|
|
||||||
|
VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
|
||||||
|
data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
|
||||||
|
data.user_env, data.plugin_options), SUDO_RC_OK);
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
create_io_plugin_options(data.tmp_dir2);
|
||||||
|
|
||||||
|
free(data.plugin_argv);
|
||||||
|
data.plugin_argc = 1;
|
||||||
|
data.plugin_argv = create_str_array(2, "whoami", NULL);
|
||||||
|
|
||||||
|
free(data.command_info);
|
||||||
|
data.command_info = create_str_array(3, "command=/bin/whoami", "runas_uid=1", NULL);
|
||||||
|
|
||||||
|
VERIFY_INT(python_io2->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
|
||||||
|
data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
|
||||||
|
data.user_env, data.plugin_options), SUDO_RC_OK);
|
||||||
|
|
||||||
|
VERIFY_INT(python_io->log_stdin("stdin for plugin 1", strlen("stdin for plugin 1")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_stdin("stdin for plugin 2", strlen("stdin for plugin 2")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_stdout("stdout for plugin 1", strlen("stdout for plugin 1")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_stdout("stdout for plugin 2", strlen("stdout for plugin 2")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_stderr("stderr for plugin 1", strlen("stderr for plugin 1")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_stderr("stderr for plugin 2", strlen("stderr for plugin 2")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_suspend(SIGTSTP), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_suspend(SIGSTOP), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_suspend(SIGCONT), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_suspend(SIGCONT), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->change_winsize(20, 10), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->change_winsize(30, 40), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_ttyin("tty input for plugin 1", strlen("tty input for plugin 1")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_ttyin("tty input for plugin 2", strlen("tty input for plugin 2")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io->log_ttyout("tty output for plugin 1", strlen("tty output for plugin 1")), SUDO_RC_OK);
|
||||||
|
VERIFY_INT(python_io2->log_ttyout("tty output for plugin 2", strlen("tty output for plugin 2")), SUDO_RC_OK);
|
||||||
|
|
||||||
|
python_io->close(1, 0); // successful execution, command returned 1
|
||||||
|
python_io2->close(2, 0); // command returned 2
|
||||||
|
|
||||||
|
VERIFY_STDOUT(expected_path("check_example_io_plugin_command_log_multiple.stdout"));
|
||||||
|
VERIFY_STDERR(expected_path("check_example_io_plugin_command_log_multiple.stderr"));
|
||||||
|
VERIFY_FILE("sudo.log", expected_path("check_example_io_plugin_command_log_multiple1.stored"));
|
||||||
|
VERIFY_TRUE(verify_file(data.tmp_dir2, "sudo.log", expected_path("check_example_io_plugin_command_log_multiple2.stored")));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
check_example_io_plugin_failed_to_start_command(void)
|
check_example_io_plugin_failed_to_start_command(void)
|
||||||
{
|
{
|
||||||
@@ -710,7 +790,7 @@ int
|
|||||||
check_python_plugin_can_be_loaded(const char *python_plugin_path)
|
check_python_plugin_can_be_loaded(const char *python_plugin_path)
|
||||||
{
|
{
|
||||||
printf("Loading python plugin from '%s'\n", python_plugin_path);
|
printf("Loading python plugin from '%s'\n", python_plugin_path);
|
||||||
void *python_plugin_handle = sudo_dso_load(python_plugin_path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
|
python_plugin_handle = sudo_dso_load(python_plugin_path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
|
||||||
VERIFY_PTR_NE(python_plugin_handle, NULL);
|
VERIFY_PTR_NE(python_plugin_handle, NULL);
|
||||||
|
|
||||||
python_io = sudo_dso_findsym(python_plugin_handle, "python_io");
|
python_io = sudo_dso_findsym(python_plugin_handle, "python_io");
|
||||||
@@ -737,6 +817,7 @@ main(int argc, char *argv[])
|
|||||||
RUN_TEST(check_example_io_plugin_version_display(true));
|
RUN_TEST(check_example_io_plugin_version_display(true));
|
||||||
RUN_TEST(check_example_io_plugin_version_display(false));
|
RUN_TEST(check_example_io_plugin_version_display(false));
|
||||||
RUN_TEST(check_example_io_plugin_command_log());
|
RUN_TEST(check_example_io_plugin_command_log());
|
||||||
|
RUN_TEST(check_example_io_plugin_command_log_multiple());
|
||||||
RUN_TEST(check_example_io_plugin_failed_to_start_command());
|
RUN_TEST(check_example_io_plugin_failed_to_start_command());
|
||||||
RUN_TEST(check_example_io_plugin_fails_with_python_backtrace());
|
RUN_TEST(check_example_io_plugin_fails_with_python_backtrace());
|
||||||
RUN_TEST(check_io_plugin_callbacks_are_optional());
|
RUN_TEST(check_io_plugin_callbacks_are_optional());
|
||||||
|
0
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr
vendored
Normal file
0
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr
vendored
Normal file
2
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout
vendored
Normal file
2
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
|
||||||
|
Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX2/sudo.log
|
16
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored
vendored
Normal file
16
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
-- Plugin STARTED --
|
||||||
|
EXEC id --help
|
||||||
|
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
|
||||||
|
SUSPEND SIGTSTP
|
||||||
|
SUSPEND SIGCONT
|
||||||
|
WINSIZE 20x10
|
||||||
|
TTY IN tty input for plugin 1
|
||||||
|
TTY OUT tty output for plugin 1
|
||||||
|
CLOSE Command returned 1
|
||||||
|
-- Plugin DESTROYED --
|
16
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored
vendored
Normal file
16
plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
-- Plugin STARTED --
|
||||||
|
EXEC whoami
|
||||||
|
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
|
||||||
|
SUSPEND SIGSTOP
|
||||||
|
SUSPEND SIGCONT
|
||||||
|
WINSIZE 30x40
|
||||||
|
TTY IN tty input for plugin 2
|
||||||
|
TTY OUT tty output for plugin 2
|
||||||
|
CLOSE Command returned 2
|
||||||
|
-- Plugin DESTROYED --
|
@@ -33,6 +33,10 @@ clean_output(char *output)
|
|||||||
{
|
{
|
||||||
// we replace some output which otherwise would be test run dependant
|
// we replace some output which otherwise would be test run dependant
|
||||||
str_replace_in_place(output, MAX_OUTPUT, data.tmp_dir, TEMP_PATH_TEMPLATE);
|
str_replace_in_place(output, MAX_OUTPUT, data.tmp_dir, TEMP_PATH_TEMPLATE);
|
||||||
|
|
||||||
|
if (data.tmp_dir2)
|
||||||
|
str_replace_in_place(output, MAX_OUTPUT, data.tmp_dir2, TEMP_PATH_TEMPLATE "2");
|
||||||
|
|
||||||
str_replace_in_place(output, MAX_OUTPUT, SRC_DIR, "SRC_DIR");
|
str_replace_in_place(output, MAX_OUTPUT, SRC_DIR, "SRC_DIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,10 +102,10 @@ verify_content(char *actual_content, const char *reference_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
verify_file(const char *actual_file_name, const char *reference_path)
|
verify_file(const char *actual_dir, const char *actual_file_name, const char *reference_path)
|
||||||
{
|
{
|
||||||
char actual_path[PATH_MAX];
|
char actual_path[PATH_MAX];
|
||||||
snprintf(actual_path, sizeof(actual_path), "%s/%s", data.tmp_dir, actual_file_name);
|
snprintf(actual_path, sizeof(actual_path), "%s/%s", actual_dir, actual_file_name);
|
||||||
|
|
||||||
char actual_str[MAX_OUTPUT];
|
char actual_str[MAX_OUTPUT];
|
||||||
if (!freadall(actual_path, actual_str, sizeof(actual_str))) {
|
if (!freadall(actual_path, actual_str, sizeof(actual_str))) {
|
||||||
|
@@ -38,6 +38,7 @@ extern const char *sudo_conf_normal_mode;
|
|||||||
|
|
||||||
extern struct TestData {
|
extern struct TestData {
|
||||||
char *tmp_dir;
|
char *tmp_dir;
|
||||||
|
char *tmp_dir2;
|
||||||
char stdout_str[MAX_OUTPUT];
|
char stdout_str[MAX_OUTPUT];
|
||||||
char stderr_str[MAX_OUTPUT];
|
char stderr_str[MAX_OUTPUT];
|
||||||
|
|
||||||
@@ -141,10 +142,10 @@ int verify_content(char *actual_content, const char *reference_path);
|
|||||||
#define VERIFY_CONV(reference_name) \
|
#define VERIFY_CONV(reference_name) \
|
||||||
VERIFY_CONTENT(data.conv_str, reference_name)
|
VERIFY_CONTENT(data.conv_str, reference_name)
|
||||||
|
|
||||||
int verify_file(const char *actual_file_name, const char *reference_path);
|
int verify_file(const char *actual_dir, const char *actual_file_name, const char *reference_path);
|
||||||
|
|
||||||
#define VERIFY_FILE(actual_file_name, reference_path) \
|
#define VERIFY_FILE(actual_file_name, reference_path) \
|
||||||
VERIFY_TRUE(verify_file(actual_file_name, reference_path))
|
VERIFY_TRUE(verify_file(data.tmp_dir, actual_file_name, reference_path))
|
||||||
|
|
||||||
int fake_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
int fake_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
||||||
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
|
struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
|
||||||
|
Reference in New Issue
Block a user