Giter VIP home page Giter VIP logo

pamela's Introduction

Pamela: yet another Python wrapper for PAM

There seems to be a glut of Python wrappers for PAM that have since been abandoned. This repo merges two separate efforts:

  • gnosek/python-pam
    • adds wrappers for a few more calls, e.g. opening sessions
    • raises PamError on failure instead of returning False, with informative error messages
  • simplepam
    • adds Python 3 support
    • resets credentials after authentication, apparently for kerberos users

Why?

Both projects appear to be abandoned, with no response to issues or pull requests in at least a year, and I need it for JupyterHub.

Use it

Install:

pip install pamela

Test:

python -m pamela -a `whoami`

pamela's People

Contributors

bluecmd avatar cmd-ntrf avatar gnosek avatar hardening avatar minrk avatar njwhite avatar parente avatar rgbkrk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pamela's Issues

authentication succeeds for expired password

I've been using the default pam-authenticator in a jupyterhub-instance and came across a user who could login to jupyterhub despite a long expired password.

It seems indeed that

import pamela as pam
pam.authenticate('username','password',service='sshd')

always succeeds as long as username/password match, even if the password is expired.

Naively I would simply use in authenticate()

    retval = PAM_AUTHENTICATE(handle, 0)

    if retval == 0:
        retval = PAM_ACCT_MGMT(handle, 0)

to ensure accounts validity but there are probably better ways??

Issues with pamela installed via anaconda

I am able to sudo switch from one user to the next, with the limitation to the sudospawner as required by jupyterhub 1.
sudo -u rhea sudo -n -u $USER sudospawner --help

The shadow configuration is set:
-rw-r----- 1 root shadow 536 Jun 22 10:59 /etc/shadow
uid=35052(jan) gid=12500(mpd) groups=15(shadow),12505(pyjam),12500(mpd)

