[Zope3-dev] Principal Comparison and/or References

Jeff Shell eucci.group at gmail.com
Fri Jan 13 15:19:28 EST 2006


On 1/13/06, Gary Poster <gary at zope.com> wrote:
> > Comparing the id attribute works. Is it reasonable to assume that
> > zapi.principals().getPrincipal(request.principal.id) should return the
> > same principal as request.principal? And thus if
> > somerecord['creator_id'] == request.principal.id, that's considered a
> > good match?
>
> Yes.  We compare on principal id.
>
> I believe it would be relatively easy to set up your system in such a
> way that this would not be safe.  For instance, you could have two
> sites, both with authentication utilities.  If each authentication
> utility had the same prefix and had a user with the same key in the
> auth utility, then you would have two different users with identical
> ids in the system.

I was thinking of that, and the possibility that (somehow) the system
could be hijacked in a way that after authentication a different
utility would respond first to getUtility(IAuthentication) and provide
a different matching principal for the principal id. I don't know how
big of a concern that is. It might fall into the realm of "if your
code is doing that, it's stupid; if some other code managed to do
that, you're probably severely hacked anyways and this is the least of
your problems."

What I'm saying is that I'm not sure what a security auditor would
look for in a situation like this. For our applications right now,
we're not too concerned about really tight security, so if I know that
comparing the IDs is good enough, I'd just go ahead and do that. I
have a feeling that it might not be enough for everybody.

I know that Zope 2 would keep track of the authentication path, and
its entries in the transaction log include the path to the acl_users
the user came out of. I think most other people using RDBMS systems
for managing users or storing a user id in the RDBMS didn't use this,
and would basically store just the user id. I guess most people found
that good enough..?

> It might be reasonable to add a bit to the IPrincipal interface that
> __eq__ is provided and uses id to compare.  That seems reasonable to
> me, but maybe others have qualms.  Care to write a mini-proposal? ;-)

I'm interested in what others think. Other people here have a deeper
knowledge of the security policies, principals, than I do. I don't
know if this is something that should be pluggable -
IComparablePrincipal? - so that a tighter security policy (I guess?)
could compare principals on more than the ID. Since IPrincipals aren't
locatable, you can't really compare the path that yielded the
principal. That's the part that I'm unsure about - if it's possible
(or worth worrying about) for a getPrincipal() call later in a request
to yield a different result than it would have when request.principal
was set.

So maybe something that wanted tighter control and wanted to compare
not just the id but the authentication utility that yielded the Found
or Authenticated principal could listen for the respective events
(zope.app.authentication.interface.FoundPrincipalCreated |
AuthenticatedPrincipalCreated) and tag the principal with information
about the authentication utility that provided it, such as the path
(if the authentication utility is locatable). The adapter then says
the principal directly provides IPathAwarePrincipal. An
IComparablePrincipal adapter is provided for IPathAwarePrincipal that
compares the paths of two principals as well as the id.

It seems like a heavy scenario, and again I add the disclaimer that
for me it doesn't matter much for our current customers and people who
think harder about security may have better insight, but it seems like
a way to allow applications to install stricter comparisons so that
any code - regardless of where it is or who wrote it - can do
something like:

# obj.author = 'foo.user.1'
owner = zapi.principals().getPrincipal(obj.author)
if owner == request.principal:
    # it's the owner.

that code stays simple, natural, and "pythonic" (no need to remember
looking up something like IPrincipalComparator as a utility or
adapter), but comparison can be rich if the application wants.

I've already found one spot in Python code that does a comparison like
this, and it works for global registry principals. Regardless of how
it's made to work, it should work for all. At the same time, I
recognize the desire to keep the zope.security.interfaces.IPrincipal
interface small, so I'm not sure what to suggest. Since comparison
works fine for global registry items, maybe __eq__ should just be put
into zope.app.authentication.principalfolder.Principal since that's
what's created by the default Found / Authenticated principal
factories?

Or is the answer "if this is something you care about, provide your
own principal factories for pluggable auth that provide the principal
you want and don't pressure the core to do more?"


More information about the Zope3-dev mailing list