Re: [Monotone-devel] Security is hard. Let's work on policy branches anyway.
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.
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.
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.
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.
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.
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