Hi!
Ludovic Courtès <ludo@gnu.org> skribis:
> The good news with this model is that an adversary cannot trick users
> into fetching an unrelated branch where the authorizations would be
> different: they can always detect that it’s a disconnected branch or
> that it’s not a fast-forward pull.
>
> The bad news is that this also prevents “unauthorized forks” in general.
> Unless Guix folks explicitly push a commit authorizing the key of the
> person who forks, commits by that person will appear as unauthorized.
>
> So we need an extra mechanism to say: “this fork starts here”. However,
> modifications to that piece of information must be detectable so that
> one cannot serve a malicious fork that pretends to forego history.
We have two issues to address: (1) bootstraping trust in a channel the
first time ‘guix pull’ obtains it, and (2) supporting “unauthorized”
forks as described above. The two are very similar.
I think we need a way to “introduce” a channel to its users that goes
beyond a mere URL.
It should be possible to obtain a “channel introduction” out-of-band
(i.e., not in the channel’s repo). For example, the introduction to the
official ‘guix’ channel would be in ‘%default-channels’, in (guix
channels), which users obtained in the binary tarball or ISO. For other
channels where there’s no practical out-of-band transmission of the
introduction, it would very much be trust-on-first-use (TOFU).
I think the introduction needs to include:
1. The commit used as a starting point for ‘.guix-authorizations’
checks.
2. The OpenPGP fingerprint of the signer of this first commit.
3. A signature over this commit/fingerprint pair made by the signer of
the commit.
Rationale
~~~~~~~~~
1. The ‘guix’ channel and others will have their authorization start
long after their initial commit. Thus, authors need to state where
to start the authentication process. (Currently the starting point
is hard-coded in ‘Makefile.am’ and passed as an argument to
‘build-aux/git-authenticate.scm’.)
If that information were stored in ‘.guix-channel’, it would be
trivial for an attacker to fork the project (or push a new commit)
and pretend the authentication process must not take previous
commits into account.
2. The fingerprint of the signer of the initial commit makes it easy
for ‘guix pull’ to verify that initial commit on its first clone.
3. The signature over the commit/fingerprint pair makes sure that it
was emitted by an authorized party. Without it, anyone could emit
a channel introduction that skips over a range of commits.
4. When publishing a fork of a channel, one emits a new channel
introduction. Users switching to the fork have to explicitly allow
that new channel via its introduction; flipping the URL won’t be
enough because ‘guix pull’ would report unauthorized commits.
5. The channel URL is not included in the introduction. However, the
official URL is an important piece of information: it tells users
this is where they’ll get the latest updates. It should be
possible to create mirrors, but by default users should go to the
official URL. They should be aware that mirrors can be outdated.
I think the official URL can be stored in ‘.guix-channel’ in the
repo (which is subject to the authentication machinery). That way,
‘guix pull’ can let the user know if they’re talking to a mirror
rather than to the official channel.
Prototype
~~~~~~~~~
The attached code creates channel introductions. One implementation
uses a “compact” binary encoding, which, one encoded in Radix-64, looks
like this:
-----BEGIN GUIX CHANNEL INTRODUCTION-----
R1hDSQAAAAAAFJdEzHtGNvr7dyyUrbjwWWG1s58WPORkVYqE/cadtAz7CQsRmT2a67UCvaMBAbYC
Sf2QDQMACgEJCxGZPZrrtQHLb2IAXtUHUCgoY29tbWl0ICI5NzQ0Y2M3YjQ2MzZmYWZiNzcyYzk0
YWRiOGYwNTk2MWI1YjM5ZjE2IikgKHNpZ25lciAiM2NlNDY0NTU4YTg0ZmRjNjlkYjQwY2ZiMDkw
YjExOTkzZDlhZWJiNSIpKYkCMwQAAQoAHRYhBDzkZFWKhP3GnbQM+wkLEZk9muu1BQJe1QdQAAoJ
EAkLEZk9muu1SlUQAIQVO6JeNmDywM5bAVIktX0VbPmPl0CNCt2oTN8jPZ30lwa3osckOEa2LqQv
0xP59n9tPUue8rXoACcdZ4RS7fZeWjn9qBGCr7h/cQIS0p7II08jHccovvEfgQGxqQCe5hZ++Ehv
OyKV84bG3VOxLFe7B2wIqoIAtmFYCeNmqBfOixSWgzCwC/G5fh7frXR+O9BzvhfBVeFSgzgayNnu
GxgO+Jx7ZhnxR8rRIxrOxCEUjbi8ilIhw++z4ea7g4yTFCkmpPY54HIhzgERanm0/iJUBj9nv9kQ
TXnJ2dcFeZL7b+fWdh8kiKaTgYKV3BGQOKpdqSBQcV9Ys+FFJ+I5ZRCzmTxafPLmR8eGM3aT4Fld
drCjSHga4hbppQJPpNyKsrhwJ4d5tLuLHYUNlXEhcYi11Uo2i30T+TbOynD/uWFRY1+s0ffI1LmX
FhSaqk44jfQoXYeeS8FO471ze3087fsp2WVwNZ5kdPOFNa1Iv+uj/CDILsb4kooRrawQod2W7eb6
jMCayWCUApah22BisQepkFVtKeEAG6aSkIa6Haq4ZrEtzz9gu4n6Pmgv60+n3t77rb7GbPafdSKu
LiJ8PeYSBR3II2YdjIn9PTQ75Xg90IeFxt5PF70q/yb/WoRTIokHFho1QEmbmAm1HBO8SVlmHG+X
8WFn7ex7cx3iYH6H
=xZUu
-----END GUIX CHANNEL INTRODUCTION-----
(guix channels) could provide a ‘channel-introduction->channel’
procedure. In ~/.config/guix/channels.scm, one would write:
(list (channel-introduction->channel "https://…"
"\
-----BEGIN GUIX CHANNEL INTRODUCTION-----
…"))
The introduction needs to be decoded and checked only the first time
‘guix pull’ encounters a channel.
This verbose interface creates an incentive to create a ‘guix channel’
command that could make it easier to add a new channel.
Thoughts?
Ludo’.
Debbugs is free software and licensed under the terms of the
GNU Public License version 2. The current version can be
obtained from https://bugs.debian.org/debbugs-source/.