And when I run:
ldd /{,usr/}{bin,sbin}/* | grep -B 5 libpam | grep '^/'
I get:

    /bin/login:
    /bin/su:
    /sbin/mkhomedir_helper:
    /sbin/pam_tally2:
    /usr/bin/chage:
    /usr/bin/chfn:
    /usr/bin/chsh:
    /usr/bin/passwd:
    /usr/sbin/atd:
    /usr/sbin/cron:
    /usr/sbin/sshd:
    /sbin/pam_timestamp_check:
    /sbin/unix2_chkpwd:
    /usr/bin/c_rehash1:
    /usr/bin/crontab:
    /usr/bin/passmass:
    /usr/bin/sudo:
    /usr/bin/sudoedit:
    /usr/bin/vlock:
    /usr/bin/xdmshell:
    /usr/sbin/create-cracklib-dict:
    /usr/sbin/groupadd:
    /usr/sbin/groupadd.local:
    /usr/sbin/groupdel:
    /usr/sbin/groupmod:
    /usr/sbin/in.rexecd:
    /usr/sbin/in.rlogind:
    /usr/sbin/in.rshd:
    /usr/sbin/routel:
    /usr/sbin/rpasswdd:
    /usr/sbin/update-usbids.sh:
    /usr/sbin/useradd:
    /usr/sbin/useradd.local:
    /usr/sbin/userdel:
    /usr/sbin/userdel-pre.local:
    /usr/sbin/usermod:

I am wondering whether python should not also appear in this list and if that is the case how to add it. Or maybe that is just an missunderstanding from my side and there is a unix command besides sudo, which I can use to test my PAM configuration.

Correction:
What fails for me is the simple test command:
python -m pamela -a whoami
It promots me for my password and is never able to correctly login but instead always returns an
[PAM Error 7] Authentication failure
error

When I load the module directly in python :

>>> import pamela as pamela
>>> pamela.authenticate('kwotuveang3k4bk')
Password: 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/u/system/SLES11/soft/pyjam/jupyterhub/0-8-0/lib/python3.5/site-packages/pamela.py", line 272, in authenticate
    return pam_end(handle, retval)
  File "/u/system/SLES11/soft/pyjam/jupyterhub/0-8-0/lib/python3.5/site-packages/pamela.py", line 220, in pam_end
    raise PAMError(errno=retval)
pamela.PAMError: [PAM Error 7] Authentication failure

Versions:

Python 3.5.1 |Anaconda 4.1.0 (64-bit)
pamela: __version__ = '0.2.1'

Non-root using pamela to auth non-root

non-root user "foo" goes "python3.4 -m pamela -a foo", enters password, and it works. but if user foo then goes "python3.4 -m pamela -a bar" and enters bar's password (bar's un/pw works in console and ssh) then "[PAM Error 7] Authentication failure". Is there a way to configure so that this will work? trying to avoid running jupyterhub as root.

Which permissions does a non-root user need to make a successfull call to pam_open_session

Hi,
I am trying to run JupyterHub as non-root user and still use the PAMAuthenticator. I already added the non-root user to shadow group, so that the authentication works. When I run JupyterHub as root and login with a user into JupyterHub this is the output of /var/log/secure:

Mar 26 10:57:57 picard python3[5637]: pam_loginuid(login:session): Error writing /proc/self/loginuid: Operation not permitted
Mar 26 10:57:57 picard python3[5637]: pam_loginuid(login:session): set_loginuid failed
Mar 26 10:57:57 picard systemd[5654]: pam_unix(systemd-user:session): session opened for user testuser by (uid=0)
Mar 26 10:57:57 picard python3[5637]: pam_unix(login:session): session opened for user testuser by (uid=0)

When I run JupyterHub as non-root user the output looks like this:

Mar 26 11:48:31 picard python3[5834]: pam_loginuid(login:session): Error writing /proc/self/loginuid: Operation not permitted
Mar 26 11:48:31 picard python3[5834]: pam_loginuid(login:session): set_loginuid failed
Mar 26 11:48:31 picard python3[5834]: pam_selinux(login:session): Error sending audit message.
Mar 26 11:48:31 picard python3[5834]: pam_keyinit(login:session): Unable to change GID to 1005 temporarily
Mar 26 11:48:31 picard python3[5834]: pam_keyinit(login:session): Unable to change GID to 1005 temporarily
Mar 26 11:48:31 picard python3[5834]: pam_systemd(login:session): Failed to create session: Access denied
Mar 26 11:48:31 picard python3[5834]: pam_unix(login:session): session opened for user testuser by (uid=991)
Mar 26 11:48:31 picard python3[5834]: pam_lastlog(login:session): unable to open /var/log/btmp: Permission denied

I now understand, that this might not be much of a problem, and I could set in the JupyterHub config the following

c.PAMAuthenticator.open_sessions = False

From the Linux man pages (http://man7.org/linux/man-pages/man3/pam_open_session.3.html) I found this

It should be noted that the effective uid, geteuid(2). of the application should be of sufficient privilege to perform such tasks as creating or mounting the user's home directory for example.

Since the sshd daemon is also run as a separate non-root user and somehow manages to run pam_open_session, I wonder which privileges need to be set for the non-root user in order to open a new PAM session for a user.

I do have a 2nd question: What are the actual effects of pam_open_session for the calling process? As I understand, this changes the whole context the process is run in. This means after authentication JupyterHub should fork itself before calling pam_open_session? Otherwise the main JupyterHub process would run in a new context, that it should not run in?

EDIT: I found out that one can set the capabilities CAP_SETGID and CAP_SETUID of a process via systemd for a non-root user. I think there must be more CAP_s that I need to add in order of a process to run pam_open_session correctly.

Freshly installed pamela via conda on windows does not work

Hi,

just installed pamela and got the following error while execution:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\ProgramData\miniconda3\envs\Test\Lib\site-packages\pamela.py", line 49, in <module>
    LIBPAM = CDLL(find_library("pam"))
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\ProgramData\miniconda3\envs\Test\Lib\ctypes\__init__.py", line 366, in __init__
    if '/' in name or '\\' in name:
       ^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable

authentication fails with linuxbrew python3

I cannot authenticate myself ([PAM Error 7] Authentication failure upon python3 -m pamela -a `whoami`). Possibly this has to do with the way I installed python3. I'm on an slc6 machine and used linuxbrew for the install, I have /home/linuxbrew/ (python3 is here) and /home/usr1 /home/usr2 etc. Maybe I'm missing something else. Can you help?

unable to Change_password for different user

Hello,

I try to use this pamela module to change user password.
It work great for the current user.

In the source code, there is this comment saying (Line 409) :

# Password x2 to answer the "Retype new UNIX password:" prompt
# TODO: If we're not running as root the first prompt will be
# 'current password' which we will not answer, so this will not work
# in that case.

I tryied to add a "current_password" in table containing the passwords in the new_simple_password_conv call :

conv_func = new_simple_password_conv((current_password, password, password), encoding)

I do not understand why it still does not work. It throw :
pamela.PAMError: [PAM Error 20] Authentication token manipulation error
As if passwords were not good.
In my debug, I can see that current_password seems right because I go to the next step (new UNIX password prompt).

Here is my call :
pamela.change_password("user", "oldPass", "newPass", service="passwd")
And here is my outpout :

[b'newPass', b'newPass', b'oldPass']
----------------
<pamela.LP_LP_PamMessage** object at 0x7fb350e0e158>
----------------
b'o'
b'l'
b'd'
b'P'
b'a'
0
----------------
<pamela.LP_LP_PamMessage object at 0x7fb350e0e158>
----------------
b'n'
b'e'
b'w'
b'P'
b'a'
0
----------------
<pamela.LP_LP_PamMessage object at 0x7fb350e0e158>
----------------
b'n'
b'e'
b'w'
b'P'
b'a'
0
----------------
20
Traceback (most recent call last):
  File "test.py", line 11, in <module>
    ret = pamela.change_password("user", "oldPass", "newPass", service="passwd")
  File "/usr/local/lib/python3.6/dist-packages/pamela.py", line 440, in change_password
    return pam_end(handle, ret)
  File "/usr/local/lib/python3.6/dist-packages/pamela.py", line 362, in pam_end
    raise PAMError(errno=retval)
pamela.PAMError: [PAM Error 20] Authentication token manipulation error

Is there a way to get more debug info ? Or do you have any idea on what could happen ?
Thanks in advance, I can provide more file if needed.

notoriousPig

Can't `pam_mount` a `cifs` volume.

Hi,
First of all thank you for your work on jupyterhub ! ๐Ÿ™

I'm working in an environement where I think pamela prevents me from mounting a volume using pam_mount.
This is similara/related to jupyterhub/jupyterhub#810

Here are the details:

  • Ubuntu 20.04, python 3.8
  • Users are authenticated against an Active Directory using https://arthurdejong.org/nss-pam-ldapd.
  • Their home folder is created if it doesn't exist using pam_mkhomedir.
  • The Active Directory credentials are then used to automatically mount a volume from a networked file system using cifs.

The flow works properly with ssh but when connecting through jupyterhub the mounting part of the flow fails with a permission denied or pam_mount asks me to reenter the password (depending on whether the disable_interactive flag is passed to pam_mount).

After some digging, my understanding is that the authenticate method of pamela does not start a pam session and expects the pam sessions to be started later on after authentication succeeds.

If that is the case then the credentials to pam_mount are lost befire the pam_session is created and therefore the pam_mount cannot proceed accordingly.

The current dirty fix that I use is opening a pam session directly at the end of authenticate:

    if retval == 0 and resetcred:
        PAM_SETCRED(handle, resetcred)
    
    # CHANGE BEGIN
    # open_session before the handle gets destroyed with pam_end
    # (ex: pam_mount needs state info stored previously in the auth facility)
    if retval == 0:
        retval = PAM_OPEN_SESSION(handle, 0)
    # CHANGE END

    if close:
        return pam_end(handle, retval)

I've tried to pass close=False to the function but it did not work.

I'm not sure that's the proper way of doing things. What do you think ? Could that change be activated using a flag just like resetcred ?

test_session fails

Bug description

test_session fails

Expected behaviour

Tests pass

Actual behaviour

+ cd pamela-1.0.0
+ py.test-3.10 -v
============================= test session starts ==============================
platform linux -- Python 3.10.0rc1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/orion/fedora/python-pamela/pamela-1.0.0
plugins: forked-1.3.0, cov-2.12.1, arraydiff-0.3, mpi-0+unknown, xdist-2.3.0, remotedata-0.3.2, doctestplus-0.9.0, pyfakefs-4.4.0, mock-3.6.1, openfiles-0.5.0, timeout-1.4.2
collecting ... collected 7 items

test_pamela.py::test_pam_error_noargs PASSED                             [ 14%]
test_pamela.py::test_pam_error_errno PASSED                              [ 28%]
test_pamela.py::test_auth_nouser PASSED                                  [ 42%]
test_pamela.py::test_auth_badpassword PASSED                             [ 57%]
test_pamela.py::test_all PASSED                                          [ 71%]
test_pamela.py::test_environment PASSED                                  [ 85%]
test_pamela.py::test_session FAILED                                      [100%]

=================================== FAILURES ===================================
_________________________________ test_session _________________________________

    def test_session():
        handle = pamela.pam_start(getpass.getuser(), 'login')
>       handle.open_session()

test_pamela.py:76: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pamela.PamHandle object at 0x7f2d087312c0>

    def open_session(self):
        retval = PAM_OPEN_SESSION(self, 0)
        if retval != PAM_SUCCESS:
>           raise PAMError(errno=retval)
E           pamela.PAMError: [PAM Error 14] Cannot make/remove an entry for the specified session

pamela.py:150: PAMError
=========================== short test summary info ============================
FAILED test_pamela.py::test_session - pamela.PAMError: [PAM Error 14] Cannot ...
========================= 1 failed, 6 passed in 4.54s ==========================

Your personal set up

Fedora Rawhide and CentOS 8

OSError: libpam.so.0: cannot open shared object file: No such file or directory

I upgraded my Ubuntu 20.04 install, and now pamela can't find libpam.so.0:

$ python3 -m pamela -a `whoami`
Traceback (most recent call last):
  File "/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.10.8/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.10.8/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.10.8/lib/python3.10/site-packages/pamela.py", line 49, in <module>
    LIBPAM = CDLL(find_library("pam"))
  File "/home/linuxbrew/.linuxbrew/Cellar/[email protected]/3.10.8/lib/python3.10/ctypes/__init__.py", line 374, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: libpam.so.0: cannot open shared object file: No such file or directory

libpam.so.0 is definitely available in a number of places:

$ locate libpam.so.0
/lib/libpam.so.0
/lib/x86_64-linux-gnu/libpam.so.0
/lib/x86_64-linux-gnu/libpam.so.0.84.2
/snap/core/13741/lib/x86_64-linux-gnu/libpam.so.0
   ...(more /snap/core locations)...
/usr/lib/libpam.so.0

I'd really appreciate some help getting pamela to find libpam.so.0. Thanks!

Pamela doesn't run in conda virtual environment

(jupyterhub) C:\Users\bach_ar>python -m pamela -a bach_ar
Traceback (most recent call last):
  File "d:\apps\Miniconda3\envs\jupyterhub\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "d:\apps\Miniconda3\envs\jupyterhub\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "d:\apps\Miniconda3\envs\jupyterhub\lib\site-packages\pamela.py", line 49, in <module>
    LIBPAM = CDLL(find_library("pam"))
  File "d:\apps\Miniconda3\envs\jupyterhub\lib\ctypes\__init__.py", line 351, in __init__
    self._handle = _dlopen(self._name, mode)
TypeError: LoadLibrary() argument 1 must be str, not None

Could it be that the DLL is somehow hardcoded and not found if pamela installed into the environment?

Given test command is NOT working

After installing Jupyterhub on kubernates with PAMAuthenticator on CentOS 7, unable to login with user to jupyterhub,

When I check the test command given, I got error, as mentioned below.

[root@kdss-4qdzl-0 home]# python -m pamela -a whoami
/usr/bin/python: No module named pamela
[root@kdss home]#
[root@kdss home]#
[root@kdss home]# python3 -m pamela -a whoami
Password:
[PAM Error 3] Error in service module

[root@kdss home]#
[root@kdss home]#
[root@kdss home]# find / -name pamela.py
/opt/anaconda3/lib/python3.6/site-packages/pamela.py
[root@kdss home]#

pamela fails for non-current user

python3 -m pamela -a '[other_user]' fails with [PAM Error 7] Authentication failure
, but python3 -m pamela -a '[current_user]' succeeds. Not sure where to start debugging this.

sudo python3 -m pamela -a '[anyone]' works as expected.

Pamela.py Authenticate "help" comment lies :(

Great module, thanks a lot for you work.
One thing I figured out the hard(er) way, the Authenticate function does not return "True" as it is says in the help text, it either raise or keeps silent.

Br,
Peter.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.