summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2016-04-27 08:34:29 +0200
committerWerner Koch <wk@gnupg.org>2016-04-27 08:34:29 +0200
commit87de9e19edf0311ca0342e15ef44ebe40e32861e (patch)
tree20f8f2c384040344ece6e00c64036c666dd4a843 /g10
parentdirmngr: Add experimental command WKD_GET. (diff)
downloadgnupg2-87de9e19edf0311ca0342e15ef44ebe40e32861e.tar.xz
gnupg2-87de9e19edf0311ca0342e15ef44ebe40e32861e.zip
gpg: Add experimental AKL method "wkd" and option --with-wkd-hash.
* g10/getkey.c (parse_auto_key_locate): Add method "wkd". (get_pubkey_byname): Implement that method. Also rename a variable. * g10/call-dirmngr.c (gpg_dirmngr_wkd_get): New. * g10/keyserver.c (keyserver_import_wkd): New. * g10/test-stubs.c (keyserver_import_wkd): Add stub. * g10/gpgv.c (keyserver_import_wkd): Ditto. * g10/options.h (opt): Add field 'with_wkd_hash'. (AKL_WKD): New. * g10/gpg.c (oWithWKDHash): New. (opts): Add option --with-wkd-hash. (main): Set that option. * g10/keylist.c (list_keyblock_print): Implement that option. -- The Web Key Directory is an experimental feature to retrieve a key via https. It is similar to OpenPGP DANE but also uses an encryption to reveal less information about a key lookup. For example the URI to lookup the key for Joe.Doe@Example.ORG is: https://example.org/.well-known/openpgpkey/ hu/example.org/iy9q119eutrkn8s1mk4r39qejnbu3n5q (line has been wrapped for rendering purposes). The hash is a z-Base-32 encoded SHA-1 hash of the mail address' local-part. The address wk@gnupg.org can be used for testing. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g10')
-rw-r--r--g10/call-dirmngr.c61
-rw-r--r--g10/call-dirmngr.h2
-rw-r--r--g10/getkey.c34
-rw-r--r--g10/gpg.c6
-rw-r--r--g10/gpgv.c11
-rw-r--r--g10/import.c2
-rw-r--r--g10/keylist.c36
-rw-r--r--g10/keyserver-internal.h2
-rw-r--r--g10/keyserver.c33
-rw-r--r--g10/options.h2
-rw-r--r--g10/test-stubs.c11
11 files changed, 178 insertions, 22 deletions
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index e59653362..b0f249e8c 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -1064,7 +1064,7 @@ gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
-/* Data callback for the DNS_CERT command. */
+/* Data callback for the DNS_CERT and WKD_GET commands. */
static gpg_error_t
dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
{
@@ -1287,3 +1287,62 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
close_context (ctrl, ctx);
return err;
}
+
+
+
+/* Ask the dirmngr to retrieve a key via the Web Key Directory
+ * protocol. On success a new estream with the key is stored at
+ * R_KEY.
+ */
+gpg_error_t
+gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, estream_t *r_key)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct dns_cert_parm_s parm;
+ char *line = NULL;
+
+ memset (&parm, 0, sizeof parm);
+
+ err = open_context (ctrl, &ctx);
+ if (err)
+ return err;
+
+ line = es_bsprintf ("WKD_GET -- %s", name);
+ if (!line)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+
+ parm.memfp = es_fopenmem (0, "rwb");
+ if (!parm.memfp)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
+ NULL, NULL, NULL, &parm);
+ if (err)
+ goto leave;
+
+ if (r_key)
+ {
+ es_rewind (parm.memfp);
+ *r_key = parm.memfp;
+ parm.memfp = NULL;
+ }
+
+ leave:
+ xfree (parm.fpr);
+ xfree (parm.url);
+ es_fclose (parm.memfp);
+ xfree (line);
+ close_context (ctrl, ctx);
+ return err;
+}
diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
index cdad645ad..4dc1e3020 100644
--- a/g10/call-dirmngr.h
+++ b/g10/call-dirmngr.h
@@ -40,6 +40,8 @@ gpg_error_t gpg_dirmngr_dns_cert (ctrl_t ctrl,
gpg_error_t gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
unsigned char **r_fpr, size_t *r_fprlen,
char **r_url);
+gpg_error_t gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name,
+ estream_t *r_key);
#endif /*GNUPG_G10_CALL_DIRMNGR_H*/
diff --git a/g10/getkey.c b/g10/getkey.c
index 481e8dd92..a3d29f50a 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1274,7 +1274,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
{
unsigned char *fpr = NULL;
size_t fpr_len;
- int did_key_byname = 0;
+ int did_akl_local = 0;
int no_fingerprint = 0;
const char *mechanism = "?";
@@ -1288,7 +1288,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
case AKL_LOCAL:
mechanism = "Local";
- did_key_byname = 1;
+ did_akl_local = 1;
if (retctx)
{
getkey_end (*retctx);
@@ -1321,6 +1321,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
glo_ctrl.in_auto_key_retrieve--;
break;
+ case AKL_WKD:
+ mechanism = "WKD";
+ glo_ctrl.in_auto_key_retrieve++;
+ rc = keyserver_import_wkd (ctrl, name, &fpr, &fpr_len);
+ glo_ctrl.in_auto_key_retrieve--;
+ break;
+
case AKL_LDAP:
mechanism = "LDAP";
glo_ctrl.in_auto_key_retrieve++;
@@ -1386,22 +1393,20 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
add_to_strlist (&namelist, fpr_string);
}
- else if (!rc && !fpr && !did_key_byname)
- /* The acquisition method said no failure occurred, but it
- didn't return a fingerprint. That's a failure. */
- {
- no_fingerprint = 1;
+ else if (!rc && !fpr && !did_akl_local)
+ { /* The acquisition method said no failure occurred, but
+ it didn't return a fingerprint. That's a failure. */
+ no_fingerprint = 1;
rc = GPG_ERR_NO_PUBKEY;
}
xfree (fpr);
fpr = NULL;
- if (!rc && !did_key_byname)
- /* There was no error and we didn't do a local lookup.
- This means that we imported a key into the local
- keyring. Try to read the imported key from the
- keyring. */
- {
+ if (!rc && !did_akl_local)
+ { /* There was no error and we didn't do a local lookup.
+ This means that we imported a key into the local
+ keyring. Try to read the imported key from the
+ keyring. */
if (retctx)
{
getkey_end (*retctx);
@@ -3195,6 +3200,7 @@ finish_lookup (GETKEY_CTX ctx, KBNODE keyblock)
if (DBG_LOOKUP)
log_debug ("\tsubkey has expired\n");
continue;
+
}
if (pk->timestamp > curtime && !opt.ignore_valid_from)
{
@@ -3769,6 +3775,8 @@ parse_auto_key_locate (char *options)
akl->type = AKL_PKA;
else if (ascii_strcasecmp (tok, "dane") == 0)
akl->type = AKL_DANE;
+ else if (ascii_strcasecmp (tok, "wkd") == 0)
+ akl->type = AKL_WKD;
else if ((akl->spec = parse_keyserver_uri (tok, 1)))
akl->type = AKL_SPEC;
else
diff --git a/g10/gpg.c b/g10/gpg.c
index b9d69a7cb..2f687fceb 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -185,6 +185,7 @@ enum cmd_and_opt_values
oWithICAOSpelling,
oWithKeygrip,
oWithSecret,
+ oWithWKDHash,
oAnswerYes,
oAnswerNo,
oKeyring,
@@ -721,6 +722,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"),
ARGPARSE_s_n (oWithSecret, "with-secret", "@"),
+ ARGPARSE_s_n (oWithWKDHash, "with-wkd-hash", "@"),
ARGPARSE_s_s (oDisableCipherAlgo, "disable-cipher-algo", "@"),
ARGPARSE_s_s (oDisablePubkeyAlgo, "disable-pubkey-algo", "@"),
ARGPARSE_s_n (oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", "@"),
@@ -2575,6 +2577,10 @@ main (int argc, char **argv)
opt.with_secret = 1;
break;
+ case oWithWKDHash:
+ opt.with_wkd_hash = 1;
+ break;
+
case oSecretKeyring:
/* Ignore this old option. */
break;
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 19a2ff6c7..2a53e693a 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -374,6 +374,17 @@ keyserver_import_pka (const char *name,unsigned char *fpr)
return -1;
}
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+ unsigned char **fpr, size_t *fpr_len)
+{
+ (void)ctrl;
+ (void)name;
+ (void)fpr;
+ (void)fpr_len;
+ return GPG_ERR_BUG;
+}
+
int
keyserver_import_name (const char *name,struct keyserver_spec *spec)
{
diff --git a/g10/import.c b/g10/import.c
index 369be35d9..e9fc014cc 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1279,7 +1279,7 @@ import_one (ctrl_t ctrl,
{
xfree (*fpr);
/* Note that we need to compare against 0 here because
- COUNT gets only incremented after returning form this
+ COUNT gets only incremented after returning from this
function. */
if (!stats->count)
*fpr = fingerprint_from_pk (pk, NULL, fpr_len);
diff --git a/g10/keylist.c b/g10/keylist.c
index d71bf4f9f..0812d9c9b 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1116,6 +1116,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr,
if (node->pkt->pkttype == PKT_USER_ID)
{
PKT_user_id *uid = node->pkt->pkt.user_id;
+ int indent;
if ((uid->is_expired || uid->is_revoked)
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
@@ -1133,25 +1134,46 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr,
|| (opt.list_options & LIST_SHOW_UID_VALIDITY))
{
const char *validity;
- int indent;
validity = uid_trust_string_fixed (pk, uid);
- indent =
- (keystrlen () + (opt.legacy_list_mode? 9:11)) -
- atoi (uid_trust_string_fixed (NULL, NULL));
-
+ indent = ((keystrlen () + (opt.legacy_list_mode? 9:11))
+ - atoi (uid_trust_string_fixed (NULL, NULL)));
if (indent < 0 || indent > 40)
indent = 0;
es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
}
else
- es_fprintf (es_stdout, "uid%*s",
- (int) keystrlen () + (opt.legacy_list_mode? 10:12), "");
+ {
+ indent = keystrlen () + (opt.legacy_list_mode? 10:12);
+ es_fprintf (es_stdout, "uid%*s", indent, "");
+ }
print_utf8_buffer (es_stdout, uid->name, uid->len);
es_putc ('\n', es_stdout);
+ if (opt.with_wkd_hash)
+ {
+ char *mbox, *hash, *p;
+ char hashbuf[32];
+
+ mbox = mailbox_from_userid (uid->name);
+ if (mbox && (p = strchr (mbox, '@')))
+ {
+ *p++ = 0;
+ gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
+ mbox, strlen (mbox));
+ hash = zb32_encode (hashbuf, 8*20);
+ if (hash)
+ {
+ es_fprintf (es_stdout, " %*s%s@%s\n",
+ indent, "", hash, p);
+ xfree (hash);
+ }
+ }
+ xfree (mbox);
+ }
+
if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
show_photos (uid->attribs, uid->numattribs, pk, uid);
}
diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h
index 6f6f43070..f57dcaa53 100644
--- a/g10/keyserver-internal.h
+++ b/g10/keyserver-internal.h
@@ -45,6 +45,8 @@ int keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
unsigned char **fpr,size_t *fpr_len);
gpg_error_t keyserver_import_pka (ctrl_t ctrl, const char *name,
unsigned char **fpr,size_t *fpr_len);
+gpg_error_t keyserver_import_wkd (ctrl_t ctrl, const char *name,
+ unsigned char **fpr, size_t *fpr_len);
int keyserver_import_name (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
diff --git a/g10/keyserver.c b/g10/keyserver.c
index e9ccb5893..95ef441ef 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -2004,6 +2004,39 @@ keyserver_import_pka (ctrl_t ctrl, const char *name,
}
+/* Import a key using the Web Key Directory protocol. */
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+ unsigned char **fpr, size_t *fpr_len)
+{
+ gpg_error_t err;
+ estream_t key;
+
+ err = gpg_dirmngr_wkd_get (ctrl, name, &key);
+ if (err)
+ ;
+ else if (key)
+ {
+ int armor_status = opt.no_armor;
+
+ /* Keys returned via WKD are in binary format. */
+ opt.no_armor = 1;
+
+ err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
+ (opt.keyserver_options.import_options
+ | IMPORT_NO_SECKEY),
+ NULL, NULL);
+
+ opt.no_armor = armor_status;
+
+ es_fclose (key);
+ key = NULL;
+ }
+
+ return err;
+}
+
+
/* Import a key by name using LDAP */
int
keyserver_import_ldap (ctrl_t ctrl,
diff --git a/g10/options.h b/g10/options.h
index 1407b2f57..0de04188d 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -73,6 +73,7 @@ struct
int with_fingerprint; /* Option --with-fingerprint active. */
int with_keygrip; /* Option --with-keygrip active. */
int with_secret; /* Option --with-secret active. */
+ int with_wkd_hash; /* Option --with-wkd-hash. */
int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */
int print_pka_records;
@@ -245,6 +246,7 @@ struct
AKL_CERT,
AKL_PKA,
AKL_DANE,
+ AKL_WKD,
AKL_LDAP,
AKL_KEYSERVER,
AKL_SPEC
diff --git a/g10/test-stubs.c b/g10/test-stubs.c
index 74b6bf76d..2edae1808 100644
--- a/g10/test-stubs.c
+++ b/g10/test-stubs.c
@@ -186,6 +186,17 @@ keyserver_import_pka (const char *name,unsigned char *fpr)
return -1;
}
+gpg_error_t
+keyserver_import_wkd (ctrl_t ctrl, const char *name,
+ unsigned char **fpr, size_t *fpr_len)
+{
+ (void)ctrl;
+ (void)name;
+ (void)fpr;
+ (void)fpr_len;
+ return GPG_ERR_BUG;
+}
+
int
keyserver_import_name (const char *name,struct keyserver_spec *spec)
{