Chris AtLee wrote: > Sorry for the repeat post...I'm not sure if my first post (on May > 30th) went through or > not. > > 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 > [snip some code] > > 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)()
The memory allocated to r is garbage collected immediately after my_conv returns. You need to allocate it explicitly using C's calloc or such. This assumes pam_start will free the memory for you. addr = calloc(sizeof(pam_response), nMessages) addr is the memory address as a Python integer. > pResponse.contents = cast(r, POINTER(pam_response)) pResponse.contents changes the actual value of pResponse, a value on the stack. You want to change the value of the pointer pResponse points to: pResponse[0] = cast(addr, POINTER(pam_response)) The cast creates a POINTER(pam_reponse) instance with value addr. > 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), > 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 > If you are going to do any serious ctypes coding consider joining the ctypes mailing list at sourceforge.net . -- Lenard Lindstrom <[EMAIL PROTECTED]> -- http://mail.python.org/mailman/listinfo/python-list