[E-Lang] MintMaker with ACLs

Tyler Close tclose@oilspace.com
Tue, 30 Jan 2001 21:09:01 -0000


Hal wrote:
> Let me try again, then, to make it more ACL-like.  Instead
> of passwords
> I'll use UIDs.

This is what I think of as an ACL ( given the current discussions, I'm
not sure I know what the word actually means anymore ;)

Right off the bat, there are a couple of things that bug me about this
implementation.

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.

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.

>  See what you think of this one:
>
>     // account balances, indexed by account number
>     int balance[];
>     // User IDs of account owners, indexed by account number
>     UID ownerUID[];
>
>     // Message requesting transfer
>     int transfer (int sourceAccount, int destAccount, int amount)
>     {
>         // See that this user is owner of account
>         if( getuid() != ownerUID[sourceAccount] )
>             return ERROR_INVALIDACCESS;
>         if( balance[sourceAccount] < amount )
>             return ERROR_INSUFFICIENTFUNDS;
>         // Proceed with transfer
>         balance[sourceAccount] -= amount;
>         balance[destAccount]   += amount;
>         return NOERROR;
>     }

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.

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.

I'll help you out here and code what I think your extension of the
example would be:

	int next_account;

	int makeAccount()
	{
		int acct = next_account++;
		balance[acct] = 0;
		ownerUID[acct] = getuid();
		return acct;
	}

	int delegate(int acct, UID new_owner)
	{
          	if( getuid() != ownerUID[sourceAccount] )
              	return ERROR_INVALIDACCESS;
		ownerUID[acct] = new_owner;
          	return NOERROR;
	}

Let's assume that ints are integers, and we have infinite memory.
(It's just an example people!!!) Assuming the ACL system has a public
newUID() system call, Marcs can now be philanthropic with good
samaritans.

The makeAccount() method is the logical equivalent of the MintMaker's
makePurse(). The delegate() method has no equivalent in the MintMaker.
Using a HalMint there are two steps to passing authority over an
account to another UID. First, you must pass the account number to the
new UID holder, then you must call the delegate() method. With a
MintMaker, there is only one step, pass the cap for the purse to the
other party. In the case of the HalMint, both of the actions taken
have the same logical intent, yet the ACL system requires that you
take both steps. This is precisely the duplication of effort that I
referred to in my response to Jonathan.

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.

> 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.

> 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. New roles are then added to the application by
creating different groupings of capabilities. Creating these new
groupings has no effect on the coding of the individual capabilities.
This goes back to my point about ACLs requiring static security
policies.

The explicit coding of security policies also has a devastating effect
on code size. How much of the HalMint code is now dedicated to
maintaining and checking ACLs? Does security feel like an additional
burden placed on the code's functionality? Do you get the same feeling
when looking at the MintMaker? "Who has time for implementing
security?".

> For the confused deputy example, let there be an agent
> which will reveal
> my public balance under certain conditions.  This agent needs to be
> running with its own UID and that UID is put on the
> accessUIDs list above.
> This way I don't have to give the agent more power than he
> needs and the
> POLA is satisfied.

The design laid out in this email now contains a confused deputy
attack. Consider the trade facilitator I mentioned above, where that
trade facilitator charges a fee for its services.

> 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.  I
> can achieve
> this by changing one line in the getBalance call above, from
>
>         if( ! accessUIDs[account].contains( getuid() ) )
> to
>         if( ! accessUIDs[account].contains( getuid() ) &&
> getuid() != MASTERUID )
>
> Can the MintMaker at
>
http://www.erights.org/elib/capability/ode/ode-capabilities.html#simpl
e-money
> 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).

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.

Tyler