There are several design decisions you may stumble across
when using pam_python.
One is that the Python PAM module is isolated
from the rest of the Python environment.
This differs from a import
'ed Python module,
where regardless of how many times a module is imported
there is only one copy that shares the one global name space.
So, for example, if you import
your Python PAM module
and then debug it as suggested above then there will be 2 copies
of your Python PAM module in memory -
the imported one and the one PAM is using.
If the PAM module sets a global variable
you won't see it in the import'ed one.
Indeed, obtaining any sort of handle to the module the PAM is using
is near impossible.
This means the debugger can inspect variables in the module
only when a breakpoint has one of the modules functions
in its backtrace.
There are a few of reasons for this.
Firstly, the PAM Module Writers Guide
says this is the way it should be,
so pam_python encourages it.
Secondly, if a PAM application is using a Python PAM Module
its important the PAM module remains as near to invisible as possible
to avoid conflicts.
Finally, and most importantly,
references to objects constructed by the Python PAM module
must never leak.
This is because the destructors to those objects are C functions
that live in pam_python,
and those destructors are called when all references to the objects are gone.
When pam_end(3) is called pam_python is unloaded,
and with it goes the destructor code.
Should a reference to an object defined by pam_python
exist after pam_end(3) returns
the call to destructor will result in a jump to a non-existent address
causing a SIGSEGV
.
Another potential trap is the initialisation and finalisation
of the Python interpreter itself.
Calling the interpreter's finalisation routine while it is in use
would I imagine be a big no-no.
If pam_python has to initialise the interpreter
(by calling Py_Initialize())
then it will call its finaliser (Py_Finalize()
when the last Python PAM module is destroyed.
This is heuristic works in most scenarios.
One example where is won't work is a sequence like:
start-python-pam-module; application-initialises-interpreter;
stop-python-pam-module; application-stops-interpreter
.
This is doomed to fail.