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 "dns-stuff.h"
42 #include "ks-engine.h"
44 /* Substitutes for missing Mingw macro. The EAI_SYSTEM mechanism
45 seems not to be available (probably because there is only one set
46 of error codes anyway). For now we use WSAEINVAL. */
48 # define EAI_OVERFLOW EAI_FAIL
50 #ifdef HAVE_W32_SYSTEM
52 # define EAI_SYSTEM WSAEINVAL
57 /* Number of seconds after a host is marked as resurrected. */
58 #define RESURRECT_INTERVAL (3600*3) /* 3 hours */
60 /* To match the behaviour of our old gpgkeys helper code we escape
61 more characters than actually needed. */
62 #define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
64 /* How many redirections do we allow. */
65 #define MAX_REDIRECTS 2
67 /* Number of retries done for a dead host etc. */
68 #define SEND_REQUEST_RETRIES 3
70 /* Objects used to maintain information about hosts. */
72 typedef struct hostinfo_s *hostinfo_t;
75 time_t lastfail; /* Time we tried to connect and failed. */
76 time_t lastused; /* Time of last use. */
77 int *pool; /* A -1 terminated array with indices into
78 HOSTTABLE or NULL if NAME is not a pool
80 int poolidx; /* Index into POOL with the used host. -1 if not set. */
81 unsigned int v4:1; /* Host supports AF_INET. */
82 unsigned int v6:1; /* Host supports AF_INET6. */
83 unsigned int onion:1;/* NAME is an onion (Tor HS) address. */
84 unsigned int dead:1; /* Host is currently unresponsive. */
85 time_t died_at; /* The time the host was marked dead. If this is
86 0 the host has been manually marked dead. */
87 char *cname; /* Canonical name of the host. Only set if this
88 is a pool or NAME has a numerical IP address. */
89 char *v4addr; /* A string with the v4 IP address of the host.
90 NULL if NAME has a numeric IP address or no v4
91 address is available. */
92 char *v6addr; /* A string with the v6 IP address of the host.
93 NULL if NAME has a numeric IP address or no v6
94 address is available. */
95 unsigned short port; /* The port used by the host, 0 if unknown. */
96 char name[1]; /* The hostname. */
100 /* An array of hostinfo_t for all hosts requested by the caller or
101 resolved from a pool name and its allocated size.*/
102 static hostinfo_t *hosttable;
103 static int hosttable_size;
105 /* The number of host slots we initially allocate for HOSTTABLE. */
106 #define INITIAL_HOSTTABLE_SIZE 10
109 /* Create a new hostinfo object, fill in NAME and put it into
110 HOSTTABLE. Return the index into hosttable on success or -1 on
113 create_new_hostinfo (const char *name)
115 hostinfo_t hi, *newtable;
119 hi = xtrymalloc (sizeof *hi + strlen (name));
122 strcpy (hi->name, name);
125 hi->lastused = (time_t)(-1);
126 hi->lastfail = (time_t)(-1);
137 /* Add it to the hosttable. */
138 for (idx=0; idx < hosttable_size; idx++)
144 /* Need to extend the hosttable. */
145 newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
146 newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
152 hosttable = newtable;
153 idx = hosttable_size;
154 hosttable_size = newsize;
156 hosttable[idx++] = hi;
157 while (idx < hosttable_size)
158 hosttable[idx++] = NULL;
164 /* Find the host NAME in our table. Return the index into the
165 hosttable or -1 if not found. */
167 find_hostinfo (const char *name)
171 for (idx=0; idx < hosttable_size; idx++)
172 if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
179 sort_hostpool (const void *xa, const void *xb)
184 assert (a >= 0 && a < hosttable_size);
185 assert (b >= 0 && b < hosttable_size);
186 assert (hosttable[a]);
187 assert (hosttable[b]);
189 return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
193 /* Return true if the host with the hosttable index TBLIDX is in POOL. */
195 host_in_pool_p (int *pool, int tblidx)
199 for (i=0; (pidx = pool[i]) != -1; i++)
200 if (pidx == tblidx && hosttable[pidx])
207 host_is_alive (hostinfo_t hi, time_t curtime)
214 return 0; /* manually marked dead */
215 if (hi->died_at + RESURRECT_INTERVAL <= curtime
216 || hi->died_at > curtime)
219 log_info ("resurrected host '%s'", hi->name);
225 /* Select a random host. Consult TABLE which indices into the global
226 hosttable. Returns index into TABLE or -1 if no host could be
229 select_random_host (int *table)
236 curtime = gnupg_get_time ();
237 /* We create a new table so that we randomly select only from
238 currently alive hosts. */
239 for (idx=0; (pidx = table[idx]) != -1; idx++)
240 if (hosttable[pidx] && host_is_alive (hosttable[pidx], curtime))
243 tbl = xtryrealloc(tbl, tblsize * sizeof *tbl);
245 return -1; /* memory allocation failed! */
246 tbl[tblsize-1] = pidx;
249 return -1; /* No hosts. */
251 if (tblsize == 1) /* Save a get_uint_nonce. */
254 pidx = tbl[get_uint_nonce () % tblsize];
261 /* Figure out if a set of DNS records looks like a pool. */
263 arecords_is_pool (dns_addrinfo_t aibuf)
269 for (ai = aibuf; ai; ai = ai->next)
271 if (ai->family == AF_INET6)
273 else if (ai->family == AF_INET)
277 return n_v6 > 1 || n_v4 > 1;
281 /* Print a warninng iff Tor is not running but Tor has been requested.
282 * Also return true if it is not running. */
284 tor_not_running_p (ctrl_t ctrl)
288 if (!dirmngr_use_tor ())
291 sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
292 if (sock != ASSUAN_INVALID_FD)
294 assuan_sock_close (sock);
298 log_info ("(it seems Tor is not running)\n");
299 dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
300 "Tor is enabled but the local Tor daemon"
301 " seems to be down", NULL);
306 /* Add the host AI under the NAME into the HOSTTABLE. If PORT is not
307 zero, it specifies which port to use to talk to the host. If NAME
308 specifies a pool (as indicated by IS_POOL), update the given
309 reference table accordingly. */
311 add_host (const char *name, int is_pool,
312 const dns_addrinfo_t ai, unsigned short port,
313 int *reftbl, size_t reftblsize, int *refidx)
321 idx = find_hostinfo (name);
323 if (!is_pool && !is_ip_address (name))
325 /* This is a hostname but not a pool. Use the name
326 as given without going through resolve_dns_addr. */
327 tmphost = xtrystrdup (name);
329 tmperr = gpg_error_from_syserror ();
335 tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
336 DNS_WITHBRACKET, &tmphost);
337 if (tmphost && is_ip_address (tmphost))
343 log_info ("resolve_dns_addr failed while checking '%s': %s\n",
344 name, gpg_strerror (tmperr));
346 else if ((*refidx) + 1 >= reftblsize)
348 log_error ("resolve_dns_addr for '%s': '%s'"
349 " [index table full - ignored]\n", name, tmphost);
353 if (!is_pool && is_ip_address (name))
354 /* Update the original entry. */
357 tmpidx = find_hostinfo (tmphost);
358 log_info ("resolve_dns_addr for '%s': '%s'%s\n",
360 tmpidx == -1? "" : " [already known]");
362 if (tmpidx == -1) /* Create a new entry. */
363 tmpidx = create_new_hostinfo (tmphost);
367 log_error ("map_host for '%s' problem: %s - '%s'"
369 name, strerror (errno), tmphost);
371 else /* Set or update the entry. */
376 hosttable[tmpidx]->port = port;
381 tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
386 log_info ("resolve_dns_addr failed: %s\n",
387 gpg_strerror (tmperr));
395 if (ai->family == AF_INET6)
397 hosttable[tmpidx]->v6 = 1;
398 xfree (hosttable[tmpidx]->v6addr);
399 hosttable[tmpidx]->v6addr = ipaddr;
401 else if (ai->family == AF_INET)
403 hosttable[tmpidx]->v4 = 1;
404 xfree (hosttable[tmpidx]->v4addr);
405 hosttable[tmpidx]->v4addr = ipaddr;
410 for (i=0; i < *refidx; i++)
411 if (reftbl[i] == tmpidx)
413 if (!(i < *refidx) && tmpidx != idx)
414 reftbl[(*refidx)++] = tmpidx;
421 /* Map the host name NAME to the actual to be used host name. This
422 * allows us to manage round robin DNS names. We use our own strategy
423 * to choose one of the hosts. For example we skip those hosts which
424 * failed for some time and we stick to one host for a time
425 * independent of DNS retry times. If FORCE_RESELECT is true a new
426 * host is always selected. If SRVTAG is NULL no service record
427 * lookup will be done, if it is set that service name is used. The
428 * selected host is stored as a malloced string at R_HOST; on error
429 * NULL is stored. If we know the port used by the selected host from
430 * a service record, a string representation is written to R_PORTSTR,
431 * otherwise it is left untouched. If R_HTTPFLAGS is not NULL it will
432 * receive flags which are to be passed to http_open. If R_HTTPHOST
433 * is not NULL a malloced name of the host is stored there; this might
434 * be different from R_HOST in case it has been selected from a
437 map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
438 char **r_host, char *r_portstr,
439 unsigned int *r_httpflags, char **r_httphost)
452 /* No hostname means localhost. */
455 *r_host = xtrystrdup ("localhost");
456 return *r_host? 0 : gpg_error_from_syserror ();
459 /* See whether the host is in our table. */
460 idx = find_hostinfo (name);
461 if (idx == -1 && is_onion_address (name))
463 idx = create_new_hostinfo (name);
465 return gpg_error_from_syserror ();
471 /* We never saw this host. Allocate a new entry. */
472 dns_addrinfo_t aibuf, ai;
478 struct srventry *srvs;
479 unsigned int srvscount;
482 reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
484 return gpg_error_from_syserror ();
487 idx = create_new_hostinfo (name);
490 err = gpg_error_from_syserror ();
496 if (srvtag && !is_ip_address (name))
498 /* Check for SRV records. */
499 err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
503 if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
504 tor_not_running_p (ctrl);
511 is_pool = srvscount > 1;
513 for (i = 0; i < srvscount; i++)
515 err = resolve_dns_name (srvs[i].target, 0,
516 AF_UNSPEC, SOCK_STREAM,
521 add_host (name, is_pool, ai, srvs[i].port,
522 reftbl, reftblsize, &refidx);
529 /* Find all A records for this entry and put them into the pool
531 err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
534 log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
539 /* First figure out whether this is a pool. For a pool we
540 use a different strategy than for a plain server: We use
541 the canonical name of the pool as the virtual host along
542 with the IP addresses. If it is not a pool, we use the
545 is_pool = arecords_is_pool (aibuf);
546 if (is_pool && cname)
552 for (ai = aibuf; ai; ai = ai->next)
554 if (ai->family != AF_INET && ai->family != AF_INET6)
556 if (opt.disable_ipv4 && ai->family == AF_INET)
560 add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
565 free_dns_addrinfo (aibuf);
567 if (refidx && is_pool)
570 hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
573 err = gpg_error_from_syserror ();
574 log_error ("shrinking index table in map_host failed: %s\n",
579 qsort (hi->pool, refidx, sizeof *reftbl, sort_hostpool);
585 curtime = gnupg_get_time ();
589 /* Deal with the pool name before selecting a host. */
592 *r_httphost = xtrystrdup (hi->cname? hi->cname : hi->name);
594 return gpg_error_from_syserror ();
597 /* If the currently selected host is now marked dead, force a
601 else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
602 && hosttable[hi->poolidx] && !host_is_alive (hosttable[hi->poolidx], curtime))
605 /* Select a host if needed. */
606 if (hi->poolidx == -1)
608 hi->poolidx = select_random_host (hi->pool);
609 if (hi->poolidx == -1)
611 log_error ("no alive host found in pool '%s'\n", name);
617 return gpg_error (GPG_ERR_NO_KEYSERVER);
621 assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
622 hi = hosttable[hi->poolidx];
625 else if (r_httphost && is_ip_address (hi->name))
627 /* This is a numerical IP address and not a pool. We want to
628 * find the canonical name so that it can be used in the HTTP
629 * Host header. Fixme: We should store that name in the
631 dns_addrinfo_t aibuf, ai;
634 err = resolve_dns_name (hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
637 for (ai = aibuf; ai; ai = ai->next)
639 if (ai->family == AF_INET6
640 || (!opt.disable_ipv4 && ai->family == AF_INET))
642 err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
645 /* Okay, we return the first found name. */
652 free_dns_addrinfo (aibuf);
655 if (!host_is_alive (hi, curtime))
657 log_error ("host '%s' marked as dead\n", hi->name);
663 return gpg_error (GPG_ERR_NO_KEYSERVER);
668 /* If the hosttable does not indicate that a certain host
669 supports IPv<N>, we explicit set the corresponding http
670 flags. The reason for this is that a host might be listed in
671 a pool as not v6 only but actually support v6 when later
672 the name is resolved by our http layer. */
674 *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
676 *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
678 /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion
679 addresses because the http module detects this itself. This
680 also allows us to use an onion address without Tor mode being
684 *r_host = xtrystrdup (hi->name);
687 err = gpg_error_from_syserror ();
696 snprintf (r_portstr, 6 /* five digits and the sentinel */,
702 /* Mark the host NAME as dead. NAME may be given as an URL. Returns
703 true if a host was really marked as dead or was already marked dead
704 (e.g. by a concurrent session). */
706 mark_host_dead (const char *name)
709 char *host_buffer = NULL;
710 parsed_uri_t parsed_uri = NULL;
713 if (name && *name && !http_parse_uri (&parsed_uri, name, 1))
715 if (parsed_uri->v6lit)
717 host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
719 log_error ("out of core in mark_host_dead");
723 host = parsed_uri->host;
728 if (host && *host && strcmp (host, "localhost"))
733 idx = find_hostinfo (host);
737 log_info ("marking host '%s' as dead%s\n",
738 hi->name, hi->dead? " (again)":"");
740 hi->died_at = gnupg_get_time ();
747 http_release_parsed_uri (parsed_uri);
753 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
756 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
760 int idx, idx2, idx3, n, is_alive;
763 if (!name || !*name || !strcmp (name, "localhost"))
766 idx = find_hostinfo (name);
768 return gpg_error (GPG_ERR_NOT_FOUND);
770 curtime = gnupg_get_time ();
772 is_alive = host_is_alive (hi, curtime);
773 if (alive && !is_alive)
776 err = ks_printf_help (ctrl, "marking '%s' as alive", name);
778 else if (!alive && is_alive)
781 hi->died_at = 0; /* Manually set dead. */
782 err = ks_printf_help (ctrl, "marking '%s' as dead", name);
785 /* If the host is a pool mark all member hosts. */
786 if (!err && hi->pool)
788 for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
790 assert (n >= 0 && n < hosttable_size);
794 /* Do not mark a host from a pool dead if it is also a
795 member in another pool. */
796 for (idx3=0; idx3 < hosttable_size; idx3++)
799 && hosttable[idx3]->pool
801 && host_in_pool_p (hosttable[idx3]->pool, n))
804 if (idx3 < hosttable_size)
805 continue; /* Host is also a member of another pool. */
811 is_alive = host_is_alive (hi2, curtime);
812 if (alive && !is_alive)
815 err = ks_printf_help (ctrl, "marking '%s' as alive",
818 else if (!alive && is_alive)
821 hi2->died_at = 0; /* Manually set dead. */
822 err = ks_printf_help (ctrl, "marking '%s' as dead",
832 /* Debug function to print the entire hosttable. */
834 ks_hkp_print_hosttable (ctrl_t ctrl)
844 err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
848 curtime = gnupg_get_time ();
849 for (idx=0; idx < hosttable_size; idx++)
850 if ((hi=hosttable[idx]))
852 if (hi->dead && hi->died_at)
854 died = elapsed_time_string (hi->died_at, curtime);
855 diedstr = died? died : "error";
858 diedstr = died = NULL;
859 err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n",
861 hi->onion? "O" : hi->v6? "6":" ",
865 hi->v6addr? " v6=":"",
866 hi->v6addr? hi->v6addr:"",
867 hi->v4addr? " v4=":"",
868 hi->v4addr? hi->v4addr:"",
877 err = ks_printf_help (ctrl, " . %s", hi->cname);
883 init_membuf (&mb, 256);
884 put_membuf_printf (&mb, " . -->");
885 for (idx2=0; hi->pool[idx2] != -1; idx2++)
887 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
888 if (hi->poolidx == hi->pool[idx2])
889 put_membuf_printf (&mb, "*");
891 put_membuf( &mb, "", 1);
892 p = get_membuf (&mb, NULL);
894 return gpg_error_from_syserror ();
895 err = ks_print_help (ctrl, p);
906 /* Print a help output for the schemata supported by this module. */
908 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
911 "Handler for HKP URLs:\n"
913 #if HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
916 "Supported methods: search, get, put\n";
919 #if HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
920 const char data2[] = " hkp\n hkps";
922 const char data2[] = " hkp";
926 err = ks_print_help (ctrl, data2);
927 else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
928 || !strcmp (uri->scheme, "hkps")))
929 err = ks_print_help (ctrl, data);
937 /* Build the remote part of the URL from SCHEME, HOST and an optional
938 * PORT. If NO_SRV is set no SRV record lookup will be done. Returns
939 * an allocated string at R_HOSTPORT or NULL on failure. If
940 * R_HTTPHOST is not NULL it receives a malloced string with the
941 * hostname; this may be different from HOST if HOST is selected from
944 make_host_part (ctrl_t ctrl,
945 const char *scheme, const char *host, unsigned short port,
946 int force_reselect, int no_srv,
947 char **r_hostport, unsigned int *r_httpflags, char **r_httphost)
956 if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
959 srvtag = no_srv? NULL : "pgpkey-https";
961 else /* HKP or HTTP. */
964 srvtag = no_srv? NULL : "pgpkey-http";
968 err = map_host (ctrl, host, srvtag, force_reselect,
969 &hostname, portstr, r_httpflags, r_httphost);
973 /* If map_host did not return a port (from a SRV record) but a port
974 * has been specified (implicitly or explicitly) then use that port.
975 * In the case that a port was not specified (which is probably a
976 * bug in https.c) we will set up defaults. */
979 else if (!*portstr && port)
980 snprintf (portstr, sizeof portstr, "%hu", port);
981 else if (!strcmp (scheme,"https"))
982 strcpy (portstr, "443");
984 strcpy (portstr, "11371");
986 if (*hostname != '[' && is_ip_address (hostname) == 6)
987 *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
989 *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
998 return gpg_error_from_syserror ();
1004 /* Resolve all known keyserver names and update the hosttable. This
1005 is mainly useful for debugging because the resolving is anyway done
1008 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
1011 char *hostport = NULL;
1013 /* NB: With an explicitly given port we do not want to consult a
1014 * service record because that might be in conflict with the port
1015 * from such a service record. */
1016 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1017 1, uri->explicit_port,
1018 &hostport, NULL, NULL);
1021 err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
1022 uri->scheme, uri->host, uri->port,
1023 gpg_strerror (err));
1027 err = ks_printf_help (ctrl, "%s", hostport);
1034 /* Reload (SIGHUP) action for this module. We mark all host alive
1035 * even those which have been manually shot. */
1037 ks_hkp_reload (void)
1042 for (idx=count=0; idx < hosttable_size; idx++)
1044 hi = hosttable[idx];
1053 log_info ("number of resurrected hosts: %d", count);
1057 /* Send an HTTP request. On success returns an estream object at
1058 R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is
1059 not NULL it will be used as HTTP "Host" header. If POST_CB is not
1060 NULL a post request is used and that callback is called to allow
1061 writing the post data. If R_HTTP_STATUS is not NULL, the http
1062 status code will be stored there. */
1064 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
1065 const char *httphost, unsigned int httpflags,
1066 gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
1067 estream_t *r_fp, unsigned int *r_http_status)
1070 http_session_t session = NULL;
1072 int redirects_left = MAX_REDIRECTS;
1073 estream_t fp = NULL;
1074 char *request_buffer = NULL;
1078 err = http_session_new (&session, NULL, httphost, HTTP_FLAG_TRUST_DEF);
1081 http_session_set_log_cb (session, cert_log_cb);
1084 err = http_open (&http,
1085 post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1088 /* fixme: AUTH */ NULL,
1090 |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
1091 |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
1092 |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)),
1096 /*FIXME curl->srvtag*/NULL);
1099 fp = http_get_write_ptr (http);
1100 /* Avoid caches to get the most recent copy of the key. We set
1101 both the Pragma and Cache-Control versions of the header, so
1102 we're good with both HTTP 1.0 and 1.1. */
1103 es_fputs ("Pragma: no-cache\r\n"
1104 "Cache-Control: no-cache\r\n", fp);
1106 err = post_cb (post_cb_value, http);
1109 http_start_data (http);
1111 err = gpg_error_from_syserror ();
1116 /* Fixme: After a redirection we show the old host name. */
1117 log_error (_("error connecting to '%s': %s\n"),
1118 hostportstr, gpg_strerror (err));
1122 /* Wait for the response. */
1123 dirmngr_tick (ctrl);
1124 err = http_wait_response (http);
1127 log_error (_("error reading HTTP response for '%s': %s\n"),
1128 hostportstr, gpg_strerror (err));
1132 if (http_get_tls_info (http, NULL))
1134 /* Update the httpflags so that a redirect won't fallback to an
1135 unencrypted connection. */
1136 httpflags |= HTTP_FLAG_FORCE_TLS;
1140 *r_http_status = http_get_status_code (http);
1142 switch (http_get_status_code (http))
1146 break; /* Success. */
1152 const char *s = http_get_header (http, "Location");
1154 log_info (_("URL '%s' redirected to '%s' (%u)\n"),
1155 request, s?s:"[none]", http_get_status_code (http));
1156 if (s && *s && redirects_left-- )
1158 xfree (request_buffer);
1159 request_buffer = xtrystrdup (s);
1162 request = request_buffer;
1163 http_close (http, 0);
1167 err = gpg_error_from_syserror ();
1170 err = gpg_error (GPG_ERR_NO_DATA);
1171 log_error (_("too many redirections\n"));
1176 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1180 log_error (_("error accessing '%s': http status %u\n"),
1181 request, http_get_status_code (http));
1182 err = gpg_error (GPG_ERR_NO_DATA);
1186 /* FIXME: We should register a permanent redirection and whether a
1187 host has ever used TLS so that future calls will always use
1190 fp = http_get_read_ptr (http);
1193 err = gpg_error (GPG_ERR_BUG);
1197 /* Return the read stream and close the HTTP context. */
1199 http_close (http, 1);
1203 http_close (http, 0);
1204 http_session_release (session);
1205 xfree (request_buffer);
1210 /* Helper to evaluate the error code ERR from a send_request() call
1211 with REQUEST. The function returns true if the caller shall try
1212 again. TRIES_LEFT points to a variable to track the number of
1213 retries; this function decrements it and won't return true if it is
1216 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
1217 unsigned int *tries_left)
1221 /* Fixme: Should we disable all hosts of a protocol family if a
1222 * request for an address of that familiy returned ENETDOWN? */
1224 switch (gpg_err_code (err))
1226 case GPG_ERR_ECONNREFUSED:
1227 if (tor_not_running_p (ctrl))
1228 break; /* A retry does not make sense. */
1229 /* Okay: Tor is up or --use-tor is not used. */
1231 case GPG_ERR_ENETUNREACH:
1232 case GPG_ERR_ENETDOWN:
1233 case GPG_ERR_UNKNOWN_HOST:
1234 case GPG_ERR_NETWORK:
1235 if (mark_host_dead (request) && *tries_left)
1239 case GPG_ERR_ETIMEDOUT:
1242 log_info ("selecting a different host due to a timeout\n");
1247 case GPG_ERR_EACCES:
1248 if (dirmngr_use_tor ())
1250 log_info ("(Tor configuration problem)\n");
1251 dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
1252 "Please check that the \"SocksPort\" flag "
1253 "\"IPv6Traffic\" is set in torrc", NULL);
1268 /* Search the keyserver identified by URI for keys matching PATTERN.
1269 On success R_FP has an open stream to read the data. If
1270 R_HTTP_STATUS is not NULL, the http status code will be stored
1273 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1274 estream_t *r_fp, unsigned int *r_http_status)
1277 KEYDB_SEARCH_DESC desc;
1278 char fprbuf[2+40+1];
1279 char *hostport = NULL;
1280 char *request = NULL;
1281 estream_t fp = NULL;
1283 unsigned int httpflags;
1284 char *httphost = NULL;
1285 unsigned int tries = SEND_REQUEST_RETRIES;
1289 /* Remove search type indicator and adjust PATTERN accordingly.
1290 Note that HKP keyservers like the 0x to be present when searching
1291 by keyid. We need to re-format the fingerprint and keyids so to
1292 remove the gpg specific force-use-of-this-key flag ("!"). */
1293 err = classify_user_id (pattern, &desc, 1);
1298 case KEYDB_SEARCH_MODE_EXACT:
1299 case KEYDB_SEARCH_MODE_SUBSTR:
1300 case KEYDB_SEARCH_MODE_MAIL:
1301 case KEYDB_SEARCH_MODE_MAILSUB:
1302 pattern = desc.u.name;
1304 case KEYDB_SEARCH_MODE_SHORT_KID:
1305 snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1308 case KEYDB_SEARCH_MODE_LONG_KID:
1309 snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1310 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1313 case KEYDB_SEARCH_MODE_FPR16:
1316 bin2hex (desc.u.fpr, 16, fprbuf+2);
1319 case KEYDB_SEARCH_MODE_FPR20:
1320 case KEYDB_SEARCH_MODE_FPR:
1323 bin2hex (desc.u.fpr, 20, fprbuf+2);
1327 return gpg_error (GPG_ERR_INV_USER_ID);
1330 /* Build the request string. */
1336 xfree (hostport); hostport = NULL;
1337 xfree (httphost); httphost = NULL;
1338 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1339 reselect, uri->explicit_port,
1340 &hostport, &httpflags, &httphost);
1344 searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1347 err = gpg_error_from_syserror ();
1352 request = strconcat (hostport,
1353 "/pks/lookup?op=index&options=mr&search=",
1359 err = gpg_error_from_syserror ();
1364 /* Send the request. */
1365 err = send_request (ctrl, request, hostport, httphost, httpflags,
1366 NULL, NULL, &fp, r_http_status);
1367 if (handle_send_request_error (ctrl, err, request, &tries))
1375 err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1379 /* Peek at the response. */
1381 int c = es_getc (fp);
1384 err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1385 log_error ("error reading response: %s\n", gpg_strerror (err));
1390 /* The document begins with a '<': Assume a HTML response,
1391 which we don't support. */
1392 err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1398 /* Return the read stream. */
1411 /* Get the key described key the KEYSPEC string from the keyserver
1412 identified by URI. On success R_FP has an open stream to read the
1413 data. The data will be provided in a format GnuPG can import
1414 (either a binary OpenPGP message or an armored one). */
1416 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1419 KEYDB_SEARCH_DESC desc;
1420 char kidbuf[2+40+1];
1421 const char *exactname = NULL;
1422 char *searchkey = NULL;
1423 char *hostport = NULL;
1424 char *request = NULL;
1425 estream_t fp = NULL;
1427 char *httphost = NULL;
1428 unsigned int httpflags;
1429 unsigned int tries = SEND_REQUEST_RETRIES;
1433 /* Remove search type indicator and adjust PATTERN accordingly.
1434 Note that HKP keyservers like the 0x to be present when searching
1435 by keyid. We need to re-format the fingerprint and keyids so to
1436 remove the gpg specific force-use-of-this-key flag ("!"). */
1437 err = classify_user_id (keyspec, &desc, 1);
1442 case KEYDB_SEARCH_MODE_SHORT_KID:
1443 snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1445 case KEYDB_SEARCH_MODE_LONG_KID:
1446 snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1447 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1449 case KEYDB_SEARCH_MODE_FPR20:
1450 case KEYDB_SEARCH_MODE_FPR:
1451 /* This is a v4 fingerprint. */
1454 bin2hex (desc.u.fpr, 20, kidbuf+2);
1457 case KEYDB_SEARCH_MODE_EXACT:
1458 exactname = desc.u.name;
1461 case KEYDB_SEARCH_MODE_FPR16:
1462 log_error ("HKP keyservers do not support v3 fingerprints\n");
1464 return gpg_error (GPG_ERR_INV_USER_ID);
1467 searchkey = http_escape_string (exactname? exactname : kidbuf,
1468 EXTRA_ESCAPE_CHARS);
1471 err = gpg_error_from_syserror ();
1477 /* Build the request string. */
1478 xfree (hostport); hostport = NULL;
1479 xfree (httphost); httphost = NULL;
1480 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1481 reselect, uri->explicit_port,
1482 &hostport, &httpflags, &httphost);
1487 request = strconcat (hostport,
1488 "/pks/lookup?op=get&options=mr&search=",
1490 exactname? "&exact=on":"",
1494 err = gpg_error_from_syserror ();
1498 /* Send the request. */
1499 err = send_request (ctrl, request, hostport, httphost, httpflags,
1500 NULL, NULL, &fp, NULL);
1501 if (handle_send_request_error (ctrl, err, request, &tries))
1509 err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1513 /* Return the read stream and close the HTTP context. */
1529 /* Callback parameters for put_post_cb. */
1530 struct put_post_parm_s
1536 /* Helper for ks_hkp_put. */
1538 put_post_cb (void *opaque, http_t http)
1540 struct put_post_parm_s *parm = opaque;
1541 gpg_error_t err = 0;
1545 fp = http_get_write_ptr (http);
1546 len = strlen (parm->datastring);
1549 "Content-Type: application/x-www-form-urlencoded\r\n"
1550 "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1551 http_start_data (http);
1552 if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1553 err = gpg_error_from_syserror ();
1558 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI. */
1560 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1563 char *hostport = NULL;
1564 char *request = NULL;
1565 estream_t fp = NULL;
1566 struct put_post_parm_s parm;
1567 char *armored = NULL;
1569 char *httphost = NULL;
1570 unsigned int httpflags;
1571 unsigned int tries = SEND_REQUEST_RETRIES;
1573 parm.datastring = NULL;
1575 err = armor_data (&armored, data, datalen);
1579 parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1580 if (!parm.datastring)
1582 err = gpg_error_from_syserror ();
1588 /* Build the request string. */
1591 xfree (hostport); hostport = NULL;
1592 xfree (httphost); httphost = NULL;
1593 err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1594 reselect, uri->explicit_port,
1595 &hostport, &httpflags, &httphost);
1600 request = strconcat (hostport, "/pks/add", NULL);
1603 err = gpg_error_from_syserror ();
1607 /* Send the request. */
1608 err = send_request (ctrl, request, hostport, httphost, 0,
1609 put_post_cb, &parm, &fp, NULL);
1610 if (handle_send_request_error (ctrl, err, request, &tries))
1620 xfree (parm.datastring);