[Twisted-Python] authentication problem
Hi, I'm setting up a service with both a web and a perspective broken interface. I'd like to share the credential mechanism between the two. Enclosed are code excerpts from the server and the test client. On the server I get the following error when the client tries to connect: 2004/07/27 23:00 CEST [Broker,0,127.0.0.1] Failure: twisted.cred.error.UnhandledCredentials: No checker for twisted.spread.interfaces.IJellyable, twisted.cred.credentials.IUsernameHashedPassword, twisted.cred.credentials.ICredentials, twisted.spread.pb.IUsernameMD5Password Any idea what's wrong? Thanks! Frédéric
Fr=E9d=E9ric Gobry wrote:
[snip - correct looking client] =
There are a couple problems with your server.
import os, sys =
authfile =3D os.path.expanduser ('~/.garlic/auth') db =3D None port =3D 8081 =
from twisted.cred import portal, checkers, credentials from twisted.spread import pb from twisted.internet import reactor from twisted.web import static, server from twisted.cred import checkers, portal =
from twisted.python import log log.startLogging (sys.stderr) =
class Avatar (pb.Avatar): def __init__ (self, uid): self.id =3D uid return Anonymous =3D Avatar ('') =
class User (Avatar): def __init__ (self, uid, db): self.id =3D uid self.db =3D db =
class Realm: """A simple implementor of cred's IRealm.""" __implements__ =3D portal.IRealm def __init__ (self, db): self.db =3D db =
def requestAvatar (self, avatarId, mind, *interfaces): if User not in interfaces: raise NotImplementedError ("no supported interface")
You almost certainly wanted "pb.IPerspective" above, not "User".
return (pb.IPerspective, User (avatarId, self.db), lambda : None) =
def pw_hash (user, proposed, actual): parts =3D actual.split ('$', 3) salt =3D '$'.join (parts [:3]) return crypt.crypt (proposed, salt) =
check =3D checkers.FilePasswordDB (authfile, hash =3D pw_hash)
The exception given was that no checker was registered to handle = IJellyable, IUsernameHashedPassword, IUsernameMD5Password, or = ICredentials. This is accurate. When given an argument for hash, = checkers.FilePasswordDB is a checker _only_ for IUsernamePassword. It = cannot authenticate for a PB connection, which uses an MD5-hashed password.
=
remote_portal =3D portal.Portal (Realm (db)) remote_portal.registerChecker (check) =
from twisted.spread import pb reactor.listenTCP (port, pb.PBServerFactory (remote_portal)) reactor.run () =
A checker that will work with PB must be a checker for = IUsernamePassword, which means storing unhashed passwords on your = server. They can still be encrypted, if you like, but you must reverse = the encryption before the credentials can be checked. If storing hashed passwords is a requirement, you can write your own = authentication mechanism on top of PB and ignore the built-in version. = Unless you are somewhat familiar with the ins and outs of = authentication, I recommend against. Jp
def requestAvatar (self, avatarId, mind, *interfaces): if User not in interfaces: raise NotImplementedError ("no supported interface")
You almost certainly wanted "pb.IPerspective" above, not "User".
Right, I changed that in the meantime (this was a leftover of older code)
The exception given was that no checker was registered to handle = IJellyable, IUsernameHashedPassword, IUsernameMD5Password, or = ICredentials. This is accurate. When given an argument for hash, = checkers.FilePasswordDB is a checker _only_ for IUsernamePassword. It = cannot authenticate for a PB connection, which uses an MD5-hashed password.
This is what I feared from the error message.
A checker that will work with PB must be a checker for = IUsernamePassword, which means storing unhashed passwords on your = server. They can still be encrypted, if you like, but you must reverse = the encryption before the credentials can be checked. If storing hashed passwords is a requirement, you can write your own = authentication mechanism on top of PB and ignore the built-in version. = Unless you are somewhat familiar with the ins and outs of = authentication, I recommend against.
Well, regarding the use of crypted file, I don't like the idea of having to type in a password before starting the server, so I think I'll make the assumption that the local system is safe, and go without it. Thanks for pointing out the problems in my code. Frédéric
participants (3)
-
Andrew Bennetts
-
Frédéric Gobry
-
Jp Calderone