On Fri, Feb 21, 2014 at 03:23:44PM +0100, Pino Toscano wrote:
Extend Sigchecker so it allows both fingerprints (to be imported
from
user's keyring, as before) and keys stored in files. To simplify this
process (and have the fingerprint always around), the key is imported
on Sigchecker.create time, instead of lazily at the first verification.
---
builder/builder.ml | 3 +-
builder/sigchecker.ml | 120 ++++++++++++++++++++++++++++---------------------
builder/sigchecker.mli | 6 ++-
3 files changed, 76 insertions(+), 53 deletions(-)
diff --git a/builder/builder.ml b/builder/builder.ml
index 7fa3cc7..80ccef7 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -141,7 +141,8 @@ let main () =
List.map (
fun (source, fingerprint) ->
let sigchecker =
- Sigchecker.create ~debug ~gpg ~fingerprint ~check_signature in
+ Sigchecker.create ~debug ~gpg ~check_signature
+ ~gpgkey:(Sigchecker.Fingerprint fingerprint) in
Index_parser.get_index ~prog ~debug ~downloader ~sigchecker source
) sources
) in
diff --git a/builder/sigchecker.ml b/builder/sigchecker.ml
index 10e342e..7459e4b 100644
--- a/builder/sigchecker.ml
+++ b/builder/sigchecker.ml
@@ -96,41 +96,97 @@ ZvXkQ3FVJwZoLmHw47vvlVpLD/4gi1SuHWieRvZ+UdDq00E348pm
-----END PGP PUBLIC KEY BLOCK-----
"
+type gpgkey_type =
+ | Fingerprint of string
+ | KeyFile of string
+
type t = {
debug : bool;
gpg : string;
fingerprint : string;
check_signature : bool;
gpghome : string;
- mutable key_imported : bool;
}
-let create ~debug ~gpg ~fingerprint ~check_signature =
- (* Create a temporary directory for gnupg. *)
- let tmpdir = Mkdtemp.mkdtemp (Filename.temp_dir_name // "vb.gpghome.XXXXXX")
in
- rmdir_on_exit tmpdir;
- (* Run gpg once, so it can setup its own home directory, failing
- * if it cannot.
- *)
- let cmd = sprintf "%s --homedir %s --list-keys%s"
- gpg tmpdir (if debug then "" else " >/dev/null 2>&1")
in
+(* Import the specified key file. *)
+let import_keyfile ~gpg ~gpghome ~debug keyfile =
+ let status_file = Filename.temp_file "vbstat" ".txt" in
+ unlink_on_exit status_file;
+ let cmd = sprintf "%s --homedir %s --status-file %s --import %s%s"
+ gpg gpghome (quote status_file) (quote keyfile)
+ (if debug then "" else " >/dev/null 2>&1") in
if debug then eprintf "%s\n%!" cmd;
let r = Sys.command cmd in
if r <> 0 then (
- eprintf (f_"virt-builder: error: GPG failure: could not run GPG the first
time\nUse the '-v' option and look for earlier error messages.\n");
+ eprintf (f_"virt-builder: error: could not import public key\nUse the
'-v' option and look for earlier error messages.\n");
exit 1
);
+ status_file
+
+let rec create ~debug ~gpg ~gpgkey ~check_signature =
+ (* Create a temporary directory for gnupg. *)
+ let tmpdir = Mkdtemp.mkdtemp (Filename.temp_dir_name // "vb.gpghome.XXXXXX")
in
+ rmdir_on_exit tmpdir;
+ let fingerprint =
+ if check_signature then (
+ (* Run gpg so it can setup its own home directory, failing if it
+ * cannot.
+ *)
+ let cmd = sprintf "%s --homedir %s --list-keys%s"
+ gpg tmpdir (if debug then "" else " >/dev/null
2>&1") in
+ if debug then eprintf "%s\n%!" cmd;
+ let r = Sys.command cmd in
+ if r <> 0 then (
+ eprintf (f_"virt-builder: error: GPG failure: could not run GPG the first
time\nUse the '-v' option and look for earlier error messages.\n");
+ exit 1
+ );
+ match gpgkey with
+ | KeyFile kf ->
+ let status_file = import_keyfile gpg tmpdir debug kf in
+ let status = read_whole_file status_file in
+ let status = string_nsplit "\n" status in
+ let fingerprint = ref "" in
+ List.iter (
+ fun line ->
+ let line = string_nsplit " " line in
+ match line with
+ | "[GNUPG:]" :: "IMPORT_OK" :: _ :: fp :: _ ->
fingerprint := fp
+ | _ -> ()
+ ) status;
+ !fingerprint
+ | Fingerprint fp when equal_fingerprints default_fingerprint fp ->
+ let filename, chan = Filename.open_temp_file "vbpubkey"
".asc" in
+ unlink_on_exit filename;
+ output_string chan default_pubkey;
+ close_out chan;
+ ignore (import_keyfile gpg tmpdir debug filename);
+ fp
+ | Fingerprint fp ->
+ let filename = Filename.temp_file "vbpubkey" ".asc" in
+ unlink_on_exit filename;
+ let cmd = sprintf "%s --yes --armor --output %s --export %s%s"
+ gpg (quote filename) (quote fp)
+ (if debug then "" else " >/dev/null 2>&1") in
+ if debug then eprintf "%s\n%!" cmd;
+ let r = Sys.command cmd in
+ if r <> 0 then (
+ eprintf (f_"virt-builder: error: could not export public key\nUse the
'-v' option and look for earlier error messages.\n");
+ exit 1
+ );
+ ignore (import_keyfile gpg tmpdir debug filename);
+ fp
+ ) else
+ "" in
{
debug = debug;
gpg = gpg;
fingerprint = fingerprint;
check_signature = check_signature;
gpghome = tmpdir;
- key_imported = false;
}
(* Compare two strings of hex digits ignoring whitespace and case. *)
-let rec equal_fingerprints fp1 fp2 =
+and equal_fingerprints fp1 fp2 =
let len1 = String.length fp1 and len2 = String.length fp2 in
let rec loop i j =
if i = len1 && j = len2 then true (* match! *)
@@ -171,8 +227,6 @@ and verify_detached t filename sigfile =
)
and do_verify t args =
- import_key t;
-
let status_file = Filename.temp_file "vbstat" ".txt" in
unlink_on_exit status_file;
let cmd =
@@ -206,42 +260,6 @@ and do_verify t args =
exit 1
)
-(* Import the requested public key. *)
-and import_key t =
- if not t.key_imported then (
- let keyfile = ref "" in
- if equal_fingerprints default_fingerprint t.fingerprint then (
- let filename, chan = Filename.open_temp_file "vbpubkey" ".asc"
in
- unlink_on_exit filename;
- output_string chan default_pubkey;
- close_out chan;
- keyfile := filename
- ) else (
- let filename = Filename.temp_file "vbpubkey" ".asc" in
- unlink_on_exit filename;
- let cmd = sprintf "%s --yes --armor --output %s --export %s%s"
- t.gpg (quote filename) (quote t.fingerprint)
- (if t.debug then "" else " >/dev/null 2>&1") in
- if t.debug then eprintf "%s\n%!" cmd;
- let r = Sys.command cmd in
- if r <> 0 then (
- eprintf (f_"virt-builder: error: could not export public key\nUse the
'-v' option and look for earlier error messages.\n");
- exit 1
- );
- keyfile := filename
- );
-
- let cmd = sprintf "%s --homedir %s --import %s%s"
- t.gpg t.gpghome (quote !keyfile)
- (if t.debug then "" else " >/dev/null 2>&1") in
- let r = Sys.command cmd in
- if r <> 0 then (
- eprintf (f_"virt-builder: error: could not import public key\nUse the
'-v' option and look for earlier error messages.\n");
- exit 1
- );
- t.key_imported <- true
- )
-
type csum_t = SHA512 of string
let verify_checksum t (SHA512 csum) filename =
diff --git a/builder/sigchecker.mli b/builder/sigchecker.mli
index cdd800e..f4e817e 100644
--- a/builder/sigchecker.mli
+++ b/builder/sigchecker.mli
@@ -20,7 +20,11 @@ val default_fingerprint : string
type t
-val create : debug:bool -> gpg:string -> fingerprint:string ->
check_signature:bool -> t
+type gpgkey_type =
+ | Fingerprint of string
+ | KeyFile of string
+
+val create : debug:bool -> gpg:string -> gpgkey:gpgkey_type ->
check_signature:bool -> t
val verify : t -> string -> unit
(** Verify the file is signed (if check_signature is true). *)
ACK.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://people.redhat.com/~rjones/virt-df/