[Twisted-Python] Question on pamauth.py

I'm planning to use twisted.cred and just went to look for ways to implement a back end credentials checker that I could plug in. I soon ran across mentions of pamauth.py, and was pleasantly surprised to find it sitting in my Twisted-2.2.0/twisted/cred/pamauth.py But, I don't see a mention of how to use it. Most of what's on the web shows pamauth.py as living under twisted.conch, which I take to be an old code layout. This: $ find . -name '*.html' -print0 | xargs -0 grep -i pamauth at the top of my Twisted-Sumo tree gets me no hits. I see a little use of pamauth test/test_newcred.py, but it's not terribly enlightening. Is there somewhere I can read about how to use this? A bit more generally, is using pamauth considered roughly best practice? Are there other credentials checkers in wide use (and yes, I know /etc/password is in wide use :-)) If I want to build a web site where users authenticate themselves, I presumably will be setting a cookie on the browser and authentication will just happen when the browser visits. (I'm happy to hear more details on how this is best done). But what if a user is trying to run a command line app or a remote script that's talking to the server via twisted.pb? Presumably some form of credential is stored locally and transmitted with the connection. Is the passed credential in this case stored (supposing it is even stored on disk, as opposed to being stored in the user's head and entered on the command line) in a way that's totally orthogonal to cookies, or does Twisted have yet more functionality to deal with this? One final one: I imagine it's a standard pattern that people want to implement users and groups, with some form of permissions model in which users attempt actions and their privileges are checked (with fallback to their groups' permission if the user does not have explicit permission). Can anyone point me to Twisted code that does something like this? Sorry for so many questions. I don't expect anyone to start writing code for me, I plan to do that myself. But it's nice to not reinvent wheels, that's the point after all. So having just discovered the lightly (or un-) documented pamauth.py, I'm can't help but wonder what more there might be. Regards, Terry

On May 1, 2006, at 7:28 AM, Terry Jones wrote:
I'm planning to use twisted.cred and just went to look for ways to implement a back end credentials checker that I could plug in. I soon ran across mentions of pamauth.py, and was pleasantly surprised to find it sitting in my Twisted-2.2.0/twisted/cred/pamauth.py
But, I don't see a mention of how to use it.
The really great thing about cred is that it works the same regardless of the underlying authentication mechanism. I suggest writing a couple toy examples and plugging those into your twisted app, just to get a feel for how things work. In the process you will gain genuine knowledge (as opposed to "a feel"). You probably wouldn't ever need to use twisted.cred.pamauth. You would use the twisted.cred.checkers.PluggableAuthenticationModulesChecker, and that works just like, well, a cred checker :-) You biggest problem is actually going to be getting PyPAM working. As far as I know, and as far as tummy.com knows (the original sponsors of PyPAM), there's been no release since 1999. I toyed with the idea of using it at one point, but the amount of work necessary in updating the python was too onerous. Perhaps you have a stronger stomach than I :-)
If I want to build a web site where users authenticate themselves [snip] cookie [snip] But what if a user is trying to run a command line app [snip]
If I'm understanding what you are asking, this isn't a cred question. cred is cred. It handles avatars/ids, realms, portals, etc. You can put anything you want in your realm (or checker, or...). It's up to you to provide/restrict resources based on that and it's up to you to decide what to do about persisting authentication information.
Can anyone point me to Twisted code that does something like this?
I'm totally not being snotty when I say this (again): cred is cred. One of the really great things about it is how easy it is to do whatever you want. You can create interfaces that represent groups, have a single realm and set/check interfaces, have different realms for different levels of access, etc. You can have your resources implement your group/role interfaces. There's all kinds of stuff you can do, it really depends on your needs. Once you are comfortable with it and have written a few working toys/examples, you will see the potential. Writing the code necessary to plug your twisted app into somebody else's authentication system can be easier than doing it any other way (given that you are working with open, sane standards). I've actually written working cred code faster than other project members have *configured* (GUI) the user management systems I was writing against. Here's a great resource: http://twistedmatrix.com/projects/core/documentation/howto/cred.html And if you don't have the O'Reilly twisted book, do yourself a favor and pick up a copy. Abe did a wonderful job explaining cred very clearly in it. Good luck! d

Duncan McGreggor wrote:
You biggest problem is actually going to be getting PyPAM working. As far as I know, and as far as tummy.com knows (the original sponsors of PyPAM), there's been no release since 1999. I toyed with the idea of using it at one point, but the amount of work necessary in updating the python was too onerous. Perhaps you have a stronger stomach than I :-)
Agreed that PyPAM has bitrotted. FWIW, I circumvented this by using Cyrus SASLs "saslauthd" unix socket protocol, with saslauthd configured to talk to PAM. /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -c -n 0 def encode_short(s): i = socket.htons(s) return chr(i & 0xff) + chr((i >> 8) & 0xff) def encode_str(s): l = encode_short(len(s)) return l+s def decode_short(s): return socket.ntohs( (ord(s[1]) << 8) + ord(s[0]) ) class SaslAuthdProtocol(protocol.Protocol): def connectionMade(self): self.data = '' # we're going to check this lot username = encode_str(self.factory.username) password = encode_str(self.factory.password) service = encode_str(PAMSERVICENAME) realm = encode_str(YOURREALM) # ok message = username + password + service + realm self.transport.write(message) def dataReceived(self, data): # ok, we've an outstanding request - where are we? # we're expecting 2 bytes of length, then length bytes of # data which is "code<SP>reason" self.data = self.data + data dl = len(self.data) if dl < 2: # we don't have the length yet return l = decode_short(self.data[:2]) if dl < l + 2: # we don't have the rest of the reply yet return if dl > l + 2: # wtf? self.transport.loseConnection() # Ok, we can reply resp = self.data[2:2+l] if ' ' in resp: resp, reason = resp.split(' ', 1) else: reason = '' if resp=='OK': self.factory.deferred.callback(reason) else: self.factory.deferred.errback(Exception(reason)) class SaslChecker: # We are an ICredentialsChecker implementor interface.implements(checkers.ICredentialsChecker) # We can only check plaintext username/password combos credentialInterfaces = ( credentials.IUsernamePassword, ) # return the "avatar ID" - username def ok(self, matched, username): return username def err(self, f, username): raise error.UnauthorizedLogin(f.getErrorMessage()) def requestAvatarId(self, creds): # Adapt the credentials to a username/password pair up = credentials.IUsernamePassword(creds, default=None) # It's going to be a deferred reply d = defer.Deferred() d.addCallbacks( self.ok, self.err, (up.username,), {}, (up.username,), {} ) # Send the reply off to saslauthd via unix socket f = protocol.ClientFactory() f.username = up.username f.password = up.password f.deferred = d f.protocol = SaslAuthdProtocol reactor.connectUNIX('/var/run/saslauthd/mux', f) return d Works like a charm.
participants (3)
-
Duncan McGreggor
-
Phil Mayers
-
Terry Jones