Create a temporary directory and tell gpg to use it as homedir, so
imported keys do not get into the user's keyring. This also avoid
importing the default key when a different one is needed to check the
signature.
The only exception is when a non-default fingerprint is used: in this
case, that key is read from the user's keyring, since it is where it is.
---
builder/Makefile.am | 5 +++++
builder/mkdtemp-c.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
builder/mkdtemp.ml | 19 ++++++++++++++++
builder/mkdtemp.mli | 20 +++++++++++++++++
builder/sigchecker.ml | 61 ++++++++++++++++++++++++++++++++++++++++-----------
po/POTFILES | 1 +
po/POTFILES-ml | 1 +
7 files changed, 150 insertions(+), 13 deletions(-)
create mode 100644 builder/mkdtemp-c.c
create mode 100644 builder/mkdtemp.ml
create mode 100644 builder/mkdtemp.mli
diff --git a/builder/Makefile.am b/builder/Makefile.am
index 23336c0..d668377 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -48,6 +48,9 @@ SOURCES = \
index-parser-c.c \
list_entries.mli \
list_entries.ml \
+ mkdtemp.mli \
+ mkdtemp.ml \
+ mkdtemp-c.c \
paths.ml \
pxzcat.ml \
pxzcat.mli \
@@ -92,6 +95,8 @@ OBJECTS = \
pxzcat.cmx \
setlocale-c.o \
setlocale.cmx \
+ mkdtemp-c.o \
+ mkdtemp.cmx \
paths.cmx \
get_kernel.cmx \
downloader.cmx \
diff --git a/builder/mkdtemp-c.c b/builder/mkdtemp-c.c
new file mode 100644
index 0000000..2284e3a
--- /dev/null
+++ b/builder/mkdtemp-c.c
@@ -0,0 +1,56 @@
+/* virt-builder
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#ifdef HAVE_CAML_UNIXSUPPORT_H
+#include <caml/unixsupport.h>
+#else
+#define Nothing ((value) 0)
+extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
+#endif
+
+value
+virt_builder_mkdtemp (value val_pattern)
+{
+ CAMLparam1 (val_pattern);
+ CAMLlocal1 (rv);
+ char *pattern, *ret;
+
+ pattern = strdup (String_val (val_pattern));
+ if (pattern == NULL)
+ unix_error (errno, (char *) "strdup", val_pattern);
+
+ ret = mkdtemp (pattern);
+ if (ret == NULL)
+ unix_error (errno, (char *) "mkdtemp", val_pattern);
+
+ rv = caml_copy_string (ret);
+ free (pattern);
+
+ CAMLreturn (rv);
+}
diff --git a/builder/mkdtemp.ml b/builder/mkdtemp.ml
new file mode 100644
index 0000000..2e64862
--- /dev/null
+++ b/builder/mkdtemp.ml
@@ -0,0 +1,19 @@
+(* virt-builder
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+external mkdtemp : string -> string = "virt_builder_mkdtemp"
diff --git a/builder/mkdtemp.mli b/builder/mkdtemp.mli
new file mode 100644
index 0000000..674e6f2
--- /dev/null
+++ b/builder/mkdtemp.mli
@@ -0,0 +1,20 @@
+(* virt-builder
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val mkdtemp : string -> string
+(** [mkdtemp pattern] Tiny wrapper to the C [mkdtemp]. *)
diff --git a/builder/sigchecker.ml b/builder/sigchecker.ml
index b20a186..10e342e 100644
--- a/builder/sigchecker.ml
+++ b/builder/sigchecker.ml
@@ -95,21 +95,38 @@ ZvXkQ3FVJwZoLmHw47vvlVpLD/4gi1SuHWieRvZ+UdDq00E348pm
=neBW
-----END PGP PUBLIC KEY BLOCK-----
"
-let key_imported = ref false
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
+ 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
+ );
{
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. *)
@@ -159,8 +176,9 @@ and do_verify t args =
let status_file = Filename.temp_file "vbstat" ".txt" in
unlink_on_exit status_file;
let cmd =
- sprintf "%s --verify%s --status-file %s %s"
- t.gpg (if t.debug then "" else " -q --logger-file
/dev/null")
+ sprintf "%s --homedir %s --verify%s --status-file %s %s"
+ t.gpg t.gpghome
+ (if t.debug then "" else " -q --logger-file /dev/null")
(quote status_file) args in
if t.debug then eprintf "%s\n%!" cmd;
let r = Sys.command cmd in
@@ -188,23 +206,40 @@ and do_verify t args =
exit 1
)
-(* Import the default public key. *)
+(* Import the requested public key. *)
and import_key t =
- if not !key_imported then (
- let filename, chan = Filename.open_temp_file "vbpubkey" ".asc"
in
- unlink_on_exit filename;
- output_string chan default_pubkey;
- close_out chan;
-
- let cmd = sprintf "%s --import %s%s"
- t.gpg (quote filename)
+ 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
);
- key_imported := true
+ t.key_imported <- true
)
type csum_t = SHA512 of string
diff --git a/po/POTFILES b/po/POTFILES
index c0d20f0..1de501e 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -4,6 +4,7 @@ builder/index-parser-c.c
builder/index-scan.c
builder/index-struct.c
builder/index-validate.c
+builder/mkdtemp-c.c
builder/pxzcat-c.c
builder/setlocale-c.c
cat/cat.c
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 301fe81..56551ab 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -4,6 +4,7 @@ builder/downloader.ml
builder/get_kernel.ml
builder/index_parser.ml
builder/list_entries.ml
+builder/mkdtemp.ml
builder/paths.ml
builder/pxzcat.ml
builder/setlocale.ml
--
1.8.3.1