-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remote GPG key info #2401
Merged
Merged
Remote GPG key info #2401
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
dba2cdc
lib/repo: Factor out GPG verifier key imports
dbnicholson c8715c1
lib/repo: Factor out GPG verifier preparation
dbnicholson fc07365
lib/repo: Allow preparing GPG verifier without global keyrings
dbnicholson a50f6d0
lib/repo: Add ostree_repo_remote_get_gpg_keys()
dbnicholson 74fb0c5
bin/remote: Add list-gpg-keys subcommand
dbnicholson fbff05e
libotutil: Import implementation of zbase32 encoding
dbnicholson 4fa403a
libotutil: Add helper for GPG WKD update URLs
dbnicholson 27dc5d7
lib/repo: Include WKD update URLs in GPG key listing
dbnicholson 90a3bda
bin/remote: Include update URLs in list-gpg-keys
dbnicholson 30c054b
fixup! lib/repo: Add ostree_repo_remote_get_gpg_keys()
dbnicholson 814e481
fixup! bin/remote: Add list-gpg-keys subcommand
dbnicholson 81df5c8
fixup! lib/repo: Add ostree_repo_remote_get_gpg_keys()
dbnicholson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,43 +91,16 @@ verify_result_finalized_cb (gpointer data, | |
(void) glnx_shutil_rm_rf_at (AT_FDCWD, tmp_dir, NULL, NULL); | ||
} | ||
|
||
OstreeGpgVerifyResult * | ||
_ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | ||
GBytes *signed_data, | ||
GBytes *signatures, | ||
GCancellable *cancellable, | ||
GError **error) | ||
static gboolean | ||
_ostree_gpg_verifier_import_keys (OstreeGpgVerifier *self, | ||
gpgme_ctx_t gpgme_ctx, | ||
GOutputStream *pubring_stream, | ||
GCancellable *cancellable, | ||
GError **error) | ||
{ | ||
GLNX_AUTO_PREFIX_ERROR("GPG", error); | ||
gpgme_error_t gpg_error = 0; | ||
g_auto(gpgme_data_t) data_buffer = NULL; | ||
g_auto(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 | ||
* temporary directory, then tell GPGME to use that directory as the | ||
* home directory. */ | ||
|
||
if (g_cancellable_set_error_if_cancelled (cancellable, error)) | ||
goto out; | ||
|
||
result = g_initable_new (OSTREE_TYPE_GPG_VERIFY_RESULT, | ||
cancellable, error, NULL); | ||
if (result == NULL) | ||
goto out; | ||
|
||
if (!ot_gpgme_ctx_tmp_home_dir (result->context, | ||
&tmp_dir, &target_stream, | ||
cancellable, error)) | ||
goto out; | ||
|
||
for (link = self->keyrings; link != NULL; link = link->next) | ||
for (GList *link = self->keyrings; link != NULL; link = link->next) | ||
{ | ||
g_autoptr(GFileInputStream) source_stream = NULL; | ||
GFile *keyring_file = link->data; | ||
|
@@ -145,15 +118,15 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | |
else if (local_error != NULL) | ||
{ | ||
g_propagate_error (error, local_error); | ||
goto out; | ||
return FALSE; | ||
} | ||
|
||
bytes_written = g_output_stream_splice (target_stream, | ||
bytes_written = g_output_stream_splice (pubring_stream, | ||
G_INPUT_STREAM (source_stream), | ||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, | ||
cancellable, error); | ||
if (bytes_written < 0) | ||
goto out; | ||
return FALSE; | ||
} | ||
|
||
for (guint i = 0; i < self->keyring_data->len; i++) | ||
|
@@ -162,23 +135,25 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | |
gsize len; | ||
gsize bytes_written; | ||
const guint8 *buf = g_bytes_get_data (keyringd, &len); | ||
if (!g_output_stream_write_all (target_stream, buf, len, &bytes_written, | ||
if (!g_output_stream_write_all (pubring_stream, buf, len, &bytes_written, | ||
cancellable, error)) | ||
goto out; | ||
return FALSE; | ||
} | ||
|
||
if (!g_output_stream_close (target_stream, cancellable, error)) | ||
goto out; | ||
if (!g_output_stream_close (pubring_stream, cancellable, error)) | ||
return FALSE; | ||
|
||
/* 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); | ||
gboolean ret = FALSE; | ||
int armor = gpgme_get_armor (gpgme_ctx); | ||
gpgme_set_armor (gpgme_ctx, 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++) | ||
{ | ||
gpgme_error_t gpg_error; | ||
const char *path = self->key_ascii_files->pdata[i]; | ||
glnx_autofd int fd = -1; | ||
g_auto(gpgme_data_t) kdata = NULL; | ||
|
@@ -193,7 +168,7 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | |
goto out; | ||
} | ||
|
||
gpg_error = gpgme_op_import (result->context, kdata); | ||
gpg_error = gpgme_op_import (gpgme_ctx, kdata); | ||
if (gpg_error != GPG_ERR_NO_ERROR) | ||
{ | ||
ot_gpgme_throw (gpg_error, error, "Failed to import key"); | ||
|
@@ -202,7 +177,136 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | |
} | ||
} | ||
|
||
gpgme_set_armor (result->context, armor); | ||
ret = TRUE; | ||
|
||
out: | ||
gpgme_set_armor (gpgme_ctx, armor); | ||
|
||
return ret; | ||
} | ||
|
||
gboolean | ||
_ostree_gpg_verifier_list_keys (OstreeGpgVerifier *self, | ||
const char * const *key_ids, | ||
GPtrArray **out_keys, | ||
GCancellable *cancellable, | ||
GError **error) | ||
{ | ||
GLNX_AUTO_PREFIX_ERROR("GPG", error); | ||
g_auto(gpgme_ctx_t) context = NULL; | ||
g_autoptr(GOutputStream) pubring_stream = NULL; | ||
g_autofree char *tmp_dir = NULL; | ||
g_autoptr(GPtrArray) keys = NULL; | ||
gpgme_error_t gpg_error = 0; | ||
gboolean ret = FALSE; | ||
|
||
if (g_cancellable_set_error_if_cancelled (cancellable, error)) | ||
goto out; | ||
|
||
context = ot_gpgme_new_ctx (NULL, error); | ||
if (context == NULL) | ||
goto out; | ||
|
||
if (!ot_gpgme_ctx_tmp_home_dir (context, &tmp_dir, &pubring_stream, | ||
cancellable, error)) | ||
goto out; | ||
|
||
if (!_ostree_gpg_verifier_import_keys (self, context, pubring_stream, | ||
cancellable, error)) | ||
goto out; | ||
|
||
keys = g_ptr_array_new_with_free_func ((GDestroyNotify) gpgme_key_unref); | ||
if (key_ids != NULL) | ||
{ | ||
for (guint i = 0; key_ids[i] != NULL; i++) | ||
{ | ||
gpgme_key_t key = NULL; | ||
|
||
gpg_error = gpgme_get_key (context, key_ids[i], &key, 0); | ||
if (gpg_error != GPG_ERR_NO_ERROR) | ||
{ | ||
ot_gpgme_throw (gpg_error, error, "Unable to find key \"%s\"", | ||
key_ids[i]); | ||
goto out; | ||
} | ||
|
||
/* Transfer ownership. */ | ||
g_ptr_array_add (keys, key); | ||
} | ||
} | ||
else | ||
{ | ||
gpg_error = gpgme_op_keylist_start (context, NULL, 0); | ||
while (gpg_error == GPG_ERR_NO_ERROR) | ||
{ | ||
gpgme_key_t key = NULL; | ||
|
||
gpg_error = gpgme_op_keylist_next (context, &key); | ||
if (gpg_error != GPG_ERR_NO_ERROR) | ||
break; | ||
|
||
/* Transfer ownership. */ | ||
g_ptr_array_add (keys, key); | ||
} | ||
|
||
if (gpgme_err_code (gpg_error) != GPG_ERR_EOF) | ||
{ | ||
ot_gpgme_throw (gpg_error, error, "Unable to list keys"); | ||
goto out; | ||
} | ||
} | ||
|
||
if (out_keys != NULL) | ||
*out_keys = g_steal_pointer (&keys); | ||
|
||
ret = TRUE; | ||
|
||
out: | ||
if (tmp_dir != NULL) { | ||
ot_gpgme_kill_agent (tmp_dir); | ||
(void) glnx_shutil_rm_rf_at (AT_FDCWD, tmp_dir, NULL, NULL); | ||
Comment on lines
+265
to
+267
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably make these autocleanups too in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so. The gpgme code could use some sprucing up. |
||
} | ||
|
||
return ret; | ||
} | ||
|
||
OstreeGpgVerifyResult * | ||
_ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self, | ||
GBytes *signed_data, | ||
GBytes *signatures, | ||
GCancellable *cancellable, | ||
GError **error) | ||
{ | ||
GLNX_AUTO_PREFIX_ERROR("GPG", error); | ||
gpgme_error_t gpg_error = 0; | ||
g_auto(gpgme_data_t) data_buffer = NULL; | ||
g_auto(gpgme_data_t) signature_buffer = NULL; | ||
g_autofree char *tmp_dir = NULL; | ||
g_autoptr(GOutputStream) target_stream = NULL; | ||
OstreeGpgVerifyResult *result = NULL; | ||
gboolean success = FALSE; | ||
|
||
/* GPGME has no API for using multiple keyrings (aka, gpg --keyring), | ||
* so we concatenate all the keyring files into one pubring.gpg in a | ||
* temporary directory, then tell GPGME to use that directory as the | ||
* home directory. */ | ||
|
||
if (g_cancellable_set_error_if_cancelled (cancellable, error)) | ||
goto out; | ||
|
||
result = g_initable_new (OSTREE_TYPE_GPG_VERIFY_RESULT, | ||
cancellable, error, NULL); | ||
if (result == NULL) | ||
goto out; | ||
|
||
if (!ot_gpgme_ctx_tmp_home_dir (result->context, | ||
&tmp_dir, &target_stream, | ||
cancellable, error)) | ||
goto out; | ||
|
||
if (!_ostree_gpg_verifier_import_keys (self, result->context, target_stream, | ||
cancellable, error)) | ||
goto out; | ||
|
||
/* Both the signed data and signature GBytes instances will outlive the | ||
* gpgme_data_t structs, so we can safely reuse the GBytes memory buffer | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To align with the command above,
gpg-list-keys
orgpg-list
maybe?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I like
gpg-list-keys
.