New upstream version 2016.14
This commit is contained in:
commit
90f43fba94
100 files changed
+1821
-1339
No files matched your search
@@ -359,14 +359,28 @@ global:
|
||||
/* No new symbols in 2016.12 */
|
||||
/* No new symbols in 2016.13 */
|
||||
|
||||
LIBOSTREE_2016.14 {
|
||||
global:
|
||||
ostree_repo_verify_commit_for_remote;
|
||||
} LIBOSTREE_2016.8;
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
* Versions above here are released. Only add symbols below this line.
|
||||
* NOTE NOTE NOTE
|
||||
*/
|
||||
|
||||
/* Remove comment when first new symbol is added, replace XX with new stable version.
|
||||
LIBOSTREE_2016.XX
|
||||
/* Remove comment when first new symbol is added
|
||||
LIBOSTREE_2016.XX {
|
||||
global:
|
||||
someostree_symbol_deleteme;
|
||||
} LIBOSTREE_2016.8;
|
||||
* Remove comment when first new symbol is added */
|
||||
} LIBOSTREE_2016.14;
|
||||
*/
|
||||
|
||||
/* Stub section for the stable release *after* this development one; don't
|
||||
* edit this other than to update the last number. This is just a copy/paste
|
||||
* source.
|
||||
LIBOSTREE_2016.XX {
|
||||
global:
|
||||
someostree_symbol_deleteme;
|
||||
} LIBOSTREE_2016.14;
|
||||
*/
|
||||
@@ -53,6 +53,7 @@ typedef struct {
|
||||
GLnxLockFile tmpdir_lock;
|
||||
int base_tmpdir_dfd;
|
||||
|
||||
GVariant *extra_headers;
|
||||
int max_outstanding;
|
||||
|
||||
/* Queue for libsoup, see bgo#708591 */
|
||||
@@ -127,11 +128,10 @@ G_DEFINE_TYPE (OstreeFetcher, _ostree_fetcher, G_TYPE_OBJECT)
|
||||
static ThreadClosure *
|
||||
thread_closure_ref (ThreadClosure *thread_closure)
|
||||
{
|
||||
int refcount;
|
||||
g_return_val_if_fail (thread_closure != NULL, NULL);
|
||||
g_return_val_if_fail (thread_closure->ref_count > 0, NULL);
|
||||
|
||||
g_atomic_int_inc (&thread_closure->ref_count);
|
||||
|
||||
refcount = g_atomic_int_add (&thread_closure->ref_count, 1);
|
||||
g_assert (refcount > 0);
|
||||
return thread_closure;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,6 @@ static void
|
||||
thread_closure_unref (ThreadClosure *thread_closure)
|
||||
{
|
||||
g_return_if_fail (thread_closure != NULL);
|
||||
g_return_if_fail (thread_closure->ref_count > 0);
|
||||
|
||||
if (g_atomic_int_dec_and_test (&thread_closure->ref_count))
|
||||
{
|
||||
@@ -148,6 +147,8 @@ thread_closure_unref (ThreadClosure *thread_closure)
|
||||
|
||||
g_clear_pointer (&thread_closure->main_context, g_main_context_unref);
|
||||
|
||||
g_clear_pointer (&thread_closure->extra_headers, (GDestroyNotify)g_variant_unref);
|
||||
|
||||
if (thread_closure->tmpdir_dfd != -1)
|
||||
close (thread_closure->tmpdir_dfd);
|
||||
|
||||
@@ -194,11 +195,10 @@ pending_task_compare (gconstpointer a,
|
||||
static OstreeFetcherPendingURI *
|
||||
pending_uri_ref (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
gint refcount;
|
||||
g_return_val_if_fail (pending != NULL, NULL);
|
||||
g_return_val_if_fail (pending->ref_count > 0, NULL);
|
||||
|
||||
g_atomic_int_inc (&pending->ref_count);
|
||||
|
||||
refcount = g_atomic_int_add (&pending->ref_count, 1);
|
||||
g_assert (refcount > 0);
|
||||
return pending;
|
||||
}
|
||||
|
||||
@@ -336,6 +336,16 @@ session_thread_set_cookie_jar_cb (ThreadClosure *thread_closure,
|
||||
SOUP_SESSION_FEATURE (jar));
|
||||
}
|
||||
|
||||
static void
|
||||
session_thread_set_headers_cb (ThreadClosure *thread_closure,
|
||||
gpointer data)
|
||||
{
|
||||
GVariant *headers = data;
|
||||
|
||||
g_clear_pointer (&thread_closure->extra_headers, (GDestroyNotify)g_variant_unref);
|
||||
thread_closure->extra_headers = g_variant_ref (headers);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
|
||||
static void
|
||||
session_thread_set_tls_interaction_cb (ThreadClosure *thread_closure,
|
||||
@@ -448,6 +458,17 @@ session_thread_request_uri (ThreadClosure *thread_closure,
|
||||
return;
|
||||
}
|
||||
|
||||
if (SOUP_IS_REQUEST_HTTP (pending->request) && thread_closure->extra_headers)
|
||||
{
|
||||
glnx_unref_object SoupMessage *msg = soup_request_http_get_message ((SoupRequestHTTP*) pending->request);
|
||||
g_autoptr(GVariantIter) viter = g_variant_iter_new (thread_closure->extra_headers);
|
||||
const char *key;
|
||||
const char *value;
|
||||
|
||||
while (g_variant_iter_next (viter, "(&s&s)", &key, &value))
|
||||
soup_message_headers_append (msg->request_headers, key, value);
|
||||
}
|
||||
|
||||
if (pending->is_stream)
|
||||
{
|
||||
soup_request_send_async (pending->request,
|
||||
@@ -812,6 +833,16 @@ _ostree_fetcher_set_tls_database (OstreeFetcher *self,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_ostree_fetcher_set_extra_headers (OstreeFetcher *self,
|
||||
GVariant *extra_headers)
|
||||
{
|
||||
session_thread_idle_add (self->thread_closure,
|
||||
session_thread_set_headers_cb,
|
||||
g_variant_ref (extra_headers),
|
||||
(GDestroyNotify) g_variant_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
finish_stream (OstreeFetcherPendingURI *pending,
|
||||
GCancellable *cancellable,
|
||||
|
||||
@@ -71,6 +71,9 @@ void _ostree_fetcher_set_client_cert (OstreeFetcher *fetcher,
|
||||
void _ostree_fetcher_set_tls_database (OstreeFetcher *self,
|
||||
GTlsDatabase *db);
|
||||
|
||||
void _ostree_fetcher_set_extra_headers (OstreeFetcher *self,
|
||||
GVariant *extra_headers);
|
||||
|
||||
guint64 _ostree_fetcher_bytes_transferred (OstreeFetcher *self);
|
||||
|
||||
void _ostree_fetcher_mirrored_request_with_partial_async (OstreeFetcher *self,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree-gpg-verifier.h"
|
||||
#include "ot-gpg-utils.h"
|
||||
#include "ostree-gpg-verify-result-private.h"
|
||||
#include "otutil.h"
|
||||
|
||||
@@ -39,6 +40,7 @@ struct OstreeGpgVerifier {
|
||||
GObject parent;
|
||||
|
||||
GList *keyrings;
|
||||
GPtrArray *key_ascii_files;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OstreeGpgVerifier, _ostree_gpg_verifier, G_TYPE_OBJECT)
|
||||
@@ -49,6 +51,8 @@ ostree_gpg_verifier_finalize (GObject *object)
|
||||
OstreeGpgVerifier *self = OSTREE_GPG_VERIFIER (object);
|
||||
|
||||
g_list_free_full (self->keyrings, g_object_unref);
|
||||
if (self->key_ascii_files)
|
||||
g_ptr_array_unref (self->key_ascii_files);
|
||||
|
||||
G_OBJECT_CLASS (_ostree_gpg_verifier_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -89,15 +93,15 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gpgme_ctx_t gpg_ctx = NULL;
|
||||
gpgme_error_t gpg_error = 0;
|
||||
gpgme_data_t data_buffer = NULL;
|
||||
gpgme_data_t signature_buffer = NULL;
|
||||
ot_auto_gpgme_data gpgme_data_t data_buffer = NULL;
|
||||
ot_auto_gpgme_data gpgme_data_t signature_buffer = NULL;
|
||||
g_autofree char *tmp_dir = NULL;
|
||||
g_autoptr(GOutputStream) target_stream = NULL;
|
||||
OstreeGpgVerifyResult *result = NULL;
|
||||
gboolean success = FALSE;
|
||||
GList *link;
|
||||
int armor;
|
||||
|
||||
/* GPGME has no API for using multiple keyrings (aka, gpg --keyring),
|
||||
* so we concatenate all the keyring files into one pubring.gpg in a
|
||||
@@ -149,6 +153,44 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
|
||||
if (!g_output_stream_close (target_stream, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* Save the previous armor value - we need it on for importing ASCII keys */
|
||||
armor = gpgme_get_armor (result->context);
|
||||
gpgme_set_armor (result->context, 1);
|
||||
|
||||
/* Now, use the API to import ASCII-armored keys */
|
||||
if (self->key_ascii_files)
|
||||
{
|
||||
for (guint i = 0; i < self->key_ascii_files->len; i++)
|
||||
{
|
||||
const char *path = self->key_ascii_files->pdata[i];
|
||||
glnx_fd_close int fd = -1;
|
||||
ot_auto_gpgme_data gpgme_data_t kdata = NULL;
|
||||
|
||||
fd = openat (AT_FDCWD, path, O_RDONLY | O_CLOEXEC) ;
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "Opening %s", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpg_error = gpgme_data_new_from_fd (&kdata, fd);
|
||||
if (gpg_error != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (gpg_error, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpg_error = gpgme_op_import (result->context, kdata);
|
||||
if (gpg_error != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (gpg_error, error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpgme_set_armor (result->context, armor);
|
||||
|
||||
/* Both the signed data and signature GBytes instances will outlive the
|
||||
* gpgme_data_t structs, so we can safely reuse the GBytes memory buffer
|
||||
* directly and avoid a copy. */
|
||||
@@ -191,14 +233,6 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
|
||||
if (gpg_ctx != NULL)
|
||||
gpgme_release (gpg_ctx);
|
||||
if (data_buffer != NULL)
|
||||
gpgme_data_release (data_buffer);
|
||||
if (signature_buffer != NULL)
|
||||
gpgme_data_release (signature_buffer);
|
||||
|
||||
if (success)
|
||||
{
|
||||
/* Keep the temporary directory around for the life of the result
|
||||
@@ -233,6 +267,15 @@ _ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
|
||||
self->keyrings = g_list_append (self->keyrings, g_object_ref (path));
|
||||
}
|
||||
|
||||
void
|
||||
_ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
||||
const char *path)
|
||||
{
|
||||
if (!self->key_ascii_files)
|
||||
self->key_ascii_files = g_ptr_array_new_with_free_func (g_free);
|
||||
g_ptr_array_add (self->key_ascii_files, g_strdup (path));
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
|
||||
GFile *path,
|
||||
|
||||
@@ -62,4 +62,7 @@ gboolean _ostree_gpg_verifier_add_global_keyring_dir (OstreeGpgVerifier *s
|
||||
void _ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
|
||||
GFile *path);
|
||||
|
||||
void _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
||||
const char *path);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -632,6 +632,9 @@ _ostree_metalink_request_sync (OstreeMetalink *self,
|
||||
if (mainctx)
|
||||
g_main_context_pop_thread_default (mainctx);
|
||||
g_clear_object (&request.metalink);
|
||||
g_clear_pointer (&request.verification_sha256, g_free);
|
||||
g_clear_pointer (&request.verification_sha512, g_free);
|
||||
g_clear_pointer (&request.last_metalink_error, g_free);
|
||||
g_clear_pointer (&request.urls, g_ptr_array_unref);
|
||||
g_clear_pointer (&request.parser, g_markup_parse_context_free);
|
||||
return ret;
|
||||
|
||||
@@ -2281,7 +2281,15 @@ get_modified_xattrs (OstreeRepo *self,
|
||||
}
|
||||
else if (!(modifier && (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) > 0))
|
||||
{
|
||||
if (path)
|
||||
if (path && OSTREE_IS_REPO_FILE (path))
|
||||
{
|
||||
if (!ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (path),
|
||||
&ret_xattrs,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
else if (path)
|
||||
{
|
||||
if (!glnx_dfd_name_get_all_xattrs (AT_FDCWD, gs_file_get_path_cached (path),
|
||||
&ret_xattrs, cancellable, error))
|
||||
@@ -2542,16 +2550,6 @@ write_directory_to_mtree_internal (OstreeRepo *self,
|
||||
|
||||
ostree_mutable_tree_set_metadata_checksum (mtree, ostree_repo_file_tree_get_metadata_checksum (repo_dir));
|
||||
|
||||
/* If the mtree was empty beforehand, the checksums on the mtree can simply
|
||||
* become the checksums on the tree in the repo. Super simple. */
|
||||
if (g_hash_table_size (ostree_mutable_tree_get_files (mtree)) == 0 &&
|
||||
g_hash_table_size (ostree_mutable_tree_get_subdirs (mtree)) == 0)
|
||||
{
|
||||
ostree_mutable_tree_set_contents_checksum (mtree, ostree_repo_file_tree_get_contents_checksum (repo_dir));
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
filter_result = OSTREE_REPO_COMMIT_FILTER_ALLOW;
|
||||
}
|
||||
else
|
||||
@@ -2961,7 +2959,8 @@ ostree_repo_commit_modifier_new (OstreeRepoCommitModifierFlags flags,
|
||||
OstreeRepoCommitModifier *
|
||||
ostree_repo_commit_modifier_ref (OstreeRepoCommitModifier *modifier)
|
||||
{
|
||||
g_atomic_int_inc (&modifier->refcount);
|
||||
gint refcount = g_atomic_int_add (&modifier->refcount, 1);
|
||||
g_assert (refcount > 0);
|
||||
return modifier;
|
||||
}
|
||||
|
||||
|
||||
@@ -943,7 +943,10 @@ ostree_repo_write_archive_to_mtree (OstreeRepo *self,
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (a)
|
||||
(void)archive_read_close (a);
|
||||
{
|
||||
(void)archive_read_close (a);
|
||||
(void)archive_read_free (a);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
|
||||
@@ -54,6 +54,8 @@ typedef struct {
|
||||
GCancellable *cancellable;
|
||||
OstreeAsyncProgress *progress;
|
||||
|
||||
GVariant *extra_headers;
|
||||
|
||||
gboolean dry_run;
|
||||
gboolean dry_run_emitted_progress;
|
||||
gboolean legacy_transaction_resuming;
|
||||
@@ -100,7 +102,6 @@ typedef struct {
|
||||
gboolean is_untrusted;
|
||||
|
||||
GPtrArray *dirs;
|
||||
gboolean commitpartial_exists;
|
||||
|
||||
gboolean have_previous_bytes;
|
||||
guint64 previous_bytes_sec;
|
||||
@@ -1026,6 +1027,57 @@ static_deltapart_fetch_on_complete (GObject *object,
|
||||
fetch_static_delta_data_free (fetch_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_verify_result (OtPullData *pull_data,
|
||||
const char *checksum,
|
||||
OstreeGpgVerifyResult *result,
|
||||
GError **error)
|
||||
{
|
||||
if (result == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Allow callers to output the results immediately. */
|
||||
g_signal_emit_by_name (pull_data->repo,
|
||||
"gpg-verify-result",
|
||||
checksum, result);
|
||||
|
||||
return ostree_gpg_verify_result_require_valid_signature (result, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gpg_verify_unwritten_commit (OtPullData *pull_data,
|
||||
const char *checksum,
|
||||
GVariant *commit,
|
||||
GVariant *detached_metadata,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
if (pull_data->gpg_verify)
|
||||
{
|
||||
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit);
|
||||
|
||||
if (!detached_metadata)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No detached metadata found for GPG verification");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = _ostree_repo_gpg_verify_with_metadata (pull_data->repo,
|
||||
signed_data,
|
||||
detached_metadata,
|
||||
pull_data->remote_name,
|
||||
NULL, NULL,
|
||||
cancellable,
|
||||
error);
|
||||
if (!process_verify_result (pull_data, checksum, result, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scan_commit_object (OtPullData *pull_data,
|
||||
const char *checksum,
|
||||
@@ -1034,11 +1086,17 @@ scan_commit_object (OtPullData *pull_data,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
/* If we found a legacy transaction flag, assume we have to scan.
|
||||
* We always do a scan of dirtree objects; see
|
||||
* https://github.com/ostreedev/ostree/issues/543
|
||||
*/
|
||||
OstreeRepoCommitState commitstate;
|
||||
g_autoptr(GVariant) commit = NULL;
|
||||
g_autoptr(GVariant) parent_csum = NULL;
|
||||
const guchar *parent_csum_bytes = NULL;
|
||||
gpointer depthp;
|
||||
gint depth;
|
||||
gboolean is_partial;
|
||||
|
||||
if (recursion_depth > OSTREE_MAX_RECURSION)
|
||||
{
|
||||
@@ -1063,30 +1121,22 @@ scan_commit_object (OtPullData *pull_data,
|
||||
{
|
||||
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||
|
||||
result = _ostree_repo_verify_commit_internal (pull_data->repo,
|
||||
checksum,
|
||||
pull_data->remote_name,
|
||||
NULL,
|
||||
NULL,
|
||||
cancellable,
|
||||
error);
|
||||
|
||||
if (result == NULL)
|
||||
result = ostree_repo_verify_commit_for_remote (pull_data->repo,
|
||||
checksum,
|
||||
pull_data->remote_name,
|
||||
cancellable,
|
||||
error);
|
||||
if (!process_verify_result (pull_data, checksum, result, error))
|
||||
goto out;
|
||||
|
||||
/* Allow callers to output the results immediately. */
|
||||
g_signal_emit_by_name (pull_data->repo,
|
||||
"gpg-verify-result",
|
||||
checksum, result);
|
||||
|
||||
if (ostree_gpg_verify_result_count_valid (result) == 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"GPG signatures found, but none are in trusted keyring");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ostree_repo_load_commit (pull_data->repo, checksum, &commit, &commitstate, error))
|
||||
goto out;
|
||||
|
||||
/* If we found a legacy transaction flag, assume all commits are partial */
|
||||
is_partial = pull_data->legacy_transaction_resuming
|
||||
|| (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) > 0;
|
||||
|
||||
if (!ostree_repo_load_variant (pull_data->repo, OSTREE_OBJECT_TYPE_COMMIT, checksum,
|
||||
&commit, error))
|
||||
goto out;
|
||||
@@ -1135,7 +1185,11 @@ scan_commit_object (OtPullData *pull_data,
|
||||
}
|
||||
}
|
||||
|
||||
if (!pull_data->is_commit_only)
|
||||
/* We only recurse to looking whether we need dirtree/dirmeta
|
||||
* objects if the commit is partial, and we're not doing a
|
||||
* commit-only fetch.
|
||||
*/
|
||||
if (is_partial && !pull_data->is_commit_only)
|
||||
{
|
||||
g_autoptr(GVariant) tree_contents_csum = NULL;
|
||||
g_autoptr(GVariant) tree_meta_csum = NULL;
|
||||
@@ -1249,8 +1303,11 @@ scan_one_metadata_object_c (OtPullData *pull_data,
|
||||
do_fetch_detached = (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
||||
enqueue_one_object_request (pull_data, tmp_checksum, objtype, path, do_fetch_detached, FALSE);
|
||||
}
|
||||
else if (objtype == OSTREE_OBJECT_TYPE_COMMIT && pull_data->is_commit_only)
|
||||
else if (is_stored && objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||
{
|
||||
/* For commits, always refetch detached metadata. */
|
||||
enqueue_one_object_request (pull_data, tmp_checksum, objtype, path, TRUE, TRUE);
|
||||
|
||||
if (!scan_commit_object (pull_data, tmp_checksum, recursion_depth,
|
||||
pull_data->cancellable, error))
|
||||
goto out;
|
||||
@@ -1258,59 +1315,12 @@ scan_one_metadata_object_c (OtPullData *pull_data,
|
||||
g_hash_table_insert (pull_data->scanned_metadata, g_variant_ref (object), object);
|
||||
pull_data->n_scanned_metadata++;
|
||||
}
|
||||
else if (is_stored)
|
||||
else if (is_stored && objtype == OSTREE_OBJECT_TYPE_DIR_TREE)
|
||||
{
|
||||
gboolean do_scan = pull_data->legacy_transaction_resuming || is_requested || pull_data->commitpartial_exists;
|
||||
if (!scan_dirtree_object (pull_data, tmp_checksum, path, recursion_depth,
|
||||
pull_data->cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* For commits, always refetch detached metadata. */
|
||||
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||
enqueue_one_object_request (pull_data, tmp_checksum, objtype, path, TRUE, TRUE);
|
||||
|
||||
/* For commits, check whether we only had a partial fetch */
|
||||
if (!do_scan && objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||
{
|
||||
OstreeRepoCommitState commitstate;
|
||||
|
||||
if (!ostree_repo_load_commit (pull_data->repo, tmp_checksum, NULL, &commitstate, error))
|
||||
goto out;
|
||||
|
||||
if (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL)
|
||||
{
|
||||
do_scan = TRUE;
|
||||
pull_data->commitpartial_exists = TRUE;
|
||||
}
|
||||
else if (pull_data->maxdepth != 0)
|
||||
{
|
||||
/* Not fully accurate, but the cost here of scanning all
|
||||
* input commit objects if we're doing a depth fetch is
|
||||
* pretty low. We'll do more accurate handling of depth
|
||||
* when parsing the actual commit.
|
||||
*/
|
||||
do_scan = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_scan)
|
||||
{
|
||||
switch (objtype)
|
||||
{
|
||||
case OSTREE_OBJECT_TYPE_COMMIT:
|
||||
if (!scan_commit_object (pull_data, tmp_checksum, recursion_depth,
|
||||
pull_data->cancellable, error))
|
||||
goto out;
|
||||
break;
|
||||
case OSTREE_OBJECT_TYPE_DIR_META:
|
||||
break;
|
||||
case OSTREE_OBJECT_TYPE_DIR_TREE:
|
||||
if (!scan_dirtree_object (pull_data, tmp_checksum, path, recursion_depth,
|
||||
pull_data->cancellable, error))
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_hash_table_insert (pull_data->scanned_metadata, g_variant_ref (object), object);
|
||||
pull_data->n_scanned_metadata++;
|
||||
}
|
||||
@@ -1595,7 +1605,6 @@ process_one_static_delta (OtPullData *pull_data,
|
||||
{
|
||||
g_autoptr(GVariant) to_csum_v = NULL;
|
||||
g_autofree char *to_checksum = NULL;
|
||||
g_autoptr(GVariant) to_commit = NULL;
|
||||
gboolean have_to_commit;
|
||||
|
||||
to_csum_v = g_variant_get_child_value (delta_superblock, 3);
|
||||
@@ -1610,10 +1619,16 @@ process_one_static_delta (OtPullData *pull_data,
|
||||
if (!have_to_commit)
|
||||
{
|
||||
FetchObjectData *fetch_data;
|
||||
g_autoptr(GVariant) to_commit = g_variant_get_child_value (delta_superblock, 4);
|
||||
g_autofree char *detached_path = _ostree_get_relative_static_delta_path (from_revision, to_revision, "commitmeta");
|
||||
g_autoptr(GVariant) detached_data = NULL;
|
||||
|
||||
detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}"));
|
||||
|
||||
if (!gpg_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (detached_data && !ostree_repo_write_commit_detached_metadata (pull_data->repo,
|
||||
to_revision,
|
||||
detached_data,
|
||||
@@ -1627,8 +1642,6 @@ process_one_static_delta (OtPullData *pull_data,
|
||||
fetch_data->is_detached_meta = FALSE;
|
||||
fetch_data->object_is_stored = FALSE;
|
||||
|
||||
to_commit = g_variant_get_child_value (delta_superblock, 4);
|
||||
|
||||
ostree_repo_write_metadata_async (pull_data->repo, OSTREE_OBJECT_TYPE_COMMIT, to_checksum,
|
||||
to_commit,
|
||||
pull_data->cancellable,
|
||||
@@ -1969,7 +1982,7 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
|
||||
g_autofree char *cookie_file = g_strdup_printf ("%s.cookies.txt",
|
||||
remote_name);
|
||||
|
||||
jar_path = g_build_filename (g_file_get_path (self->repodir), cookie_file,
|
||||
jar_path = g_build_filename (gs_file_get_path_cached (self->repodir), cookie_file,
|
||||
NULL);
|
||||
|
||||
if (g_file_test(jar_path, G_FILE_TEST_IS_REGULAR))
|
||||
@@ -2048,7 +2061,7 @@ fetch_mirrorlist (OstreeFetcher *fetcher,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char **lines = NULL;
|
||||
g_auto(GStrv) lines = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
SoupURI *mirrorlist = NULL;
|
||||
g_autoptr(GPtrArray) ret_mirrorlist =
|
||||
@@ -2276,6 +2289,23 @@ repo_remote_fetch_summary (OstreeRepo *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create the fetcher by unioning options from the remote config, plus
|
||||
* any options specific to this pull (such as extra headers).
|
||||
*/
|
||||
static gboolean
|
||||
reinitialize_fetcher (OtPullData *pull_data, const char *remote_name, GError **error)
|
||||
{
|
||||
g_clear_object (&pull_data->fetcher);
|
||||
pull_data->fetcher = _ostree_repo_remote_new_fetcher (pull_data->repo, remote_name, error);
|
||||
if (pull_data->fetcher == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (pull_data->extra_headers)
|
||||
_ostree_fetcher_set_extra_headers (pull_data->fetcher, pull_data->extra_headers);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* Below is the libsoup-invariant API; these should match
|
||||
* the stub functions in the #else clause
|
||||
@@ -2308,6 +2338,7 @@ repo_remote_fetch_summary (OstreeRepo *self,
|
||||
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
|
||||
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
|
||||
* * inherit-transaction (b): Don't initiate, finish or abort a transaction, usefult to do mutliple pulls in one transaction.
|
||||
* * http-headers (a(ss)): Additional headers to add to all HTTP requests
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
@@ -2336,7 +2367,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
const char *dir_to_pull = NULL;
|
||||
g_autofree char **dirs_to_pull = NULL;
|
||||
g_autofree char **refs_to_fetch = NULL;
|
||||
char **override_commit_ids = NULL;
|
||||
g_autofree char **override_commit_ids = NULL;
|
||||
GSource *update_timeout = NULL;
|
||||
gboolean disable_static_deltas = FALSE;
|
||||
gboolean require_static_deltas = FALSE;
|
||||
@@ -2368,6 +2399,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
|
||||
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
|
||||
(void) g_variant_lookup (options, "inherit-transaction", "b", &inherit_transaction);
|
||||
(void) g_variant_lookup (options, "http-headers", "@a(ss)", &pull_data->extra_headers);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE);
|
||||
@@ -2467,8 +2499,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
|
||||
pull_data->phase = OSTREE_PULL_PHASE_FETCHING_REFS;
|
||||
|
||||
pull_data->fetcher = _ostree_repo_remote_new_fetcher (self, remote_name_or_baseurl, error);
|
||||
if (pull_data->fetcher == NULL)
|
||||
if (!reinitialize_fetcher (pull_data, remote_name_or_baseurl, error))
|
||||
goto out;
|
||||
|
||||
pull_data->tmpdir_dfd = pull_data->repo->tmp_dir_fd;
|
||||
@@ -2745,15 +2776,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
NULL,
|
||||
cancellable,
|
||||
error);
|
||||
if (result == NULL)
|
||||
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
|
||||
goto out;
|
||||
|
||||
if (ostree_gpg_verify_result_count_valid (result) == 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"GPG signatures found, but none are in trusted keyring");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (pull_data->summary)
|
||||
@@ -2906,9 +2930,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
/* Now discard the previous fetcher, as it was bound to a temporary main context
|
||||
* for synchronous requests.
|
||||
*/
|
||||
g_clear_object (&pull_data->fetcher);
|
||||
pull_data->fetcher = _ostree_repo_remote_new_fetcher (self, remote_name_or_baseurl, error);
|
||||
if (pull_data->fetcher == NULL)
|
||||
if (!reinitialize_fetcher (pull_data, remote_name_or_baseurl, error))
|
||||
goto out;
|
||||
|
||||
pull_data->legacy_transaction_resuming = FALSE;
|
||||
@@ -3120,6 +3142,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
g_source_destroy (update_timeout);
|
||||
g_strfreev (configured_branches);
|
||||
g_clear_object (&pull_data->fetcher);
|
||||
g_clear_pointer (&pull_data->extra_headers, (GDestroyNotify)g_variant_unref);
|
||||
g_clear_object (&pull_data->cancellable);
|
||||
g_clear_object (&pull_data->remote_repo_local);
|
||||
g_free (pull_data->remote_name);
|
||||
|
||||
@@ -243,7 +243,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo *repo,
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GHashTable) ret_modified_regfile_content =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_ptr_array_unref);
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
g_autoptr(GPtrArray) from_sizes = NULL;
|
||||
g_autoptr(GPtrArray) to_sizes = NULL;
|
||||
guint i, j;
|
||||
|
||||
@@ -157,6 +157,9 @@ xattr_chunk_equals (const void *one, const void *two)
|
||||
if (l1 != l2)
|
||||
return FALSE;
|
||||
|
||||
if (l1 == 0)
|
||||
return l2 == 0;
|
||||
|
||||
return memcmp (g_variant_get_data (v1), g_variant_get_data (v2), l1) == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -880,7 +880,9 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
|
||||
OT_VARIANT_MAP_TRUSTED, &delta_superblock, error))
|
||||
goto out;
|
||||
|
||||
g_print ("%s\n", g_variant_print (delta_superblock, 1));
|
||||
{ g_autofree char *variant_string = g_variant_print (delta_superblock, 1);
|
||||
g_print ("%s\n", variant_string);
|
||||
}
|
||||
|
||||
g_print ("Delta: %s\n", delta_id);
|
||||
{ const char *endianness_description;
|
||||
|
||||
@@ -842,7 +842,7 @@ dispatch_set_read_source (OstreeRepo *repo,
|
||||
gboolean ret = FALSE;
|
||||
guint64 source_offset;
|
||||
|
||||
if (state->read_source_fd)
|
||||
if (state->read_source_fd != -1)
|
||||
{
|
||||
(void) close (state->read_source_fd);
|
||||
state->read_source_fd = -1;
|
||||
@@ -887,7 +887,7 @@ dispatch_unset_read_source (OstreeRepo *repo,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (state->read_source_fd)
|
||||
if (state->read_source_fd != -1)
|
||||
{
|
||||
(void) close (state->read_source_fd);
|
||||
state->read_source_fd = -1;
|
||||
|
||||
+55
-61
@@ -161,11 +161,10 @@ ost_remote_new_from_keyfile (GKeyFile *keyfile,
|
||||
static OstreeRemote *
|
||||
ost_remote_ref (OstreeRemote *remote)
|
||||
{
|
||||
gint refcount;
|
||||
g_return_val_if_fail (remote != NULL, NULL);
|
||||
g_return_val_if_fail (remote->ref_count > 0, NULL);
|
||||
|
||||
g_atomic_int_inc (&remote->ref_count);
|
||||
|
||||
refcount = g_atomic_int_add (&remote->ref_count, 1);
|
||||
g_assert (refcount > 0);
|
||||
return remote;
|
||||
}
|
||||
|
||||
@@ -1440,9 +1439,9 @@ ostree_repo_remote_gpg_import (OstreeRepo *self,
|
||||
GError **error)
|
||||
{
|
||||
OstreeRemote *remote;
|
||||
gpgme_ctx_t source_context = NULL;
|
||||
gpgme_ctx_t target_context = NULL;
|
||||
gpgme_data_t data_buffer = NULL;
|
||||
ot_auto_gpgme_ctx gpgme_ctx_t source_context = NULL;
|
||||
ot_auto_gpgme_ctx gpgme_ctx_t target_context = NULL;
|
||||
ot_auto_gpgme_data gpgme_data_t data_buffer = NULL;
|
||||
gpgme_import_result_t import_result;
|
||||
gpgme_import_status_t import_status;
|
||||
const char *tmp_dir = NULL;
|
||||
@@ -1479,13 +1478,9 @@ ostree_repo_remote_gpg_import (OstreeRepo *self,
|
||||
* the keys to a new pubring.gpg file. If the key data format is ASCII
|
||||
* armored, this step will convert them to binary. */
|
||||
|
||||
gpg_error = gpgme_new (&source_context);
|
||||
if (gpg_error != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (gpg_error, error);
|
||||
g_prefix_error (error, "Unable to create context: ");
|
||||
goto out;
|
||||
}
|
||||
source_context = ot_gpgme_new_ctx (NULL, error);
|
||||
if (!source_context)
|
||||
goto out;
|
||||
|
||||
if (source_stream != NULL)
|
||||
{
|
||||
@@ -1569,13 +1564,9 @@ ostree_repo_remote_gpg_import (OstreeRepo *self,
|
||||
* of the remote's keyring file. We'll let the import operation alter
|
||||
* the pubring.gpg file, then rename it back to its permanent home. */
|
||||
|
||||
gpg_error = gpgme_new (&target_context);
|
||||
if (gpg_error != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (gpg_error, error);
|
||||
g_prefix_error (error, "Unable to create context: ");
|
||||
goto out;
|
||||
}
|
||||
target_context = ot_gpgme_new_ctx (NULL, error);
|
||||
if (!target_context)
|
||||
goto out;
|
||||
|
||||
/* No need for an output stream since we copy in a pubring.gpg. */
|
||||
if (!ot_gpgme_ctx_tmp_home_dir (target_context, tmp_dir, &target_tmp_dir,
|
||||
@@ -1700,15 +1691,6 @@ out:
|
||||
if (target_tmp_dir != NULL)
|
||||
(void) glnx_shutil_rm_rf_at (AT_FDCWD, target_tmp_dir, NULL, NULL);
|
||||
|
||||
if (source_context != NULL)
|
||||
gpgme_release (source_context);
|
||||
|
||||
if (target_context != NULL)
|
||||
gpgme_release (target_context);
|
||||
|
||||
if (data_buffer != NULL)
|
||||
gpgme_data_release (data_buffer);
|
||||
|
||||
g_prefix_error (error, "GPG: ");
|
||||
|
||||
return ret;
|
||||
@@ -3989,7 +3971,6 @@ sign_data (OstreeRepo *self,
|
||||
g_autoptr(GOutputStream) tmp_signature_output = NULL;
|
||||
gpgme_ctx_t context = NULL;
|
||||
g_autoptr(GBytes) ret_signature = NULL;
|
||||
gpgme_engine_info_t info;
|
||||
gpgme_error_t err;
|
||||
gpgme_key_t key = NULL;
|
||||
gpgme_data_t commit_buffer = NULL;
|
||||
@@ -4001,34 +3982,9 @@ sign_data (OstreeRepo *self,
|
||||
goto out;
|
||||
tmp_signature_output = g_unix_output_stream_new (tmp_fd, FALSE);
|
||||
|
||||
if ((err = gpgme_new (&context)) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (err, error);
|
||||
g_prefix_error (error, "Unable to create gpg context: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = gpgme_ctx_get_engine_info (context);
|
||||
|
||||
if ((err = gpgme_set_protocol (context, GPGME_PROTOCOL_OpenPGP)) !=
|
||||
GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (err, error);
|
||||
g_prefix_error (error, "Unable to set gpg protocol: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (homedir != NULL)
|
||||
{
|
||||
if ((err = gpgme_ctx_set_engine_info (context, info->protocol, NULL, homedir))
|
||||
!= GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (err, error);
|
||||
g_prefix_error (error, "Unable to set gpg homedir to '%s': ",
|
||||
homedir);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
context = ot_gpgme_new_ctx (homedir, error);
|
||||
if (!context)
|
||||
goto out;
|
||||
|
||||
/* Get the secret keys with the given key id */
|
||||
err = gpgme_get_key (context, key_id, &key, 1);
|
||||
@@ -4045,7 +4001,7 @@ sign_data (OstreeRepo *self,
|
||||
g_prefix_error (error, "Unable to lookup key ID %s: ", key_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/* Add the key to the context as a signer */
|
||||
if ((err = gpgme_signers_add (context, key)) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
@@ -4325,6 +4281,7 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
|
||||
}
|
||||
else if (remote_name != NULL)
|
||||
{
|
||||
g_autofree char *gpgkeypath = NULL;
|
||||
/* Add the remote's keyring file if it exists. */
|
||||
|
||||
OstreeRemote *remote;
|
||||
@@ -4342,6 +4299,13 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
|
||||
add_global_keyring_dir = FALSE;
|
||||
}
|
||||
|
||||
if (!ot_keyfile_get_value_with_default (remote->options, remote->group, "gpgkeypath", NULL,
|
||||
&gpgkeypath, error))
|
||||
return NULL;
|
||||
|
||||
if (gpgkeypath)
|
||||
_ostree_gpg_verifier_add_key_ascii_file (verifier, gpgkeypath);
|
||||
|
||||
ost_remote_unref (remote);
|
||||
}
|
||||
|
||||
@@ -4544,6 +4508,36 @@ ostree_repo_verify_commit_ext (OstreeRepo *self,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_verify_commit_for_remote:
|
||||
* @self: Repository
|
||||
* @commit_checksum: ASCII SHA256 checksum
|
||||
* @remote_name: OSTree remote to use for configuration
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Read GPG signature(s) on the commit named by the ASCII checksum
|
||||
* @commit_checksum and return detailed results, based on the keyring
|
||||
* configured for @remote.
|
||||
*
|
||||
* Returns: (transfer full): an #OstreeGpgVerifyResult, or %NULL on error
|
||||
*/
|
||||
OstreeGpgVerifyResult *
|
||||
ostree_repo_verify_commit_for_remote (OstreeRepo *self,
|
||||
const gchar *commit_checksum,
|
||||
const gchar *remote_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return _ostree_repo_verify_commit_internal (self,
|
||||
commit_checksum,
|
||||
remote_name,
|
||||
NULL,
|
||||
NULL,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_gpg_verify_data:
|
||||
* @self: Repository
|
||||
@@ -4875,7 +4869,7 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
|
||||
|
||||
/* We put the lock outside the dir, so we can hold the lock
|
||||
* until the directory is fully removed */
|
||||
if (!_ostree_repo_try_lock_tmpdir (dfd_iter.fd, dent->d_name,
|
||||
if (!_ostree_repo_try_lock_tmpdir (tmpdir_dfd, dent->d_name,
|
||||
file_lock_out, &did_lock,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
@@ -1064,6 +1064,14 @@ OstreeGpgVerifyResult * ostree_repo_verify_commit_ext (OstreeRepo *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeGpgVerifyResult *
|
||||
ostree_repo_verify_commit_for_remote (OstreeRepo *self,
|
||||
const gchar *commit_checksum,
|
||||
const gchar *remote_name,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeGpgVerifyResult * ostree_repo_gpg_verify_data (OstreeRepo *self,
|
||||
const gchar *remote_name,
|
||||
|
||||
@@ -258,7 +258,7 @@ initable_init (GInitable *initable,
|
||||
g_autoptr(GFileInputStream) filein = NULL;
|
||||
g_autoptr(GDataInputStream) datain = NULL;
|
||||
gboolean enabled = FALSE;
|
||||
char *policytype = NULL;
|
||||
g_autofree char *policytype = NULL;
|
||||
const char *selinux_prefix = "SELINUX=";
|
||||
const char *selinuxtype_prefix = "SELINUXTYPE=";
|
||||
|
||||
@@ -352,7 +352,7 @@ initable_init (GInitable *initable,
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->selinux_policy_name = g_strdup (policytype);
|
||||
self->selinux_policy_name = g_steal_pointer (&policytype);
|
||||
self->selinux_policy_root = g_object_ref (etc_selinux_dir);
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ prune_repo (OstreeRepo *repo,
|
||||
|
||||
if (freed_space > 0)
|
||||
{
|
||||
char *freed_space_str = g_format_size_full (freed_space, 0);
|
||||
g_autofree char *freed_space_str = g_format_size_full (freed_space, 0);
|
||||
g_print ("Freed objects: %s\n", freed_space_str);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ parse_refspec (OstreeSysrootUpgrader *self,
|
||||
csum = g_key_file_get_string (self->origin, "origin", "override-commit", NULL);
|
||||
if (csum != NULL && !ostree_validate_checksum_string (csum, error))
|
||||
goto out;
|
||||
g_clear_pointer (&self->override_csum, g_free);
|
||||
self->override_csum = g_steal_pointer (&csum);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
@@ -411,3 +411,36 @@ ot_gpgme_data_output (GOutputStream *output_stream)
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
gpgme_ctx_t
|
||||
ot_gpgme_new_ctx (const char *homedir,
|
||||
GError **error)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
ot_auto_gpgme_ctx gpgme_ctx_t context = NULL;
|
||||
|
||||
if ((err = gpgme_new (&context)) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (err, error);
|
||||
g_prefix_error (error, "Unable to create gpg context: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (homedir != NULL)
|
||||
{
|
||||
gpgme_engine_info_t info;
|
||||
|
||||
info = gpgme_ctx_get_engine_info (context);
|
||||
|
||||
if ((err = gpgme_ctx_set_engine_info (context, info->protocol, NULL, homedir))
|
||||
!= GPG_ERR_NO_ERROR)
|
||||
{
|
||||
ot_gpgme_error_to_gio_error (err, error);
|
||||
g_prefix_error (error, "Unable to set gpg homedir to '%s': ",
|
||||
homedir);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&context);
|
||||
}
|
||||
@@ -22,9 +22,15 @@
|
||||
|
||||
#include <gpgme.h>
|
||||
#include <gio/gio.h>
|
||||
#include "libglnx.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GLNX_DEFINE_CLEANUP_FUNCTION0(gpgme_data_t, ot_cleanup_gpgme_data, gpgme_data_release)
|
||||
#define ot_auto_gpgme_data __attribute__((cleanup(ot_cleanup_gpgme_data)))
|
||||
GLNX_DEFINE_CLEANUP_FUNCTION0(gpgme_ctx_t, ot_cleanup_gpgme_ctx, gpgme_release)
|
||||
#define ot_auto_gpgme_ctx __attribute__((cleanup(ot_cleanup_gpgme_ctx)))
|
||||
|
||||
void ot_gpgme_error_to_gio_error (gpgme_error_t gpg_error, GError **error);
|
||||
|
||||
gboolean ot_gpgme_ctx_tmp_home_dir (gpgme_ctx_t gpgme_ctx,
|
||||
@@ -37,4 +43,7 @@ gboolean ot_gpgme_ctx_tmp_home_dir (gpgme_ctx_t gpgme_ctx,
|
||||
gpgme_data_t ot_gpgme_data_input (GInputStream *input_stream);
|
||||
gpgme_data_t ot_gpgme_data_output (GOutputStream *output_stream);
|
||||
|
||||
gpgme_ctx_t ot_gpgme_new_ctx (const char *homedir,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -67,7 +67,7 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
|
||||
g_autoptr(GFile) subtree = NULL;
|
||||
g_autofree char *commit = NULL;
|
||||
g_autoptr(GVariant) commit_data = NULL;
|
||||
struct archive *a;
|
||||
struct archive *a = NULL;
|
||||
OstreeRepoExportArchiveOptions opts = { 0, };
|
||||
|
||||
context = g_option_context_new ("COMMIT - Stream COMMIT to stdout in tar format");
|
||||
@@ -154,6 +154,10 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
#ifdef HAVE_LIBARCHIVE
|
||||
if (a)
|
||||
archive_write_free (a);
|
||||
#endif
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return ret;
|
||||
|
||||
@@ -287,7 +287,7 @@ ostree_builtin_fsck (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
if (opt_add_tombstones)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
const char *parent = ostree_commit_get_parent (commit);
|
||||
g_autofree char *parent = ostree_commit_get_parent (commit);
|
||||
if (parent)
|
||||
{
|
||||
g_autoptr(GVariant) parent_commit = NULL;
|
||||
|
||||
@@ -35,6 +35,7 @@ static gboolean opt_disable_static_deltas;
|
||||
static gboolean opt_require_static_deltas;
|
||||
static gboolean opt_untrusted;
|
||||
static char** opt_subpaths;
|
||||
static char** opt_http_headers;
|
||||
static char* opt_cache_dir;
|
||||
static int opt_depth = 0;
|
||||
static char* opt_url;
|
||||
@@ -51,6 +52,7 @@ static GOptionEntry options[] = {
|
||||
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
|
||||
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
|
||||
{ "url", 0, 0, G_OPTION_ARG_STRING, &opt_url, "Pull objects from this URL instead of the one from the remote config", NULL },
|
||||
{ "http-header", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_http_headers, "Add NAME=VALUE as HTTP header to all requests", "NAME=VALUE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -249,6 +251,29 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
g_variant_builder_add (&builder, "{s@v}", "override-commit-ids",
|
||||
g_variant_new_variant (g_variant_new_strv ((const char*const*)override_commit_ids->pdata, override_commit_ids->len)));
|
||||
|
||||
if (opt_http_headers)
|
||||
{
|
||||
GVariantBuilder hdr_builder;
|
||||
g_variant_builder_init (&hdr_builder, G_VARIANT_TYPE ("a(ss)"));
|
||||
|
||||
for (char **iter = opt_http_headers; iter && *iter; iter++)
|
||||
{
|
||||
const char *kv = *iter;
|
||||
const char *eq = strchr (kv, '=');
|
||||
g_autofree char *key = NULL;
|
||||
if (!eq)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Missing '=' in --http-header");
|
||||
goto out;
|
||||
}
|
||||
key = g_strndup (kv, eq - kv);
|
||||
g_variant_builder_add (&hdr_builder, "(ss)", key, eq + 1);
|
||||
}
|
||||
g_variant_builder_add (&builder, "{s@v}", "http-headers",
|
||||
g_variant_new_variant (g_variant_builder_end (&hdr_builder)));
|
||||
}
|
||||
|
||||
if (!opt_dry_run)
|
||||
{
|
||||
if (console.is_tty)
|
||||
|
||||
@@ -34,6 +34,7 @@ static char* opt_print_metadata_key;
|
||||
static char* opt_print_detached_metadata_key;
|
||||
static gboolean opt_raw;
|
||||
static char *opt_gpg_homedir;
|
||||
static char *opt_gpg_verify_remote;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "print-related", 0, 0, G_OPTION_ARG_NONE, &opt_print_related, "Show the \"related\" commits", NULL },
|
||||
@@ -42,6 +43,7 @@ static GOptionEntry options[] = {
|
||||
{ "print-detached-metadata-key", 0, 0, G_OPTION_ARG_STRING, &opt_print_detached_metadata_key, "Print string value of detached metadata key", "KEY" },
|
||||
{ "raw", 0, 0, G_OPTION_ARG_NONE, &opt_raw, "Show raw variant data" },
|
||||
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
|
||||
{ "gpg-verify-remote", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_verify_remote, "Use REMOTE name for GPG configuration", "REMOTE"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -170,9 +172,17 @@ print_object (OstreeRepo *repo,
|
||||
GError *local_error = NULL;
|
||||
g_autoptr(GFile) gpg_homedir = opt_gpg_homedir ? g_file_new_for_path (opt_gpg_homedir) : NULL;
|
||||
|
||||
result = ostree_repo_verify_commit_ext (repo, checksum,
|
||||
gpg_homedir, NULL, NULL,
|
||||
&local_error);
|
||||
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))
|
||||
{
|
||||
|
||||
@@ -43,8 +43,8 @@ static int opt_random_500s_percentage;
|
||||
* cases involving repeated random 500s. */
|
||||
static int opt_random_500s_max = 100;
|
||||
static gint opt_port = 0;
|
||||
|
||||
static gchar **opt_expected_cookies;
|
||||
static gchar **opt_expected_headers;
|
||||
|
||||
static guint emitted_random_500s_count = 0;
|
||||
|
||||
@@ -64,6 +64,7 @@ static GOptionEntry options[] = {
|
||||
{ "random-500s-max", 0, 0, G_OPTION_ARG_INT, &opt_random_500s_max, "Limit HTTP 500 errors to MAX (default 100)", "MAX" },
|
||||
{ "log-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_log, "Put logs here", "PATH" },
|
||||
{ "expected-cookies", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_expected_cookies, "Expect given cookies in the http request", "KEY=VALUE" },
|
||||
{ "expected-header", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_expected_headers, "Expect given headers in the http request", "KEY=VALUE" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -238,6 +239,36 @@ do_get (OtTrivialHttpd *self,
|
||||
soup_cookies_free (cookies);
|
||||
}
|
||||
|
||||
if (opt_expected_headers)
|
||||
{
|
||||
for (int i = 0 ; opt_expected_headers[i] != NULL; i++)
|
||||
{
|
||||
const gchar *kv = opt_expected_headers[i];
|
||||
const gchar *eq = strchr (kv, '=');
|
||||
|
||||
g_assert (eq);
|
||||
|
||||
{
|
||||
g_autofree char *k = g_strndup (kv, eq - kv);
|
||||
const gchar *expected_v = eq + 1;
|
||||
const gchar *found_v = soup_message_headers_get_one (msg->request_headers, k);
|
||||
|
||||
if (!found_v)
|
||||
{
|
||||
httpd_log (self, "Expected header not found %s\n", k);
|
||||
soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp (found_v, expected_v) != 0)
|
||||
{
|
||||
httpd_log (self, "Expected header %s: %s but found %s\n", k, expected_v, found_v);
|
||||
soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strstr (path, "../") != NULL)
|
||||
{
|
||||
soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
|
||||
|
||||
@@ -125,7 +125,6 @@ ostree_run (int argc,
|
||||
GError *error = NULL;
|
||||
GCancellable *cancellable = NULL;
|
||||
const char *command_name = NULL;
|
||||
g_autofree char *prgname = NULL;
|
||||
gboolean success = FALSE;
|
||||
int in, out;
|
||||
|
||||
@@ -202,10 +201,6 @@ ostree_run (int argc,
|
||||
goto out;
|
||||
}
|
||||
|
||||
prgname = g_strdup_printf ("%s %s", g_get_prgname (), command_name);
|
||||
g_set_prgname (prgname);
|
||||
|
||||
|
||||
if (!command->fn (argc, argv, cancellable, &error))
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ ot_remote_builtin_add_cookie (int argc, char **argv, GCancellable *cancellable,
|
||||
value = argv[5];
|
||||
|
||||
cookie_file = g_strdup_printf ("%s.cookies.txt", remote_name);
|
||||
jar_path = g_build_filename (g_file_get_path (repo->repodir), cookie_file, NULL);
|
||||
jar_path = g_build_filename (gs_file_get_path_cached (repo->repodir), cookie_file, NULL);
|
||||
|
||||
jar = soup_cookie_jar_text_new (jar_path, FALSE);
|
||||
|
||||
@@ -80,5 +80,7 @@ ot_remote_builtin_add_cookie (int argc, char **argv, GCancellable *cancellable,
|
||||
/* jar takes ownership of cookie */
|
||||
soup_cookie_jar_add_cookie (jar, cookie);
|
||||
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ ot_remote_builtin_delete_cookie (int argc, char **argv, GCancellable *cancellabl
|
||||
cookie_name = argv[4];
|
||||
|
||||
cookie_file = g_strdup_printf ("%s.cookies.txt", remote_name);
|
||||
jar_path = g_build_filename (g_file_get_path (repo->repodir), cookie_file, NULL);
|
||||
jar_path = g_build_filename (gs_file_get_path_cached (repo->repodir), cookie_file, NULL);
|
||||
|
||||
jar = soup_cookie_jar_text_new (jar_path, FALSE);
|
||||
cookies = soup_cookie_jar_all_cookies (jar);
|
||||
@@ -92,5 +92,7 @@ ot_remote_builtin_delete_cookie (int argc, char **argv, GCancellable *cancellabl
|
||||
if (!found)
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Cookie not found in jar");
|
||||
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return found;
|
||||
}
|
||||
Reference in new issue
Block a user