Skip to content

Commit

Permalink
lib/repo: Search a list of paths in gpgkeypath for gpg keys
Browse files Browse the repository at this point in the history
This allows specifying gpgpath as semicolon-separated list of
paths that can point to a file or a directory. If a directory path
is given, paths to all regular files in the directory are added
to the remote as gpg ascii keys. If the path is not a directory,
the file is directly added (whether regular file, empty - errors
will be reported later when verifying gpg keys e.g. when pulling).

Adding the gpgkeypath property looks like:

ostree --repo=repo remote add --set=gpgpath="/path/key1.asc;/path/keys.d" R1 https://example.com/some/remote/ostree/repo

Closes ostreedev#773
  • Loading branch information
rfairley committed Nov 6, 2018
1 parent 34a8867 commit d0e4065
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 1 deletion.
64 changes: 64 additions & 0 deletions src/libostree/ostree-gpg-verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,70 @@ _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
g_ptr_array_add (self->key_ascii_files, g_strdup (path));
}

/* Check if the file at @path is a directory, and add ascii key files that
* exist one level below the directory. If @path does not lead to a directory,
* the file is added.
*/
void
_ostree_gpg_verifier_add_key_ascii_files_check_dir (OstreeGpgVerifier *self,
const char *path,
GCancellable *cancellable,
GError **error)
{
GFile *file;
GFileType file_type;

file = g_file_new_for_path (path);
file_type = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, cancellable);

if (file_type == G_FILE_TYPE_DIRECTORY)
{
GFileEnumerator *direnum;
g_autofree char *sep = NULL;

if (!g_str_has_suffix (path, "/"))
sep = g_strdup ("/");

direnum = g_file_enumerate_children (file, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NONE, cancellable, error);
if (direnum)
{
while (TRUE)
{
GFileInfo *child_info;
GFile *child;
const char *name;
guint32 type;

if (!g_file_enumerator_iterate (direnum, &child_info, &child,
NULL, error))
break;
if (child_info == NULL)
break;

name = g_file_info_get_attribute_byte_string (child_info, "standard::name");
type = g_file_info_get_attribute_uint32 (child_info, "standard::type");

if (type == G_FILE_TYPE_REGULAR)
{
g_autofree char *child_path = NULL;

child_path = g_strjoin (sep, path, name, NULL);

_ostree_gpg_verifier_add_key_ascii_file (self, child_path);
}
}
}

g_object_unref (direnum);
g_object_unref (file);
}
else
{
_ostree_gpg_verifier_add_key_ascii_file (self, path);
}
}

gboolean
_ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
GFile *path,
Expand Down
6 changes: 6 additions & 0 deletions src/libostree/ostree-gpg-verifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,10 @@ void _ostree_gpg_verifier_add_keyring_file (OstreeGpgVerifier *self,
void _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
const char *path);

void
_ostree_gpg_verifier_add_key_ascii_files_check_dir (OstreeGpgVerifier *self,
const char *path,
GCancellable *cancellable,
GError **error);

G_END_DECLS
23 changes: 22 additions & 1 deletion src/libostree/ostree-repo.c
Original file line number Diff line number Diff line change
Expand Up @@ -5082,6 +5082,8 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
else if (remote_name != NULL)
{
g_autofree char *gpgkeypath = NULL;
char **gpgkeypath_list = NULL;

/* Add the remote's keyring file if it exists. */

g_autoptr(OstreeRemote) remote = NULL;
Expand All @@ -5105,7 +5107,26 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
return NULL;

if (gpgkeypath)
_ostree_gpg_verifier_add_key_ascii_file (verifier, gpgkeypath);
{
if (strchr (gpgkeypath, ';'))
{
gpgkeypath_list = g_strsplit (gpgkeypath, ";", -1);
}
else
{
_ostree_gpg_verifier_add_key_ascii_files_check_dir (verifier, gpgkeypath, cancellable, error);
}
}

if (gpgkeypath_list)
{
for (char **iter = gpgkeypath_list; *iter != NULL; ++iter)
{
_ostree_gpg_verifier_add_key_ascii_files_check_dir (verifier, *iter, cancellable, error);
}
}

g_strfreev (gpgkeypath_list);
}

if (add_global_keyring_dir)
Expand Down
58 changes: 58 additions & 0 deletions tests/test-remote-gpg-import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,64 @@ ${OSTREE} prune --refs-only
${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/key3.asc R4 $(cat httpd-address)/ostree/gnomerepo
${OSTREE} pull R4:main >/dev/null

# Test gpgkeypath success with multiple keys to try
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/key1.asc;${test_tmpdir}/gpghome/key2.asc;${test_tmpdir}/gpghome/key3.asc" R7 $(cat httpd-address)/ostree/gnomerepo
${OSTREE} pull R7:main >/dev/null

# Test gpgkeypath failure with multiple keys but none in keyring (invalid)
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/key1.asc;${test_tmpdir}/gpghome/key2.asc" R8 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R8:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with different key"
fi
assert_file_has_content err.txt "GPG signatures found, but none are in trusted keyring"

# Test gpgkeypath success with directory containing a valid key
${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/ R9 $(cat httpd-address)/ostree/gnomerepo
${OSTREE} pull R9:main >/dev/null

# Test gpgkeypath failure with nonexistent directory
${OSTREE} remote add --set=gpgkeypath=${test_tmpdir}/gpghome/INVALIDKEYDIRPATH/ R10 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R10:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with nonexistent key directory"
fi
assert_file_has_content err.txt "GPG: openat.*No such file or directory"

# Test gpgkeypath failure with a directory containing a valid key and a nonexistent key
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/;${test_tmpdir}/gpghome/INVALIDKEYPATH.asc" R11 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R11:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with nonexistent key"
fi
assert_file_has_content err.txt "GPG: openat.*No such file or directory"

# Test gpgkeypath success with a directory containing a valid key and an invalid key
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/;${test_tmpdir}/gpghome/key1.asc" R14 $(cat httpd-address)/ostree/gnomerepo
${OSTREE} pull R14:main >/dev/null

# Test gpgkeypath failure with a nonexistent directory and a valid key
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/INVALIDKEYDIRPATH/;${test_tmpdir}/gpghome/key3.asc" R12 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R12:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with nonexistent key directory"
fi
assert_file_has_content err.txt "GPG: openat.*No such file or directory"

# Test gpgkeypath failure with a nonexistent directory and a nonexistent key
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome/INVALIDKEYDIRPATH/;${test_tmpdir}/gpghome/INVALIDKEYPATH.asc" R13 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R13:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with nonexistent key directory"
fi
assert_file_has_content err.txt "GPG: openat.*No such file or directory"

# Test gpgkeypath success for trailing slash
${OSTREE} remote add --set=gpgkeypath="${test_tmpdir}/gpghome" R15 $(cat httpd-address)/ostree/gnomerepo
${OSTREE} pull R15:main >/dev/null

# Test gpgkeypath failure for empty string given with prefixed semicolon
${OSTREE} remote add --set=gpgkeypath=";${test_tmpdir}/gpghome/key3.asc" R16 $(cat httpd-address)/ostree/gnomerepo
if ${OSTREE} pull R16:main 2>err.txt; then
assert_not_reached "Unexpectedly succeeded at pulling with nonexistent key directory"
fi
assert_file_has_content err.txt "GPG: openat.*No such file or directory"

rm repo/refs/remotes/* -rf
${OSTREE} prune --refs-only

Expand Down

0 comments on commit d0e4065

Please sign in to comment.