source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/contrib/pam.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 3.7 KB
Line 
1# (c) 2007 Chris AtLee <chris@atlee.ca>
2# Licensed under the MIT license:
3# http://www.opensource.org/licenses/mit-license.php
4"""
5PAM module for python
6
7Provides an authenticate function that will allow the caller to authenticate
8a user against the Pluggable Authentication Modules (PAM) on the system.
9
10Implemented using ctypes, so no compilation is necessary.
11"""
12from __future__ import print_function
13__all__ = ['authenticate']
14
15from ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, pointer, sizeof
16from ctypes import c_void_p, c_uint, c_char_p, c_char, c_int
17from ctypes.util import find_library
18
19LIBPAM = CDLL(find_library("pam"))
20LIBC = CDLL(find_library("c"))
21
22CALLOC = LIBC.calloc
23CALLOC.restype = c_void_p
24CALLOC.argtypes = [c_uint, c_uint]
25
26STRDUP = LIBC.strdup
27STRDUP.argstypes = [c_char_p]
28STRDUP.restype = POINTER(c_char)  # NOT c_char_p !!!!
29
30# Various constants
31PAM_PROMPT_ECHO_OFF = 1
32PAM_PROMPT_ECHO_ON = 2
33PAM_ERROR_MSG = 3
34PAM_TEXT_INFO = 4
35
36
37class PamHandle(Structure):
38    """wrapper class for pam_handle_t"""
39    _fields_ = [
40        ("handle", c_void_p)
41    ]
42
43    def __init__(self):
44        Structure.__init__(self)
45        self.handle = 0
46
47
48class PamMessage(Structure):
49    """wrapper class for pam_message structure"""
50    _fields_ = [
51        ("msg_style", c_int),
52        ("msg", c_char_p),
53    ]
54
55    def __repr__(self):
56        return "<PamMessage %i '%s'>" % (self.msg_style, self.msg)
57
58
59class PamResponse(Structure):
60    """wrapper class for pam_response structure"""
61    _fields_ = [
62        ("resp", c_char_p),
63        ("resp_retcode", c_int),
64    ]
65
66    def __repr__(self):
67        return "<PamResponse %i '%s'>" % (self.resp_retcode, self.resp)
68
69CONV_FUNC = CFUNCTYPE(c_int,
70                      c_int, POINTER(POINTER(PamMessage)),
71                      POINTER(POINTER(PamResponse)), c_void_p)
72
73
74class PamConv(Structure):
75    """wrapper class for pam_conv structure"""
76    _fields_ = [
77        ("conv", CONV_FUNC),
78        ("appdata_ptr", c_void_p)
79    ]
80
81PAM_START = LIBPAM.pam_start
82PAM_START.restype = c_int
83PAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv),
84                      POINTER(PamHandle)]
85
86PAM_AUTHENTICATE = LIBPAM.pam_authenticate
87PAM_AUTHENTICATE.restype = c_int
88PAM_AUTHENTICATE.argtypes = [PamHandle, c_int]
89
90
91def authenticate(username, password, service='login'):
92    """Returns True if the given username and password authenticate for the
93    given service.  Returns False otherwise
94
95    ``username``: the username to authenticate
96
97    ``password``: the password in plain text
98
99    ``service``: the PAM service to authenticate against.
100                 Defaults to 'login'"""
101    @CONV_FUNC
102    def my_conv(n_messages, messages, p_response, app_data):
103        """Simple conversation function that responds to any
104        prompt where the echo is off with the supplied password"""
105        # Create an array of n_messages response objects
106        addr = CALLOC(n_messages, sizeof(PamResponse))
107        p_response[0] = cast(addr, POINTER(PamResponse))
108        for i in range(n_messages):
109            if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
110                pw_copy = STRDUP(str(password))
111                p_response.contents[i].resp = cast(pw_copy, c_char_p)
112                p_response.contents[i].resp_retcode = 0
113        return 0
114
115    handle = PamHandle()
116    conv = PamConv(my_conv, 0)
117    retval = PAM_START(service, username, pointer(conv), pointer(handle))
118
119    if retval != 0:
120        # TODO: This is not an authentication error, something
121        # has gone wrong starting up PAM
122        return False
123
124    retval = PAM_AUTHENTICATE(handle, 0)
125    return retval == 0
126
127if __name__ == "__main__":
128    import getpass
129    print(authenticate(getpass.getuser(), getpass.getpass()))
Note: See TracBrowser for help on using the repository browser.