Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-23 Thread Nathaniel J. Smith
On Tue, Jan 23, 2007 at 01:10:30PM +1100, Brian May wrote:
  Timothy == Timothy Brownawell Timothy writes:
 
 Timothy You don't identify the key by a human-readable
 Timothy name. Instead, you identify it by its hash, and there's a
 Timothy users/ section in the policy tree that maps the hash to
 Timothy something human-readable for UI purposes. So you rename
 Timothy the lost key, and add the new one (maybe even with the
 Timothy same name).
 
 Unfortunately, as currently implemented, get_netsync_read_permitted
 and get_netsync_write_permitted (and probably others), use the
 human-readable name, not the hash.
 
 In fact, according to the documentation, what you describe cannot
 happen, as it is not possible to have more then one key share the same
 human readable name:

Yes, emphasis on as currently implemented :-).

All this discussion is design work for the rewrite of all of
monotone's security stuff, because as you note, the current stuff is
really limited.

-- Nathaniel


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-22 Thread Timothy Brownawell
On Tue, 2007-01-23 at 12:03 +1100, Brian May wrote:

 What happens if Bob's access needs to be revoked, not because we don't
 trust him anymore, but because we no longer trust his key (e.g. his
 laptop was stolen).
 
 Presumably, all signatures before the event can still be trusted, but
 new ones can't be trusted. How do we allow new users to pull from a
 database which contains versions from no-longer trusted signatures?


Presumably we'll have a way to explicity list which certs by a revoked
key should be trusted.

 Bob will need to create a new key, but as his email address remains
 constant how do you distinguish the old key from the new key?

You don't identify the key by a human-readable name. Instead, you
identify it by its hash, and there's a users/ section in the policy tree
that maps the hash to something human-readable for UI purposes. So you
rename the lost key, and add the new one (maybe even with the same
name).

-- 
Timothy

Free (experimental) public monotone hosting: http://mtn-host.prjek.net



___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-22 Thread Nathaniel J. Smith
On Tue, Jan 23, 2007 at 12:03:55PM +1100, Brian May wrote:
  Nathaniel == Nathaniel J Smith [EMAIL PROTECTED] writes:
 
 Nathaniel Alice and Bob both have access, and then Bob's access
 Nathaniel is revoked, and life continues on indefinitely:
 
 Nathaniel   +ab
 Nathaniel|
 Nathaniel  -b|
 Nathaniel|
 Nathaniel   a1
 Nathaniel|
 Nathaniel:
 Nathaniel|
 Nathaniel   a50
 
 I haven't read the full details yet, but my immediately thought is:
 
 What happens if Bob's access needs to be revoked, not because we don't
 trust him anymore, but because we no longer trust his key (e.g. his
 laptop was stolen).
 
 Presumably, all signatures before the event can still be trusted, but
 new ones can't be trusted. How do we allow new users to pull from a
 database which contains versions from no-longer trusted signatures?

Check the bottom of my email, where I talk about this problem :-).

 Bob will need to create a new key, but as his email address remains
 constant how do you distinguish the old key from the new key?
 
 You might end up accidently trusting the old key again.

The binding from key to keyname is planned to be part of the policy
branch data (so you can rename keys etc.), it's just being ignored for
now because we don't anticipate any major difficulties.

 What happens if Bob is unable to alert anybody of the problem until
 after a fraudulent version is committed and synced?  Not unreasonable,
 he just lost his laptop...

Just revoke trust for that particular fraudulent cert.

-- Nathaniel


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-22 Thread Brian May
 Timothy == Timothy Brownawell Timothy writes:

Timothy You don't identify the key by a human-readable
Timothy name. Instead, you identify it by its hash, and there's a
Timothy users/ section in the policy tree that maps the hash to
Timothy something human-readable for UI purposes. So you rename
Timothy the lost key, and add the new one (maybe even with the
Timothy same name).

Unfortunately, as currently implemented, get_netsync_read_permitted
and get_netsync_write_permitted (and probably others), use the
human-readable name, not the hash.

