static GVariant * rpmostreed_deployment_gpg_results (OstreeRepo *repo, const gchar *origin_refspec, const gchar *csum) { GError *error = NULL; GVariant *ret = NULL; g_autofree gchar *remote = NULL; glnx_unref_object OstreeGpgVerifyResult *result = NULL; guint n_sigs, i; gboolean gpg_verify; GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE ("av")); if (!ostree_parse_refspec (origin_refspec, &remote, NULL, &error)) goto out; if (!ostree_repo_remote_get_gpg_verify (repo, remote, &gpg_verify, &error)) goto out; if (!gpg_verify) goto out; result = ostree_repo_verify_commit_ext (repo, csum, NULL, NULL, NULL, &error); if (!result) goto out; n_sigs = ostree_gpg_verify_result_count_all (result); if (n_sigs < 1) goto out; for (i = 0; i < n_sigs; i++) { g_variant_builder_add (&builder, "v", ostree_gpg_verify_result_get_all (result, i)); } ret = g_variant_builder_end (&builder); out: /* NOT_FOUND just means the commit is not signed. */ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_warning ("error loading gpg verify result %s", error->message); g_clear_error (&error); return ret; }
void ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result) { guint n_sigs = ostree_gpg_verify_result_count_all (result); /* XXX If we ever add internationalization, use ngettext() here. */ g_print ("GPG: Verification enabled, found %u signature%s:\n", n_sigs, n_sigs == 1 ? "" : "s"); g_autoptr(GString) buffer = g_string_sized_new (256); for (guint ii = 0; ii < n_sigs; ii++) { g_string_append_c (buffer, '\n'); ostree_gpg_verify_result_describe (result, ii, buffer, " ", OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); } g_print ("%s", buffer->str); }
gboolean ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { const int is_tty = isatty (1); const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : ""; const char *red_bold_suffix = is_tty ? "\x1b[22m\x1b[0m" : ""; g_autoptr(GOptionContext) context = g_option_context_new (""); g_autoptr(OstreeSysroot) sysroot = NULL; if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, invocation, &sysroot, cancellable, error)) return FALSE; g_autoptr(OstreeRepo) repo = NULL; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) return FALSE; g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); g_autoptr(OstreeDeployment) pending_deployment = NULL; g_autoptr(OstreeDeployment) rollback_deployment = NULL; if (booted_deployment) ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, &rollback_deployment); if (deployments->len == 0) { g_print ("No deployments.\n"); } else { for (guint i = 0; i < deployments->len; i++) { OstreeDeployment *deployment = deployments->pdata[i]; const char *ref = ostree_deployment_get_csum (deployment); /* Load the backing commit; shouldn't normally fail, but if it does, * we stumble on. */ g_autoptr(GVariant) commit = NULL; (void)ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, ref, &commit, NULL); g_autoptr(GVariant) commit_metadata = NULL; if (commit) commit_metadata = g_variant_get_child_value (commit, 0); const char *version = NULL; const char *source_title = NULL; if (commit_metadata) { (void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_VERSION, "&s", &version); (void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_SOURCE_TITLE, "&s", &source_title); } GKeyFile *origin = ostree_deployment_get_origin (deployment); const char *deployment_status = ""; if (deployment == pending_deployment) deployment_status = " (pending)"; else if (deployment == rollback_deployment) deployment_status = " (rollback)"; g_print ("%c %s %s.%d%s\n", deployment == booted_deployment ? '*' : ' ', ostree_deployment_get_osname (deployment), ostree_deployment_get_csum (deployment), ostree_deployment_get_deployserial (deployment), deployment_status); if (version) g_print (" Version: %s\n", version); OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment); switch (unlocked) { case OSTREE_DEPLOYMENT_UNLOCKED_NONE: break; default: g_print (" %sUnlocked: %s%s\n", red_bold_prefix, ostree_deployment_unlocked_state_to_string (unlocked), red_bold_suffix); } if (!origin) g_print (" origin: none\n"); else { g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); if (!origin_refspec) g_print (" origin: <unknown origin type>\n"); else g_print (" origin refspec: %s\n", origin_refspec); if (source_title) g_print (" `- %s\n", source_title); } if (deployment_get_gpg_verify (deployment, repo)) { g_autoptr(GString) output_buffer = g_string_sized_new (256); /* Print any digital signatures on this commit. */ g_autoptr(GError) local_error = NULL; g_autoptr(OstreeGpgVerifyResult) result = ostree_repo_verify_commit_ext (repo, ref, NULL, NULL, cancellable, &local_error); /* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&local_error); continue; } else if (local_error != NULL) { g_propagate_error (error, g_steal_pointer (&local_error)); return FALSE; } const guint n_signatures = ostree_gpg_verify_result_count_all (result); for (guint jj = 0; jj < n_signatures; jj++) { ostree_gpg_verify_result_describe (result, jj, output_buffer, " GPG: ", OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); } g_print ("%s", output_buffer->str); } } } return TRUE; }
gboolean ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL; gboolean ret = FALSE; glnx_unref_object OstreeRepo *repo = NULL; OstreeDeployment *booted_deployment = NULL; g_autoptr(GPtrArray) deployments = NULL; const int is_tty = isatty (1); const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : ""; const char *red_bold_suffix = is_tty ? "\x1b[22m\x1b[0m" : ""; guint i; context = g_option_context_new ("List deployments"); if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, &sysroot, cancellable, error)) goto out; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) goto out; deployments = ostree_sysroot_get_deployments (sysroot); booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); if (deployments->len == 0) { g_print ("No deployments.\n"); } else { for (i = 0; i < deployments->len; i++) { OstreeDeployment *deployment = deployments->pdata[i]; GKeyFile *origin; const char *ref = ostree_deployment_get_csum (deployment); OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment); g_autofree char *version = version_of_commit (repo, ref); glnx_unref_object OstreeGpgVerifyResult *result = NULL; GString *output_buffer; guint jj, n_signatures; GError *local_error = NULL; origin = ostree_deployment_get_origin (deployment); g_print ("%c %s %s.%d\n", deployment == booted_deployment ? '*' : ' ', ostree_deployment_get_osname (deployment), ostree_deployment_get_csum (deployment), ostree_deployment_get_deployserial (deployment)); if (version) g_print (" Version: %s\n", version); switch (unlocked) { case OSTREE_DEPLOYMENT_UNLOCKED_NONE: break; default: g_print (" %sUnlocked: %s%s\n", red_bold_prefix, ostree_deployment_unlocked_state_to_string (unlocked), red_bold_suffix); } if (!origin) g_print (" origin: none\n"); else { g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); if (!origin_refspec) g_print (" origin: <unknown origin type>\n"); else g_print (" origin refspec: %s\n", origin_refspec); } if (deployment_get_gpg_verify (deployment, repo)) { /* Print any digital signatures on this commit. */ result = ostree_repo_verify_commit_ext (repo, ref, NULL, NULL, cancellable, &local_error); /* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&local_error); continue; } else if (local_error != NULL) { g_propagate_error (error, local_error); goto out; } output_buffer = g_string_sized_new (256); n_signatures = ostree_gpg_verify_result_count_all (result); for (jj = 0; jj < n_signatures; jj++) { ostree_gpg_verify_result_describe (result, jj, output_buffer, " GPG: ", OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); } g_print ("%s", output_buffer->str); g_string_free (output_buffer, TRUE); } } } ret = TRUE; out: return ret; }
static gboolean print_object (OstreeRepo *repo, OstreeObjectType objtype, const char *checksum, GError **error) { OstreeDumpFlags flags = OSTREE_DUMP_NONE; g_autoptr(GVariant) variant = NULL; if (!ostree_repo_load_variant (repo, objtype, checksum, &variant, error)) return FALSE; if (opt_raw) flags |= OSTREE_DUMP_RAW; ot_dump_object (objtype, checksum, variant, flags); if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { g_autoptr(OstreeGpgVerifyResult) result = NULL; g_autoptr(GError) local_error = NULL; g_autoptr(GFile) gpg_homedir = opt_gpg_homedir ? g_file_new_for_path (opt_gpg_homedir) : NULL; if (opt_gpg_verify_remote) { result = ostree_repo_verify_commit_for_remote (repo, checksum, opt_gpg_verify_remote, NULL, &local_error); } else { result = ostree_repo_verify_commit_ext (repo, checksum, gpg_homedir, NULL, NULL, &local_error); } if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { /* Ignore */ } else if (local_error != NULL) { g_propagate_error (error, g_steal_pointer (&local_error)); return FALSE; } else { guint n_sigs = ostree_gpg_verify_result_count_all (result); g_print ("Found %u signature%s:\n", n_sigs, n_sigs == 1 ? "" : "s"); g_autoptr(GString) buffer = g_string_sized_new (256); for (guint ii = 0; ii < n_sigs; ii++) { g_string_append_c (buffer, '\n'); ostree_gpg_verify_result_describe (result, ii, buffer, " ", OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT); } g_print ("%s", buffer->str); } } return TRUE; }