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 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 7, 2018
1 parent 34a8867 commit 1bd6eb6
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 1bd6eb6

Please sign in to comment.