5292da8445930d86d5132c61e844878dbfca99b8
[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 whey we allow a downgrade for hkp requests.
1246    * Needs at least an explanation here..  */
1247
1248  once_more:
1249   err = http_session_new (&session, httphost,
1250                           ((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
1251                            | HTTP_FLAG_TRUST_DEF),
1252                           gnupg_http_tls_verify_cb, ctrl);
1253   if (err)
1254     goto leave;
1255   http_session_set_log_cb (session, cert_log_cb);
1256   http_session_set_timeout (session, ctrl->timeout);
1257
1258   err = http_open (ctrl, &http,
1259                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1260                    request,
1261                    httphost,
1262                    /* fixme: AUTH */ NULL,
1263                    (httpflags
1264                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
1265                     |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
1266                     |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
1267                     |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
1268                    ctrl->http_proxy,
1269                    session,
1270                    NULL,
1271                    /*FIXME curl->srvtag*/NULL);
1272   if (!err)
1273     {
1274       fp = http_get_write_ptr (http);
1275       /* Avoid caches to get the most recent copy of the key.  We set
1276          both the Pragma and Cache-Control versions of the header, so
1277          we're good with both HTTP 1.0 and 1.1.  */
1278       es_fputs ("Pragma: no-cache\r\n"
1279                 "Cache-Control: no-cache\r\n", fp);
1280       if (post_cb)
1281         err = post_cb (post_cb_value, http);
1282       if (!err)
1283         {
1284           http_start_data (http);
1285           if (es_ferror (fp))
1286             err = gpg_error_from_syserror ();
1287         }
1288     }
1289   if (err)
1290     {
1291       /* Fixme: After a redirection we show the old host name.  */
1292       log_error (_("error connecting to '%s': %s\n"),
1293                  hostportstr, gpg_strerror (err));
1294       goto leave;
1295     }
1296
1297   /* Wait for the response.  */
1298   dirmngr_tick (ctrl);
1299   err = http_wait_response (http);
1300   if (err)
1301     {
1302       log_error (_("error reading HTTP response for '%s': %s\n"),
1303                  hostportstr, gpg_strerror (err));
1304       goto leave;
1305     }
1306
1307   if (http_get_tls_info (http, NULL))
1308     {
1309       /* Update the httpflags so that a redirect won't fallback to an
1310          unencrypted connection.  */
1311       httpflags |= HTTP_FLAG_FORCE_TLS;
1312     }
1313
1314   if (r_http_status)
1315     *r_http_status = http_get_status_code (http);
1316
1317   switch (http_get_status_code (http))
1318     {
1319     case 200:
1320       err = 0;
1321       break; /* Success.  */
1322
1323     case 301:
1324     case 302:
1325     case 307:
1326       {
1327         xfree (request_buffer);
1328         err = http_prepare_redirect (&redirinfo, http_get_status_code (http),
1329                                      http_get_header (http, "Location"),
1330                                      &request_buffer);
1331         if (err)
1332           goto leave;
1333
1334         request = request_buffer;
1335         http_close (http, 0);
1336         http = NULL;
1337         http_session_release (session);
1338         session = NULL;
1339       }
1340       goto once_more;
1341
1342     case 501:
1343       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1344       goto leave;
1345
1346     case 413:  /* Payload too large */
1347       err = gpg_error (GPG_ERR_TOO_LARGE);
1348       goto leave;
1349
1350     default:
1351       log_error (_("error accessing '%s': http status %u\n"),
1352                  request, http_get_status_code (http));
1353       err = gpg_error (GPG_ERR_NO_DATA);
1354       goto leave;
1355     }
1356
1357   /* FIXME: We should register a permanent redirection and whether a
1358      host has ever used TLS so that future calls will always use
1359      TLS. */
1360
1361   fp = http_get_read_ptr (http);
1362   if (!fp)
1363     {
1364       err = gpg_error (GPG_ERR_BUG);
1365       goto leave;
1366     }
1367
1368   /* Return the read stream and close the HTTP context.  */
1369   *r_fp = fp;
1370   http_close (http, 1);
1371   http = NULL;
1372
1373  leave:
1374   http_close (http, 0);
1375   http_session_release (session);
1376   xfree (request_buffer);
1377   http_release_parsed_uri (uri);
1378   return err;
1379 }
1380
1381
1382 /* Helper to evaluate the error code ERR from a send_request() call
1383    with REQUEST.  The function returns true if the caller shall try
1384    again.  TRIES_LEFT points to a variable to track the number of
1385    retries; this function decrements it and won't return true if it is
1386    down to zero.  EXTRA_TRIES_LEFT does the same but only for
1387    transient http status codes.  */
1388 static int
1389 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
1390                            unsigned int http_status, unsigned int *tries_left,
1391                            unsigned int *extra_tries_left)
1392 {
1393   int retry = 0;
1394
1395   /* Fixme: Should we disable all hosts of a protocol family if a
1396    * request for an address of that family returned ENETDOWN?  */
1397
1398   switch (gpg_err_code (err))
1399     {
1400     case GPG_ERR_ECONNREFUSED:
1401       if (tor_not_running_p (ctrl))
1402         break; /* A retry does not make sense.  */
1403       /* Okay: Tor is up or --use-tor is not used.  */
1404       /*FALLTHRU*/
1405     case GPG_ERR_ENETUNREACH:
1406     case GPG_ERR_ENETDOWN:
1407     case GPG_ERR_UNKNOWN_HOST:
1408     case GPG_ERR_NETWORK:
1409     case GPG_ERR_EIO:  /* Sometimes used by estream cookie functions.  */
1410     case GPG_ERR_EADDRNOTAVAIL:  /* e.g. when IPv6 is disabled */
1411     case GPG_ERR_EAFNOSUPPORT:  /* e.g. when IPv6 is not compiled in */
1412       if (mark_host_dead (request) && *tries_left)
1413         retry = 1;
1414       break;
1415
1416     case GPG_ERR_ETIMEDOUT:
1417       if (*tries_left)
1418         {
1419           log_info ("selecting a different host due to a timeout\n");
1420           retry = 1;
1421         }
1422       break;
1423
1424     case GPG_ERR_EACCES:
1425       if (dirmngr_use_tor ())
1426         {
1427           log_info ("(Tor configuration problem)\n");
1428           dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
1429                           "Please check that the \"SocksPort\" flag "
1430                           "\"IPv6Traffic\" is set in torrc", NULL);
1431         }
1432       break;
1433
1434     case GPG_ERR_NO_DATA:
1435       {
1436         switch (http_status)
1437           {
1438           case 502: /* Bad Gateway  */
1439             log_info ("marking host dead due to a %u (%s)\n",
1440                       http_status, http_status2string (http_status));
1441             if (mark_host_dead (request) && *tries_left)
1442               retry = 1;
1443             break;
1444
1445           case 503: /* Service Unavailable */
1446           case 504: /* Gateway Timeout    */
1447             if (*extra_tries_left)
1448               {
1449                 log_info ("selecting a different host due to a %u (%s)",
1450                           http_status, http_status2string (http_status));
1451                 retry = 2;
1452               }
1453             break;
1454           }
1455       }
1456       break;
1457
1458     default:
1459       break;
1460     }
1461
1462   if (retry == 2)
1463     {
1464       if (*extra_tries_left)
1465         --*extra_tries_left;
1466     }
1467   else
1468     {
1469       if (*tries_left)
1470         --*tries_left;
1471     }
1472
1473   return retry;
1474 }
1475
1476 \f
1477 /* Search the keyserver identified by URI for keys matching PATTERN.
1478    On success R_FP has an open stream to read the data.  If
1479    R_HTTP_STATUS is not NULL, the http status code will be stored
1480    there.  */
1481 gpg_error_t
1482 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1483                estream_t *r_fp, unsigned int *r_http_status)
1484 {
1485   gpg_error_t err;
1486   KEYDB_SEARCH_DESC desc;
1487   char fprbuf[2+64+1];
1488   char *namebuffer = NULL;
1489   char *hostport = NULL;
1490   char *request = NULL;
1491   estream_t fp = NULL;
1492   int reselect;
1493   unsigned int httpflags;
1494   char *httphost = NULL;
1495   unsigned int http_status;
1496   unsigned int tries = SEND_REQUEST_RETRIES;
1497   unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1498
1499   *r_fp = NULL;
1500
1501   /* Remove search type indicator and adjust PATTERN accordingly.
1502      Note that HKP keyservers like the 0x to be present when searching
1503      by keyid.  We need to re-format the fingerprint and keyids so to
1504      remove the gpg specific force-use-of-this-key flag ("!").  */
1505   err = classify_user_id (pattern, &desc, 1);
1506   if (err)
1507     return err;
1508   log_assert (desc.fprlen <= 64);
1509   switch (desc.mode)
1510     {
1511     case KEYDB_SEARCH_MODE_EXACT:
1512     case KEYDB_SEARCH_MODE_SUBSTR:
1513     case KEYDB_SEARCH_MODE_MAILSUB:
1514       pattern = desc.u.name;
1515       break;
1516     case KEYDB_SEARCH_MODE_MAIL:
1517       namebuffer = xtrystrdup (desc.u.name);
1518       if (!namebuffer)
1519         {
1520           err = gpg_error_from_syserror ();
1521           goto leave;
1522         }
1523       /* Strip trailing angle bracket.  */
1524       if (namebuffer[0] && namebuffer[1]
1525           && namebuffer[strlen (namebuffer)-1] == '>')
1526         namebuffer[strlen(namebuffer)-1] = 0;
1527       /* Strip optional leading angle bracket.  */
1528       if (*namebuffer == '<' && namebuffer[1])
1529         pattern = namebuffer + 1;
1530       else
1531         pattern = namebuffer;
1532       break;
1533     case KEYDB_SEARCH_MODE_SHORT_KID:
1534       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1535       pattern = fprbuf;
1536       break;
1537     case KEYDB_SEARCH_MODE_LONG_KID:
1538       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1539                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1540       pattern = fprbuf;
1541       break;
1542     case KEYDB_SEARCH_MODE_FPR:
1543       fprbuf[0] = '0';
1544       fprbuf[1] = 'x';
1545       bin2hex (desc.u.fpr, desc.fprlen, fprbuf+2);
1546       pattern = fprbuf;
1547       break;
1548     default:
1549       return gpg_error (GPG_ERR_INV_USER_ID);
1550     }
1551
1552   /* Build the request string.  */
1553   reselect = 0;
1554  again:
1555   {
1556     char *searchkey;
1557
1558     xfree (hostport); hostport = NULL;
1559     xfree (httphost); httphost = NULL;
1560     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1561                           reselect, uri->explicit_port,
1562                           &hostport, &httpflags, &httphost);
1563     if (err)
1564       goto leave;
1565
1566     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1567     if (!searchkey)
1568       {
1569         err = gpg_error_from_syserror ();
1570         goto leave;
1571       }
1572
1573     xfree (request);
1574     request = strconcat (hostport,
1575                          "/pks/lookup?op=index&options=mr&fingerprint=on&search=",
1576                          searchkey,
1577                          NULL);
1578     xfree (searchkey);
1579     if (!request)
1580       {
1581         err = gpg_error_from_syserror ();
1582         goto leave;
1583       }
1584   }
1585
1586   /* Send the request.  */
1587   err = send_request (ctrl, request, hostport, httphost, httpflags,
1588                       NULL, NULL, &fp, &http_status);
1589   if (handle_send_request_error (ctrl, err, request, http_status,
1590                                  &tries, &extra_tries))
1591     {
1592       reselect = 1;
1593       goto again;
1594     }
1595   if (r_http_status)
1596     *r_http_status = http_status;
1597   if (err)
1598     {
1599       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1600         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1601       goto leave;
1602     }
1603
1604   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1605   if (err)
1606     goto leave;
1607
1608   /* Peek at the response.  */
1609   {
1610     int c = es_getc (fp);
1611     if (c == -1)
1612       {
1613         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1614         log_error ("error reading response: %s\n", gpg_strerror (err));
1615         goto leave;
1616       }
1617     if (c == '<')
1618       {
1619         /* The document begins with a '<': Assume a HTML response,
1620            which we don't support.  */
1621         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1622         goto leave;
1623       }
1624     es_ungetc (c, fp);
1625   }
1626
1627   /* Return the read stream.  */
1628   *r_fp = fp;
1629   fp = NULL;
1630
1631  leave:
1632   es_fclose (fp);
1633   xfree (request);
1634   xfree (hostport);
1635   xfree (httphost);
1636   xfree (namebuffer);
1637   return err;
1638 }
1639
1640
1641 /* Get the key described key the KEYSPEC string from the keyserver
1642    identified by URI.  On success R_FP has an open stream to read the
1643    data.  The data will be provided in a format GnuPG can import
1644    (either a binary OpenPGP message or an armored one).  */
1645 gpg_error_t
1646 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1647 {
1648   gpg_error_t err;
1649   KEYDB_SEARCH_DESC desc;
1650   char kidbuf[2+64+1];
1651   const char *exactname = NULL;
1652   char *namebuffer = NULL;
1653   char *searchkey = NULL;
1654   char *hostport = NULL;
1655   char *request = NULL;
1656   estream_t fp = NULL;
1657   int reselect;
1658   char *httphost = NULL;
1659   unsigned int httpflags;
1660   unsigned int http_status;
1661   unsigned int tries = SEND_REQUEST_RETRIES;
1662   unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1663
1664   *r_fp = NULL;
1665
1666   /* Remove search type indicator and adjust PATTERN accordingly.
1667      Note that HKP keyservers like the 0x to be present when searching
1668      by keyid.  We need to re-format the fingerprint and keyids so to
1669      remove the gpg specific force-use-of-this-key flag ("!").  */
1670   err = classify_user_id (keyspec, &desc, 1);
1671   if (err)
1672     return err;
1673   log_assert (desc.fprlen <= 64);
1674   switch (desc.mode)
1675     {
1676     case KEYDB_SEARCH_MODE_SHORT_KID:
1677       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1678       break;
1679     case KEYDB_SEARCH_MODE_LONG_KID:
1680       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1681                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1682       break;
1683     case KEYDB_SEARCH_MODE_FPR:
1684       if (desc.fprlen < 20)
1685         {
1686           log_error ("HKP keyservers do not support v3 fingerprints\n");
1687           return gpg_error (GPG_ERR_INV_USER_ID);
1688         }
1689       kidbuf[0] = '0';
1690       kidbuf[1] = 'x';
1691       bin2hex (desc.u.fpr, desc.fprlen, kidbuf+2);
1692       break;
1693
1694     case KEYDB_SEARCH_MODE_EXACT:
1695       exactname = desc.u.name;
1696       break;
1697
1698     case KEYDB_SEARCH_MODE_MAIL:
1699       namebuffer = xtrystrdup (desc.u.name);
1700       if (!namebuffer)
1701         {
1702           err = gpg_error_from_syserror ();
1703           goto leave;
1704         }
1705       /* Strip trailing angle bracket.  */
1706       if (namebuffer[0] && namebuffer[1]
1707           && namebuffer[strlen (namebuffer)-1] == '>')
1708         namebuffer[strlen(namebuffer)-1] = 0;
1709       /* Strip optional leading angle bracket.  */
1710       if (*namebuffer == '<' && namebuffer[1])
1711         exactname = namebuffer + 1;
1712       else
1713         exactname = namebuffer;
1714       break;
1715
1716     default:
1717       return gpg_error (GPG_ERR_INV_USER_ID);
1718     }
1719
1720   searchkey = http_escape_string (exactname? exactname : kidbuf,
1721                                   EXTRA_ESCAPE_CHARS);
1722   if (!searchkey)
1723     {
1724       err = gpg_error_from_syserror ();
1725       goto leave;
1726     }
1727
1728   reselect = 0;
1729  again:
1730   /* Build the request string.  */
1731   xfree (hostport); hostport = NULL;
1732   xfree (httphost); httphost = NULL;
1733   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1734                         reselect, uri->explicit_port,
1735                         &hostport, &httpflags, &httphost);
1736   if (err)
1737     goto leave;
1738
1739   xfree (request);
1740   request = strconcat (hostport,
1741                        "/pks/lookup?op=get&options=mr&search=",
1742                        searchkey,
1743                        exactname? "&exact=on":"",
1744                        NULL);
1745   if (!request)
1746     {
1747       err = gpg_error_from_syserror ();
1748       goto leave;
1749     }
1750
1751   /* Send the request.  */
1752   err = send_request (ctrl, request, hostport, httphost, httpflags,
1753                       NULL, NULL, &fp, &http_status);
1754   if (handle_send_request_error (ctrl, err, request, http_status,
1755                                  &tries, &extra_tries))
1756     {
1757       reselect = 1;
1758       goto again;
1759     }
1760   if (err)
1761     {
1762       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1763         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1764       goto leave;
1765     }
1766
1767   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1768   if (err)
1769     goto leave;
1770
1771   /* Return the read stream and close the HTTP context.  */
1772   *r_fp = fp;
1773   fp = NULL;
1774
1775  leave:
1776   es_fclose (fp);
1777   xfree (namebuffer);
1778   xfree (request);
1779   xfree (hostport);
1780   xfree (httphost);
1781   xfree (searchkey);
1782   return err;
1783 }
1784
1785
1786
1787 \f
1788 /* Callback parameters for put_post_cb.  */
1789 struct put_post_parm_s
1790 {
1791   char *datastring;
1792 };
1793
1794
1795 /* Helper for ks_hkp_put.  */
1796 static gpg_error_t
1797 put_post_cb (void *opaque, http_t http)
1798 {
1799   struct put_post_parm_s *parm = opaque;
1800   gpg_error_t err = 0;
1801   estream_t fp;
1802   size_t len;
1803
1804   fp = http_get_write_ptr (http);
1805   len = strlen (parm->datastring);
1806
1807   es_fprintf (fp,
1808               "Content-Type: application/x-www-form-urlencoded\r\n"
1809               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1810   http_start_data (http);
1811   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1812     err = gpg_error_from_syserror ();
1813   return err;
1814 }
1815
1816
1817 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1818 gpg_error_t
1819 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1820 {
1821   gpg_error_t err;
1822   char *hostport = NULL;
1823   char *request = NULL;
1824   estream_t fp = NULL;
1825   struct put_post_parm_s parm;
1826   char *armored = NULL;
1827   int reselect;
1828   char *httphost = NULL;
1829   unsigned int httpflags;
1830   unsigned int http_status;
1831   unsigned int tries = SEND_REQUEST_RETRIES;
1832   unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
1833
1834   parm.datastring = NULL;
1835
1836   err = armor_data (&armored, data, datalen);
1837   if (err)
1838     goto leave;
1839
1840   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1841   if (!parm.datastring)
1842     {
1843       err = gpg_error_from_syserror ();
1844       goto leave;
1845     }
1846   xfree (armored);
1847   armored = NULL;
1848
1849   /* Build the request string.  */
1850   reselect = 0;
1851  again:
1852   xfree (hostport); hostport = NULL;
1853   xfree (httphost); httphost = NULL;
1854   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1855                         reselect, uri->explicit_port,
1856                         &hostport, &httpflags, &httphost);
1857   if (err)
1858     goto leave;
1859
1860   xfree (request);
1861   request = strconcat (hostport, "/pks/add", NULL);
1862   if (!request)
1863     {
1864       err = gpg_error_from_syserror ();
1865       goto leave;
1866     }
1867
1868   /* Send the request.  */
1869   err = send_request (ctrl, request, hostport, httphost, 0,
1870                       put_post_cb, &parm, &fp, &http_status);
1871   if (handle_send_request_error (ctrl, err, request, http_status,
1872                                  &tries, &extra_tries))
1873     {
1874       reselect = 1;
1875       goto again;
1876     }
1877   if (err)
1878     goto leave;
1879
1880  leave:
1881   es_fclose (fp);
1882   xfree (parm.datastring);
1883   xfree (armored);
1884   xfree (request);
1885   xfree (hostport);
1886   xfree (httphost);
1887   return err;
1888 }
1889
1890 void
1891 ks_hkp_init (void)
1892 {
1893   int err;
1894
1895   err = npth_mutex_init (&hosttable_lock, NULL);
1896   if (err)
1897     log_fatal ("error initializing mutex: %s\n", strerror (err));
1898 }