Trying out github repos for what started off as a blog post, on how fixpoint combinators relate to Python:
Showing posts with label python. Show all posts
Showing posts with label python. Show all posts
07 November, 2021
07 May, 2011
PAM python module for out-of-band one-time tokens
I previous wrote about integrating openid with unix shell logins for my public shell server barwen.ch. This post talks about the out-of-band PAM token module that I wrote as part of that - where I'm generating the tokens when the user is authenticated by OpenID. But I guess it could also have use when there's some other out of band mechanism (such as sending something by SMS?)
Subject to some other non-PAM web-based authentication (openid in this case, but it could be anything really), I want to issue a token value to the user in-band with respect to that other authentication (i.e. in a web page shown to the user), which is out-of-band with respect to PAM. That token should then be usable for a short period of time to make a single PAM authorisation to sshd.
That is, if you can log into the web-based authentication, you should then be able to log into the ssh system.
So on one side I need a PAM module (which I will write in Python) to check the tokens, and on the other side I need something (a command line tool) to issue the tokens. To complete the loop, I need some database (the filesystem) to store the tokens on the server side.
So here's the code. The PAM module comes complete with documented security vulnerability which allows anyone to delete certain files on your file system. ho ho.
First the token creator:
and secondly the PAM module, which is based on the PAM module in my previous post:
Subject to some other non-PAM web-based authentication (openid in this case, but it could be anything really), I want to issue a token value to the user in-band with respect to that other authentication (i.e. in a web page shown to the user), which is out-of-band with respect to PAM. That token should then be usable for a short period of time to make a single PAM authorisation to sshd.
That is, if you can log into the web-based authentication, you should then be able to log into the ssh system.
So on one side I need a PAM module (which I will write in Python) to check the tokens, and on the other side I need something (a command line tool) to issue the tokens. To complete the loop, I need some database (the filesystem) to store the tokens on the server side.
So here's the code. The PAM module comes complete with documented security vulnerability which allows anyone to delete certain files on your file system. ho ho.
First the token creator:
#!/usr/bin/python import base64 import os import pickle import sys import time VALIDTIME = 60 tokenbits = os.urandom(8) token = base64.b64encode(tokenbits, "+-") print token fn = token + ".token" fh = open(fn, 'w') obj = (sys.argv[1], time.time() + VALIDTIME) pickle.dump(obj, fh)
and secondly the PAM module, which is based on the PAM module in my previous post:
import os
import syslog
import pickle
import time
def pam_sm_authenticate(pamh, flags, argv):
syslog.syslog("start benc")
pamh.authtok
if pamh.authtok == None:
syslog.syslog("got no password in authtok - trying through conversation")
passmsg = pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, "Monkeyballs?")
rsp = pamh.conversation(passmsg)
syslog.syslog("response is "+rsp.resp)
pamh.authtok = rsp.resp
# so we should at this point have the password either through the
# prompt or from previous module
syslog.syslog("got password: "+pamh.authtok)
# now look for token
# SECURITY BUG TODO: we're using this to make a path so we need to make sure
# we're not being directed out into some other directory. We know the
# range of characters that can be used in a token so we can reject if
# anything other than those exists.
# Especially as we delete the token file on use - otherwise could delete
# arbitrary files on the system...
tfn = "/root/" + pamh.authtok + ".token"
if os.path.exists(tfn):
fh = open(tfn)
tokendata = pickle.load(fh)
tokenuser = tokendata[0]
tokentime = tokendata[1]
fh.close()
os.remove(tfn);
# will remove the token even if it was for the wrong user
# not sure if there's any security different wrt leaving it there if
# its the wrong user?
if tokentime < time.time():
syslog.syslog("token time expired")
return pamh.PAM_AUTH_ERR
if tokenuser != pamh.user:
syslog.syslog("token user "+tokenuser+" does not match requested user "+pamh.user)
return pamh.PAM_AUTH_ERR
return pamh.PAM_SUCCESS
return pamh.PAM_AUTH_ERR
def pam_sm_setcred(pamh, flags, argv):
return pamh.PAM_SUCCESS
23 April, 2011
pam_python
I came across pam_python, a PAM module that lets you write PAM modules in Python. I've come across things scripted by python a couple of times in the last few weeks at work so it seems interesting to play in this direction.
The first module I got sort-of working is this, which lets anyone log in with the password
Now this cheats a bit - it assumes that some other module has read in the password from the user - I used pam_unix to do that, configured as below, so that first a check against the unix password happens and then if that fails, check against
The specific use I am thinking of, I don't want unix passwords to work. So in that case, I need to read in the password myself if it isn't already set.
Here's how I made that work:
To use this with sshd, I need to enable sshd options
So I'm happy that I can grab some string from the remote user now, and process it to get an authentication decision.
Thought its pretty weird to have a regular ssh client giving me a
Modified: 2011-05-08: Later I used pam_python to write an out of band token module
The first module I got sort-of working is this, which lets anyone log in with the password
poop53.import syslog
def pam_sm_authenticate(pamh, flags, argv):
syslog.syslog("start benc")
at = pamh.authtok
syslog.syslog("got password: "+at)
if at == "poop53" :
return pamh.PAM_SUCCESS
else:
return pamh.PAM_AUTH_ERR
def pam_sm_setcred(pamh, flags, argv):
return pamh.PAM_SUCCESS
Now this cheats a bit - it assumes that some other module has read in the password from the user - I used pam_unix to do that, configured as below, so that first a check against the unix password happens and then if that fails, check against
poop53.auth sufficient pam_unix.so auth sufficient pam_python.so /root/auth.py
The specific use I am thinking of, I don't want unix passwords to work. So in that case, I need to read in the password myself if it isn't already set.
Here's how I made that work:
def pam_sm_authenticate(pamh, flags, argv):
syslog.syslog("start benc")
pamh.authtok
if pamh.authtok == None:
syslog.syslog("got no password in authtok - trying through conversation")
passmsg = pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, "Monkeyballs?")
rsp = pamh.conversation(passmsg)
syslog.syslog("response is "+rsp.resp)
pamh.authtok = rsp.resp
# so we should at this point have the password either through the
# prompt or from previous module
syslog.syslog("got password: "+pamh.authtok)
if pamh.authtok == "poop53" :
return pamh.PAM_SUCCESS
else:
return pamh.PAM_AUTH_ERR
def pam_sm_setcred(pamh, flags, argv):
return pamh.PAM_SUCCESS
To use this with sshd, I need to enable sshd options
UsePAM and ChallengeResponseAuthentication, and now I get this:$ ssh root@192.168.141.128 Monkeyballs?poop53 Linux alcf3 2.6.35-28-generic #49-Ubuntu SMP Tue Mar 1 14:40:58 UTC 2011 i686 GNU/Linux #
So I'm happy that I can grab some string from the remote user now, and process it to get an authentication decision.
Thought its pretty weird to have a regular ssh client giving me a
Monkeyballs? prompt at auth time...Modified: 2011-05-08: Later I used pam_python to write an out of band token module
Subscribe to:
Posts (Atom)