diff options
author | Dan Nicholson <nicholson@endlessm.com> | 2019-08-27 10:28:10 -0600 |
---|---|---|
committer | Dan Nicholson <dbn@endlessos.org> | 2021-07-15 15:50:04 -0600 |
commit | 4fa403aee500df058a7d3ee2b6b1db4300ad7a92 (patch) | |
tree | 671d694e8c868b84b5d5e9b71f429b56009e0ad5 /src/libotutil | |
parent | fbff05e28d0e0d3c8424a7d4a5652a253a553b04 (diff) | |
download | ostree-4fa403aee500df058a7d3ee2b6b1db4300ad7a92.tar.gz |
libotutil: Add helper for GPG WKD update URLs
Calculate the advanced and direct update URLs for the key discovery
portion[1] of the OpenPGP Web Key Directory specification, and include
the URLs in the key listing in ostree_repo_remote_get_gpg_keys(). These
URLs can be used to locate updated GPG keys for the remote.
1. https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service#section-3.1
Diffstat (limited to 'src/libotutil')
-rw-r--r-- | src/libotutil/ot-gpg-utils.c | 75 | ||||
-rw-r--r-- | src/libotutil/ot-gpg-utils.h | 5 |
2 files changed, 80 insertions, 0 deletions
diff --git a/src/libotutil/ot-gpg-utils.c b/src/libotutil/ot-gpg-utils.c index 743d941e..4dbefdbd 100644 --- a/src/libotutil/ot-gpg-utils.c +++ b/src/libotutil/ot-gpg-utils.c @@ -27,6 +27,7 @@ #include <gio/gunixoutputstream.h> #include "libglnx.h" +#include "zbase32.h" /* Like glnx_throw_errno_prefix, but takes @gpg_error */ gboolean @@ -538,3 +539,77 @@ ot_gpgme_kill_agent (const char *homedir) return; } } + +/* Takes the SHA1 checksum of the local component of an email address and + * returns the zbase32 encoding. + */ +static char * +encode_wkd_local (const char *local) +{ + g_return_val_if_fail (local != NULL, NULL); + + guint8 digest[20] = { 0 }; + gsize len = sizeof (digest); + g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA1); + g_checksum_update (checksum, (const guchar *)local, -1); + g_checksum_get_digest (checksum, digest, &len); + + char *encoded = zbase32_encode (digest, len); + + /* If the returned string is NULL, then there must have been a memory + * allocation problem. Just exit immediately like g_malloc. + */ + if (encoded == NULL) + g_error ("%s: %s", G_STRLOC, g_strerror (errno)); + + return encoded; +} + +/* Implementation of OpenPGP Web Key Directory URLs as defined in + * https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service + */ +gboolean +ot_gpg_wkd_urls (const char *email, + char **out_advanced_url, + char **out_direct_url, + GError **error) +{ + g_return_val_if_fail (email != NULL, FALSE); + + g_auto(GStrv) email_parts = g_strsplit (email, "@", -1); + if (g_strv_length (email_parts) != 2) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + "Invalid email address \"%s\"", email); + return FALSE; + } + + g_autofree char *local_lowered = g_ascii_strdown (email_parts[0], -1); + g_autofree char *domain_lowered = g_ascii_strdown (email_parts[1], -1); + g_autofree char *local_encoded = encode_wkd_local (local_lowered); + g_autofree char *local_escaped = g_uri_escape_string (email_parts[0], NULL, FALSE); + + g_autofree char *advanced_url = g_strdup_printf ("https://openpgpkey.%s" + "/.well-known/openpgpkey" + "/%s/hu/%s?l=%s", + email_parts[1], + domain_lowered, + local_encoded, + local_escaped); + g_debug ("GPG UID \"%s\" advanced WKD URL: %s", email, advanced_url); + + g_autofree char *direct_url = g_strdup_printf ("https://%s" + "/.well-known/openpgpkey" + "/hu/%s?l=%s", + email_parts[1], + local_encoded, + local_escaped); + g_debug ("GPG UID \"%s\" direct WKD URL: %s", email, direct_url); + + if (out_advanced_url != NULL) + *out_advanced_url = g_steal_pointer (&advanced_url); + if (out_direct_url != NULL) + *out_direct_url = g_steal_pointer (&direct_url); + + return TRUE; +} diff --git a/src/libotutil/ot-gpg-utils.h b/src/libotutil/ot-gpg-utils.h index e8a240b5..b559b695 100644 --- a/src/libotutil/ot-gpg-utils.h +++ b/src/libotutil/ot-gpg-utils.h @@ -48,4 +48,9 @@ gpgme_ctx_t ot_gpgme_new_ctx (const char *homedir, void ot_gpgme_kill_agent (const char *homedir); +gboolean ot_gpg_wkd_urls (const char *email, + char **out_advanced_url, + char **out_direct_url, + GError **error); + G_END_DECLS |