summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Whiting <jeremy.whiting@collabora.com>2013-09-05 12:50:36 -0600
committerColin Walters <walters@verbum.org>2013-09-29 14:49:47 -0400
commit7f9eefb62d2b5a977289fa5a5a1d34755f597679 (patch)
tree066943d31be8969ed92bda7dbd860f76738462d1
parentb0645815770e0721d8915f924903d3a0a51e3964 (diff)
downloadostree-7f9eefb62d2b5a977289fa5a5a1d34755f597679.tar.gz
pull: Verify commits with gpg signatures from detached metadata
This uses gpgv for verification against DATADIR/ostree/pubring.gpg by default. The keyring can be overridden by specifying OSTREE_GPG_HOME. Add a unit test for commit signing with gpg key and verifying on pull; to implement this we ship a test GPG key generated with no password for Ostree Tester <test@test.com>. Change all of the existing tests to disable GPG verification.
-rw-r--r--Makefile-libostree.am5
-rw-r--r--Makefile-tests.am1
m---------src/libgsystem0
-rw-r--r--src/libostree/README-gpg2
-rw-r--r--src/libostree/ostree-gpg-verifier.c307
-rw-r--r--src/libostree/ostree-gpg-verifier.h64
-rw-r--r--src/libostree/ostree-repo-pull.c23
-rw-r--r--src/libostree/ostree-repo.c133
-rw-r--r--src/libostree/ostree-repo.h7
-rw-r--r--src/libostree/ostree-sysroot.c3
-rw-r--r--src/ostree/ot-admin-builtin-upgrade.c3
-rw-r--r--tests/libtest.sh1
-rwxr-xr-xtests/pull-test.sh2
-rwxr-xr-xtests/test-admin-deploy-1.sh2
-rwxr-xr-xtests/test-admin-deploy-2.sh4
-rwxr-xr-xtests/test-archivez.sh2
-rwxr-xr-xtests/test-commit-sign.sh102
-rwxr-xr-xtests/test-pull-corruption.sh2
-rwxr-xr-xtests/test-pull-resume.sh2
19 files changed, 656 insertions, 9 deletions
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index badbb92d..35d0ec0e 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -57,6 +57,8 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-bootloader-uboot.c \
src/libostree/ostree-ordered-hash.h \
src/libostree/ostree-ordered-hash.c \
+ src/libostree/ostree-gpg-verifier.c \
+ src/libostree/ostree-gpg-verifier.h \
$(NULL)
if USE_LIBARCHIVE
libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
@@ -102,5 +104,8 @@ pkgconfig_DATA += src/libostree/ostree-1.pc
if USE_GPGME
libostree_1_la_LIBADD += $(GPGME_LIBS)
+
+gpgreadme_DATA = src/libostree/README-gpg
+gpgreadmedir = $(pkgdatadir)
endif
diff --git a/Makefile-tests.am b/Makefile-tests.am
index d6b3e448..c0121411 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -23,6 +23,7 @@ insttestdir=$(pkglibexecdir)/installed-tests
testfiles = test-basic \
test-archivez \
test-remote-add \
+ test-commit-sign \
test-corruption \
test-libarchive \
test-pull-archive-z \
diff --git a/src/libgsystem b/src/libgsystem
-Subproject e0b2fefbb69d03f7aa1390f723e4dfc46f301e7
+Subproject 020fa7de344d9f10136ae1a3cb9bf6baa868218
diff --git a/src/libostree/README-gpg b/src/libostree/README-gpg
new file mode 100644
index 00000000..9c1d479c
--- /dev/null
+++ b/src/libostree/README-gpg
@@ -0,0 +1,2 @@
+Any GPG keyring files ending in ".gpg" placed in this directory will
+be automatically trusted by OSTree.
diff --git a/src/libostree/ostree-gpg-verifier.c b/src/libostree/ostree-gpg-verifier.c
new file mode 100644
index 00000000..bb02b94c
--- /dev/null
+++ b/src/libostree/ostree-gpg-verifier.c
@@ -0,0 +1,307 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ * Copyright (C) 2013 Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ */
+
+#include "ostree-gpg-verifier.h"
+#include "otutil.h"
+
+#define GPGVGOODPREFIX "[GNUPG:] GOODSIG "
+
+typedef struct {
+ GObjectClass parent_class;
+} OstreeGpgVerifierClass;
+
+struct OstreeGpgVerifier {
+ GObject parent;
+
+ GList *keyrings;
+ gchar *homedir;
+};
+
+static void _ostree_gpg_verifier_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (OstreeGpgVerifier, _ostree_gpg_verifier, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, _ostree_gpg_verifier_initable_iface_init))
+
+static void
+ostree_gpg_verifier_finalize (GObject *object)
+{
+ OstreeGpgVerifier *self = OSTREE_GPG_VERIFIER (object);
+
+ g_list_free_full (self->keyrings, g_object_unref);
+ g_free (self->homedir);
+
+ G_OBJECT_CLASS (_ostree_gpg_verifier_parent_class)->finalize (object);
+}
+
+static void
+_ostree_gpg_verifier_class_init (OstreeGpgVerifierClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ostree_gpg_verifier_finalize;
+}
+
+static void
+_ostree_gpg_verifier_init (OstreeGpgVerifier *self)
+{
+}
+
+static gboolean
+ostree_gpg_verifier_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ OstreeGpgVerifier *self = (OstreeGpgVerifier*)initable;
+ const char *default_keyring_path = g_getenv ("OSTREE_GPG_HOME");
+ gs_unref_object GFile *default_keyring_dir = NULL;
+ gs_unref_object GFile *default_pubring_file = NULL;
+ gs_unref_object GFile *default_pubring = NULL;
+
+ if (!default_keyring_path)
+ default_keyring_path = DATADIR "/ostree/trusted.gpg.d/";
+
+ default_keyring_dir = g_file_new_for_path (default_keyring_path);
+ default_pubring_file = g_file_get_child (default_keyring_dir, "pubring.gpg");
+
+ if (!_ostree_gpg_verifier_add_keyring (self, default_pubring_file,
+ cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+static void
+_ostree_gpg_verifier_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = ostree_gpg_verifier_initable_init;
+}
+
+typedef struct {
+ OstreeGpgVerifier *self;
+ GCancellable *cancellable;
+ gboolean gpgv_done;
+ gboolean status_done;
+
+ gint goodsigs;
+ gint exitcode;
+ GError *error;
+ GMainLoop *loop;
+} VerifyRun;
+
+static void
+_gpgv_parse_line (VerifyRun *v, const gchar *line)
+{
+ if (g_str_has_prefix (line, GPGVGOODPREFIX))
+ v->goodsigs++;
+}
+
+static void
+on_process_done (GObject *s, GAsyncResult *res, gpointer user_data)
+{
+ VerifyRun *v = user_data;
+ gs_subprocess_wait_finish (GS_SUBPROCESS (s), res,
+ &v->exitcode, &v->error);
+
+ v->gpgv_done = TRUE;
+
+ g_main_loop_quit (v->loop);
+}
+
+static void
+on_read_line (GObject *s, GAsyncResult *res, gpointer user_data)
+{
+ VerifyRun *v = user_data;
+ gchar *line;
+
+ /* Ignore errors when reading from the data input */
+ line = g_data_input_stream_read_line_finish (G_DATA_INPUT_STREAM (s),
+ res, NULL, NULL);
+
+ if (line == NULL)
+ {
+ v->status_done = TRUE;
+ g_main_loop_quit (v->loop);
+ }
+ else
+ {
+ _gpgv_parse_line (v, line);
+ g_free (line);
+ g_data_input_stream_read_line_async (G_DATA_INPUT_STREAM (s),
+ G_PRIORITY_DEFAULT, v->cancellable,
+ on_read_line, v);
+ }
+}
+
+
+gboolean
+_ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
+ GFile *file,
+ GFile *signature,
+ gboolean *out_had_valid_sig,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gboolean ret_had_valid_sig = FALSE;
+ gs_unref_object GSSubprocessContext *context = NULL;
+ gs_unref_object GSSubprocess *proc = NULL;
+ gs_unref_object GDataInputStream *data = NULL;
+ gs_free gchar *status_fd_str = NULL;
+ GInputStream *output;
+ gint fd;
+ VerifyRun v = { 0, };
+ GList *item;
+ GMainContext *maincontext = NULL;
+ GMainLoop *loop = NULL;
+
+ g_return_val_if_fail (out_had_valid_sig != NULL, FALSE);
+
+ maincontext = g_main_context_new ();
+ loop = g_main_loop_new (maincontext, FALSE);
+
+ g_main_context_push_thread_default (maincontext);
+
+ context = gs_subprocess_context_newv ("gpgv", NULL);
+ gs_subprocess_context_set_stdin_disposition (context,
+ GS_SUBPROCESS_STREAM_DISPOSITION_NULL);
+ gs_subprocess_context_set_stdout_disposition (context,
+ GS_SUBPROCESS_STREAM_DISPOSITION_NULL);
+ gs_subprocess_context_set_stderr_disposition (context,
+ GS_SUBPROCESS_STREAM_DISPOSITION_NULL);
+
+ if (!gs_subprocess_context_open_pipe_read (context, &output, &fd, error))
+ goto out;
+
+ status_fd_str = g_strdup_printf ("%d", fd);
+ gs_subprocess_context_argv_append (context, "--status-fd");
+ gs_subprocess_context_argv_append (context, status_fd_str);
+
+ for (item = self->keyrings ; item != NULL; item = g_list_next (item))
+ {
+ GFile *keyring = item->data;
+ gs_subprocess_context_argv_append (context, "--keyring");
+ gs_subprocess_context_argv_append (context, gs_file_get_path_cached (keyring));
+ }
+
+ gs_subprocess_context_argv_append (context, gs_file_get_path_cached (signature));
+ gs_subprocess_context_argv_append (context, gs_file_get_path_cached (file));
+
+ proc = gs_subprocess_new (context, cancellable, error);
+ if (proc == NULL)
+ goto out;
+
+ data = g_data_input_stream_new (output);
+
+ v.self = self;
+ v.cancellable = cancellable;
+ v.loop = loop;
+
+ gs_subprocess_wait (proc, cancellable, on_process_done, &v);
+ g_data_input_stream_read_line_async (data, G_PRIORITY_DEFAULT, cancellable,
+ on_read_line, &v);
+
+ while (!v.gpgv_done || !v.status_done)
+ g_main_loop_run (loop);
+
+ if (v.goodsigs > 0)
+ ret_had_valid_sig = TRUE;
+
+ ret = TRUE;
+ *out_had_valid_sig = ret_had_valid_sig;
+ out:
+ if (maincontext)
+ {
+ g_main_context_pop_thread_default (maincontext);
+ g_main_context_unref (maincontext);
+ }
+ if (loop)
+ g_main_loop_unref (loop);
+
+ return ret;
+}
+
+void
+_ostree_gpg_verifier_set_homedir (OstreeGpgVerifier *self,
+ const gchar *path)
+{
+ g_free (self->homedir);
+ self->homedir = g_strdup (path);
+}
+
+gboolean
+_ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
+ GFile *path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ self->keyrings = g_list_append (self->keyrings, g_object_ref (path));
+ return TRUE;
+}
+
+gboolean
+_ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
+ GFile *path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object GFileEnumerator *enumerator = NULL;
+
+ enumerator = g_file_enumerate_children (path, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable, error);
+ if (!enumerator)
+ goto out;
+
+ while (TRUE)
+ {
+ GFileInfo *file_info;
+ GFile *path;
+
+ if (!gs_file_enumerator_iterate (enumerator, &file_info, &path,
+ cancellable, error))
+ goto out;
+ if (file_info == NULL)
+ break;
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR &&
+ g_str_has_suffix (g_file_info_get_name (file_info), ".gpg"))
+ self->keyrings = g_list_append (self->keyrings, g_object_ref (path));
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+OstreeGpgVerifier*
+_ostree_gpg_verifier_new (GCancellable *cancellable,
+ GError **error)
+{
+ return g_initable_new (OSTREE_TYPE_GPG_VERIFIER, cancellable, error, NULL);
+}
diff --git a/src/libostree/ostree-gpg-verifier.h b/src/libostree/ostree-gpg-verifier.h
new file mode 100644
index 00000000..f69af06e
--- /dev/null
+++ b/src/libostree/ostree-gpg-verifier.h
@@ -0,0 +1,64 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ * Copyright (C) 2013 Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
+ */
+
+//#pragma once
+
+#include "config.h"
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define OSTREE_TYPE_GPG_VERIFIER _ostree_gpg_verifier_get_type()
+#define OSTREE_GPG_VERIFIER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSTREE_TYPE_GPG_VERIFIER, OstreeGpgVerifier))
+#define OSTREE_IS_GPG_VERIFIER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_GPG_VERIFIER))
+
+typedef struct OstreeGpgVerifier OstreeGpgVerifier;
+
+GType _ostree_gpg_verifier_get_type (void);
+
+OstreeGpgVerifier *_ostree_gpg_verifier_new (GCancellable *cancellable,
+ GError **error);
+
+gboolean _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
+ GFile *file,
+ GFile *signature,
+ gboolean *had_valid_signature,
+ GCancellable *cancellable,
+ GError **error);
+
+void _ostree_gpg_verifier_set_homedir (OstreeGpgVerifier *self,
+ const gchar *path);
+
+gboolean _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
+ GFile *path,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean _ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
+ GFile *path,
+ GCancellable *cancellable,
+ GError **error);
+G_END_DECLS
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 416e3b15..763ab5b1 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -91,6 +91,8 @@ typedef struct {
gboolean transaction_resuming;
volatile gint n_scanned_metadata;
SoupURI *fetching_sync_uri;
+
+ gboolean gpg_verify;
GThread *metadata_thread;
GMainContext *metadata_thread_context;
@@ -747,6 +749,19 @@ scan_commit_object (OtPullData *pull_data,
goto out;
}
+#ifdef HAVE_GPGME
+ if (pull_data->gpg_verify)
+ {
+ if (!ostree_repo_verify_commit (pull_data->repo,
+ checksum,
+ NULL,
+ NULL,
+ cancellable,
+ error))
+ goto out;
+ }
+#endif
+
if (!ostree_repo_load_variant (pull_data->repo, OSTREE_OBJECT_TYPE_COMMIT, checksum,
&commit, error))
goto out;
@@ -1234,6 +1249,14 @@ ostree_repo_pull (OstreeRepo *self,
goto out;
pull_data->base_uri = soup_uri_new (baseurl);
+#ifdef HAVE_GPGME
+ if (!ot_keyfile_get_boolean_with_default (config, remote_key, "gpg-verify",
+ TRUE, &pull_data->gpg_verify, error))
+ goto out;
+#else
+ pull_data->gpg_verify = FALSE;
+#endif
+
if (!ot_keyfile_get_boolean_with_default (config, remote_key, "tls-permissive",
FALSE, &tls_permissive, error))
goto out;
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 189740f0..f8738a88 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -31,6 +31,8 @@
#include "ostree-core-private.h"
#include "ostree-repo-private.h"
#include "ostree-repo-file.h"
+#include "ostree-repo-file-enumerator.h"
+#include "ostree-gpg-verifier.h"
#ifdef HAVE_GPGME
#include <locale.h>
@@ -403,6 +405,7 @@ ostree_repo_create (OstreeRepo *self,
config_data = g_string_new (DEFAULT_CONFIG_CONTENTS);
g_string_append_printf (config_data, "mode=%s\n", mode_str);
+
if (!g_file_replace_contents (self->config_file,
config_data->str,
config_data->len,
@@ -1646,4 +1649,134 @@ out:
return ret;
}
+/**
+ * ostree_repo_verify_commit:
+ * @self: Repository
+ * @commit_checksum: ASCII SHA256 checksum
+ * @keyringdir: (allow-none): Path to directory GPG keyrings; overrides built-in default if given
+ * @extra_keyring: (allow-none): Path to additional keyring file (not a directory)
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Check for a valid GPG signature on commit named by the ASCII
+ * checksum @commit_checksum.
+ */
+gboolean
+ostree_repo_verify_commit (OstreeRepo *self,
+ const gchar *commit_checksum,
+ GFile *keyringdir,
+ GFile *extra_keyring,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_object OstreeGpgVerifier *verifier = NULL;
+ gs_unref_variant GVariant *commit_variant = NULL;
+ gs_unref_object GFile *commit_tmp_path = NULL;
+ gs_unref_object GFile *keyringdir_ref = NULL;
+ gs_unref_variant GVariant *metadata = NULL;
+ gs_unref_variant GVariant *signaturedata = NULL;
+ gs_free gchar *commit_filename = NULL;
+ gint i, n;
+ gboolean had_valid_signataure = FALSE;
+
+ if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT,
+ commit_checksum, &commit_variant,
+ error))
+ goto out;
+
+ verifier = _ostree_gpg_verifier_new (cancellable, error);
+ if (!verifier)
+ goto out;
+
+ if (keyringdir)
+ {
+ if (!_ostree_gpg_verifier_add_keyring_dir (verifier, keyringdir,
+ cancellable, error))
+ goto out;
+ }
+ if (extra_keyring != NULL)
+ {
+ if (!_ostree_gpg_verifier_add_keyring (verifier, extra_keyring,
+ cancellable, error))
+ goto out;
+ }
+
+ if (!ostree_repo_read_commit_detached_metadata (self,
+ commit_checksum,
+ &metadata,
+ cancellable,
+ error))
+ {
+ g_prefix_error (error, "Failed to read detached metadata: ");
+ goto out;
+ }
+
+ if (metadata)
+ signaturedata = g_variant_lookup_value (metadata, "ostree.gpgsigs", G_VARIANT_TYPE ("aay"));
+ if (!signaturedata)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ "No signatures found");
+ goto out;
+ }
+
+ if (!gs_file_open_in_tmpdir (self->tmp_dir, 0644,
+ &commit_tmp_path, NULL,
+ cancellable, error))
+ goto out;
+
+ if (!g_file_replace_contents (commit_tmp_path,
+ (char*)g_variant_get_data (commit_variant),
+ g_variant_get_size (commit_variant),
+ NULL, FALSE, 0, NULL,
+ cancellable, error))
+ goto out;
+
+ n = g_variant_n_children (signaturedata);
+ for (i = 0; i < n; i++)
+ {
+ GVariant *signature_variant = g_variant_get_child_value (signaturedata, i);
+ gs_unref_object GFile *temp_sig_path = NULL;
+
+ if (!gs_file_open_in_tmpdir (self->tmp_dir, 0644,
+ &temp_sig_path, NULL,
+ cancellable, error))
+ goto out;
+
+ if (!g_file_replace_contents (temp_sig_path,
+ (char*)g_variant_get_data (signature_variant),
+ g_variant_get_size (signature_variant),
+ NULL, FALSE, 0, NULL,
+ cancellable, error))
+ goto out;
+
+ if (!_ostree_gpg_verifier_check_signature (verifier,
+ commit_tmp_path,
+ temp_sig_path,
+ &had_valid_signataure,
+ cancellable, error))
+ {
+ (void) gs_file_unlink (temp_sig_path, NULL, NULL);
+ goto out;
+ }
+ (void) gs_file_unlink (temp_sig_path, NULL, NULL);
+ if (had_valid_signataure)
+ break;
+ }
+
+ if (!had_valid_signataure)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "GPG signatures found, but none are in trusted keyring");
+ goto out;
+ }
+
+ ret = TRUE;
+out:
+ if (commit_tmp_path)
+ (void) gs_file_unlink (commit_tmp_path, NULL, NULL);
+ return ret;
+}
+
#endif
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 4f40b9f9..147893dc 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -470,6 +470,13 @@ gboolean ostree_repo_sign_commit (OstreeRepo *self,
const gchar *homedir,
GCancellable *cancellable,
GError **error);
+
+gboolean ostree_repo_verify_commit (OstreeRepo *self,
+ const gchar *commit_checksum,
+ GFile *keyringdir,
+ GFile *extra_keyring,
+ GCancellable *cancellable,
+ GError **error);
#endif
G_END_DECLS
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index df381069..bf064d5a 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -232,7 +232,8 @@ ostree_sysroot_ensure_initialized (OstreeSysroot *self,
if (!g_file_query_exists (dir, NULL))
{
gs_unref_object OstreeRepo *repo = ostree_repo_new (repo_dir);
- if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE, cancellable, error))
+ if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE,
+ cancellable, error))
goto out;
}
diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c
index 27925c58..73b1bf57 100644
--- a/src/ostree/ot-admin-builtin-upgrade.c
+++ b/src/ostree/ot-admin-builtin-upgrade.c
@@ -104,11 +104,12 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel
if (origin_remote)
{
+ OstreeRepoPullFlags pullflags = 0;
char *refs_to_fetch[] = { origin_ref, NULL };
g_print ("Fetching remote %s ref %s\n", origin_remote, origin_ref);
- if (!ostree_repo_pull (repo, origin_remote, refs_to_fetch, OSTREE_REPO_PULL_FLAGS_NONE,
+ if (!ostree_repo_pull (repo, origin_remote, refs_to_fetch, pullflags,
cancellable, error))
goto out;
}
diff --git a/tests/libtest.sh b/tests/libtest.sh
index 84fd88f5..a3650580 100644
--- a/tests/libtest.sh
+++ b/tests/libtest.sh
@@ -24,6 +24,7 @@ export G_DEBUG=fatal-warnings
export TEST_GPG_KEYID="472CDAFA"
export TEST_GPG_HOME=${SRCDIR}/gpghome
+export OSTREE_GPG_HOME=${TEST_GPG_HOME}
if test -n "${OT_TESTS_DEBUG}"; then
set -x
diff --git a/tests/pull-test.sh b/tests/pull-test.sh
index dd93b88d..5a96b087 100755
--- a/tests/pull-test.sh
+++ b/tests/pull-test.sh
@@ -20,7 +20,7 @@
cd ${test_tmpdir}
mkdir repo
${CMD_PREFIX} ostree --repo=repo init
-${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
${CMD_PREFIX} ostree --repo=repo pull origin main
${CMD_PREFIX} ostree --repo=repo fsck
echo "ok pull"
diff --git a/tests/test-admin-deploy-1.sh b/tests/test-admin-deploy-1.sh
index d02752dd..66139d54 100755
--- a/tests/test-admin-deploy-1.sh
+++ b/tests/test-admin-deploy-1.sh
@@ -132,7 +132,7 @@ ostree admin --sysroot=sysroot status
echo "ok upgrade bare"
os_repository_new_commit
-ostree --repo=sysroot/ostree/repo remote add testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
+ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
ostree admin --sysroot=sysroot upgrade --os=testos
origrev=${rev}
rev=${newrev}
diff --git a/tests/test-admin-deploy-2.sh b/tests/test-admin-deploy-2.sh
index 2e6e248e..0667ed5d 100755
--- a/tests/test-admin-deploy-2.sh
+++ b/tests/test-admin-deploy-2.sh
@@ -41,12 +41,12 @@ echo "ok deploy command"
# Commit + upgrade twice, so that we'll rotate out the original deployment
bootcsum1=${bootcsum}
os_repository_new_commit
-ostree --repo=sysroot/ostree/repo remote add testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
+ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
ostree admin --sysroot=sysroot upgrade --os=testos
bootcsum2=${bootcsum}
os_repository_new_commit "1"
bootcsum3=${bootcsum}
-ostree --repo=sysroot/ostree/repo remote add testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
+ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime
ostree admin --sysroot=sysroot upgrade --os=testos
rev=${newrev}
diff --git a/tests/test-archivez.sh b/tests/test-archivez.sh
index 34ba7bcd..c228a66e 100755
--- a/tests/test-archivez.sh
+++ b/tests/test-archivez.sh
@@ -31,7 +31,7 @@ echo "ok setup"
cd ${test_tmpdir}
mkdir repo2
${CMD_PREFIX} ostree --repo=repo2 init
-${CMD_PREFIX} ostree --repo=repo2 remote add aremote file://$(pwd)/repo test2
+${CMD_PREFIX} ostree --repo=repo2 remote add --set=gpg-verify=false aremote file://$(pwd)/repo test2
ostree --repo=repo2 pull aremote
ostree --repo=repo2 rev-parse aremote/test2
ostree --repo=repo2 fsck
diff --git a/tests/test-commit-sign.sh b/tests/test-commit-sign.sh
new file mode 100755
index 00000000..516d6550
--- /dev/null
+++ b/tests/test-commit-sign.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 Jeremy Whiting <jeremy.whiting@collabora.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -e
+
+if ! ostree --version | grep -q -e '\+gpgme'; then
+ exit 77
+fi
+
+. $(dirname $0)/libtest.sh
+
+keyid="472CDAFA"
+oldpwd=`pwd`
+mkdir ostree-srv
+cd ostree-srv
+mkdir gnomerepo
+${CMD_PREFIX} ostree --repo=gnomerepo init --mode="archive-z2"
+mkdir gnomerepo-files
+cd gnomerepo-files
+echo first > firstfile
+mkdir baz
+echo moo > baz/cow
+echo alien > baz/saucer
+${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit -b main -s "A remote commit" -m "Some Commit body" --gpg-sign=$keyid --gpg-homedir=${SRCDIR}/gpghome
+mkdir baz/deeper
+${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit -b main -s "Add deeper" --gpg-sign=$keyid --gpg-homedir=${SRCDIR}/gpghome
+echo hi > baz/deeper/ohyeah
+mkdir baz/another/
+echo x > baz/another/y
+${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit -b main -s "The rest" --gpg-sign=$keyid --gpg-homedir=${SRCDIR}/gpghome
+cd ..
+rm -rf gnomerepo-files
+
+cd ${test_tmpdir}
+mkdir ${test_tmpdir}/httpd
+cd httpd
+ln -s ${test_tmpdir}/ostree-srv ostree
+ostree trivial-httpd --daemonize -p ${test_tmpdir}/httpd-port
+port=$(cat ${test_tmpdir}/httpd-port)
+echo "http://127.0.0.1:${port}" > ${test_tmpdir}/httpd-address
+cd ${oldpwd}
+
+export OSTREE="ostree --repo=repo"
+
+repopath=${test_tmpdir}/ostree-srv/gnomerepo
+cp -a ${repopath} ${repopath}.orig
+
+# Set OSTREE_GPG_HOME to a place with no keyrings, we shouldn't trust the signature
+cd ${test_tmpdir}
+mkdir repo
+${CMD_PREFIX} ostree --repo=repo init
+${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+if env OSTREE_GPG_HOME=${test_tmpdir} ${CMD_PREFIX} ostree --repo=repo pull origin main; then
+ assert_not_reached "pull with no trusted GPG keys unexpectedly succeeded!"
+fi
+rm repo -rf
+
+# And a test case with valid signature
+cd ${test_tmpdir}
+mkdir repo
+${CMD_PREFIX} ostree --repo=repo init
+${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+${CMD_PREFIX} ostree --repo=repo pull origin main
+rm repo -rf
+
+# A test with corrupted detached signature
+cd ${test_tmpdir}
+find ${test_tmpdir}/ostree-srv/gnomerepo -name '*.commitmeta' | while read fname; do
+ echo borkborkbork > ${fname};
+done
+mkdir repo
+${CMD_PREFIX} ostree --repo=repo init
+${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+if ${CMD_PREFIX} ostree --repo=repo pull origin main; then
+ assert_not_reached "pull with corrupted signature unexpectedly succeeded!"
+fi
+rm repo -rf
+
+# And now attempt to pull the same corrupted commit, but with GPG
+# verification off
+cd ${test_tmpdir}
+mkdir repo
+${CMD_PREFIX} ostree --repo=repo init
+${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
+${CMD_PREFIX} ostree --repo=repo pull origin main
+rm repo -rf
diff --git a/tests/test-pull-corruption.sh b/tests/test-pull-corruption.sh
index 70efa886..394a9e81 100755
--- a/tests/test-pull-corruption.sh
+++ b/tests/test-pull-corruption.sh
@@ -33,7 +33,7 @@ do_corrupt_pull_test() {
rm repo -rf
mkdir repo
${CMD_PREFIX} ostree --repo=repo init
- ${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+ ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
if ${CMD_PREFIX} ostree --repo=repo pull origin main; then
assert_not_reached "pull unexpectedly succeeded!"
fi
diff --git a/tests/test-pull-resume.sh b/tests/test-pull-resume.sh
index 4770c0b1..fcca8393 100755
--- a/tests/test-pull-resume.sh
+++ b/tests/test-pull-resume.sh
@@ -32,7 +32,7 @@ cd ${test_tmpdir}
rm repo -rf
mkdir repo
${CMD_PREFIX} ostree --repo=repo init
-${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo
+${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
maxtries=`find ${repopath}/objects | wc -l`
maxtries=`expr $maxtries \* 2`