On Tue, Jul 28, 2015 at 11:24:45AM +0200, Pino Toscano wrote:
When importing a key, read the list of the valid subkeys of it, and
use
it to check whether a signature was done by one of them.
This allows index provides to sign them using a subkey instead of the
main key.
---
builder/sigchecker.ml | 41 +++++++++++++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 6 deletions(-)
diff --git a/builder/sigchecker.ml b/builder/sigchecker.ml
index cb9144f..06c60ae 100644
--- a/builder/sigchecker.ml
+++ b/builder/sigchecker.ml
@@ -27,6 +27,7 @@ open Unix
type t = {
gpg : string;
fingerprint : string;
+ subkeys_fingerprints : string list;
check_signature : bool;
gpghome : string;
}
@@ -63,7 +64,34 @@ let import_keyfile ~gpg ~gpghome ?(trust = true) keyfile =
if r <> 0 then
error (f_"GPG failure: could not trust the imported key\nUse the '-v'
option and look for earlier error messages.");
);
- !fingerprint
+ let subkeys =
+ (* --with-fingerprint is specified twice so gpg outputs the full
+ * fingerprint of the subkeys. *)
+ let cmd = sprintf "%s --homedir %s --with-colons --with-fingerprint
--with-fingerprint --list-keys %s"
+ gpg gpghome !fingerprint in
+ if verbose () then printf "%s\n%!" cmd;
+ let lines = external_command cmd in
+ let current = ref None in
+ let subkeys = ref [] in
+ List.iter (
+ fun line ->
+ let line = string_nsplit ":" line in
+ match line with
+ | "sub" :: ("u"|"-") :: _ :: _ :: id :: _ ->
+ current := Some id
+ | "fpr" :: _ :: _ :: _ :: _ :: _ :: _ :: _ :: _ :: id :: _ ->
+ (match !current with
+ | None -> ()
+ | Some k ->
+ if string_suffix id k then (
+ subkeys := id :: !subkeys;
+ );
+ current := None
+ )
+ | _ -> ()
+ ) lines;
+ !subkeys in
+ !fingerprint, subkeys
let rec create ~gpg ~gpgkey ~check_signature =
(* Create a temporary directory for gnupg. *)
@@ -74,7 +102,7 @@ let rec create ~gpg ~gpgkey ~check_signature =
match check_signature, gpgkey with
| true, No_Key -> false, No_Key
| x, y -> x, y in
- let fingerprint =
+ let fingerprint, subkeys =
if check_signature then (
(* Run gpg so it can setup its own home directory, failing if it
* cannot.
@@ -100,13 +128,13 @@ let rec create ~gpg ~gpgkey ~check_signature =
let r = Sys.command cmd in
if r <> 0 then
error (f_"could not export public key\nUse the '-v' option and
look for earlier error messages.");
- ignore (import_keyfile gpg tmpdir filename);
- fp
+ import_keyfile gpg tmpdir filename
) else
- "" in
+ "", [] in
{
gpg = gpg;
fingerprint = fingerprint;
+ subkeys_fingerprints = subkeys;
check_signature = check_signature;
gpghome = tmpdir;
}
@@ -177,6 +205,7 @@ and do_verify t args =
| _ -> ()
) status;
- if not (equal_fingerprints !fingerprint t.fingerprint) then
+ if not (equal_fingerprints !fingerprint t.fingerprint) &&
+ not (List.exists (equal_fingerprints !fingerprint) t.subkeys_fingerprints) then
error (f_"fingerprint of signature does not match the expected fingerprint!\n
found fingerprint: %s\n expected fingerprint: %s")
!fingerprint t.fingerprint
--
Looks reasonable, ACK.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html