From 256a280c51f9ea862e4bfb0bb530c2a96f9088f9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 22 Oct 2018 20:13:08 +0200 Subject: dirmngr: Prepare for updated WKD specs with ?l= param * dirmngr/server.c (proc_wkd_get): Tack the raw local address to the request. -- We append the raw non-canonicalized local address part to the hash. Servers who serve the requests from static files will ignore the parameters and a test with posteo shows that also services using a database ignore the parameter. The general idea is that service providers may use their own canonicalization rules. The problem is that we currently filter the returned key for the full mail address and thus we will never see a key if the service did a different canonicalization than we. So consider this to be an experiment. Signed-off-by: Werner Koch --- dirmngr/server.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'dirmngr/server.c') diff --git a/dirmngr/server.c b/dirmngr/server.c index 2519fd601..05a530bce 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -957,19 +957,28 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) } else { - uri = strconcat ("https://", - domain, - portstr, - "/.well-known/openpgpkey/hu/", - encodedhash, - NULL); - no_log = 1; - if (uri) + char *escapedmbox; + + escapedmbox = http_escape_string (mbox, "%;?&="); + if (escapedmbox) { - err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s", - domain, portstr); - if (err) - goto leave; + uri = strconcat ("https://", + domain, + portstr, + "/.well-known/openpgpkey/hu/", + encodedhash, + "?l=", + escapedmbox, + NULL); + xfree (escapedmbox); + no_log = 1; + if (uri) + { + err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s", + domain, portstr); + if (err) + goto leave; + } } } if (!uri) -- cgit From 6b9f772914624cc673ba26d49b6e3adc32dd7e0a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 12 Nov 2018 07:44:33 +0100 Subject: common: Prepare for parsing mail sub-addresses. * common/mbox-util.c (mailbox_from_userid): Add arg subaddress and implement. Change all callers to pass false for it. * common/t-mbox-util.c (run_mbox_no_sub_test): New. (run_filter): Add arg no_sub. (main): Call new test and add option --no-sub. -- Some stats: In the about 5300000 keys on the SKS servers we found 3055 unique mailboxes with a '+' in it. After removing leading and trailing '+' as well as multiple '+' (e.g. "c++" or "foo+bar+baz") 2697 were left which seem to be valid sub-addresses. To filter mailboxes out from a line delimited list with user-ids (e.g. an SQL output), the command t-mbox-util --verbose --filter can be used; to output w/o sub-addresses add --no-sub. GnuPG-bug-id: 4200 Signed-off-by: Werner Koch --- common/mbox-util.c | 32 ++++++++++++++--- common/mbox-util.h | 2 +- common/t-mbox-util.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++--- dirmngr/server.c | 4 +-- g10/export.c | 2 +- g10/getkey.c | 2 +- g10/gpg.c | 2 +- g10/import.c | 2 +- g10/keylist.c | 2 +- g10/keyserver.c | 2 +- g10/sign.c | 3 +- g10/tofu.c | 2 +- g10/trustdb.c | 2 +- tools/gpg-wks-client.c | 8 ++--- tools/gpg-wks-server.c | 4 +-- tools/wks-util.c | 2 +- 16 files changed, 139 insertions(+), 27 deletions(-) (limited to 'dirmngr/server.c') diff --git a/common/mbox-util.c b/common/mbox-util.c index 76255ba38..a9086a3f5 100644 --- a/common/mbox-util.c +++ b/common/mbox-util.c @@ -173,11 +173,12 @@ is_valid_mailbox (const char *name) /* Return the mailbox (local-part@domain) form a standard user id. - All plain ASCII characters in the result are converted to - lowercase. Caller must free the result. Returns NULL if no valid - mailbox was found (or we are out of memory). */ + * All plain ASCII characters in the result are converted to + * lowercase. If SUBADDRESS is 1, '+' denoted sub-addresses are not + * included in the result. Caller must free the result. Returns NULL + * if no valid mailbox was found (or we are out of memory). */ char * -mailbox_from_userid (const char *userid) +mailbox_from_userid (const char *userid, int subaddress) { const char *s, *s_end; size_t len; @@ -226,6 +227,29 @@ mailbox_from_userid (const char *userid) else errno = EINVAL; + if (result && subaddress == 1) + { + char *atsign, *plus; + + if ((atsign = strchr (result, '@'))) + { + /* We consider a subaddress only if there is a single '+' + * in the local part and the '+' is not the first or last + * character. */ + *atsign = 0; + if ((plus = strchr (result, '+')) + && !strchr (plus+1, '+') + && result != plus + && plus[1] ) + { + *atsign = '@'; + memmove (plus, atsign, strlen (atsign)+1); + } + else + *atsign = '@'; + } + } + return result? ascii_strlwr (result): NULL; } diff --git a/common/mbox-util.h b/common/mbox-util.h index 7355ceef5..10ff2c4a0 100644 --- a/common/mbox-util.h +++ b/common/mbox-util.h @@ -22,7 +22,7 @@ int has_invalid_email_chars (const void *buffer, size_t length); int is_valid_mailbox (const char *name); int is_valid_mailbox_mem (const void *buffer, size_t length); -char *mailbox_from_userid (const char *userid); +char *mailbox_from_userid (const char *userid, int subaddress); int is_valid_user_id (const char *uid); int is_valid_domain_name (const char *string); diff --git a/common/t-mbox-util.c b/common/t-mbox-util.c index e9cf41215..ae717f96f 100644 --- a/common/t-mbox-util.c +++ b/common/t-mbox-util.c @@ -83,7 +83,86 @@ run_mbox_test (void) for (idx=0; testtbl[idx].userid; idx++) { - char *mbox = mailbox_from_userid (testtbl[idx].userid); + char *mbox = mailbox_from_userid (testtbl[idx].userid, 0); + + if (!testtbl[idx].mbox) + { + if (mbox) + fail (idx); + } + else if (!mbox) + fail (idx); + else if (strcmp (mbox, testtbl[idx].mbox)) + fail (idx); + + xfree (mbox); + } +} + + +static void +run_mbox_no_sub_test (void) +{ + static struct + { + const char *userid; + const char *mbox; + } testtbl[] = + { + { "foo+bar@example.org", "foo@example.org" }, + { "Werner Koch ", "wk@gnupg.org" }, + { "", "wk@gnupg.org" }, + { "wk@gnupg.org", "wk@gnupg.org" }, + { "wk@gnupg.org ", NULL }, + { " wk@gnupg.org", NULL }, + { "Werner Koch (test) ", "wk@gnupg.org" }, + { "Werner Koch (test)", "wk@gnupg.org" }, + { "Werner Koch ", NULL }, + { "Werner Koch ", NULL }, + { "", "foo@example.org" }, + { "", "foo.@example.org" }, + { "<.foo.@example.org>", ".foo.@example.org" }, + { "", "foo..@example.org" }, + { "", "foo..bar@example.org" }, + { "", NULL }, + { "", NULL }, + { "", NULL }, + { "<@example.org>", NULL }, + { "", NULL }, + { "<@foo@example.org>", NULL }, + { " ()", "foo@example.org" }, + { " ()", "fo()o@example.org" }, + { " ()", "fo()o@example.org" }, + { "fo()o@example.org", NULL}, + { "Mr. Foo ", "foo@example.org"}, + { "foo+bar@example.org", "foo@example.org" }, + { "foo++bar@example.org", "foo++bar@example.org" }, + { "foo++@example.org", "foo++@example.org" }, + { "foo+@example.org", "foo+@example.org" }, + { "+foo@example.org", "+foo@example.org" }, + { "++foo@example.org", "++foo@example.org" }, + { "+foo+@example.org", "+foo+@example.org" }, + { "+@example.org", "+@example.org" }, + { "++@example.org", "++@example.org" }, + { "foo+b@example.org", "foo@example.org" }, + { "foo+ba@example.org", "foo@example.org" }, + { "foo+bar@example.org", "foo@example.org" }, + { "foo+barb@example.org", "foo@example.org" }, + { "foo+barba@example.org", "foo@example.org" }, + { "f+b@example.org", "f@example.org" }, + { "fo+b@example.org", "fo@example.org" }, + + { NULL, NULL } + }; + int idx; + + for (idx=0; testtbl[idx].userid; idx++) + { + char *mbox = mailbox_from_userid (testtbl[idx].userid, 1); if (!testtbl[idx].mbox) { @@ -151,7 +230,7 @@ run_dns_test (void) static void -run_filter (void) +run_filter (int no_sub) { char buf[4096]; int c; @@ -172,7 +251,7 @@ run_filter (void) } count1++; trim_spaces (buf); - mbox = mailbox_from_userid (buf); + mbox = mailbox_from_userid (buf, no_sub); if (mbox) { printf ("%s\n", mbox); @@ -190,6 +269,7 @@ main (int argc, char **argv) { int last_argc = -1; int opt_filter = 0; + int opt_no_sub = 0; if (argc) { argc--; argv++; } @@ -208,6 +288,7 @@ main (int argc, char **argv) " --verbose Print timings etc.\n" " --debug Flyswatter\n" " --filter Filter mboxes from input lines\n" + " --no-sub Ignore '+'-sub-addresses\n" , stdout); exit (0); } @@ -227,6 +308,11 @@ main (int argc, char **argv) opt_filter = 1; argc--; argv++; } + else if (!strcmp (*argv, "--no-sub")) + { + opt_no_sub = 1; + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) { fprintf (stderr, PGM ": unknown option '%s'\n", *argv); @@ -235,10 +321,11 @@ main (int argc, char **argv) } if (opt_filter) - run_filter (); + run_filter (opt_no_sub); else { run_mbox_test (); + run_mbox_no_sub_test (); run_dns_test (); } diff --git a/dirmngr/server.c b/dirmngr/server.c index 05a530bce..a21e1abb6 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -731,7 +731,7 @@ cmd_dns_cert (assuan_context_t ctx, char *line) /* We lowercase ascii characters but the DANE I-D does not allow this. FIXME: Check after the release of the RFC whether to change this. */ - mbox = mailbox_from_userid (line); + mbox = mailbox_from_userid (line, 0); if (!mbox || !(domain = strchr (mbox, '@'))) { err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id"); @@ -855,7 +855,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) line = skip_options (line); is_wkd_query = !(opt_policy_flags || opt_submission_addr); - mbox = mailbox_from_userid (line); + mbox = mailbox_from_userid (line, 0); if (!mbox || !(domain = strchr (mbox, '@'))) { err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id"); diff --git a/g10/export.c b/g10/export.c index 9477b7526..d53be99fe 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1469,7 +1469,7 @@ print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk, continue; xfree (mbox); - mbox = mailbox_from_userid (uid->name); + mbox = mailbox_from_userid (uid->name, 0); if (!mbox) continue; diff --git a/g10/getkey.c b/g10/getkey.c index 75ce9cb38..c776a6100 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1373,7 +1373,7 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old, n; n = find_next_kbnode (n, PKT_USER_ID)) { PKT_user_id *uid = n->pkt->pkt.user_id; - char *mbox = mailbox_from_userid (uid->name); + char *mbox = mailbox_from_userid (uid->name, 0); int match = mbox ? strcasecmp (name, mbox) == 0 : 0; xfree (mbox); diff --git a/g10/gpg.c b/g10/gpg.c index aeb9c6fc0..110289243 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -3130,7 +3130,7 @@ main (int argc, char **argv) break; case oSender: { - char *mbox = mailbox_from_userid (pargs.r.ret_str); + char *mbox = mailbox_from_userid (pargs.r.ret_str, 0); if (!mbox) log_error (_("\"%s\" is not a proper mail address\n"), pargs.r.ret_str); diff --git a/g10/import.c b/g10/import.c index 23258a0a7..8ea5144b5 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1264,7 +1264,7 @@ impex_filter_getval (void *cookie, const char *propname) { if (!uid->mbox) { - uid->mbox = mailbox_from_userid (uid->name); + uid->mbox = mailbox_from_userid (uid->name, 0); } result = uid->mbox; } diff --git a/g10/keylist.c b/g10/keylist.c index 8b7da76ee..793f7dacd 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1020,7 +1020,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, char *mbox, *hash, *p; char hashbuf[32]; - mbox = mailbox_from_userid (uid->name); + mbox = mailbox_from_userid (uid->name, 0); if (mbox && (p = strchr (mbox, '@'))) { *p++ = 0; diff --git a/g10/keyserver.c b/g10/keyserver.c index a8c222d3f..44870a610 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -2053,7 +2053,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick, /* We want to work on the mbox. That is what dirmngr will do anyway * and we need the mbox for the import filter anyway. */ - mbox = mailbox_from_userid (name); + mbox = mailbox_from_userid (name, 0); if (!mbox) { err = gpg_error_from_syserror (); diff --git a/g10/sign.c b/g10/sign.c index df888136f..b2d1c1826 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -153,7 +153,8 @@ mk_notation_policy_etc (PKT_signature *sig, char *mbox; /* For now we use the uid which was used to locate the key. */ - if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name))) + if (pksk->user_id + && (mbox = mailbox_from_userid (pksk->user_id->name, 0))) { if (DBG_LOOKUP) log_debug ("setting Signer's UID to '%s'\n", mbox); diff --git a/g10/tofu.c b/g10/tofu.c index 762b19b7a..44f354512 100644 --- a/g10/tofu.c +++ b/g10/tofu.c @@ -3292,7 +3292,7 @@ show_warning (const char *fingerprint, strlist_t user_id_list) static char * email_from_user_id (const char *user_id) { - char *email = mailbox_from_userid (user_id); + char *email = mailbox_from_userid (user_id, 0); if (! email) { /* Hmm, no email address was provided or we are out of core. Just diff --git a/g10/trustdb.c b/g10/trustdb.c index c46dc50c8..a230a6c03 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1131,7 +1131,7 @@ tdb_get_validity_core (ctrl_t ctrl, if (sig && sig->signers_uid) /* Make sure the UID matches. */ { - char *email = mailbox_from_userid (user_id->name); + char *email = mailbox_from_userid (user_id->name, 0); if (!email || !*email || strcmp (sig->signers_uid, email) != 0) { if (DBG_TRUST) diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index bf6b119e0..0be5ea89b 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -627,11 +627,11 @@ command_supported (char *userid) if (!strchr (userid, '@')) { char *tmp = xstrconcat ("foo@", userid, NULL); - addrspec = mailbox_from_userid (tmp); + addrspec = mailbox_from_userid (tmp, 0); xfree (tmp); } else - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), userid); @@ -694,7 +694,7 @@ command_check (char *userid) uidinfo_list_t sl; int found = 0; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), userid); @@ -805,7 +805,7 @@ command_send (const char *fingerprint, const char *userid) goto leave; } - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error (_("\"%s\" is not a proper mail address\n"), userid); diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 24b331262..1b533124a 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -2020,7 +2020,7 @@ command_install_key (const char *fname, const char *userid) char *huname = NULL; int any; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { log_error ("\"%s\" is not a proper mail address\n", userid); @@ -2153,7 +2153,7 @@ fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) if (r_addrspec) *r_addrspec = NULL; - addrspec = mailbox_from_userid (userid); + addrspec = mailbox_from_userid (userid, 0); if (!addrspec) { if (opt.verbose) diff --git a/tools/wks-util.c b/tools/wks-util.c index 729098a02..cf80a25bc 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -104,7 +104,7 @@ append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created) strcpy (sl->uid, uid); sl->created = created; - sl->mbox = mailbox_from_userid (uid); + sl->mbox = mailbox_from_userid (uid, 0); sl->next = NULL; if (!*list) *list = sl; -- cgit From 678e4706ee614a6b7e543e2a80072d75405dd4db Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Wed, 24 Oct 2018 10:40:42 +0200 Subject: dirmngr: Add FLUSHCRLs command Summary: * dirmngr/crlcache.c (crl_cache_flush): Also deinit the cache. * dirmngr/server.c (hlp_flushcrls, cmd_flushcrls): New. (register_commands): Add FLUSHCRLS. -- This allows it to flush the CRL cache of a running dirmngr server. This can be useful to debug / analyze CRL issues. GnuPG-Bug-Id: T3967 Differential Revision: https://dev.gnupg.org/D469 Signed-off-by: Andre Heinecke (cherry picked from commit 00321a025f90990a71b60b4689ede1f38fbde347) --- dirmngr/crlcache.c | 4 +++- dirmngr/server.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'dirmngr/server.c') diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c index a2867be54..c9e5ca68f 100644 --- a/dirmngr/crlcache.c +++ b/dirmngr/crlcache.c @@ -1250,13 +1250,15 @@ crl_cache_deinit (void) } -/* Delete the cache from disk. Return 0 on success.*/ +/* Delete the cache from disk and memory. Return 0 on success.*/ int crl_cache_flush (void) { int rc; + crl_cache_deinit (); rc = cleanup_cache_dir (0)? -1 : 0; + crl_cache_init (); return rc; } diff --git a/dirmngr/server.c b/dirmngr/server.c index a21e1abb6..ac2562031 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -2689,6 +2689,20 @@ cmd_reloaddirmngr (assuan_context_t ctx, char *line) } +static const char hlp_flushcrls[] = + "FLUSHCRLS\n" + "\n" + "Remove all cached CRLs from memory and\n" + "the file system."; +static gpg_error_t +cmd_flushcrls (assuan_context_t ctx, char *line) +{ + (void)line; + + return leave_cmd (ctx, crl_cache_flush () ? GPG_ERR_GENERAL : 0); +} + + /* Tell the assuan library about our commands. */ static int @@ -2719,6 +2733,7 @@ register_commands (assuan_context_t ctx) { "LOADSWDB", cmd_loadswdb, hlp_loadswdb }, { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr }, { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr }, + { "FLUSHCRLS", cmd_flushcrls, hlp_flushcrls }, { NULL, NULL } }; int i, j, rc; -- cgit From 914fa3be22bf8848a97a7dd405a040d6ef31e2fd Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 13 Nov 2018 11:35:39 +0100 Subject: dirmngr: Support the new WKD draft with the openpgpkey subdomain. * dirmngr/server.c (proc_wkd_get): Implement new openpgpkey subdomain method. Signed-off-by: Werner Koch --- dirmngr/dns-stuff.c | 21 +++++++++-------- dirmngr/domaininfo.c | 2 +- dirmngr/server.c | 64 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 68 insertions(+), 19 deletions(-) (limited to 'dirmngr/server.c') diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c index f86ccb0ae..7aa07c716 100644 --- a/dirmngr/dns-stuff.c +++ b/dirmngr/dns-stuff.c @@ -1056,16 +1056,17 @@ resolve_name_standard (ctrl_t ctrl, const char *name, unsigned short port, /* This a wrapper around getaddrinfo with slightly different semantics. - NAME is the name to resolve. - PORT is the requested port or 0. - WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4. - WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM. - - On success the result is stored in a linked list with the head - stored at the address R_AI; the caller must call gpg_addrinfo_free - on this. If R_CANONNAME is not NULL the official name of the host - is stored there as a malloced string; if that name is not available - NULL is stored. */ + * NAME is the name to resolve. + * PORT is the requested port or 0. + * WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4. + * WANT_SOCKETTYPE is either 0 for any socket type + * or SOCK_STREAM or SOCK_DGRAM. + * + * On success the result is stored in a linked list with the head + * stored at the address R_AI; the caller must call free_dns_addrinfo + * on this. If R_CANONNAME is not NULL the official name of the host + * is stored there as a malloced string; if that name is not available + * NULL is stored. */ gpg_error_t resolve_dns_name (ctrl_t ctrl, const char *name, unsigned short port, int want_family, int want_socktype, diff --git a/dirmngr/domaininfo.c b/dirmngr/domaininfo.c index a2effffef..f6263b06d 100644 --- a/dirmngr/domaininfo.c +++ b/dirmngr/domaininfo.c @@ -119,7 +119,7 @@ domaininfo_print_stats (void) } -/* Return true if DOMAIN definitely does not support WKD. Noet that +/* Return true if DOMAIN definitely does not support WKD. Note that * DOMAIN is expected to be lowercase. */ int domaininfo_is_wkd_not_supported (const char *domain) diff --git a/dirmngr/server.c b/dirmngr/server.c index ac2562031..4a242539b 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -837,8 +837,11 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) gpg_error_t err = 0; char *mbox = NULL; char *domainbuf = NULL; - char *domain; /* Points to mbox or domainbuf. */ - char *domain_orig;/* Points to mbox. */ + char *domain; /* Points to mbox or domainbuf. This is used to + * connect to the host. */ + char *domain_orig;/* Points to mbox. This is the used for the + * query; i.e. the domain part of the + * addrspec. */ char sha1buf[20]; char *uri = NULL; char *encodedhash = NULL; @@ -847,6 +850,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) int is_wkd_query; /* True if this is a real WKD query. */ int no_log = 0; char portstr[20] = { 0 }; + int subdomain_mode = 0; opt_submission_addr = has_option (line, "--submission-address"); opt_policy_flags = has_option (line, "--policy-flags"); @@ -864,7 +868,8 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) *domain++ = 0; domain_orig = domain; - /* First check whether we already know that the domain does not + + /* Let's check whether we already know that the domain does not * support WKD. */ if (is_wkd_query) { @@ -875,8 +880,41 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) } } - /* Check for SRV records. */ - if (1) + + /* First try the new "openpgp" subdomain. We check that the domain + * is valid because it is later used as an unescaped filename part + * of the URI. */ + if (is_valid_domain_name (domain_orig)) + { + dns_addrinfo_t aibuf; + + domainbuf = strconcat ( "openpgpkey.", domain_orig, NULL); + if (!domainbuf) + { + err = gpg_error_from_syserror (); + goto leave; + } + + /* FIXME: We should put a cache into dns-stuff because the same + * query (with a different port and socket type, though) will be + * done later by http function. */ + err = resolve_dns_name (ctrl, domainbuf, 0, 0, 0, &aibuf, NULL); + if (err) + { + err = 0; + xfree (domainbuf); + domainbuf = NULL; + } + else /* Got a subdomain. */ + { + free_dns_addrinfo (aibuf); + subdomain_mode = 1; + domain = domainbuf; + } + } + + /* Check for SRV records unless we have a subdomain. */ + if (!subdomain_mode) { struct srventry *srvs; unsigned int srvscount; @@ -931,6 +969,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) xfree (srvs); } + /* Prepare the hash of the local part. */ gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox)); encodedhash = zb32_encode (sha1buf, 8*20); if (!encodedhash) @@ -944,7 +983,10 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) uri = strconcat ("https://", domain, portstr, - "/.well-known/openpgpkey/submission-address", + "/.well-known/openpgpkey/", + subdomain_mode? domain_orig : "", + subdomain_mode? "/" : "", + "submission-address", NULL); } else if (opt_policy_flags) @@ -952,7 +994,10 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) uri = strconcat ("https://", domain, portstr, - "/.well-known/openpgpkey/policy", + "/.well-known/openpgpkey/", + subdomain_mode? domain_orig : "", + subdomain_mode? "/" : "", + "policy", NULL); } else @@ -965,7 +1010,10 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line) uri = strconcat ("https://", domain, portstr, - "/.well-known/openpgpkey/hu/", + "/.well-known/openpgpkey/", + subdomain_mode? domain_orig : "", + subdomain_mode? "/" : "", + "hu/", encodedhash, "?l=", escapedmbox, -- cgit