In fact, according to the documentation, what you describe cannot
happen, as it is not possible to have more then one key share the same
human readable name:

  Note that the identity value is a key ID (such as
  [EMAIL PROTECTED]) but will correspond to a unique key
  fingerprint (hash) in your database. Monotone will not permit
  two keys in your database to have the same ID. Make sure you
  confirm the key fingerprints of each key in your database, as
  key ID strings are convenience names, not security tokens.

What you say does sound to me to be like the right solution.
-- 
Brian May [EMAIL PROTECTED]


___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel


[Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-20 Thread Nathaniel J. Smith
Each revision in the policy branch contains a set of rules, such that
for any particular cert we can look at the rules and decide whether
that cert passes.  The tricky question, that has been blocking
progress on policy branches, is how -- given a root revision in the
policy branch -- we find the heads of that policy branch.  The problem
is that as we are walking down the graph finding new revisions that
are certified by valid committers, the rules defining valid
committer are simultaneously changing under our feet.

There have been a number of proposals attacking the general problem of
defining trust in the policy branch itself (see mailing list
archives), but so far they've generally required statefulness on
servers and/or requiring careful security guarantees on communication.
We may yet end up with such an approach, but I want to at least make
my best attempt at a truly monotonic solution, that does not require
either statefulness or communication-time checking.

So here are my latest thoughts on how to do that -- with the warning
that they're incomplete and probably not explained terribly well.

But before the thoughts proper, I need to make up some notation, so I
can actually give examples :-).

Notation


The diagrams I have been scribbling to myself look basically like
this:

 +abc
  / \
   -c/   \+d
/ \
  a1   b1
\ /
   +d\   /-c
  \ /
   b2

