本文共 3582 字,大约阅读时间需要 11 分钟。
# (c) 2007 Chris AtLee# Licensed under the MIT license:# http://www.opensource.org/licenses/mit-license.php"""PAM module for pythonProvides an authenticate function that will allow the caller to authenticatea user against the Pluggable Authentication Modules (PAM) on the system.Implemented using ctypes, so no compilation is necessary."""__all__ = ['authenticate']from ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, pointer, sizeoffrom ctypes import c_void_p, c_uint, c_char_p, c_char, c_intfrom ctypes.util import find_libraryLIBPAM = CDLL(find_library("pam"))LIBC = CDLL(find_library("c"))CALLOC = LIBC.callocCALLOC.restype = c_void_pCALLOC.argtypes = [c_uint, c_uint]STRDUP = LIBC.strdupSTRDUP.argstypes = [c_char_p]STRDUP.restype = POINTER(c_char) # NOT c_char_p !!!!# Various constantsPAM_PROMPT_ECHO_OFF = 1PAM_PROMPT_ECHO_ON = 2PAM_ERROR_MSG = 3PAM_TEXT_INFO = 4class PamHandle(Structure): """wrapper class for pam_handle_t""" _fields_ = [ ("handle", c_void_p) ] def __init__(self): Structure.__init__(self) self.handle = 0class PamMessage(Structure): """wrapper class for pam_message structure""" _fields_ = [ ("msg_style", c_int), ("msg", c_char_p), ] def __repr__(self): return " " % (self.msg_style, self.msg)class PamResponse(Structure): """wrapper class for pam_response structure""" _fields_ = [ ("resp", c_char_p), ("resp_retcode", c_int), ] def __repr__(self): return " " % (self.resp_retcode, self.resp)CONV_FUNC = CFUNCTYPE(c_int, c_int, POINTER(POINTER(PamMessage)), POINTER(POINTER(PamResponse)), c_void_p)class PamConv(Structure): """wrapper class for pam_conv structure""" _fields_ = [ ("conv", CONV_FUNC), ("appdata_ptr", c_void_p) ]PAM_START = LIBPAM.pam_startPAM_START.restype = c_intPAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)]PAM_AUTHENTICATE = LIBPAM.pam_authenticatePAM_AUTHENTICATE.restype = c_intPAM_AUTHENTICATE.argtypes = [PamHandle, c_int]def authenticate(username, password, service='login'): """Returns True if the given username and password authenticate for the given service. Returns False otherwise ``username``: the username to authenticate ``password``: the password in plain text ``service``: the PAM service to authenticate against. Defaults to 'login'""" @CONV_FUNC def my_conv(n_messages, messages, p_response, app_data): """Simple conversation function that responds to any prompt where the echo is off with the supplied password""" # Create an array of n_messages response objects addr = CALLOC(n_messages, sizeof(PamResponse)) p_response[0] = cast(addr, POINTER(PamResponse)) for i in range(n_messages): if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF: pw_copy = STRDUP(str(password)) p_response.contents[i].resp = cast(pw_copy, c_char_p) p_response.contents[i].resp_retcode = 0 return 0 handle = PamHandle() conv = PamConv(my_conv, 0) retval = PAM_START(service, username, pointer(conv), pointer(handle)) if retval != 0: # TODO: This is not an authentication error, something # has gone wrong starting up PAM return False retval = PAM_AUTHENTICATE(handle, 0) return retval == 0if __name__ == "__main__": import getpass print authenticate(getpass.getuser(), getpass.getpass())
转载地址:http://wxfob.baihongyu.com/