Imported Upstream version 2.4.3
[platform/upstream/gpg2.git] / dirmngr / ks-engine-hkp.c
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
4  *
5  * This file is part of GnuPG.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #ifdef HAVE_W32_SYSTEM
28 # ifdef HAVE_WINSOCK2_H
29 #  include <winsock2.h>
30 # endif
31 # include <windows.h>
32 #else /*!HAVE_W32_SYSTEM*/
33 # include <sys/types.h>
34 # include <sys/socket.h>
35 # include <netdb.h>
36 #endif /*!HAVE_W32_SYSTEM*/
37
38 #include <npth.h>
39 #include "dirmngr.h"
40 #include "misc.h"
41 #include "../common/userids.h"
42 #include "dns-stuff.h"
43 #include "ks-engine.h"
44
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. */
48 #ifndef EAI_OVERFLOW
49 # define EAI_OVERFLOW EAI_FAIL
50 #endif
51 #ifdef HAVE_W32_SYSTEM
52 # ifndef EAI_SYSTEM
53 #  define EAI_SYSTEM WSAEINVAL
54 # endif
55 #endif
56
57
58 /* Number of seconds after a host is marked as resurrected.  */
59 #define RESURRECT_INTERVAL  (3600+1800)  /* 1.5 hours */
60
61 /* To match the behaviour of our old gpgkeys helper code we escape
62    more characters than actually needed. */
63 #define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
64
65 /* How many redirections do we allow.  */
66 #define MAX_REDIRECTS 2
67
68 /* Number of retries done for a dead host etc.  */
69 #define SEND_REQUEST_RETRIES 3
70
71 /* Number of retries done in case of transient errors.  */
72 #define SEND_REQUEST_EXTRA_RETRIES 5
73
74
75 enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
76
77 /* Objects used to maintain information about hosts.  */
78 struct hostinfo_s;
79 typedef struct hostinfo_s *hostinfo_t;
80 struct hostinfo_s
81 {
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
99                                      lookup.  */
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
107                         if unknown.  */
108   char name[1];      /* The hostname.  */
109 };
110
111
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;
118
119 /* The number of host slots we initially allocate for HOSTTABLE.  */
120 #define INITIAL_HOSTTABLE_SIZE 50
121
122
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
125    error. */
126 static int
127 create_new_hostinfo (const char *name)
128 {
129   hostinfo_t hi, *newtable;
130   int newsize;
131   int idx, rc;
132
133   hi = xtrymalloc (sizeof *hi + strlen (name));
134   if (!hi)
135     return -1;
136   strcpy (hi->name, name);
137   hi->pool = NULL;
138   hi->pool_len = 0;
139   hi->pool_size = 0;
140   hi->poolidx = -1;
141   hi->lastused = (time_t)(-1);
142   hi->lastfail = (time_t)(-1);
143   hi->v4 = 0;
144   hi->v6 = 0;
145   hi->onion = 0;
146   hi->dead = 0;
147   hi->did_a_lookup = 0;
148   hi->did_srv_lookup = 0;
149   hi->iporname_valid = 0;
150   hi->died_at = 0;
151   hi->cname = NULL;
152   hi->iporname = NULL;
153   hi->port[KS_PROTOCOL_HKP] = 0;
154   hi->port[KS_PROTOCOL_HKPS] = 0;
155
156   /* Add it to the hosttable. */
157   for (idx=0; idx < hosttable_size; idx++)
158     if (!hosttable[idx])
159       {
160         hosttable[idx] = hi;
161         return idx;
162       }
163   /* Need to extend the hosttable.  */
164   newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
165   newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
166   if (!newtable)
167     {
168       xfree (hi);
169       return -1;
170     }
171   hosttable = newtable;
172   idx = hosttable_size;
173   hosttable_size = newsize;
174   rc = idx;
175   hosttable[idx++] = hi;
176   while (idx < hosttable_size)
177     hosttable[idx++] = NULL;
178
179   return rc;
180 }
181
182
183 /* Find the host NAME in our table.  Return the index into the
184    hosttable or -1 if not found.  */
185 static int
186 find_hostinfo (const char *name)
187 {
188   int idx;
189
190   for (idx=0; idx < hosttable_size; idx++)
191     if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
192       return idx;
193   return -1;
194 }
195
196
197 static int
198 sort_hostpool (const void *xa, const void *xb)
199 {
200   int a = *(int *)xa;
201   int b = *(int *)xb;
202
203   assert (a >= 0 && a < hosttable_size);
204   assert (b >= 0 && b < hosttable_size);
205   assert (hosttable[a]);
206   assert (hosttable[b]);
207
208   return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
209 }
210
211
212 /* Return true if the host with the hosttable index TBLIDX is in HI->pool.  */
213 static int
214 host_in_pool_p (hostinfo_t hi, int tblidx)
215 {
216   int i, pidx;
217
218   for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
219     if (pidx == tblidx && hosttable[pidx])
220       return 1;
221   return 0;
222 }
223
224
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
227    selected.  */
228 static int
229 select_random_host (hostinfo_t hi)
230 {
231   int *tbl;
232   size_t tblsize;
233   int pidx, idx;
234
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/ */
237
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;
242        idx++)
243     if (hosttable[pidx] && !hosttable[pidx]->dead)
244       tblsize++;
245   if (!tblsize)
246     return -1; /* No hosts.  */
247
248   tbl = xtrymalloc (tblsize * sizeof *tbl);
249   if (!tbl)
250     return -1;
251   for (idx = 0, tblsize = 0;
252        idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
253        idx++)
254     if (hosttable[pidx] && !hosttable[pidx]->dead)
255       tbl[tblsize++] = pidx;
256
257   if (tblsize == 1)  /* Save a get_uint_nonce.  */
258     pidx = tbl[0];
259   else
260     pidx = tbl[get_uint_nonce () % tblsize];
261
262   xfree (tbl);
263   return pidx;
264 }
265
266
267 /* Figure out if a set of DNS records looks like a pool.  */
268 static int
269 arecords_is_pool (dns_addrinfo_t aibuf)
270 {
271   dns_addrinfo_t ai;
272   int n_v6, n_v4;
273
274   n_v6 = n_v4 = 0;
275   for (ai = aibuf; ai; ai = ai->next)
276     {
277       if (ai->family == AF_INET6)
278         n_v6++;
279       else if (ai->family == AF_INET)
280         n_v4++;
281     }
282
283   return n_v6 > 1 || n_v4 > 1;
284 }
285
286
287 /* Print a warning iff Tor is not running but Tor has been requested.
288  * Also return true if it is not running.  */
289 static int
290 tor_not_running_p (ctrl_t ctrl)
291 {
292   assuan_fd_t sock;
293
294   if (!dirmngr_use_tor ())
295     return 0;
296
297   sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
298   if (sock != ASSUAN_INVALID_FD)
299     {
300       assuan_sock_close (sock);
301       return 0;
302     }
303
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);
308   return 1;
309 }
310
311
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.  */
316 static void
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)
320 {
321   gpg_error_t tmperr;
322   char *tmphost;
323   int idx, tmpidx;
324   hostinfo_t host;
325   int i;
326
327   idx = find_hostinfo (name);
328   host = hosttable[idx];
329
330   if (is_pool)
331     {
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);
335     }
336   else if (!is_ip_address (name))
337     {
338       /* This is a hostname.  Use the name as given without going
339        * through resolve_dns_addr.  */
340       tmphost = xtrystrdup (name);
341       if (!tmphost)
342         tmperr = gpg_error_from_syserror ();
343       else
344         tmperr = 0;
345     }
346   else
347     {
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);
352     }
353
354   if (tmperr)
355     {
356       log_info ("resolve_dns_addr failed while checking '%s': %s\n",
357                 name, gpg_strerror (tmperr));
358     }
359   else if (host->pool_len + 1 >= MAX_POOL_SIZE)
360     {
361       log_error ("resolve_dns_addr for '%s': '%s'"
362                  " [index table full - ignored]\n", name, tmphost);
363     }
364   else
365     {
366       if (!is_pool && is_ip_address (name))
367         /* Update the original entry.  */
368         tmpidx = idx;
369       else
370         tmpidx = find_hostinfo (tmphost);
371       log_info ("resolve_dns_addr for '%s': '%s'%s\n",
372                 name, tmphost,
373                 tmpidx == -1? "" : " [already known]");
374
375       if (tmpidx == -1) /* Create a new entry.  */
376         tmpidx = create_new_hostinfo (tmphost);
377
378       if (tmpidx == -1)
379         {
380           log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
381                      name, strerror (errno), tmphost);
382         }
383       else  /* Set or update the entry. */
384         {
385           if (port)
386             hosttable[tmpidx]->port[protocol] = port;
387
388           if (ai->family == AF_INET6)
389             {
390               hosttable[tmpidx]->v6 = 1;
391             }
392           else if (ai->family == AF_INET)
393             {
394               hosttable[tmpidx]->v4 = 1;
395             }
396           else
397             BUG ();
398
399           /* If we updated the main entry, we're done.  */
400           if (idx == tmpidx)
401             goto leave;
402
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)
406               goto leave;
407
408           /* Otherwise, we need to add it to the pool.  Check if there
409              is space.  */
410           if (host->pool_len + 1 > host->pool_size)
411             {
412               int *new_pool;
413               size_t new_size;
414
415               if (host->pool_size == 0)
416                 new_size = 4;
417               else
418                 new_size = host->pool_size * 2;
419
420               new_pool = xtryrealloc (host->pool,
421                                       new_size * sizeof *new_pool);
422
423               if (new_pool == NULL)
424                 goto leave;
425
426               host->pool = new_pool;
427               host->pool_size = new_size;
428             }
429
430           /* Finally, add it.  */
431           log_assert (host->pool_len < host->pool_size);
432           host->pool[host->pool_len++] = tmpidx;
433         }
434     }
435  leave:
436   xfree (tmphost);
437 }
438
439
440 /* Sort the pool of the given hostinfo HI.  */
441 static void
442 hostinfo_sort_pool (hostinfo_t hi)
443 {
444   qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
445 }
446
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
461  * pool.  */
462 static gpg_error_t
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)
466 {
467   gpg_error_t err = 0;
468   hostinfo_t hi;
469   int idx;
470   dns_addrinfo_t aibuf, ai;
471   int is_pool;
472   int new_hosts = 0;
473   char *cname;
474
475   *r_host = NULL;
476   if (r_httpflags)
477     *r_httpflags = 0;
478   if (r_httphost)
479     *r_httphost = NULL;
480
481   /* No hostname means localhost.  */
482   if (!name || !*name)
483     {
484       *r_host = xtrystrdup ("localhost");
485       if (!*r_host)
486         return gpg_error_from_syserror ();
487       if (r_httphost)
488         {
489           *r_httphost = xtrystrdup (*r_host);
490           if (!*r_httphost)
491             {
492               err = gpg_error_from_syserror ();
493               xfree (*r_host);
494               *r_host = NULL;
495               return err;
496             }
497         }
498       return 0;
499     }
500
501   /* See whether the host is in our table.  */
502   idx = find_hostinfo (name);
503   if (idx == -1)
504     {
505       idx = create_new_hostinfo (name);
506       if (idx == -1)
507         return gpg_error_from_syserror ();
508       hi = hosttable[idx];
509       hi->onion = is_onion_address (name);
510     }
511   else
512     hi = hosttable[idx];
513
514   is_pool = hi->pool != NULL;
515
516   if (srvtag && !is_ip_address (name)
517       && ! hi->onion
518       && ! (hi->did_srv_lookup & 1 << protocol))
519     {
520       struct srventry *srvs;
521       unsigned int srvscount;
522
523       /* Check for SRV records.  */
524       err = get_dns_srv (ctrl, name, srvtag, NULL, &srvs, &srvscount);
525       if (err)
526         {
527           if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
528             tor_not_running_p (ctrl);
529           return err;
530         }
531
532       if (srvscount > 0)
533         {
534           int i;
535           if (! is_pool)
536             is_pool = srvscount > 1;
537
538           for (i = 0; i < srvscount; i++)
539             {
540               err = resolve_dns_name (ctrl, srvs[i].target, 0,
541                                       AF_UNSPEC, SOCK_STREAM,
542                                       &ai, &cname);
543               if (err)
544                 continue;
545               dirmngr_tick (ctrl);
546               add_host (ctrl, name, is_pool, ai, protocol, srvs[i].port);
547               new_hosts = 1;
548             }
549
550           xfree (srvs);
551         }
552
553       hi->did_srv_lookup |= 1 << protocol;
554     }
555
556   if (! hi->did_a_lookup
557       && ! hi->onion)
558     {
559       /* Find all A records for this entry and put them into the pool
560          list - if any.  */
561       err = resolve_dns_name (ctrl, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
562       if (err)
563         {
564           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
565           err = 0;
566         }
567       else
568         {
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
573              specified name. */
574           if (! is_pool)
575             is_pool = arecords_is_pool (aibuf);
576           if (is_pool && cname)
577             {
578               hi->cname = cname;
579               cname = NULL;
580             }
581
582           for (ai = aibuf; ai; ai = ai->next)
583             {
584               if (ai->family != AF_INET && ai->family != AF_INET6)
585                 continue;
586               if (opt.disable_ipv4 && ai->family == AF_INET)
587                 continue;
588               if (opt.disable_ipv6 && ai->family == AF_INET6)
589                 continue;
590               dirmngr_tick (ctrl);
591
592               add_host (ctrl, name, is_pool, ai, 0, 0);
593               new_hosts = 1;
594             }
595
596           hi->did_a_lookup = 1;
597         }
598       xfree (cname);
599       free_dns_addrinfo (aibuf);
600     }
601   if (new_hosts)
602     hostinfo_sort_pool (hi);
603
604   if (hi->pool)
605     {
606       /* Deal with the pool name before selecting a host. */
607       if (r_httphost)
608         {
609           *r_httphost = xtrystrdup (hi->name);
610           if (!*r_httphost)
611             return gpg_error_from_syserror ();
612         }
613
614       /* If the currently selected host is now marked dead, force a
615          re-selection .  */
616       if (force_reselect)
617         hi->poolidx = -1;
618       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
619                && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
620         hi->poolidx = -1;
621
622       /* Select a host if needed.  */
623       if (hi->poolidx == -1)
624         {
625           hi->poolidx = select_random_host (hi);
626           if (hi->poolidx == -1)
627             {
628               log_error ("no alive host found in pool '%s'\n", name);
629               if (r_httphost)
630                 {
631                   xfree (*r_httphost);
632                   *r_httphost = NULL;
633                 }
634               return gpg_error (GPG_ERR_NO_KEYSERVER);
635             }
636         }
637
638       assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
639       hi = hosttable[hi->poolidx];
640       assert (hi);
641     }
642   else if (r_httphost && is_ip_address (hi->name))
643     {
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
647        * hosttable. */
648       char *host;
649
650       err = resolve_dns_name (ctrl, hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
651       if (!err)
652         {
653           for (ai = aibuf; ai; ai = ai->next)
654             {
655               if ((!opt.disable_ipv6 && ai->family == AF_INET6)
656                   || (!opt.disable_ipv4 && ai->family == AF_INET))
657                 {
658                   err = resolve_dns_addr (ctrl,
659                                           ai->addr, ai->addrlen, 0, &host);
660                   if (!err)
661                     {
662                       /* Okay, we return the first found name.  */
663                       *r_httphost = host;
664                       break;
665                     }
666                 }
667             }
668         }
669       free_dns_addrinfo (aibuf);
670     }
671   else if (r_httphost)
672     {
673       *r_httphost = xtrystrdup (hi->name);
674       if (!*r_httphost)
675         return gpg_error_from_syserror ();
676     }
677
678   if (hi->dead)
679     {
680       log_error ("host '%s' marked as dead\n", hi->name);
681       if (r_httphost)
682         {
683           xfree (*r_httphost);
684           *r_httphost = NULL;
685         }
686       return gpg_error (GPG_ERR_NO_KEYSERVER);
687     }
688
689   if (r_httpflags)
690     {
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.  */
696       if (!hi->v4)
697         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
698       if (!hi->v6)
699         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
700
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
704          enabled.  */
705     }
706
707   *r_host = xtrystrdup (hi->name);
708   if (!*r_host)
709     {
710       err = gpg_error_from_syserror ();
711       if (r_httphost)
712         {
713           xfree (*r_httphost);
714           *r_httphost = NULL;
715         }
716       return err;
717     }
718   if (hi->port[protocol])
719     snprintf (r_portstr, 6 /* five digits and the sentinel */,
720               "%hu", hi->port[protocol]);
721   return 0;
722 }
723
724
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).  */
728 static int
729 mark_host_dead (const char *name)
730 {
731   const char *host;
732   char *host_buffer = NULL;
733   parsed_uri_t parsed_uri = NULL;
734   int done = 0;
735
736   if (name && *name
737       && !http_parse_uri (&parsed_uri, name, HTTP_PARSE_NO_SCHEME_CHECK))
738     {
739       if (parsed_uri->v6lit)
740         {
741           host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
742           if (!host_buffer)
743             log_error ("out of core in mark_host_dead");
744           host = host_buffer;
745         }
746       else
747         host = parsed_uri->host;
748     }
749   else
750     host = name;
751
752   if (host && *host && strcmp (host, "localhost"))
753     {
754       hostinfo_t hi;
755       int idx;
756
757       idx = find_hostinfo (host);
758       if (idx != -1)
759         {
760           hi = hosttable[idx];
761           log_info ("marking host '%s' as dead%s\n",
762                     hi->name, hi->dead? " (again)":"");
763           hi->dead = 1;
764           hi->died_at = gnupg_get_time ();
765           if (!hi->died_at)
766             hi->died_at = 1;
767           done = 1;
768         }
769     }
770
771   http_release_parsed_uri (parsed_uri);
772   xfree (host_buffer);
773   return done;
774 }
775
776
777 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
778    alive.  */
779 gpg_error_t
780 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
781 {
782   gpg_error_t err = 0;
783   hostinfo_t hi, hi2;
784   int idx, idx2, idx3, n;
785
786   if (!name || !*name || !strcmp (name, "localhost"))
787     return 0;
788
789   if (npth_mutex_lock (&hosttable_lock))
790     log_fatal ("failed to acquire mutex\n");
791
792   idx = find_hostinfo (name);
793   if (idx == -1)
794     {
795       err = gpg_error (GPG_ERR_NOT_FOUND);
796       goto leave;
797     }
798
799   hi = hosttable[idx];
800   if (alive && hi->dead)
801     {
802       hi->dead = 0;
803       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
804     }
805   else if (!alive && !hi->dead)
806     {
807       hi->dead = 1;
808       hi->died_at = 0; /* Manually set dead.  */
809       err = ks_printf_help (ctrl, "marking '%s' as dead", name);
810     }
811
812   /* If the host is a pool mark all member hosts. */
813   if (!err && hi->pool)
814     {
815       for (idx2 = 0;
816            !err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
817            idx2++)
818         {
819           assert (n >= 0 && n < hosttable_size);
820
821           if (!alive)
822             {
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++)
826                 {
827                   if (hosttable[idx3]
828                       && hosttable[idx3]->pool
829                       && idx3 != idx
830                       && host_in_pool_p (hosttable[idx3], n))
831                     break;
832                 }
833               if (idx3 < hosttable_size)
834                 continue;  /* Host is also a member of another pool.  */
835             }
836
837           hi2 = hosttable[n];
838           if (!hi2)
839             ;
840           else if (alive && hi2->dead)
841             {
842               hi2->dead = 0;
843               err = ks_printf_help (ctrl, "marking '%s' as alive",
844                                     hi2->name);
845             }
846           else if (!alive && !hi2->dead)
847             {
848               hi2->dead = 1;
849               hi2->died_at = 0; /* Manually set dead. */
850               err = ks_printf_help (ctrl, "marking '%s' as dead",
851                                     hi2->name);
852             }
853         }
854     }
855
856  leave:
857   if (npth_mutex_unlock (&hosttable_lock))
858     log_fatal ("failed to release mutex\n");
859
860   return err;
861 }
862
863
864 /* Debug function to print the entire hosttable.  */
865 gpg_error_t
866 ks_hkp_print_hosttable (ctrl_t ctrl)
867 {
868   gpg_error_t err;
869   int idx, idx2;
870   hostinfo_t hi;
871   membuf_t mb;
872   time_t curtime;
873   char *p, *died;
874   const char *diedstr;
875
876   err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
877   if (err)
878     return err;
879
880   if (npth_mutex_lock (&hosttable_lock))
881     log_fatal ("failed to acquire mutex\n");
882
883   curtime = gnupg_get_time ();
884   for (idx=0; idx < hosttable_size; idx++)
885     if ((hi=hosttable[idx]))
886       {
887         if (hi->dead && hi->died_at)
888           {
889             died = elapsed_time_string (hi->died_at, curtime);
890             diedstr = died? died : "error";
891           }
892         else
893           diedstr = died = NULL;
894
895         if (!hi->iporname_valid)
896           {
897             char *canon = NULL;
898
899             xfree (hi->iporname);
900             hi->iporname = NULL;
901
902             /* Do a lookup just for the display purpose.  */
903             if (hi->onion || hi->pool)
904               ;
905             else if (is_ip_address (hi->name))
906               {
907                 dns_addrinfo_t aibuf, ai;
908
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,
912                                        SOCK_STREAM,
913                                        &aibuf, &canon))
914                   {
915                     if (canon && is_ip_address (canon))
916                       {
917                         xfree (canon);
918                         canon = NULL;
919                       }
920                     for (ai = aibuf; !canon && ai; ai = ai->next)
921                       {
922                         resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
923                                           DNS_WITHBRACKET, &canon);
924                         if (canon && is_ip_address (canon))
925                           {
926                             /* We already have the numeric IP - no need to
927                              * display it a second time.  */
928                             xfree (canon);
929                             canon = NULL;
930                           }
931                       }
932                   }
933                 free_dns_addrinfo (aibuf);
934               }
935             else
936               {
937                 dns_addrinfo_t aibuf, ai;
938
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,
944                                        SOCK_STREAM,
945                                        &aibuf, NULL))
946                   {
947                     for (ai = aibuf; !canon && ai; ai = ai->next)
948                       {
949                         resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
950                                           DNS_NUMERICHOST|DNS_WITHBRACKET,
951                                           &canon);
952                       }
953                   }
954                 free_dns_addrinfo (aibuf);
955               }
956
957             hi->iporname = canon;
958             hi->iporname_valid = 1;
959           }
960
961         err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s\n",
962                               idx,
963                               hi->onion? "O" : hi->v6? "6":" ",
964                               hi->v4? "4":" ",
965                               hi->dead? "d":" ",
966                               hi->name,
967                               hi->iporname? " (":"",
968                               hi->iporname? hi->iporname : "",
969                               hi->iporname? ")":"",
970                               diedstr? "  (":"",
971                               diedstr? diedstr:"",
972                               diedstr? ")":""   );
973         xfree (died);
974         if (err)
975           goto leave;
976
977         if (hi->cname)
978           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
979         if (err)
980           goto leave;
981
982         if (hi->pool)
983           {
984             init_membuf (&mb, 256);
985             put_membuf_printf (&mb, "  .   -->");
986             for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
987               {
988                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
989                 if (hi->poolidx == hi->pool[idx2])
990                   put_membuf_printf (&mb, "*");
991               }
992             put_membuf( &mb, "", 1);
993             p = get_membuf (&mb, NULL);
994             if (!p)
995               {
996                 err = gpg_error_from_syserror ();
997                 goto leave;
998               }
999             err = ks_print_help (ctrl, p);
1000             xfree (p);
1001             if (err)
1002               goto leave;
1003           }
1004       }
1005
1006  leave:
1007   if (npth_mutex_unlock (&hosttable_lock))
1008     log_fatal ("failed to release mutex\n");
1009   return err;
1010 }
1011
1012
1013
1014 /* Print a help output for the schemata supported by this module. */
1015 gpg_error_t
1016 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
1017 {
1018   const char data[] =
1019     "Handler for HKP URLs:\n"
1020     "  hkp://\n"
1021 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
1022     "  hkps://\n"
1023 #endif
1024     "Supported methods: search, get, put\n";
1025   gpg_error_t err;
1026
1027 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
1028   const char data2[] = "  hkp\n  hkps";
1029 #else
1030   const char data2[] = "  hkp";
1031 #endif
1032
1033   if (!uri)
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);
1038   else
1039     err = 0;
1040
1041   return err;
1042 }
1043
1044
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
1050  * a pool.  */
1051 static gpg_error_t
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)
1056 {
1057   gpg_error_t err;
1058   const char *srvtag;
1059   char portstr[10];
1060   char *hostname;
1061   enum ks_protocol protocol;
1062
1063   *r_hostport = NULL;
1064
1065   if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
1066     {
1067       scheme = "https";
1068       srvtag = no_srv? NULL : "pgpkey-https";
1069       protocol = KS_PROTOCOL_HKPS;
1070     }
1071   else /* HKP or HTTP.  */
1072     {
1073       scheme = "http";
1074       srvtag = no_srv? NULL : "pgpkey-http";
1075       protocol = KS_PROTOCOL_HKP;
1076     }
1077
1078   if (npth_mutex_lock (&hosttable_lock))
1079     log_fatal ("failed to acquire mutex\n");
1080
1081   portstr[0] = 0;
1082   err = map_host (ctrl, host, srvtag, force_reselect, protocol,
1083                   &hostname, portstr, r_httpflags, r_httphost);
1084
1085   if (npth_mutex_unlock (&hosttable_lock))
1086     log_fatal ("failed to release mutex\n");
1087
1088   if (err)
1089     return err;
1090
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.  */
1095   if (*portstr)
1096     ;
1097   else if (!*portstr && port)
1098     snprintf (portstr, sizeof portstr, "%hu", port);
1099   else if (!strcmp (scheme,"https"))
1100     strcpy (portstr, "443");
1101   else
1102     strcpy (portstr, "11371");
1103
1104   if (*hostname != '[' && is_ip_address (hostname) == 6)
1105     *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
1106   else
1107     *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
1108   xfree (hostname);
1109   if (!*r_hostport)
1110     {
1111       if (r_httphost)
1112         {
1113           xfree (*r_httphost);
1114           *r_httphost = NULL;
1115         }
1116       return gpg_error_from_syserror ();
1117     }
1118   return 0;
1119 }
1120
1121
1122 /* Resolve all known keyserver names and update the hosttable.  This
1123    is mainly useful for debugging because the resolving is anyway done
1124    on demand.  */
1125 gpg_error_t
1126 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
1127 {
1128   gpg_error_t err;
1129   char *hostport = NULL;
1130
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);
1137   if (err)
1138     {
1139       err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
1140                             uri->scheme, uri->host, uri->port,
1141                             gpg_strerror (err));
1142     }
1143   else
1144     {
1145       err = ks_printf_help (ctrl, "%s", hostport);
1146       xfree (hostport);
1147     }
1148   return err;
1149 }
1150
1151
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
1154    some time.  */
1155 void
1156 ks_hkp_housekeeping (time_t curtime)
1157 {
1158   int idx;
1159   hostinfo_t hi;
1160
1161   if (npth_mutex_lock (&hosttable_lock))
1162     log_fatal ("failed to acquire mutex\n");
1163
1164   for (idx=0; idx < hosttable_size; idx++)
1165     {
1166       hi = hosttable[idx];
1167       if (!hi)
1168         continue;
1169       if (!hi->dead)
1170         continue;
1171       if (!hi->died_at)
1172         continue; /* Do not resurrect manually shot hosts.  */
1173       if (hi->died_at + RESURRECT_INTERVAL <= curtime
1174           || hi->died_at > curtime)
1175         {
1176           hi->dead = 0;
1177           log_info ("resurrected host '%s'", hi->name);
1178         }
1179     }
1180
1181   if (npth_mutex_unlock (&hosttable_lock))
1182     log_fatal ("failed to release mutex\n");
1183 }
1184
1185
1186 /* Reload (SIGHUP) action for this module.  We mark all host alive
1187  * even those which have been manually shot.  */
1188 void
1189 ks_hkp_reload (void)
1190 {
1191   int idx, count;
1192   hostinfo_t hi;
1193
1194   if (npth_mutex_lock (&hosttable_lock))
1195     log_fatal ("failed to acquire mutex\n");
1196
1197   for (idx=count=0; idx < hosttable_size; idx++)
1198     {
1199       hi = hosttable[idx];
1200       if (!hi)
1201         continue;
1202       hi->iporname_valid = 0;
1203       if (!hi->dead)
1204         continue;
1205       hi->dead = 0;
1206       count++;
1207     }
1208   if (count)
1209     log_info ("number of resurrected hosts: %d", count);
1210
1211   if (npth_mutex_unlock (&hosttable_lock))
1212     log_fatal ("failed to release mutex\n");
1213 }
1214
1215
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.  */
1222 static gpg_error_t
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)
1227 {
1228   gpg_error_t err;
1229   http_session_t session = NULL;
1230   http_t http = 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;
1235
1236   *r_fp = NULL;
1237
1238   err = http_parse_uri (&uri, request, 0);
1239   if (err)
1240     goto leave;
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);
1248
1249  once_more:
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);
1254   if (err)
1255     goto leave;
1256   http_session_set_log_cb (session, cert_log_cb);
1257   http_session_set_timeout (session, ctrl->timeout);
1258
1259   err = http_open (ctrl, &http,
1260                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1261                    request,
1262                    httphost,
1263                    /* fixme: AUTH */ NULL,
1264                    (httpflags
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)),
1269                    ctrl->http_proxy,
1270                    session,
1271                    NULL,
1272                    /*FIXME curl->srvtag*/NULL);
1273   if (!err)
1274     {
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);
1281       if (post_cb)
1282         err = post_cb (post_cb_value, http);
1283       if (!err)
1284         {
1285           http_start_data (http);
1286           if (es_ferror (fp))
1287             err = gpg_error_from_syserror ();
1288         }
1289     }
1290   if (err)
1291     {
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));
1295       goto leave;
1296     }
1297
1298   /* Wait for the response.  */
1299   dirmngr_tick (ctrl);
1300   err = http_wait_response (http);
1301   if (err)
1302     {
1303       log_error (_("error reading HTTP response for '%s': %s\n"),
1304                  hostportstr, gpg_strerror (err));
1305       goto leave;
1306     }
1307
1308   if (http_get_tls_info (http, NULL))
1309     {
1310       /* Update the httpflags so that a redirect won't fallback to an
1311          unencrypted connection.  */
1312       httpflags |= HTTP_FLAG_FORCE_TLS;
1313     }
1314
1315   if (r_http_status)
1316     *r_http_status = http_get_status_code (http);
1317
1318   switch (http_get_status_code (http))
1319     {
1320     case 200:
1321       err = 0;
1322       break; /* Success.  */
1323
1324     case 301:
1325     case 302:
1326     case 307:
1327       {
1328         xfree (request_buffer);
1329         err = http_prepare_redirect (&redirinfo, http_get_status_code (http),
1330                                      http_get_header (http, "Location"),
1331                                      &request_buffer);
1332         if (err)
1333           goto leave;
1334
1335         request = request_buffer;
1336         http_close (http, 0);
1337         http = NULL;
1338         http_session_release (session);
1339         session = NULL;
1340       }
1341       goto once_more;
1342
1343     case 501:
1344       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1345       goto leave;
1346
1347     case 413:  /* Payload too large */
1348       err = gpg_error (GPG_ERR_TOO_LARGE);
1349       goto leave;
1350
1351     default:
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);
1355       goto leave;
1356     }
1357
1358   /* FIXME: We should register a permanent redirection and whether a
1359      host has ever used TLS so that future calls will always use
1360      TLS. */
1361
1362   fp = http_get_read_ptr (http);
1363   if (!fp)
1364     {
1365       err = gpg_error (GPG_ERR_BUG);
1366       goto leave;
1367     }
1368
1369   /* Return the read stream and close the HTTP context.  */
1370   *r_fp = fp;
1371   http_close (http, 1);
1372   http = NULL;
1373
1374  leave:
1375   http_close (http, 0);
1376   http_session_release (session);
1377   xfree (request_buffer);
1378   http_release_parsed_uri (uri);
1379   return err;
1380 }
1381
1382
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.  */
1389 static int
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)
1393 {
1394   int retry = 0;
1395
1396   /* Fixme: Should we disable all hosts of a protocol family if a
1397    * request for an address of that family returned ENETDOWN?  */
1398
1399   switch (gpg_err_code (err))
1400     {
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.  */
1405       /*FALLTHRU*/
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)
1414         retry = 1;
1415       break;
1416
1417     case GPG_ERR_ETIMEDOUT:
1418       if (*tries_left)
1419         {
1420           log_info ("selecting a different host due to a timeout\n");
1421           retry = 1;
1422         }
1423       break;
1424
1425     case GPG_ERR_EACCES:
1426       if (dirmngr_use_tor ())
1427         {
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);
1432         }
1433       break;
1434
1435     case GPG_ERR_NO_DATA:
1436       {
1437         switch (http_status)
1438           {
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)
1443               retry = 1;
1444             break;
1445
1446           case 503: /* Service Unavailable */
1447           case 504: /* Gateway Timeout    */
1448             if (*extra_tries_left)
1449               {
1450                 log_info ("selecting a different host due to a %u (%s)",
1451                           http_status, http_status2string (http_status));
1452                 retry = 2;
1453               }
1454             break;
1455           }
1456       }
1457       break;
1458
1459     default:
1460       break;
1461     }
1462
1463   if (retry == 2)
1464     {
1465       if (*extra_tries_left)
1466         --*extra_tries_left;
1467     }
1468   else
1469     {
1470       if (*tries_left)
1471         --*tries_left;
1472     }
1473
1474   return retry;
1475 }
1476
1477 \f
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
1481    there.  */
1482 gpg_error_t
1483 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1484                estream_t *r_fp, unsigned int *r_http_status)
1485 {
1486   gpg_error_t err;
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;
1493   int reselect;
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;
1499
1500   *r_fp = NULL;
1501
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);
1507   if (err)
1508     return err;
1509   log_assert (desc.fprlen <= 64);
1510   switch (desc.mode)
1511     {
1512     case KEYDB_SEARCH_MODE_EXACT:
1513     case KEYDB_SEARCH_MODE_SUBSTR:
1514     case KEYDB_SEARCH_MODE_MAILSUB:
1515       pattern = desc.u.name;
1516       break;
1517     case KEYDB_SEARCH_MODE_MAIL:
1518       namebuffer = xtrystrdup (desc.u.name);
1519       if (!namebuffer)
1520         {
1521           err = gpg_error_from_syserror ();
1522           goto leave;
1523         }
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;
1531       else
1532         pattern = namebuffer;
1533       break;
1534     case KEYDB_SEARCH_MODE_SHORT_KID:
1535       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1536       pattern = fprbuf;
1537       break;
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]);
1541       pattern = fprbuf;
1542       break;
1543     case KEYDB_SEARCH_MODE_FPR:
1544       fprbuf[0] = '0';
1545       fprbuf[1] = 'x';
1546       bin2hex (desc.u.fpr, desc.fprlen, fprbuf+2);
1547       pattern = fprbuf;
1548       break;
1549     default:
1550       return gpg_error (GPG_ERR_INV_USER_ID);
1551     }
1552
1553   /* Build the request string.  */
1554   reselect = 0;
1555  again:
1556   {
1557     char *searchkey;
1558
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);
1564     if (err)
1565       goto leave;
1566
1567     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1568     if (!searchkey)
1569       {
1570         err = gpg_error_from_syserror ();
1571         goto leave;
1572       }
1573
1574     xfree (request);
1575     request = strconcat (hostport,
1576                          "/pks/lookup?op=index&options=mr&fingerprint=on&search=",
1577                          searchkey,
1578                          NULL);
1579     xfree (searchkey);
1580     if (!request)
1581       {
1582         err = gpg_error_from_syserror ();
1583         goto leave;
1584       }
1585   }
1586
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))
1592     {
1593       reselect = 1;
1594       goto again;
1595     }
1596   if (r_http_status)
1597     *r_http_status = http_status;
1598   if (err)
1599     {
1600       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1601         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1602       goto leave;
1603     }
1604
1605   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1606   if (err)
1607     goto leave;
1608
1609   /* Peek at the response.  */
1610   {
1611     int c = es_getc (fp);
1612     if (c == -1)
1613       {
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));
1616         goto leave;
1617       }
1618     if (c == '<')
1619       {
1620         /* The document begins with a '<': Assume a HTML response,
1621            which we don't support.  */
1622         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1623         goto leave;
1624       }
1625     es_ungetc (c, fp);
1626   }
1627
1628   /* Return the read stream.  */
1629   *r_fp = fp;
1630   fp = NULL;
1631
1632  leave:
1633   es_fclose (fp);
1634   xfree (request);
1635   xfree (hostport);
1636   xfree (httphost);
1637   xfree (namebuffer);
1638   return err;
1639 }
1640
1641
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).  */
1646 gpg_error_t
1647 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1648 {
1649   gpg_error_t err;
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;
1658   int reselect;
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;
1664
1665   *r_fp = NULL;
1666
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);
1672   if (err)
1673     return err;
1674   log_assert (desc.fprlen <= 64);
1675   switch (desc.mode)
1676     {
1677     case KEYDB_SEARCH_MODE_SHORT_KID:
1678       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1679       break;
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]);
1683       break;
1684     case KEYDB_SEARCH_MODE_FPR:
1685       if (desc.fprlen < 20)
1686         {
1687           log_error ("HKP keyservers do not support v3 fingerprints\n");
1688           return gpg_error (GPG_ERR_INV_USER_ID);
1689         }
1690       kidbuf[0] = '0';
1691       kidbuf[1] = 'x';
1692       bin2hex (desc.u.fpr, desc.fprlen, kidbuf+2);
1693       break;
1694
1695     case KEYDB_SEARCH_MODE_EXACT:
1696       exactname = desc.u.name;
1697       break;
1698
1699     case KEYDB_SEARCH_MODE_MAIL:
1700       namebuffer = xtrystrdup (desc.u.name);
1701       if (!namebuffer)
1702         {
1703           err = gpg_error_from_syserror ();
1704           goto leave;
1705         }
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;
1713       else
1714         exactname = namebuffer;
1715       break;
1716
1717     default:
1718       return gpg_error (GPG_ERR_INV_USER_ID);
1719     }
1720
1721   searchkey = http_escape_string (exactname? exactname : kidbuf,
1722                                   EXTRA_ESCAPE_CHARS);
1723   if (!searchkey)
1724     {
1725       err = gpg_error_from_syserror ();
1726       goto leave;
1727     }
1728
1729   reselect = 0;
1730  again:
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);
1737   if (err)
1738     goto leave;
1739
1740   xfree (request);
1741   request = strconcat (hostport,
1742                        "/pks/lookup?op=get&options=mr&search=",
1743                        searchkey,
1744                        exactname? "&exact=on":"",
1745                        NULL);
1746   if (!request)
1747     {
1748       err = gpg_error_from_syserror ();
1749       goto leave;
1750     }
1751
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))
1757     {
1758       reselect = 1;
1759       goto again;
1760     }
1761   if (err)
1762     {
1763       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1764         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1765       goto leave;
1766     }
1767
1768   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1769   if (err)
1770     goto leave;
1771
1772   /* Return the read stream and close the HTTP context.  */
1773   *r_fp = fp;
1774   fp = NULL;
1775
1776  leave:
1777   es_fclose (fp);
1778   xfree (namebuffer);
1779   xfree (request);
1780   xfree (hostport);
1781   xfree (httphost);
1782   xfree (searchkey);
1783   return err;
1784 }
1785
1786
1787
1788 \f
1789 /* Callback parameters for put_post_cb.  */
1790 struct put_post_parm_s
1791 {
1792   char *datastring;
1793 };
1794
1795
1796 /* Helper for ks_hkp_put.  */
1797 static gpg_error_t
1798 put_post_cb (void *opaque, http_t http)
1799 {
1800   struct put_post_parm_s *parm = opaque;
1801   gpg_error_t err = 0;
1802   estream_t fp;
1803   size_t len;
1804
1805   fp = http_get_write_ptr (http);
1806   len = strlen (parm->datastring);
1807
1808   es_fprintf (fp,
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 ();
1814   return err;
1815 }
1816
1817
1818 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1819 gpg_error_t
1820 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1821 {
1822   gpg_error_t err;
1823   char *hostport = NULL;
1824   char *request = NULL;
1825   estream_t fp = NULL;
1826   struct put_post_parm_s parm;
1827   char *armored = NULL;
1828   int reselect;
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;
1834
1835   parm.datastring = NULL;
1836
1837   err = armor_data (&armored, data, datalen);
1838   if (err)
1839     goto leave;
1840
1841   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1842   if (!parm.datastring)
1843     {
1844       err = gpg_error_from_syserror ();
1845       goto leave;
1846     }
1847   xfree (armored);
1848   armored = NULL;
1849
1850   /* Build the request string.  */
1851   reselect = 0;
1852  again:
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);
1858   if (err)
1859     goto leave;
1860
1861   xfree (request);
1862   request = strconcat (hostport, "/pks/add", NULL);
1863   if (!request)
1864     {
1865       err = gpg_error_from_syserror ();
1866       goto leave;
1867     }
1868
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))
1874     {
1875       reselect = 1;
1876       goto again;
1877     }
1878   if (err)
1879     goto leave;
1880
1881  leave:
1882   es_fclose (fp);
1883   xfree (parm.datastring);
1884   xfree (armored);
1885   xfree (request);
1886   xfree (hostport);
1887   xfree (httphost);
1888   return err;
1889 }
1890
1891 void
1892 ks_hkp_init (void)
1893 {
1894   int err;
1895
1896   err = npth_mutex_init (&hosttable_lock, NULL);
1897   if (err)
1898     log_fatal ("error initializing mutex: %s\n", strerror (err));
1899 }