diff options
author | Werner Koch <wk@gnupg.org> | 2016-04-27 08:34:29 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-04-27 08:34:29 +0200 |
commit | 87de9e19edf0311ca0342e15ef44ebe40e32861e (patch) | |
tree | 20f8f2c384040344ece6e00c64036c666dd4a843 /g10 | |
parent | dirmngr: Add experimental command WKD_GET. (diff) | |
download | gnupg2-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.c | 61 | ||||
-rw-r--r-- | g10/call-dirmngr.h | 2 | ||||
-rw-r--r-- | g10/getkey.c | 34 | ||||
-rw-r--r-- | g10/gpg.c | 6 | ||||
-rw-r--r-- | g10/gpgv.c | 11 | ||||
-rw-r--r-- | g10/import.c | 2 | ||||
-rw-r--r-- | g10/keylist.c | 36 | ||||
-rw-r--r-- | g10/keyserver-internal.h | 2 | ||||
-rw-r--r-- | g10/keyserver.c | 33 | ||||
-rw-r--r-- | g10/options.h | 2 | ||||
-rw-r--r-- | g10/test-stubs.c | 11 |
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 @@ -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) { |