1 /* ks-engine-hkp.c - HKP keyserver engine
2 * Copyright (C) 2011, 2012 Free Software Foundation, Inc.
3 * Copyright (C) 2011, 2012, 2014 Werner Koch
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
27 #ifdef HAVE_W32_SYSTEM
28 # ifdef HAVE_WINSOCK2_H
29 # include <winsock2.h>
32 #else /*!HAVE_W32_SYSTEM*/
33 # include <sys/types.h>
34 # include <sys/socket.h>
36 #endif /*!HAVE_W32_SYSTEM*/
41 #include "../common/userids.h"
42 #include "dns-stuff.h"
43 #include "ks-engine.h"
45 /* Substitutes for missing Mingw macro. The EAI_SYSTEM mechanism
46 seems not to be available (probably because there is only one set
47 of error codes anyway). For now we use WSAEINVAL. */
49 # define EAI_OVERFLOW EAI_FAIL
51 #ifdef HAVE_W32_SYSTEM
53 # define EAI_SYSTEM WSAEINVAL
58 /* Number of seconds after a host is marked as resurrected. */
59 #define RESURRECT_INTERVAL (3600+1800) /* 1.5 hours */
61 /* To match the behaviour of our old gpgkeys helper code we escape
62 more characters than actually needed. */
63 #define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
65 /* How many redirections do we allow. */
66 #define MAX_REDIRECTS 2
68 /* Number of retries done for a dead host etc. */
69 #define SEND_REQUEST_RETRIES 3
71 /* Number of retries done in case of transient errors. */
72 #define SEND_REQUEST_EXTRA_RETRIES 5
75 enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
77 /* Objects used to maintain information about hosts. */
79 typedef struct hostinfo_s *hostinfo_t;
82 time_t lastfail; /* Time we tried to connect and failed. */
83 time_t lastused; /* Time of last use. */
84 int *pool; /* An array with indices into HOSTTABLE or NULL
85 if NAME is not a pool name. */
86 size_t pool_len; /* Length of POOL. */
87 size_t pool_size; /* Allocated size of POOL. */
88 #define MAX_POOL_SIZE 128
89 int poolidx; /* Index into POOL with the used host. -1 if not set. */
90 unsigned int v4:1; /* Host supports AF_INET. */
91 unsigned int v6:1; /* Host supports AF_INET6. */
92 unsigned int onion:1;/* NAME is an onion (Tor HS) address. */
93 unsigned int dead:1; /* Host is currently unresponsive. */
94 unsigned int iporname_valid:1; /* The field IPORNAME below is valid */
95 /* (but may be NULL) */
96 unsigned int did_a_lookup:1; /* Have we done an A lookup yet? */
97 unsigned int did_srv_lookup:2; /* One bit per protocol indicating
98 whether we already did a SRV
100 time_t died_at; /* The time the host was marked dead. If this is
101 0 the host has been manually marked dead. */
102 char *cname; /* Canonical name of the host. Only set if this
103 is a pool or NAME has a numerical IP address. */
104 char *iporname; /* Numeric IP address or name for printing. */
105 unsigned short port[KS_PROTOCOL_MAX];
106 /* The port used by the host for all protocols, 0
108 char name[1]; /* The hostname. */
112 /* An array of hostinfo_t for all hosts requested by the caller or
113 resolved from a pool name and its allocated size.*/
114 static hostinfo_t *hosttable;
115 static int hosttable_size;
116 /* A mutex used to serialize access to the hosttable. */
117 static npth_mutex_t hosttable_lock;
119 /* The number of host slots we initially allocate for HOSTTABLE. */
120 #define INITIAL_HOSTTABLE_SIZE 50
123 /* Create a new hostinfo object, fill in NAME and put it into
124 HOSTTABLE. Return the index into hosttable on success or -1 on
127 create_new_hostinfo (const char *name)
129 hostinfo_t hi, *newtable;
133 hi = xtrymalloc (sizeof *hi + strlen (name));
136 strcpy (hi->name, name);
141 hi->lastused = (time_t)(-1);
142 hi->lastfail = (time_t)(-1);
147 hi->did_a_lookup = 0;
148 hi->did_srv_lookup = 0;
149 hi->iporname_valid = 0;
153 hi->port[KS_PROTOCOL_HKP] = 0;
154 hi->port[KS_PROTOCOL_HKPS] = 0;
156 /* Add it to the hosttable. */
157 for (idx=0; idx < hosttable_size; idx++)
163 /* Need to extend the hosttable. */
164 newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
165 newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
171 hosttable = newtable;
172 idx = hosttable_size;
173 hosttable_size = newsize;
175 hosttable[idx++] = hi;
176 while (idx < hosttable_size)
177 hosttable[idx++] = NULL;
183 /* Find the host NAME in our table. Return the index into the
184 hosttable or -1 if not found. */
186 find_hostinfo (const char *name)
190 for (idx=0; idx < hosttable_size; idx++)
191 if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
198 sort_hostpool (const void *xa, const void *xb)
203 assert (a >= 0 && a < hosttable_size);
204 assert (b >= 0 && b < hosttable_size);
205 assert (hosttable[a]);
206 assert (hosttable[b]);
208 return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
212 /* Return true if the host with the hosttable index TBLIDX is in HI->pool. */
214 host_in_pool_p (hostinfo_t hi, int tblidx)
218 for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
219 if (pidx == tblidx && hosttable[pidx])
225 /* Select a random host. Consult HI->pool which indices into the global
226 hosttable. Returns index into HI->pool or -1 if no host could be
229 select_random_host (hostinfo_t hi)
235 /* CHECKTHIS(); See */
236 /* https://sources.debian.org/patches/gnupg2/2.2.20-1/dirmngr-idling/dirmngr-hkp-Avoid-potential-race-condition-when-some.patch/ */
238 /* We create a new table so that we randomly select only from
239 currently alive hosts. */
240 for (idx = 0, tblsize = 0;
241 idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
243 if (hosttable[pidx] && !hosttable[pidx]->dead)
246 return -1; /* No hosts. */
248 tbl = xtrymalloc (tblsize * sizeof *tbl);
251 for (idx = 0, tblsize = 0;
252 idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
254 if (hosttable[pidx] && !hosttable[pidx]->dead)
255 tbl[tblsize++] = pidx;
257 if (tblsize == 1) /* Save a get_uint_nonce. */
260 pidx = tbl[get_uint_nonce () % tblsize];
267 /* Figure out if a set of DNS records looks like a pool. */
269 arecords_is_pool (dns_addrinfo_t aibuf)
275 for (ai = aibuf; ai; ai = ai->next)
277 if (ai->family == AF_INET6)
279 else if (ai->family == AF_INET)
283 return n_v6 > 1 || n_v4 > 1;
287 /* Print a warning iff Tor is not running but Tor has been requested.
288 * Also return true if it is not running. */
290 tor_not_running_p (ctrl_t ctrl)
294 if (!dirmngr_use_tor ())
297 sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
298 if (sock != ASSUAN_INVALID_FD)
300 assuan_sock_close (sock);
304 log_info ("(it seems Tor is not running)\n");
305 dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
306 "Tor is enabled but the local Tor daemon"
307 " seems to be down", NULL);
312 /* Add the host AI under the NAME into the HOSTTABLE. If PORT is not
313 zero, it specifies which port to use to talk to the host for
314 PROTOCOL. If NAME specifies a pool (as indicated by IS_POOL),
315 update the given reference table accordingly. */
317 add_host (ctrl_t ctrl, const char *name, int is_pool,
318 const dns_addrinfo_t ai,
319 enum ks_protocol protocol, unsigned short port)
327 idx = find_hostinfo (name);
328 host = hosttable[idx];
332 /* For a pool immediately convert the address to a string. */
333 tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
334 (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
336 else if (!is_ip_address (name))
338 /* This is a hostname. Use the name as given without going
339 * through resolve_dns_addr. */
340 tmphost = xtrystrdup (name);
342 tmperr = gpg_error_from_syserror ();
348 /* Do a PTR lookup on AI. If a name was not found the function
349 * returns the numeric address (with brackets). */
350 tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
351 DNS_WITHBRACKET, &tmphost);
356 log_info ("resolve_dns_addr failed while checking '%s': %s\n",
357 name, gpg_strerror (tmperr));
359 else if (host->pool_len + 1 >= MAX_POOL_SIZE)
361 log_error ("resolve_dns_addr for '%s': '%s'"
362 " [index table full - ignored]\n", name, tmphost);
366 if (!is_pool && is_ip_address (name))
367 /* Update the original entry. */
370 tmpidx = find_hostinfo (tmphost);
371 log_info ("resolve_dns_addr for '%s': '%s'%s\n",
373 tmpidx == -1? "" : " [already known]");
375 if (tmpidx == -1) /* Create a new entry. */
376 tmpidx = create_new_hostinfo (tmphost);
380 log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
381 name, strerror (errno), tmphost);
383 else /* Set or update the entry. */
386 hosttable[tmpidx]->port[protocol] = port;
388 if (ai->family == AF_INET6)
390 hosttable[tmpidx]->v6 = 1;
392 else if (ai->family == AF_INET)
394 hosttable[tmpidx]->v4 = 1;
399 /* If we updated the main entry, we're done. */
403 /* If we updated an existing entry, we're done. */
404 for (i = 0; i < host->pool_len; i++)
405 if (host->pool[i] == tmpidx)
408 /* Otherwise, we need to add it to the pool. Check if there
410 if (host->pool_len + 1 > host->pool_size)
415 if (host->pool_size == 0)
418 new_size = host->pool_size * 2;
420 new_pool = xtryrealloc (host->pool,
421 new_size * sizeof *new_pool);
423 if (new_pool == NULL)
426 host->pool = new_pool;
427 host->pool_size = new_size;
430 /* Finally, add it. */
431 log_assert (host->pool_len < host->pool_size);
432 host->pool[host->pool_len++] = tmpidx;
440 /* Sort the pool of the given hostinfo HI. */
442 hostinfo_sort_pool (hostinfo_t hi)
444 qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
447 /* Map the host name NAME to the actual to be used host name. This
448 * allows us to manage round robin DNS names. We use our own strategy
449 * to choose one of the hosts. For example we skip those hosts which
450 * failed for some time and we stick to one host for a time
451 * independent of DNS retry times. If FORCE_RESELECT is true a new
452 * host is always selected. If SRVTAG is NULL no service record
453 * lookup will be done, if it is set that service name is used. The
454 * selected host is stored as a malloced string at R_HOST; on error
455 * NULL is stored. If we know the port used by the selected host from
456 * a service record, a string representation is written to R_PORTSTR,
457 * otherwise it is left untouched. If R_HTTPFLAGS is not NULL it will
458 * receive flags which are to be passed to http_open. If R_HTTPHOST
459 * is not NULL a malloced name of the host is stored there; this might
460 * be different from R_HOST in case it has been selected from a
463 map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
464 enum ks_protocol protocol, char **r_host, char *r_portstr,
465 unsigned int *r_httpflags, char **r_httphost)
470 dns_addrinfo_t aibuf, ai;
481 /* No hostname means localhost. */
484 *r_host = xtrystrdup ("localhost");
486 return gpg_error_from_syserror ();
489 *r_httphost = xtrystrdup (*r_host);
492 err = gpg_error_from_syserror ();
501 /* See whether the host is in our table. */
502 idx = find_hostinfo (name);
505 idx = create_new_hostinfo (name);
507 return gpg_error_from_syserror ();
509 hi->onion = is_onion_address (name);
514 is_pool = hi->pool != NULL;
516 if (srvtag && !is_ip_address (name)
518 && ! (hi->did_srv_lookup & 1 << protocol))
520 struct srventry *srvs;
521 unsigned int srvscount;
523 /* Check for SRV records. */
524 err = get_dns_srv (ctrl, name, srvtag, NULL, &srvs, &srvscount);
527 if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
528 tor_not_running_p (ctrl);
536 is_pool = srvscount > 1;
538 for (i = 0; i < srvscount; i++)
540 err = resolve_dns_name (ctrl, srvs[i].target, 0,
541 AF_UNSPEC, SOCK_STREAM,
546 add_host (ctrl, name, is_pool, ai, protocol, srvs[i].port);
553 hi->did_srv_lookup |= 1 << protocol;
556 if (! hi->did_a_lookup
559 /* Find all A records for this entry and put them into the pool
561 err = resolve_dns_name (ctrl, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
564 log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
569 /* First figure out whether this is a pool. For a pool we
570 use a different strategy than for a plain server: We use
571 the canonical name of the pool as the virtual host along
572 with the IP addresses. If it is not a pool, we use the
575 is_pool = arecords_is_pool (aibuf);
576 if (is_pool && cname)
582 for (ai = aibuf; ai; ai = ai->next)
584 if (ai->family != AF_INET && ai->family != AF_INET6)
586 if (opt.disable_ipv4 && ai->family == AF_INET)
588 if (opt.disable_ipv6 && ai->family == AF_INET6)
592 add_host (ctrl, name, is_pool, ai, 0, 0);
596 hi->did_a_lookup = 1;
599 free_dns_addrinfo (aibuf);
602 hostinfo_sort_pool (hi);
606 /* Deal with the pool name before selecting a host. */
609 *r_httphost = xtrystrdup (hi->name);
611 return gpg_error_from_syserror ();
614 /* If the currently selected host is now marked dead, force a
618 else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
619 && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
622 /* Select a host if needed. */
623 if (hi->poolidx == -1)
625 hi->poolidx = select_random_host (hi);
626 if (hi->poolidx == -1)
628 log_error ("no alive host found in pool '%s'\n", name);
634 return gpg_error (GPG_ERR_NO_KEYSERVER);
638 assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
639 hi = hosttable[hi->poolidx];
642 else if (r_httphost && is_ip_address (hi->name))
644 /* This is a numerical IP address and not a pool. We want to
645 * find the canonical name so that it can be used in the HTTP
646 * Host header. Fixme: We should store that name in the
650 err = resolve_dns_name (ctrl, hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
653 for (ai = aibuf; ai; ai = ai->next)
655 if ((!opt.disable_ipv6 && ai->family == AF_INET6)
656 || (!opt.disable_ipv4 && ai->family == AF_INET))
658 err = resolve_dns_addr (ctrl,
659 ai->addr, ai->addrlen, 0, &host);
662 /* Okay, we return the first found name. */
669 free_dns_addrinfo (aibuf);
673 *r_httphost = xtrystrdup (hi->name);
675 return gpg_error_from_syserror ();
680 log_error ("host '%s' marked as dead\n", hi->name);
686 return gpg_error (GPG_ERR_NO_KEYSERVER);
691 /* If the hosttable does not indicate that a certain host
692 supports IPv<N>, we explicit set the corresponding http
693 flags. The reason for this is that a host might be listed in
694 a pool as not v6 only but actually support v6 when later
695 the name is resolved by our http layer. */
697 *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
699 *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
701 /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion
702 addresses because the http module detects this itself. This
703 also allows us to use an onion address without Tor mode being
707 *r_host = xtrystrdup (hi->name);
710 err = gpg_error_from_syserror ();
718 if (hi->port[protocol])
719 snprintf (r_portstr, 6 /* five digits and the sentinel */,
720 "%hu", hi->port[protocol]);
725 /* Mark the host NAME as dead. NAME may be given as an URL. Returns
726 true if a host was really marked as dead or was already marked dead
727 (e.g. by a concurrent session). */
729 mark_host_dead (const char *name)
732 char *host_buffer = NULL;
733 parsed_uri_t parsed_uri = NULL;
737 && !http_parse_uri (&parsed_uri, name, HTTP_PARSE_NO_SCHEME_CHECK))
739 if (parsed_uri->v6lit)
741 host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
743 log_error ("out of core in mark_host_dead");
747 host = parsed_uri->host;
752 if (host && *host && strcmp (host, "localhost"))
757 idx = find_hostinfo (host);
761 log_info ("marking host '%s' as dead%s\n",
762 hi->name, hi->dead? " (again)":"");
764 hi->died_at = gnupg_get_time ();
771 http_release_parsed_uri (parsed_uri);
777 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
780 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
784 int idx, idx2, idx3, n;
786 if (!name || !*name || !strcmp (name, "localhost"))
789 if (npth_mutex_lock (&hosttable_lock))
790 log_fatal ("failed to acquire mutex\n");
792 idx = find_hostinfo (name);
795 err = gpg_error (GPG_ERR_NOT_FOUND);
800 if (alive && hi->dead)
803 err = ks_printf_help (ctrl, "marking '%s' as alive", name);
805 else if (!alive && !hi->dead)
808 hi->died_at = 0; /* Manually set dead. */
809 err = ks_printf_help (ctrl, "marking '%s' as dead", name);
812 /* If the host is a pool mark all member hosts. */
813 if (!err && hi->pool)
816 !err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
819 assert (n >= 0 && n < hosttable_size);
823 /* Do not mark a host from a pool dead if it is also a
824 member in another pool. */
825 for (idx3=0; idx3 < hosttable_size; idx3++)
828 && hosttable[idx3]->pool
830 && host_in_pool_p (hosttable[idx3], n))
833 if (idx3 < hosttable_size)
834 continue; /* Host is also a member of another pool. */
840 else if (alive && hi2->dead)
843 err = ks_printf_help (ctrl, "marking '%s' as alive",
846 else if (!alive && !hi2->dead)
849 hi2->died_at = 0; /* Manually set dead. */
850 err = ks_printf_help (ctrl, "marking '%s' as dead",
857 if (npth_mutex_unlock (&hosttable_lock))
858 log_fatal ("failed to release mutex\n");
864 /* Debug function to print the entire hosttable. */
866 ks_hkp_print_hosttable (ctrl_t ctrl)
876 err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
880 if (npth_mutex_lock (&hosttable_lock))
881 log_fatal ("failed to acquire mutex\n");
883 curtime = gnupg_get_time ();
884 for (idx=0; idx < hosttable_size; idx++)
885 if ((hi=hosttable[idx]))
887 if (hi->dead && hi->died_at)
889 died = elapsed_time_string (hi->died_at, curtime);
890 diedstr = died? died : "error";
893 diedstr = died = NULL;
895 if (!hi->iporname_valid)
899 xfree (hi->iporname);
902 /* Do a lookup just for the display purpose. */
903 if (hi->onion || hi->pool)
905 else if (is_ip_address (hi->name))
907 dns_addrinfo_t aibuf, ai;
909 /* Turn the numerical IP address string into an AI and
910 * then do a DNS PTR lookup. */
911 if (!resolve_dns_name (ctrl, hi->name, 0, 0,
915 if (canon && is_ip_address (canon))
920 for (ai = aibuf; !canon && ai; ai = ai->next)
922 resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
923 DNS_WITHBRACKET, &canon);
924 if (canon && is_ip_address (canon))
926 /* We already have the numeric IP - no need to
927 * display it a second time. */
933 free_dns_addrinfo (aibuf);
937 dns_addrinfo_t aibuf, ai;
939 /* Get the IP address as a string from a name. Note
940 * that resolve_dns_addr allocates CANON on success
941 * and thus terminates the loop. */
942 if (!resolve_dns_name (ctrl, hi->name, 0,
943 hi->v6? AF_INET6 : AF_INET,
947 for (ai = aibuf; !canon && ai; ai = ai->next)
949 resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
950 DNS_NUMERICHOST|DNS_WITHBRACKET,
954 free_dns_addrinfo (aibuf);
957 hi->iporname = canon;
958 hi->iporname_valid = 1;
961 err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s\n",
963 hi->onion? "O" : hi->v6? "6":" ",
967 hi->iporname? " (":"",
968 hi->iporname? hi->iporname : "",
969 hi->iporname? ")":"",
978 err = ks_printf_help (ctrl, " . %s", hi->cname);
984 init_membuf (&mb, 256);
985 put_membuf_printf (&mb, " . -->");
986 for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
988 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
989 if (hi->poolidx == hi->pool[idx2])
990 put_membuf_printf (&mb, "*");
992 put_membuf( &mb, "", 1);
993 p = get_membuf (&mb, NULL);
996 err = gpg_error_from_syserror ();
999 err = ks_print_help (ctrl, p);
1007 if (npth_mutex_unlock (&hosttable_lock))
1008 log_fatal ("failed to release mutex\n");
1014 /* Print a help output for the schemata supported by this module. */
1016 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
1019 "Handler for HKP URLs:\n"
1021 #if HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
1024 "Supported methods: search, get, put\n";
1027 #if HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
1028 const char data2[] = " hkp\n hkps";
1030 const char data2[] = " hkp";
1034 err = ks_print_help (ctrl, data2);
1035 else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
1036 || !strcmp (uri->scheme, "hkps")))
1037 err = ks_print_help (ctrl, data);
1045 /* Build the remote part of the URL from SCHEME, HOST and an optional
1046 * PORT. If NO_SRV is set no SRV record lookup will be done. Returns
1047 * an allocated string at R_HOSTPORT or NULL on failure. If
1048 * R_HTTPHOST is not NULL it receives a malloced string with the
1049 * hostname; this may be different from HOST if HOST is selected from
1052 make_host_part (ctrl_t ctrl,
1053 const char *scheme, const char *host, unsigned short port,
1054 int force_reselect, int no_srv,
1055 char **r_hostport, unsigned int *r_httpflags, char **r_httphost)
1061 enum ks_protocol protocol;
1065 if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
1068 srvtag = no_srv? NULL : "pgpkey-https";
1069 protocol = KS_PROTOCOL_HKPS;
1071 else /* HKP or HTTP. */
1074 srvtag = no_srv? NULL : "pgpkey-http";
1075 protocol = KS_PROTOCOL_HKP;
1078 if (npth_mutex_lock (&hosttable_lock))
1079 log_fatal ("failed to acquire mutex\n");
1082 err = map_host (ctrl, host, srvtag, force_reselect, protocol,
1083 &hostname, portstr, r_httpflags, r_httphost);
1085 if (npth_mutex_unlock (&hosttable_lock))
1086 log_fatal ("failed to release mutex\n");
1091 /* If map_host did not return a port (from a SRV record) but a port
1092 * has been specified (implicitly or explicitly) then use that port.
1093 * In the case that a port was not specified (which is probably a
1094 * bug in https.c) we will set up defaults. */
1097 else if (!*portstr && port)
1098 snprintf (portstr, sizeof portstr, "%hu", port);
1099 else if (!strcmp (scheme,"https"))
1100 strcpy (portstr, "443");
1102 strcpy (portstr, "11371");
1104 if (*hostname != '[' && is_ip_address (hostname) == 6)
1105 *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
1107 *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
1113 xfree (*r_httphost);
1116 return gpg_error_from_syserror ();
1122 /* Resolve all known keyserver names and update the hosttable. This
1123 is mainly useful for debugging because the resolving is anyway done
1126 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
1129 char *hostport = NULL;
1131 /* NB: With an explicitly given port we do not want to consult a
1132 * service record because that might be in conflict with the port
1133 * from such a service record. */
1134 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1135 1, uri->explicit_port,
1136 &hostport, NULL, NULL);
1139 err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
1140 uri->scheme, uri->host, uri->port,
1141 gpg_strerror (err));
1145 err = ks_printf_help (ctrl, "%s", hostport);
1152 /* Housekeeping function called from the housekeeping thread. It is
1153 used to mark dead hosts alive so that they may be tried again after
1156 ks_hkp_housekeeping (time_t curtime)
1161 if (npth_mutex_lock (&hosttable_lock))
1162 log_fatal ("failed to acquire mutex\n");
1164 for (idx=0; idx < hosttable_size; idx++)
1166 hi = hosttable[idx];
1172 continue; /* Do not resurrect manually shot hosts. */
1173 if (hi->died_at + RESURRECT_INTERVAL <= curtime
1174 || hi->died_at > curtime)
1177 log_info ("resurrected host '%s'", hi->name);
1181 if (npth_mutex_unlock (&hosttable_lock))
1182 log_fatal ("failed to release mutex\n");
1186 /* Reload (SIGHUP) action for this module. We mark all host alive
1187 * even those which have been manually shot. */
1189 ks_hkp_reload (void)
1194 if (npth_mutex_lock (&hosttable_lock))
1195 log_fatal ("failed to acquire mutex\n");
1197 for (idx=count=0; idx < hosttable_size; idx++)
1199 hi = hosttable[idx];
1202 hi->iporname_valid = 0;
1209 log_info ("number of resurrected hosts: %d", count);
1211 if (npth_mutex_unlock (&hosttable_lock))
1212 log_fatal ("failed to release mutex\n");
1216 /* Send an HTTP request. On success returns an estream object at
1217 R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is
1218 not NULL it will be used as HTTP "Host" header. If POST_CB is not
1219 NULL a post request is used and that callback is called to allow
1220 writing the post data. If R_HTTP_STATUS is not NULL, the http
1221 status code will be stored there. */
1223 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
1224 const char *httphost, unsigned int httpflags,
1225 gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
1226 estream_t *r_fp, unsigned int *r_http_status)
1229 http_session_t session = NULL;
1231 http_redir_info_t redirinfo = { MAX_REDIRECTS };
1232 estream_t fp = NULL;
1233 char *request_buffer = NULL;
1234 parsed_uri_t uri = NULL;
1238 err = http_parse_uri (&uri, request, 0);
1241 redirinfo.ctrl = ctrl;
1242 redirinfo.orig_url = request;
1243 redirinfo.orig_onion = uri->onion;
1244 redirinfo.allow_downgrade = 1;
1245 /* FIXME: I am not sure why we allow a downgrade for hkp requests.
1246 * Needs at least an explanation here. */
1247 redirinfo.restrict_redir = !!(opt.compat_flags & COMPAT_RESTRICT_HTTP_REDIR);
1250 err = http_session_new (&session, httphost,
1251 ((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
1252 | HTTP_FLAG_TRUST_DEF),
1253 gnupg_http_tls_verify_cb, ctrl);
1256 http_session_set_log_cb (session, cert_log_cb);
1257 http_session_set_timeout (session, ctrl->timeout);
1259 err = http_open (ctrl, &http,
1260 post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1263 /* fixme: AUTH */ NULL,
1265 |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
1266 |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
1267 |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
1268 |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
1272 /*FIXME curl->srvtag*/NULL);
1275 fp = http_get_write_ptr (http);
1276 /* Avoid caches to get the most recent copy of the key. We set
1277 both the Pragma and Cache-Control versions of the header, so
1278 we're good with both HTTP 1.0 and 1.1. */
1279 es_fputs ("Pragma: no-cache\r\n"
1280 "Cache-Control: no-cache\r\n", fp);
1282 err = post_cb (post_cb_value, http);
1285 http_start_data (http);
1287 err = gpg_error_from_syserror ();
1292 /* Fixme: After a redirection we show the old host name. */
1293 log_error (_("error connecting to '%s': %s\n"),
1294 hostportstr, gpg_strerror (err));
1298 /* Wait for the response. */
1299 dirmngr_tick (ctrl);
1300 err = http_wait_response (http);
1303 log_error (_("error reading HTTP response for '%s': %s\n"),
1304 hostportstr, gpg_strerror (err));
1308 if (http_get_tls_info (http, NULL))
1310 /* Update the httpflags so that a redirect won't fallback to an
1311 unencrypted connection. */
1312 httpflags |= HTTP_FLAG_FORCE_TLS;
1316 *r_http_status = http_get_status_code (http);
1318 switch (http_get_status_code (http))
1322 break; /* Success. */
1328 xfree (request_buffer);
1329 err = http_prepare_redirect (&redirinfo, http_get_status_code (http),
1330 http_get_header (http, "Location"),
1335 request = request_buffer;
1336 http_close (http, 0);
1338 http_session_release (session);
1344 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1347 case 413: /* Payload too large */
1348 err = gpg_error (GPG_ERR_TOO_LARGE);
1352 log_error (_("error accessing '%s': http status %u\n"),
1353 request, http_get_status_code (http));
1354 err = gpg_error (GPG_ERR_NO_DATA);
1358 /* FIXME: We should register a permanent redirection and whether a
1359 host has ever used TLS so that future calls will always use
1362 fp = http_get_read_ptr (http);
1365 err = gpg_error (GPG_ERR_BUG);
1369 /* Return the read stream and close the HTTP context. */
1371 http_close (http, 1);
1375 http_close (http, 0);
1376 http_session_release (session);
1377 xfree (request_buffer);
1378 http_release_parsed_uri (uri);
1383 /* Helper to evaluate the error code ERR from a send_request() call
1384 with REQUEST. The function returns true if the caller shall try
1385 again. TRIES_LEFT points to a variable to track the number of
1386 retries; this function decrements it and won't return true if it is
1387 down to zero. EXTRA_TRIES_LEFT does the same but only for
1388 transient http status codes. */
1390 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
1391 unsigned int http_status, unsigned int *tries_left,
1392 unsigned int *extra_tries_left)
1396 /* Fixme: Should we disable all hosts of a protocol family if a
1397 * request for an address of that family returned ENETDOWN? */
1399 switch (gpg_err_code (err))
1401 case GPG_ERR_ECONNREFUSED:
1402 if (tor_not_running_p (ctrl))
1403 break; /* A retry does not make sense. */
1404 /* Okay: Tor is up or --use-tor is not used. */
1406 case GPG_ERR_ENETUNREACH:
1407 case GPG_ERR_ENETDOWN:
1408 case GPG_ERR_UNKNOWN_HOST:
1409 case GPG_ERR_NETWORK:
1410 case GPG_ERR_EIO: /* Sometimes used by estream cookie functions. */
1411 case GPG_ERR_EADDRNOTAVAIL: /* e.g. when IPv6 is disabled */
1412 case GPG_ERR_EAFNOSUPPORT: /* e.g. when IPv6 is not compiled in */
1413 if (mark_host_dead (request) && *tries_left)
1417 case GPG_ERR_ETIMEDOUT:
1420 log_info ("selecting a different host due to a timeout\n");
1425 case GPG_ERR_EACCES:
1426 if (dirmngr_use_tor ())
1428 log_info ("(Tor configuration problem)\n");
1429 dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
1430 "Please check that the \"SocksPort\" flag "
1431 "\"IPv6Traffic\" is set in torrc", NULL);
1435 case GPG_ERR_NO_DATA:
1437 switch (http_status)
1439 case 502: /* Bad Gateway */
1440 log_info ("marking host dead due to a %u (%s)\n",
1441 http_status, http_status2string (http_status));
1442 if (mark_host_dead (request) && *tries_left)
1446 case 503: /* Service Unavailable */
1447 case 504: /* Gateway Timeout */
1448 if (*extra_tries_left)
1450 log_info ("selecting a different host due to a %u (%s)",
1451 http_status, http_status2string (http_status));
1465 if (*extra_tries_left)
1466 --*extra_tries_left;
1478 /* Search the keyserver identified by URI for keys matching PATTERN.
1479 On success R_FP has an open stream to read the data. If
1480 R_HTTP_STATUS is not NULL, the http status code will be stored
1483 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1484 estream_t *r_fp, unsigned int *r_http_status)
1487 KEYDB_SEARCH_DESC desc;
1488 char fprbuf[2+64+1];
1489 char *namebuffer = NULL;
1490 char *hostport = NULL;
1491 char *request = NULL;
1492 estream_t fp = NULL;
1494 unsigned int httpflags;
1495 char *httphost = NULL;
1496 unsigned int http_status;
1497 unsigned int tries = SEND_REQUEST_RETRIES;
1498 unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1502 /* Remove search type indicator and adjust PATTERN accordingly.
1503 Note that HKP keyservers like the 0x to be present when searching
1504 by keyid. We need to re-format the fingerprint and keyids so to
1505 remove the gpg specific force-use-of-this-key flag ("!"). */
1506 err = classify_user_id (pattern, &desc, 1);
1509 log_assert (desc.fprlen <= 64);
1512 case KEYDB_SEARCH_MODE_EXACT:
1513 case KEYDB_SEARCH_MODE_SUBSTR:
1514 case KEYDB_SEARCH_MODE_MAILSUB:
1515 pattern = desc.u.name;
1517 case KEYDB_SEARCH_MODE_MAIL:
1518 namebuffer = xtrystrdup (desc.u.name);
1521 err = gpg_error_from_syserror ();
1524 /* Strip trailing angle bracket. */
1525 if (namebuffer[0] && namebuffer[1]
1526 && namebuffer[strlen (namebuffer)-1] == '>')
1527 namebuffer[strlen(namebuffer)-1] = 0;
1528 /* Strip optional leading angle bracket. */
1529 if (*namebuffer == '<' && namebuffer[1])
1530 pattern = namebuffer + 1;
1532 pattern = namebuffer;
1534 case KEYDB_SEARCH_MODE_SHORT_KID:
1535 snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1538 case KEYDB_SEARCH_MODE_LONG_KID:
1539 snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1540 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1543 case KEYDB_SEARCH_MODE_FPR:
1546 bin2hex (desc.u.fpr, desc.fprlen, fprbuf+2);
1550 return gpg_error (GPG_ERR_INV_USER_ID);
1553 /* Build the request string. */
1559 xfree (hostport); hostport = NULL;
1560 xfree (httphost); httphost = NULL;
1561 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1562 reselect, uri->explicit_port,
1563 &hostport, &httpflags, &httphost);
1567 searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1570 err = gpg_error_from_syserror ();
1575 request = strconcat (hostport,
1576 "/pks/lookup?op=index&options=mr&fingerprint=on&search=",
1582 err = gpg_error_from_syserror ();
1587 /* Send the request. */
1588 err = send_request (ctrl, request, hostport, httphost, httpflags,
1589 NULL, NULL, &fp, &http_status);
1590 if (handle_send_request_error (ctrl, err, request, http_status,
1591 &tries, &extra_tries))
1597 *r_http_status = http_status;
1600 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1601 dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1605 err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1609 /* Peek at the response. */
1611 int c = es_getc (fp);
1614 err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1615 log_error ("error reading response: %s\n", gpg_strerror (err));
1620 /* The document begins with a '<': Assume a HTML response,
1621 which we don't support. */
1622 err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1628 /* Return the read stream. */
1642 /* Get the key described key the KEYSPEC string from the keyserver
1643 identified by URI. On success R_FP has an open stream to read the
1644 data. The data will be provided in a format GnuPG can import
1645 (either a binary OpenPGP message or an armored one). */
1647 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1650 KEYDB_SEARCH_DESC desc;
1651 char kidbuf[2+64+1];
1652 const char *exactname = NULL;
1653 char *namebuffer = NULL;
1654 char *searchkey = NULL;
1655 char *hostport = NULL;
1656 char *request = NULL;
1657 estream_t fp = NULL;
1659 char *httphost = NULL;
1660 unsigned int httpflags;
1661 unsigned int http_status;
1662 unsigned int tries = SEND_REQUEST_RETRIES;
1663 unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1667 /* Remove search type indicator and adjust PATTERN accordingly.
1668 Note that HKP keyservers like the 0x to be present when searching
1669 by keyid. We need to re-format the fingerprint and keyids so to
1670 remove the gpg specific force-use-of-this-key flag ("!"). */
1671 err = classify_user_id (keyspec, &desc, 1);
1674 log_assert (desc.fprlen <= 64);
1677 case KEYDB_SEARCH_MODE_SHORT_KID:
1678 snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1680 case KEYDB_SEARCH_MODE_LONG_KID:
1681 snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1682 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1684 case KEYDB_SEARCH_MODE_FPR:
1685 if (desc.fprlen < 20)
1687 log_error ("HKP keyservers do not support v3 fingerprints\n");
1688 return gpg_error (GPG_ERR_INV_USER_ID);
1692 bin2hex (desc.u.fpr, desc.fprlen, kidbuf+2);
1695 case KEYDB_SEARCH_MODE_EXACT:
1696 exactname = desc.u.name;
1699 case KEYDB_SEARCH_MODE_MAIL:
1700 namebuffer = xtrystrdup (desc.u.name);
1703 err = gpg_error_from_syserror ();
1706 /* Strip trailing angle bracket. */
1707 if (namebuffer[0] && namebuffer[1]
1708 && namebuffer[strlen (namebuffer)-1] == '>')
1709 namebuffer[strlen(namebuffer)-1] = 0;
1710 /* Strip optional leading angle bracket. */
1711 if (*namebuffer == '<' && namebuffer[1])
1712 exactname = namebuffer + 1;
1714 exactname = namebuffer;
1718 return gpg_error (GPG_ERR_INV_USER_ID);
1721 searchkey = http_escape_string (exactname? exactname : kidbuf,
1722 EXTRA_ESCAPE_CHARS);
1725 err = gpg_error_from_syserror ();
1731 /* Build the request string. */
1732 xfree (hostport); hostport = NULL;
1733 xfree (httphost); httphost = NULL;
1734 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1735 reselect, uri->explicit_port,
1736 &hostport, &httpflags, &httphost);
1741 request = strconcat (hostport,
1742 "/pks/lookup?op=get&options=mr&search=",
1744 exactname? "&exact=on":"",
1748 err = gpg_error_from_syserror ();
1752 /* Send the request. */
1753 err = send_request (ctrl, request, hostport, httphost, httpflags,
1754 NULL, NULL, &fp, &http_status);
1755 if (handle_send_request_error (ctrl, err, request, http_status,
1756 &tries, &extra_tries))
1763 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1764 dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1768 err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1772 /* Return the read stream and close the HTTP context. */
1789 /* Callback parameters for put_post_cb. */
1790 struct put_post_parm_s
1796 /* Helper for ks_hkp_put. */
1798 put_post_cb (void *opaque, http_t http)
1800 struct put_post_parm_s *parm = opaque;
1801 gpg_error_t err = 0;
1805 fp = http_get_write_ptr (http);
1806 len = strlen (parm->datastring);
1809 "Content-Type: application/x-www-form-urlencoded\r\n"
1810 "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1811 http_start_data (http);
1812 if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1813 err = gpg_error_from_syserror ();
1818 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI. */
1820 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1823 char *hostport = NULL;
1824 char *request = NULL;
1825 estream_t fp = NULL;
1826 struct put_post_parm_s parm;
1827 char *armored = NULL;
1829 char *httphost = NULL;
1830 unsigned int httpflags;
1831 unsigned int http_status;
1832 unsigned int tries = SEND_REQUEST_RETRIES;
1833 unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1835 parm.datastring = NULL;
1837 err = armor_data (&armored, data, datalen);
1841 parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1842 if (!parm.datastring)
1844 err = gpg_error_from_syserror ();
1850 /* Build the request string. */
1853 xfree (hostport); hostport = NULL;
1854 xfree (httphost); httphost = NULL;
1855 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1856 reselect, uri->explicit_port,
1857 &hostport, &httpflags, &httphost);
1862 request = strconcat (hostport, "/pks/add", NULL);
1865 err = gpg_error_from_syserror ();
1869 /* Send the request. */
1870 err = send_request (ctrl, request, hostport, httphost, 0,
1871 put_post_cb, &parm, &fp, &http_status);
1872 if (handle_send_request_error (ctrl, err, request, http_status,
1873 &tries, &extra_tries))
1883 xfree (parm.datastring);
1896 err = npth_mutex_init (&hosttable_lock, NULL);
1898 log_fatal ("error initializing mutex: %s\n", strerror (err));