Help with ctypes and PAM

C

chris.atlee

Hello,

I've been trying to write a PAM module using ctypes. In the
conversation
function (my_conv in the script below), you're passed in a
pam_response**
pointer. You're supposed to allocate an array of pam_response's and
set
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
always
returns PAM_AUTHTOK_RECOVER_ERR (21), which I think means the response
doesn't
make any sense.

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

Any pointers would be appreciated!

Cheers,
Chris

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,
self.resp)

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),
POINTER(pam_handle)]

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

if __name__ == "__main__":
import getpass, os, sys
@conv_func
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.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),
pointer(handle))

if retval != 0:
print "Couldn't start pam session"
sys.exit(-1)

retval = pam_authenticate(handle, 0)
if retval == 21:
print "Authentication information cannot be recovered"
sys.exit(-1)

print retval
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top