Переглянути джерело

HUE-8682 [backend] Change PAM lib to python-pam-1.8.4

Ying Chen 6 роки тому
батько
коміт
884b58b065

+ 0 - 19
desktop/core/ext-py/pam/PKG-INFO

@@ -1,19 +0,0 @@
-Metadata-Version: 1.0
-Name: pam
-Version: 0.1.3
-Summary: PAM interface using ctypes
-Home-page: http://atlee.ca/software/pam
-Author: Chris AtLee
-Author-email: chris@atlee.ca
-License: MIT
-Download-URL: http://atlee.ca/software/pam/dist/0.1.3
-Description: An interface to the Pluggable Authentication Modules (PAM) library on linux, written in pure python (using ctypes)
-Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX :: Linux
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: System :: Systems Administration :: Authentication/Directory

+ 0 - 123
desktop/core/ext-py/pam/pam.py

@@ -1,123 +0,0 @@
-# (c) 2007 Chris AtLee <chris@atlee.ca>
-# Licensed under the MIT license:
-# http://www.opensource.org/licenses/mit-license.php
-"""
-PAM module for python
-
-Provides an authenticate function that will allow the caller to authenticate
-a 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, sizeof
-from ctypes import c_void_p, c_uint, c_char_p, c_char, c_int
-from ctypes.util import find_library
-
-LIBPAM = CDLL(find_library("pam"))
-LIBC = CDLL(find_library("c"))
-
-CALLOC = LIBC.calloc
-CALLOC.restype = c_void_p
-CALLOC.argtypes = [c_uint, c_uint]
-
-STRDUP = LIBC.strdup
-STRDUP.argstypes = [c_char_p]
-STRDUP.restype = POINTER(c_char) # NOT c_char_p !!!!
-
-# Various constants
-PAM_PROMPT_ECHO_OFF = 1
-PAM_PROMPT_ECHO_ON = 2
-PAM_ERROR_MSG = 3
-PAM_TEXT_INFO = 4
-
-class PamHandle(Structure):
-    """wrapper class for pam_handle_t"""
-    _fields_ = [
-            ("handle", c_void_p)
-            ]
-
-    def __init__(self):
-        Structure.__init__(self)
-        self.handle = 0
-
-class PamMessage(Structure):
-    """wrapper class for pam_message structure"""
-    _fields_ = [
-            ("msg_style", c_int),
-            ("msg", c_char_p),
-            ]
-
-    def __repr__(self):
-        return "<PamMessage %i '%s'>" % (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 "<PamResponse %i '%s'>" % (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_start
-PAM_START.restype = c_int
-PAM_START.argtypes = [c_char_p, c_char_p, POINTER(PamConv),
-        POINTER(PamHandle)]
-
-PAM_AUTHENTICATE = LIBPAM.pam_authenticate
-PAM_AUTHENTICATE.restype = c_int
-PAM_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 == 0
-
-if __name__ == "__main__":
-    import getpass
-    print authenticate(getpass.getuser(), getpass.getpass())

+ 0 - 32
desktop/core/ext-py/pam/setup.py

@@ -1,32 +0,0 @@
-from setuptools import setup, find_packages
-import sys, os
-
-version = '0.1.3'
-
-setup(name='pam',
-      version=version,
-      description="PAM interface using ctypes",
-      long_description="""\
-An interface to the Pluggable Authentication Modules (PAM) library on linux, written in pure python (using ctypes)""",
-      classifiers=["Development Status :: 3 - Alpha",
-          "Intended Audience :: Developers",
-          "License :: OSI Approved :: MIT License",
-          "Operating System :: POSIX :: Linux",
-          "Operating System :: MacOS :: MacOS X",
-          "Programming Language :: Python",
-          "Topic :: Software Development :: Libraries :: Python Modules",
-          "Topic :: System :: Systems Administration :: Authentication/Directory"
-          ],
-      keywords='',
-      author='Chris AtLee',
-      author_email='chris@atlee.ca',
-      url='http://atlee.ca/software/pam',
-      download_url = "http://atlee.ca/software/pam/dist/%s" % version,
-      license='MIT',
-      py_modules=["pam"],
-      zip_safe=True,
-      install_requires=[],
-      entry_points="""
-      # -*- Entry points: -*-
-      """,
-      )

+ 21 - 0
desktop/core/ext-py/python-pam-1.8.4/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 David Ford
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 2 - 0
desktop/core/ext-py/python-pam-1.8.4/MANIFEST.in

@@ -0,0 +1,2 @@
+include README.md
+include LICENSE

+ 74 - 0
desktop/core/ext-py/python-pam-1.8.4/PKG-INFO

@@ -0,0 +1,74 @@
+Metadata-Version: 1.2
+Name: python-pam
+Version: 1.8.4
+Summary: Python PAM module using ctypes, py3/py2
+Home-page: https://github.com/FirefighterBlu3/python-pam
+Author: David Ford
+Author-email: david@blue-labs.org
+Maintainer: David Ford
+Maintainer-email: david@blue-labs.org
+License: License :: OSI Approved :: MIT License
+Download-URL: https://github.com/FirefighterBlu3/python-pam
+Description: python-pam
+        ==========
+        
+        Python pam module supporting py3 (and py2)
+        
+        Commandline example:
+        
+        ```
+        [david@Scott python-pam]$ python pam.py
+        Username: david
+        Password: 
+        0 Success
+        
+        [david@Scott python-pam]$ python2 pam.py
+        Username: david
+        Password: 
+        0 Success
+        ```
+        
+        Inline examples:
+        ```
+        [david@Scott python-pam]$ python
+        Python 3.4.1 (default, May 19 2014, 17:23:49)
+        [GCC 4.9.0 20140507 (prerelease)] on linux
+        Type "help", "copyright", "credits" or "license" for more information.
+        >>> import pam
+        >>> p = pam.pam()
+        >>> p.authenticate('david', 'correctpassword')
+        True
+        >>> p.authenticate('david', 'badpassword')
+        False
+        >>> p.authenticate('david', 'correctpassword', service='login')
+        True
+        >>> p.authenticate('david', 'correctpassword', service='unknownservice')
+        False
+        >>> p.authenticate('david', 'correctpassword', service='login', resetcreds=True)
+        True
+        >>> p.authenticate('david', 'correctpassword', encoding='latin-1')
+        True
+        >>> print('{} {}'.format(p.code, p.reason))
+        0 Success
+        >>> p.authenticate('david', 'badpassword')
+        False
+        >>> print('{} {}'.format(p.code, p.reason))
+        7 Authentication failure
+        >>>
+        ```
+        
+Platform: i686
+Platform: x86_64
+Classifier: Development Status :: 6 - Mature
+Classifier: Environment :: Plugins
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Information Technology
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Security
+Classifier: Topic :: System :: Systems Administration :: Authentication/Directory

+ 47 - 0
desktop/core/ext-py/python-pam-1.8.4/README.md

@@ -0,0 +1,47 @@
+python-pam
+==========
+
+Python pam module supporting py3 (and py2)
+
+Commandline example:
+
+```
+[david@Scott python-pam]$ python pam.py
+Username: david
+Password: 
+0 Success
+
+[david@Scott python-pam]$ python2 pam.py
+Username: david
+Password: 
+0 Success
+```
+
+Inline examples:
+```
+[david@Scott python-pam]$ python
+Python 3.4.1 (default, May 19 2014, 17:23:49)
+[GCC 4.9.0 20140507 (prerelease)] on linux
+Type "help", "copyright", "credits" or "license" for more information.
+>>> import pam
+>>> p = pam.pam()
+>>> p.authenticate('david', 'correctpassword')
+True
+>>> p.authenticate('david', 'badpassword')
+False
+>>> p.authenticate('david', 'correctpassword', service='login')
+True
+>>> p.authenticate('david', 'correctpassword', service='unknownservice')
+False
+>>> p.authenticate('david', 'correctpassword', service='login', resetcreds=True)
+True
+>>> p.authenticate('david', 'correctpassword', encoding='latin-1')
+True
+>>> print('{} {}'.format(p.code, p.reason))
+0 Success
+>>> p.authenticate('david', 'badpassword')
+False
+>>> print('{} {}'.format(p.code, p.reason))
+7 Authentication failure
+>>>
+```

+ 47 - 0
desktop/core/ext-py/python-pam-1.8.4/README.rst

@@ -0,0 +1,47 @@
+python-pam
+==========
+
+Python pam module supporting py3 (and py2)
+
+Commandline example:
+
+```
+[david@Scott python-pam]$ python pam.py
+Username: david
+Password: 
+0 Success
+
+[david@Scott python-pam]$ python2 pam.py
+Username: david
+Password: 
+0 Success
+```
+
+Inline examples:
+```
+[david@Scott python-pam]$ python
+Python 3.4.1 (default, May 19 2014, 17:23:49)
+[GCC 4.9.0 20140507 (prerelease)] on linux
+Type "help", "copyright", "credits" or "license" for more information.
+>>> import pam
+>>> p = pam.pam()
+>>> p.authenticate('david', 'correctpassword')
+True
+>>> p.authenticate('david', 'badpassword')
+False
+>>> p.authenticate('david', 'correctpassword', service='login')
+True
+>>> p.authenticate('david', 'correctpassword', service='unknownservice')
+False
+>>> p.authenticate('david', 'correctpassword', service='login', resetcreds=True)
+True
+>>> p.authenticate('david', 'correctpassword', encoding='latin-1')
+True
+>>> print('{} {}'.format(p.code, p.reason))
+0 Success
+>>> p.authenticate('david', 'badpassword')
+False
+>>> print('{} {}'.format(p.code, p.reason))
+7 Authentication failure
+>>>
+```

+ 224 - 0
desktop/core/ext-py/python-pam-1.8.4/pam.py

@@ -0,0 +1,224 @@
+# (c) 2007 Chris AtLee <chris@atlee.ca>
+# Licensed under the MIT license:
+# http://www.opensource.org/licenses/mit-license.php
+#
+# Original author: Chris AtLee
+#
+# Modified by David Ford, 2011-12-6
+# added py3 support and encoding
+# added pam_end
+# added pam_setcred to reset credentials after seeing Leon Walker's remarks
+# added byref as well
+# use readline to prestuff the getuser input
+
+'''
+PAM module for python
+
+Provides an authenticate function that will allow the caller to authenticate
+a user against the Pluggable Authentication Modules (PAM) on the system.
+
+Implemented using ctypes, so no compilation is necessary.
+'''
+
+__all__      = ['pam']
+__version__  = '1.8.4'
+__author__   = 'David Ford <david@blue-labs.org>'
+__released__ = '2018 June 15'
+
+import sys
+
+from ctypes import CDLL, POINTER, Structure, CFUNCTYPE, cast, byref, sizeof
+from ctypes import c_void_p, c_size_t, c_char_p, c_char, c_int
+from ctypes import memmove
+from ctypes.util import find_library
+
+class PamHandle(Structure):
+    """wrapper class for pam_handle_t pointer"""
+    _fields_ = [ ("handle", c_void_p) ]
+
+    def __init__(self):
+        Structure.__init__(self)
+        self.handle = 0
+
+class PamMessage(Structure):
+    """wrapper class for pam_message structure"""
+    _fields_ = [ ("msg_style", c_int), ("msg", c_char_p) ]
+
+    def __repr__(self):
+        return "<PamMessage %i '%s'>" % (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 "<PamResponse %i '%s'>" % (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) ]
+
+# Various constants
+PAM_PROMPT_ECHO_OFF       = 1
+PAM_PROMPT_ECHO_ON        = 2
+PAM_ERROR_MSG             = 3
+PAM_TEXT_INFO             = 4
+PAM_REINITIALIZE_CRED     = 8
+
+libc                      = CDLL(find_library("c"))
+libpam                    = CDLL(find_library("pam"))
+
+calloc                    = libc.calloc
+calloc.restype            = c_void_p
+calloc.argtypes           = [c_size_t, c_size_t]
+
+# bug #6 (@NIPE-SYSTEMS), some libpam versions don't include this function
+if hasattr(libpam, 'pam_end'):
+    pam_end                   = libpam.pam_end
+    pam_end.restype           = c_int
+    pam_end.argtypes          = [PamHandle, c_int]
+
+pam_start                 = libpam.pam_start
+pam_start.restype         = c_int
+pam_start.argtypes        = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)]
+
+pam_setcred               = libpam.pam_setcred
+pam_setcred.restype       = c_int
+pam_setcred.argtypes      = [PamHandle, c_int]
+
+pam_strerror              = libpam.pam_strerror
+pam_strerror.restype      = c_char_p
+pam_strerror.argtypes     = [PamHandle, c_int]
+
+pam_authenticate          = libpam.pam_authenticate
+pam_authenticate.restype  = c_int
+pam_authenticate.argtypes = [PamHandle, c_int]
+
+class pam():
+    code   = 0
+    reason = None
+
+    def __init__(self):
+        pass
+
+    def authenticate(self, username, password, service='login', encoding='utf-8', resetcreds=True):
+        """username and password authentication for the given service.
+
+           Returns True for success, or False for failure.
+
+           self.code (integer) and self.reason (string) are always stored and may
+           be referenced for the reason why authentication failed. 0/'Success' will
+           be stored for success.
+
+           Python3 expects bytes() for ctypes inputs.  This function will make
+           necessary conversions using the supplied encoding.
+
+        Inputs:
+          username: username to authenticate
+          password: password in plain text
+          service:  PAM service to authenticate against, defaults to 'login'
+
+        Returns:
+          success:  True
+          failure:  False
+        """
+
+        @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))
+            response = cast(addr, POINTER(PamResponse))
+            p_response[0] = response
+            for i in range(n_messages):
+                if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF:
+                    dst = calloc(len(password)+1, sizeof(c_char))
+                    memmove(dst, cpassword, len(password))
+                    response[i].resp = dst
+                    response[i].resp_retcode = 0
+            return 0
+
+        # python3 ctypes prefers bytes
+        if sys.version_info >= (3,):
+            if isinstance(username, str): username = username.encode(encoding)
+            if isinstance(password, str): password = password.encode(encoding)
+            if isinstance(service, str):  service  = service.encode(encoding)
+        else:
+            if isinstance(username, unicode):
+                username = username.encode(encoding)
+            if isinstance(password, unicode):
+                password = password.encode(encoding)
+            if isinstance(service, unicode):
+                service  = service.encode(encoding)
+
+        if b'\x00' in username or b'\x00' in password or b'\x00' in service:
+            self.code = 4  # PAM_SYSTEM_ERR in Linux-PAM
+            self.reason = 'strings may not contain NUL'
+            return False
+
+        # do this up front so we can safely throw an exception if there's
+        # anything wrong with it
+        cpassword = c_char_p(password)
+
+        handle = PamHandle()
+        conv   = PamConv(my_conv, 0)
+        retval = pam_start(service, username, byref(conv), byref(handle))
+
+        if retval != 0:
+            # This is not an authentication error, something has gone wrong starting up PAM
+            self.code   = retval
+            self.reason = "pam_start() failed"
+            return False
+
+        retval = pam_authenticate(handle, 0)
+        auth_success = retval == 0
+
+        if auth_success and resetcreds:
+            retval = pam_setcred(handle, PAM_REINITIALIZE_CRED);
+
+        # store information to inform the caller why we failed
+        self.code   = retval
+        self.reason = pam_strerror(handle, retval)
+        if sys.version_info >= (3,):
+            self.reason = self.reason.decode(encoding)
+
+        if hasattr(libpam, 'pam_end'):
+            pam_end(handle, retval)
+
+        return auth_success
+
+
+def authenticate(*vargs, **dargs):
+    """
+    Compatibility function for older versions of python-pam.
+    """
+    return pam().authenticate(*vargs, **dargs)
+
+
+if __name__ == "__main__":
+    import readline, getpass
+
+    def input_with_prefill(prompt, text):
+        def hook():
+            readline.insert_text(text)
+            readline.redisplay()
+        readline.set_pre_input_hook(hook)
+
+        if sys.version_info >= (3,):
+            result = input(prompt)
+        else:
+            result = raw_input(prompt)
+
+        readline.set_pre_input_hook()
+        return result
+
+    pam = pam()
+
+    username = input_with_prefill('Username: ', getpass.getuser())
+
+    # enter a valid username and an invalid/valid password, to verify both failure and success
+    pam.authenticate(username, getpass.getpass())
+    print('{} {}'.format(pam.code, pam.reason))

+ 0 - 1
desktop/core/ext-py/pam/setup.cfg → desktop/core/ext-py/python-pam-1.8.4/setup.cfg

@@ -1,5 +1,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 

+ 37 - 0
desktop/core/ext-py/python-pam-1.8.4/setup.py

@@ -0,0 +1,37 @@
+import os
+from setuptools import setup
+
+def read(fname):
+    return open(os.path.join(os.path.dirname(__file__), fname)).read()
+
+__sdesc = 'Python PAM module using ctypes, py3/py2'
+
+setup(name             = 'python-pam',
+      description      =  __sdesc,
+      long_description = read('README.md'),
+      py_modules       = ['pam'],
+      version          = '1.8.4',
+      author           = 'David Ford',
+      author_email     = 'david@blue-labs.org',
+      maintainer       = 'David Ford',
+      maintainer_email = 'david@blue-labs.org',
+      url              = 'https://github.com/FirefighterBlu3/python-pam',
+      download_url     = 'https://github.com/FirefighterBlu3/python-pam',
+      license          = 'License :: OSI Approved :: MIT License',
+      platforms        = ['i686','x86_64'],
+      classifiers      = [
+          'Development Status :: 6 - Mature',
+          'Environment :: Plugins',
+          'Intended Audience :: Developers',
+          'Intended Audience :: Information Technology',
+          'Intended Audience :: System Administrators',
+          'License :: OSI Approved :: MIT License',
+          'Operating System :: POSIX',
+          'Operating System :: POSIX :: Linux',
+          'Programming Language :: Python',
+          'Programming Language :: Python :: 2',
+          'Programming Language :: Python :: 3',
+          'Topic :: Security',
+          'Topic :: System :: Systems Administration :: Authentication/Directory',
+          ],
+      )