[E-Lang] MintMaker with ACLs

hal@finney.org hal@finney.org
Wed, 31 Jan 2001 12:34:51 -0800


[CC list trimmed]

Tyler wrote, with regard to the ACL based "mint":

> Several very useful design patterns become fatal security holes:
> Visitor, Internal Iteration, Observer, Hollywood (don't call me, I'll
> call you, eg: SAX), Strategy, ... Essentially, anything that requires
> what is traditionally thought of as a callback. In a callback, I can
> provide an object that you will in turn invoke. The contents of the
> callback are totally at my discretion. In an ACL system, all of these
> patterns result in me hijacking your authority to execute arbitrary
> code. These patterns are harmless, and very useful, in a capability
> system.

Can this be addressed by using cooperating processes for these patterns,
with remote procedure calls for the callbacks?  In this way we limit
the ownership rights from spreading into subroutines.

> It is very dangerous to pass messages between UIDs when those messages
> may contain objects that can be used as designators. For example,
> consider the java.io.File object. If I can pass a message containing a
> java.io.File object from my JVM to your JVM, then I can manipulate
> arbitrary files in your JVM using your authority. This is classic
> confused deputy behaviour. Similar attacks with strings and web
> servers have sunk many a web site.

This sounds more like a problem with capabilities than something that
could happen passing messages between UIDs.  In an ACL system, the
permissions are associated with UID, hence no message passed between
different UIDs can grant authority.  With a capability system, if you
pass a File capability from one UID to another you are allowing access
to whatever that capability represents.

> In my tirade against ACLs, one of the points I tried to make is that
> an ACL design requires a static security policy. This is a good
> example of that. Assuming the existence of an IRS, I may not be
> willing to accept donations from unknown strangers. It is impossible
> for your "Bank" software to support this feature after it has been
> deployed. In contrast, a capability based design, like the MintMaker,
> can support this feature unmodified. This isn't a question of
> anticipating all possible requirements, but of not being forced to
> explicitly code all that is permitted.

Right, the code I wrote will allow anyone to make a transfer to your
account, and it would have to be changed if you wanted to be able to limit
that.  It would not be difficult to change it to require the cooperation
of both parties in order for a transfer to occur, but your broader point
seems to be that a capability system will in general be better able
to deal with changes in the requirements without modification to code.
I still don't have enough experience to judge whether this is true.

> In this design, the only UID that will ever be able to successfully
> invoke the transfer() method is the owner of the "sourceAccount". This
> is a huge restriction. For example, I don't see how it would be
> possible to conduct even a simple two-way trade using this transfer()
> method. I have an amount of currency A, you have an amount of currency
> B, we don't trust each other, but we want to trade. The problem is
> that it's impossible for the principal to delegate authority over a
> portion of his balance to a trusted third party who could perform the
> trade. The MintMaker of course supports this functionality.

How about if each of us simply pays the TTP using transfer(), and the
TTP then pays us the appropriate amount?

> Since I'm talking about duplication right now, I'll also remind you of
> the point I was making to David about the space duplication inherent
> in his ACL proposal. The computer's stack and heap already contain a
> distributed version of the access table (if designators are
> authority). An ACL duplicates these table entries in a reified version
> of the access table. Note that there is no equivalent to your many UID
> arrays in the MintMaker.

But in my case, designators are not authority, are they?  My designators
are account numbers, which do not grant authority to access the account.
So I'm not sure whether this duplication problem applies to this example.

> > To allow some of the other features Tyler suggests, let us
> > extend this
> > example with a list of UIDs which are allowed to read the balance:
> >
> >     // User IDs of those allowed to read balance
> >     UIDlist accessUIDs[];
> >
> >     // Request balance
> >     int getBalance (int account)
> >     {
> >         // See if this user is allowed public access
> >         if( ! accessUIDs[account].contains( getuid() ) )
> >             return ERROR_INVALIDACCESS;
> >         return balance[account];
> >     }
>
> At this point, we can really start to see the exploding size and
> number of the ACL lists.

Yes, you'd need to have a different list for each kind of authority you
choose to grant, and for each resource that is protected.  I'm not sure
this necessarily should be called an "explosion", though.  After all,
in a capability system, you'd have a different capability for each kind
of authority and for each resource, but I'm sure you'd agree that this
does not represent an explosion of capabilities.

> > For other features Tyler mentioned like giving my
> > accountant the ability
> > to read my account history, a similar mechanism would be
> > used: introduce
> > a new UIDlist for the required permission and check that
> > the user ID of
> > the requestor is in that list.
>
> So, do you see how the introduction of additional roles is changing
> the actual code for your HalMint, not to mention making it
> significantly more complicated? In a capability based design, all you
> have to do is let POLA be your guide and make your capabilities as
> primitive as possible.

It seems to me that some of the same problems arise with capability
systems, but you don't count them the same way.  In Mark's original example
at http://www.erights.org/elib/capability/ode/ode-capabilities.html#simple-money
there is no provision to make the purse balance visible to my accountant.
If I give him the capability to the purse, he gets too much power.

So I can solve this by creating a new object, a "publicPurse", which
holds a pointer (capability) to my purse but which only exports a single
function, getBalance().  I give a pointer to this object to my accountant.

New code had to be written to accomplish this task, just as in the
ACL example.  But in my case, you counted it as a change to the code
and an increase in complexity.  In the capability case, you don't seem
to count it.

Yet this code is just as security-critical as the code in the Mint.  If
you make a mistake, you could be giving too much power to your accountant.
If you give this capability to the wrong person by accident, you are
giving away power you didn't mean to give.  Adding the new capability
increases the amount of security-critical code and it increases the
overall complexity in terms of managing capabilities properly.

> > Now let me give an example of a change that's easy to make with this
> > system.  Suppose there were some master account belonging
> > to the bank
> > or the IRS which needs to be able to read all balances.
> > ...
> > Can the MintMaker at...
> > be modified as easily to accomodate this change?  Maybe it can, I
> > don't know.  Intuitively it seems like the ACL system would be more
> > suitable to feature like this which seems tied to identity, but
> perhaps
> > the capability system can handle this as well.
>
> Your ACL design gives the illusion of it being easier to add this
> feature because it already contains the overhead of keeping a list of
> all the outstanding accounts. The MintMaker does not impose this
> overhead (the MintMaker is vastly more efficient in both space and
> time).

The overhead was not all the great; the base code was no bigger than the
MintMaker example (granted it is a toy problem).  And the MintMaker has
overhead in its own way, in that there must be a capability in existance
for every purse in the system.  Purses are persistent objects, so there
is really just as much storage being used for the MintMaker as for the
design I showed.  I don't see the vast gain in space and time efficiency.

> To add this feature to the MintMaker, you would keep a list of all the
> created purses in the makePurse() implementation. Another facet on the
> MintMaker would then allow all of these purses to be assayed. The cap
> for this facet would be returned at the same time as the "mint" facet.

Would you be willing to show the code explicitly, as I did for the ACL
case?

Hal