Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language

Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Python Programming Language

Help with ctypes and PAM


I've been trying to write a PAM module using ctypes.  In the
function (my_conv in the script below), you're passed in a
pointer.  You're supposed to allocate an array of pam_response's and
the pointer's value to the new array.  Then you fill in the array with
appropriate data.

I can't seem to get it working in python...The authenticate function
returns PAM_AUTHTOK_RECOVER_ERR (21), which I think means the response
make any sense.

I've tried saving the response array outside of my_conv to make sure
doesn't get garbage collected, but that doesn't seem to help.

Any pointers would be appreciated!


from ctypes import *

libpam = CDLL("libpam.so")

class pam_handle(Structure):
    _fields_ = [
            ("handle", c_void_p)

    def __init__(self):
        self.handle = 0

class pam_message(Structure):
    _fields_ = [
            ("msg_style", c_int),
            ("msg", c_char_p),

    def __repr__(self):
        return "<pam_message %i '%s'>" % (self.msg_style, self.msg)

class pam_response(Structure):
    _fields_ = [
            ("resp", c_char_p),
            ("resp_retcode", c_int),

    def __repr__(self):
        return "<pam_response %i '%s'>" % (self.resp_retcode,

conv_func = CFUNCTYPE(c_int,
        c_int, POINTER(POINTER(pam_message)),
        POINTER(POINTER(pam_response)), c_void_p)

class pam_conv(Structure):
    _fields_ = [
            ("conv", conv_func),
            ("appdata_ptr", c_void_p)

pam_start = libpam.pam_start
pam_start.restype = c_int
pam_start.argtypes = [c_char_p, c_char_p, POINTER(pam_conv),

pam_authenticate = libpam.pam_authenticate
pam_authenticate.restype = c_int
pam_authenticate.argtypes = [pam_handle, c_int]

if __name__ == "__main__":
    import getpass, os, sys
    def my_conv(nMessages, messages, pResponse, appData):
        # Create an array of nMessages response objects
        # Does r get GC'ed after we're all done?
        r = (pam_response * nMessages)()
        pResponse.contents = cast(r, POINTER(pam_response))
        for i in range(nMessages):
            if messages[i].contents.msg == "Password: ":
                p = getpass.getpass()
                pResponse.contents[0].resp_retcode = 0
                pResponse.contents[0].resp = p
        return 0

    handle = pam_handle()
    c = pam_conv(my_conv, 0)
    retval = pam_start("login", os.getlogin(), pointer(c),

    if retval != 0:
        print "Couldn't start pam session"

    retval = pam_authenticate(handle, 0)
    if retval == 21:
        print "Authentication information cannot be recovered"

    print retval

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc