[Zope-PAS] Lack of user enumeration a problem

Behrens, Matt Matt.Behrens at Kohler.Com
Tue Aug 12 08:17:52 EDT 2008


Tres Seaver wrote: 

> You need to have plugins registered which implement 
> IUserEnumeration and IGroupEnumeration for your site.  
> Probably you are going to need to share the set of valid 
> users with that external program, though.

Right, but what if I can't enumerate the users?  In this scenario, I
actually cannot get a list of valid users.  Inside Zope, my sole
assurance that I have a valid user is that the hash matches up.

It's a similar situation to exUserFolder's smbAuthSource; in that case,
a username and password is provided and passed on for authentication,
and if it works, a user object is created on the fly.  Or REMOTE_USER,
if you don't have access to the list of valid users; you simply trust
the username you're given, creating that user object again.

I realize that I'm sort of diving in here - hadn't even heard about PAS
until a week ago; I've been using exUserFolder for years on 2.5 - so
please humor me :)  It does seem to me that it would be beneficial to be
able to manage groups and roles in this situation, though.  (I'm
certainly willing to provide patches if this is something worth
including in the distribution, too.)

Here's the code, in case I'm speaking poorly:

    security.declarePrivate('extractCredentials')
    def extractCredentials(self, request):
        '''extract the ticket parameters from the cookie, if any'''
        credentials = {}

        cookie = request.cookies.get('__ac_ticket')
        if cookie:
            try:
                cookie = decodestring(cookie)
                credentials['username'], \
                        credentials['expiry'], \
                        credentials['hash'] = cookie.split('\0')
            except:
                pass

        return credentials

    security.declarePrivate('authenticateCredentials')
    def authenticateCredentials(self, credentials):
        '''validate hash and expiry'''

        username = credentials.get('username')
        expiry = credentials.get('expiry')
        given_hash = credentials.get('hash')
        if username is None or expiry is None or given_hash is None:
            return None

        # validate hash
        ticket = '\0'.join([username, expiry, self.secret])
        hash = sha.new(ticket).digest()
        if given_hash != hash:
            return None

        # validate expiry
        if long(expiry) < time():
            return None

        return (username, username)


More information about the Zope-PAS mailing list