Previously we needed to include headers required by the various
sudo*h files. Now those files are more self-sufficient and we
should only include headers needed by code in the various .c files.
The Signals enum was added in Python 3.5. If it is not present we
need to iterate over the dictionary items, looking for signal name
to number mappings. Fixes the signal tests with Python 3.4.
When converting sudo options from a dictionary to a tuple we need
to track the current index into the tuple separately from the
position of the dictionary entry.
Dictionary order is not stable in Python < 3.6 so we need to sort
by key to have consistent results.
The LogHandler output is also different on older Python versions.
Also, don't stop running python tests after the first error.
so python log system can be used with sudo logsystem.
Loggers use it by default (the handler is set on the root logger).
If that is not the intent, it can be overridden explicitly.
If "ClassName" is not specified, load the one and only sudo.Plugin from
the module (if so), otherwise display which plugins are available from
which the system admin can choose.
This only happens when sudo unloads the last python plugin.
The reason doing so is because there are some python modules which
does not support importing them again after destroying the interpreter
which has imported them previously.
Another solution would be to just leak the interpreters (let the kernel
free up), but then there might be some python resources like open files
would not get cleaned up correctly if the plugin is badly written.
Tests are meant to test the scenario sudo does, so I have modified them
to generally do not unlink but only a few times (~per plugin type) so it
does not use 48 interpreters (one gets started on every plugin->open) and
it is visible at least which type of plugin fails deinit if there is an
error.
The python_plugin_api_rc_call function already decrements the
refcount of py_args.
Python avoids the double free, but the error gets shown if using python
debug build.
even if the arguments are not used (eg. when there is no "close" call
in the plugin).
It was not really a memleak, because interpreter is deinitialized anyway,
which frees the object.
Tests did not catch the issue where errstr was not set correctly, but
its pointer contained the expected data, because the memory allocator
reused the same space for storing the string.
Now it is either verified to be NULL, or reset to NULL.
The error is always stored in plugin_ctx, but it is only set into errstr
if the API version is enough. (Previously it worked the opposite:
we only stored the error if API level was enough.)
Plugins can raise a sudo.PluginError exception to add context message
for the failure.
The callback's errstr gets filled up with the specified message.
But, as sudo expects a string constant (will not free the string),
we store it in the plugin context at least until next callback
invocation.
Unfortunately the test did not catch this mistake, because it only
searches that "Python policy plugin API version" string is present
and does not check the version.