bin/static-delta: Add command to verify delta signature
authorFrédéric Danis <frederic.danis@collabora.com>
Fri, 29 Nov 2019 11:40:11 +0000 (12:40 +0100)
committerFrédéric Danis <frederic.danis@collabora.com>
Mon, 14 Sep 2020 07:27:19 +0000 (09:27 +0200)
Add new "static-delta verify" sub-command.
This supports multiple keys to verify the static-delta file.

Signed-off-by: Frédéric Danis <frederic.danis@collabora.com>
bash/ostree
man/ostree-static-delta.xml
src/ostree/ot-builtin-static-delta.c

index a7389bd7ddca580668a72a474a28aa65b947558b..34a38b2035de18e4388f0e697f24d0219172adbe 100644 (file)
@@ -1709,6 +1709,40 @@ _ostree_static_delta_show() {
     return 0
 }
 
+_ostree_static_delta_verify() {
+    local boolean_options="
+        $main_boolean_options
+    "
+
+    local options_with_args="
+        --sign-type
+        --keys-file
+        --keys-dir
+        --repo
+    "
+
+    local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
+
+    case "$prev" in
+        --keys-file|--keys-dir|--repo)
+            __ostree_compreply_dirs_only
+            return 0
+            ;;
+        $options_with_args_glob )
+            return 0
+            ;;
+    esac
+
+    case "$cur" in
+        -*)
+            local all_options="$boolean_options $options_with_args"
+            __ostree_compreply_all_options
+            ;;
+    esac
+
+    return 0
+}
+
 _ostree_static_delta() {
     local subcommands="
         apply-offline
index a4bef237a0f5d986fea8334d9ddf23a367618734..66fc7590267f15630a260016dade26c5cb253852 100644 (file)
@@ -65,6 +65,9 @@ Boston, MA 02111-1307, USA.
             <cmdsynopsis>
                 <command>ostree static-delta apply-offline</command> <arg choice="req">PATH</arg>
             </cmdsynopsis>
+            <cmdsynopsis>
+                <command>ostree static-delta verify</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">STATIC-DELTA</arg> <arg choice="opt" rep="repeat">KEY-ID</arg>
+            </cmdsynopsis>
     </refsynopsisdiv>
 
     <refsect1>
@@ -149,6 +152,67 @@ Boston, MA 02111-1307, USA.
         </variablelist>
     </refsect1>
 
+    <refsect1>
+        <title>'Verify' Options</title>
+
+        <variablelist>
+            <varlistentry>
+                <term><option>KEY-ID</option></term>
+
+                <listitem><para>
+                    <variablelist>
+                        <varlistentry>
+                            <term><option>for ed25519:</option></term>
+                            <listitem><para>
+                                    <literal>base64</literal>-encoded public key for verifying.
+                            </para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                            <term><option>for dummy:</option></term>
+                            <listitem><para>
+                                        ASCII-string used as public key.
+                            </para></listitem>
+                        </varlistentry>
+                    </variablelist>
+                </para></listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term><option>--sign-type</option>=ENGINE</term>
+
+                <listitem><para>
+                    Use particular signature engine. Currently
+                    available <arg choice="plain">ed25519</arg> and <arg choice="plain">dummy</arg>
+                    signature types.
+
+                    The default is <arg choice="plain">ed25519</arg>.
+                </para></listitem>
+            </varlistentry>
+
+            <varlistentry>
+                 <term><option>--keys-file</option></term>
+                 <listitem><para>
+                     Read key(s) from file <filename>filename</filename>.
+                 </para></listitem>
+
+                 <listitem><para>
+                     Valid for <literal>ed25519</literal> signature type.
+                     For <literal>ed25519</literal> this file must contain <literal>base64</literal>-encoded
+                     public key(s) per line for verifying.
+                 </para></listitem>
+             </varlistentry>
+
+             <varlistentry>
+                 <term><option>--keys-dir</option></term>
+                 <listitem><para>
+                     Redefine the system path, where to search files and subdirectories with
+                     well-known and revoked keys.
+                 </para></listitem>
+             </varlistentry>
+        </variablelist>
+    </refsect1>
+
 <!-- Can we have an example for when it actually does something?-->
     <refsect1>
         <title>Example</title>
index d5e937834fcabc2a94d63286874ade72ea09b734..4e507e7d41a9453e7768d96ee8a9cd9546644a78 100644 (file)
@@ -43,6 +43,7 @@ static gboolean opt_if_not_exists;
 static char **opt_key_ids;
 static char *opt_sign_name;
 static char *opt_keysfilename;
+static char *opt_keysdir;
 
 #define BUILTINPROTO(name) static gboolean ot_static_delta_builtin_ ## name (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
 
@@ -51,6 +52,7 @@ BUILTINPROTO(show);
 BUILTINPROTO(delete);
 BUILTINPROTO(generate);
 BUILTINPROTO(apply_offline);
+BUILTINPROTO(verify);
 
 #undef BUILTINPROTO
 
@@ -70,6 +72,9 @@ static OstreeCommand static_delta_subcommands[] = {
   { "apply-offline", OSTREE_BUILTIN_FLAG_NONE,
     ot_static_delta_builtin_apply_offline,
     "Apply static delta file" },
+  { "verify", OSTREE_BUILTIN_FLAG_NONE,
+    ot_static_delta_builtin_verify,
+    "Verify static delta signatures" },
   { NULL, 0, NULL, NULL }
 };
 
@@ -107,6 +112,15 @@ static GOptionEntry list_options[] = {
   { NULL }
 };
 
+static GOptionEntry verify_options[] = {
+  { "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"},
+#if defined(HAVE_LIBSODIUM)
+  { "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME"},
+  { "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir, "Redefine system-wide directories with public and revoked keys for verification", "NAME"},
+#endif
+  { NULL }
+};
+
 static void
 static_delta_usage (char    **argv,
                     gboolean  is_error)
@@ -439,6 +453,68 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvoc
   return TRUE;
 }
 
+static gboolean
+ot_static_delta_builtin_verify (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
+{
+  g_autoptr (GOptionContext) context = g_option_context_new ("STATIC-DELTA-FILE [KEY-ID...]");
+  g_autoptr (OstreeRepo) repo = NULL;
+  gboolean verified;
+  char **key_ids;
+  int n_key_ids;
+
+  if (!ostree_option_context_parse (context, verify_options, &argc, &argv, invocation, &repo, cancellable, error))
+    return FALSE;
+
+  if (argc < 3)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                           "DELTA must be specified");
+      return FALSE;
+    }
+
+  opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519;
+
+  const char *delta_id = argv[2];
+
+  g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (opt_sign_name, error);
+  if (!sign)
+    {
+      g_print("Sign-type not supported\n");
+      return FALSE;
+    }
+
+  key_ids = argv + 3;
+  n_key_ids = argc - 3;
+  for (int i = 0; i < n_key_ids; i++)
+    {
+      g_autoptr (GVariant) pk = g_variant_new_string(key_ids[i]);
+      if (!ostree_sign_add_pk(sign, pk, error))
+        return FALSE;
+    }
+  if ((n_key_ids == 0) || opt_keysfilename)
+    {
+      g_autoptr (GVariantBuilder) builder = NULL;
+      g_autoptr (GVariant) options = NULL;
+
+      builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+      /* Use custom directory with public and revoked keys instead of system-wide directories */
+      if (opt_keysdir)
+        g_variant_builder_add (builder, "{sv}", "basedir", g_variant_new_string (opt_keysdir));
+      /* The last chance for verification source -- system files */
+      if (opt_keysfilename)
+        g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (opt_keysfilename));
+      options = g_variant_builder_end (builder);
+
+      if (!ostree_sign_load_pk (sign, options, error))
+        return FALSE;
+    }
+
+  verified = ostree_repo_static_delta_verify_signature (repo, delta_id, sign, NULL, error);
+  g_print ("Verification %s\n", verified ? "OK" : "fails");
+
+  return verified;
+}
+
 gboolean
 ostree_builtin_static_delta (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
 {