This is a revision graph (particularly, the revisions in a policy
branch), with funny labeling.  The lowercase letters, here, refer not
to particular values (like they would if this was a merging diagram),
but to principals.  Keys.  People.  Whatever you want to call them.
The top node is the root of the policy branch -- the trust seed --
and it is annotated with the initial rules.  (Here, those initial
rules are a, b, and c are trusted committers.)  Then, the later
revisions are labeled by the committer -- the person whose cert
vouches for the revision -- plus a number to make it easier to refer
to particular revisions/certs.  So here, a and b each committed a
parallel child of the trust seed, creating two heads, and then b
merged them.  (The root node does not have anyone vouching for it,
because it does not need to -- you have to take _something_ on faith,
and that's the trust seed.)  Finally, the edges in the graph are
labeled with the changes made.  So what a did was revoke c's access,
and what b did was grant d's access.  Sometimes it is convenient to
also annotate each node by writing out the snapshot of the trust rules
it contains, like so:

 +abc
  / \
   -c/   \+d
/ \
  a1   b1
 +ab  +abcd
\ /
   +d\   /-c
  \ /
   b2
  +abd

This is, of course, what is actually written down in the history --
the pluses and minuses on the edges are derived from looking at the
snapshots.

Problems


Okay, now we can more easily write down some of the basic cases that
make this problem interesting.  The first few should be pretty
familiar to anyone who's read the old threads on this stuff.

Problem 1 -- making revocation stick


Alice and Bob both have access, and then Bob's access is revoked, and
life continues on indefinitely:

  +ab
   |
 -b|
   |
  a1
   |
   :
   |
  a50

But, eventually, Bob decides that he wants to make some change anyway
(naughty Bob!).  His access was revoked, so we do not want this to be
possible -- and it's easy to prevent it if he tries to commit a child
of a50, the actual current head.  (a50 says that Bob does not have
commit access, so when we go walking down the graph to see which nodes
are trusted, we will not walk from a50 to a node signed by Bob.)

However, we cannot prevent him from doing:

  +ab
   | \
 -b|  \
   |   \
  a1b1
   |
   :
   |
  a50

Here, we don't want to trust b1, even though it is the immediate child
of a node that _does_ think we should trust b1.  In fact, it's
important that we completely and silently ignore b1; even warning
messages could be exploited by Bob as a kind of denial of service.

Tentative conclusion: The characteristic feature of this case is that
while a50 and b1 both have solid paths leading to them, a50 dislikes
b1, while b1 likes a50.  So somehow we should notice this, and let
a50's dislike kill off b1.

Problem 2 -- rule snapshots are not enough
--

Here's the thing: we like to think in terms of static snapshots
(right now, a and b are allowed to make changes), but a more
delta-ish representation seems necessary (a has had access granted,
b has had access revoked).  The example is, compare these two
graphs:

 +abc   +ab  
 /  \   /  \ 
/\-c +c/\
   /  \   /  \
  a1   b1a1   b1
 +abc +ab   +abc +ab
  |  | 
  c1 c1

In both of them, you have basically the same skeleton: the root, with
some divergence hanging off 

Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.

2007-01-20 Thread Timothy Brownawell
On Sat, 2007-01-20 at 03:15 -0800, Nathaniel J. Smith wrote:
[snip snip snip] 
 Example 3:
 
  +ab
  /  \
   -b/\-a
/  \
   a1   b1
   
 Here we have some sort of determined disagreement between admins.
 There isn't much monotone can do except point out the problem, and let
 the people involved work it out.  There are basically two options:
 wedge everything until people work things out (possibly by all users
 deciding to update their trust seed to follow whichever admin is
 actually trustworthy), or drop back to the last thing that everyone
 can agree on (i.e., actually kill off _both_ a1 and b1, and go back to
 the trust seed, in this case, for now).

You must E() on this, or it becomes impossible to properly kick out an
admin.

Say b turns evil, resulting in a1 being committed. At any time after
this, b can commit b1. If this causes a fallback to the original trust
revision, then b has just re-granted itself its admin privileges. Even
if you W(), automated scripts/buildbots probably won't notice anything.

If this causes an E(), then everyone must update their trust seed. Which
is annoying, but won't fail silently like a fallback with a W() that
nobody sees would.

 Example 4:
 
  +abc
   / \
  /   \-c
 / \
c1  b1
|
a1
 
 Here, c1 is clearly not trusted wrt b1.  This means that a1 is also
 not trusted wrt b1.  Not entirely sure what this should do -- like a
 may have simply committed that revision without knowing that c was
 (about to become) illegitimate, but gets caught in the crossfire
 between b and c?  Maybe issue a warning?

This also needs to E(), at least some of the time. Otherwise, anyone who
can revoke c's access can also undo any changes committed as a
descendant of one of c's revisions. Even if those changes aren't in an
area that they should be allowed to change.

Say, b is initially allowed full access to foo/ and bar/ in the source
tree, and is allowed to grant/revoke access to bar/, and to decide who
else can grant/revoke access to bar/ . Say c1 contains changes to who
can access bar/, and a1 revokes b's access to foo/ . b can commit b1,
which denies c permission to grant/revoke access to bar/, making c1
invalid. This also erases a1, and gives back b's access to foo/ .


 (Initial)
  everything  + Admin
  /foo  + Bob
  /bar  + Bob
  grant/revoke /bar + Bob, Carol
  revoke grant/revoke /bar  + Bob

   /  \
  /\

 /bar  + Greg grant/revoke /bar  - Carol
  /   \
 revision c1 (Carol)revision b1 (Bob)
 |
 |
 /foo  - Bob
 |
  revision a1 (Admin)




Idea: In order for a head to invalidate another head, whoever committed
the change that makes it invalidate the other head must have sufficient
permissions to be able to make the inverse changes to what the
invalidated revisions did.

Idea: Require DaggyFixes-style history structure for the policy
branches, and leave unrelated heads unmerged. Policy branches would then
be much shallower and wider than a similar-sized source branch, and
would genrally have many heads.

Idea: When there are multiple heads that don't trust eachother, W() and
proceed using a virtual merge({heads}) revision, but with the merge
operator for this case being and instead of deterministic *-merge. 


-- 
Timothy

Free (experimental) public monotone hosting: http://mtn-host.prjek.net



___
Monotone-devel mailing list
Monotone-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monotone-devel