tools: Fix error handling for gpg-pair-tool.
[gnupg.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 enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
72
73 /* Objects used to maintain information about hosts.  */
74 struct hostinfo_s;
75 typedef struct hostinfo_s *hostinfo_t;
76 struct hostinfo_s
77 {
78   time_t lastfail;   /* Time we tried to connect and failed.  */
79   time_t lastused;   /* Time of last use.  */
80   int *pool;         /* An array with indices into HOSTTABLE or NULL
81                         if NAME is not a pool name.  */
82   size_t pool_len;   /* Length of POOL.  */
83   size_t pool_size;  /* Allocated size of POOL.  */
84 #define MAX_POOL_SIZE   128
85   int poolidx;       /* Index into POOL with the used host.  -1 if not set.  */
86   unsigned int v4:1; /* Host supports AF_INET.  */
87   unsigned int v6:1; /* Host supports AF_INET6.  */
88   unsigned int onion:1;/* NAME is an onion (Tor HS) address.  */
89   unsigned int dead:1; /* Host is currently unresponsive.  */
90   unsigned int iporname_valid:1;  /* The field IPORNAME below is valid */
91                                   /* (but may be NULL) */
92   unsigned int did_a_lookup:1;    /* Have we done an A lookup yet?  */
93   unsigned int did_srv_lookup:2;  /* One bit per protocol indicating
94                                      whether we already did a SRV
95                                      lookup.  */
96   time_t died_at;    /* The time the host was marked dead.  If this is
97                         0 the host has been manually marked dead.  */
98   char *cname;       /* Canonical name of the host.  Only set if this
99                         is a pool or NAME has a numerical IP address.  */
100   char *iporname;    /* Numeric IP address or name for printing.  */
101   unsigned short port[KS_PROTOCOL_MAX];
102                      /* The port used by the host for all protocols, 0
103                         if unknown.  */
104   char name[1];      /* The hostname.  */
105 };
106
107
108 /* An array of hostinfo_t for all hosts requested by the caller or
109    resolved from a pool name and its allocated size.*/
110 static hostinfo_t *hosttable;
111 static int hosttable_size;
112 /* A mutex used to serialize access to the hosttable. */
113 static npth_mutex_t hosttable_lock;
114
115 /* The number of host slots we initially allocate for HOSTTABLE.  */
116 #define INITIAL_HOSTTABLE_SIZE 50
117
118
119 /* Create a new hostinfo object, fill in NAME and put it into
120    HOSTTABLE.  Return the index into hosttable on success or -1 on
121    error. */
122 static int
123 create_new_hostinfo (const char *name)
124 {
125   hostinfo_t hi, *newtable;
126   int newsize;
127   int idx, rc;
128
129   hi = xtrymalloc (sizeof *hi + strlen (name));
130   if (!hi)
131     return -1;
132   strcpy (hi->name, name);
133   hi->pool = NULL;
134   hi->pool_len = 0;
135   hi->pool_size = 0;
136   hi->poolidx = -1;
137   hi->lastused = (time_t)(-1);
138   hi->lastfail = (time_t)(-1);
139   hi->v4 = 0;
140   hi->v6 = 0;
141   hi->onion = 0;
142   hi->dead = 0;
143   hi->did_a_lookup = 0;
144   hi->did_srv_lookup = 0;
145   hi->iporname_valid = 0;
146   hi->died_at = 0;
147   hi->cname = NULL;
148   hi->iporname = NULL;
149   hi->port[KS_PROTOCOL_HKP] = 0;
150   hi->port[KS_PROTOCOL_HKPS] = 0;
151
152   /* Add it to the hosttable. */
153   for (idx=0; idx < hosttable_size; idx++)
154     if (!hosttable[idx])
155       {
156         hosttable[idx] = hi;
157         return idx;
158       }
159   /* Need to extend the hosttable.  */
160   newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
161   newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
162   if (!newtable)
163     {
164       xfree (hi);
165       return -1;
166     }
167   hosttable = newtable;
168   idx = hosttable_size;
169   hosttable_size = newsize;
170   rc = idx;
171   hosttable[idx++] = hi;
172   while (idx < hosttable_size)
173     hosttable[idx++] = NULL;
174
175   return rc;
176 }
177
178
179 /* Find the host NAME in our table.  Return the index into the
180    hosttable or -1 if not found.  */
181 static int
182 find_hostinfo (const char *name)
183 {
184   int idx;
185
186   for (idx=0; idx < hosttable_size; idx++)
187     if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
188       return idx;
189   return -1;
190 }
191
192
193 static int
194 sort_hostpool (const void *xa, const void *xb)
195 {
196   int a = *(int *)xa;
197   int b = *(int *)xb;
198
199   assert (a >= 0 && a < hosttable_size);
200   assert (b >= 0 && b < hosttable_size);
201   assert (hosttable[a]);
202   assert (hosttable[b]);
203
204   return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
205 }
206
207
208 /* Return true if the host with the hosttable index TBLIDX is in HI->pool.  */
209 static int
210 host_in_pool_p (hostinfo_t hi, int tblidx)
211 {
212   int i, pidx;
213
214   for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
215     if (pidx == tblidx && hosttable[pidx])
216       return 1;
217   return 0;
218 }
219
220
221 /* Select a random host.  Consult HI->pool which indices into the global
222    hosttable.  Returns index into HI->pool or -1 if no host could be
223    selected.  */
224 static int
225 select_random_host (hostinfo_t hi)
226 {
227   int *tbl;
228   size_t tblsize;
229   int pidx, idx;
230
231   /* We create a new table so that we randomly select only from
232      currently alive hosts.  */
233   for (idx = 0, tblsize = 0;
234        idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
235        idx++)
236     if (hosttable[pidx] && !hosttable[pidx]->dead)
237       tblsize++;
238   if (!tblsize)
239     return -1; /* No hosts.  */
240
241   tbl = xtrymalloc (tblsize * sizeof *tbl);
242   if (!tbl)
243     return -1;
244   for (idx = 0, tblsize = 0;
245        idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
246        idx++)
247     if (hosttable[pidx] && !hosttable[pidx]->dead)
248       tbl[tblsize++] = pidx;
249
250   if (tblsize == 1)  /* Save a get_uint_nonce.  */
251     pidx = tbl[0];
252   else
253     pidx = tbl[get_uint_nonce () % tblsize];
254
255   xfree (tbl);
256   return pidx;
257 }
258
259
260 /* Figure out if a set of DNS records looks like a pool.  */
261 static int
262 arecords_is_pool (dns_addrinfo_t aibuf)
263 {
264   dns_addrinfo_t ai;
265   int n_v6, n_v4;
266
267   n_v6 = n_v4 = 0;
268   for (ai = aibuf; ai; ai = ai->next)
269     {
270       if (ai->family == AF_INET6)
271         n_v6++;
272       else if (ai->family == AF_INET)
273         n_v4++;
274     }
275
276   return n_v6 > 1 || n_v4 > 1;
277 }
278
279
280 /* Print a warning iff Tor is not running but Tor has been requested.
281  * Also return true if it is not running.  */
282 static int
283 tor_not_running_p (ctrl_t ctrl)
284 {
285   assuan_fd_t sock;
286
287   if (!dirmngr_use_tor ())
288     return 0;
289
290   sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
291   if (sock != ASSUAN_INVALID_FD)
292     {
293       assuan_sock_close (sock);
294       return 0;
295     }
296
297   log_info ("(it seems Tor is not running)\n");
298   dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
299                   "Tor is enabled but the local Tor daemon"
300                   " seems to be down", NULL);
301   return 1;
302 }
303
304
305 /* Add the host AI under the NAME into the HOSTTABLE.  If PORT is not
306    zero, it specifies which port to use to talk to the host for
307    PROTOCOL.  If NAME specifies a pool (as indicated by IS_POOL),
308    update the given reference table accordingly.  */
309 static void
310 add_host (ctrl_t ctrl, const char *name, int is_pool,
311           const dns_addrinfo_t ai,
312           enum ks_protocol protocol, unsigned short port)
313 {
314   gpg_error_t tmperr;
315   char *tmphost;
316   int idx, tmpidx;
317   hostinfo_t host;
318   int i;
319
320   idx = find_hostinfo (name);
321   host = hosttable[idx];
322
323   if (is_pool)
324     {
325       /* For a pool immediately convert the address to a string.  */
326       tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
327                                  (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
328     }
329   else if (!is_ip_address (name))
330     {
331       /* This is a hostname.  Use the name as given without going
332        * through resolve_dns_addr.  */
333       tmphost = xtrystrdup (name);
334       if (!tmphost)
335         tmperr = gpg_error_from_syserror ();
336       else
337         tmperr = 0;
338     }
339   else
340     {
341       /* Do a PTR lookup on AI.  If a name was not found the function
342        * returns the numeric address (with brackets).  */
343       tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
344                                  DNS_WITHBRACKET, &tmphost);
345     }
346
347   if (tmperr)
348     {
349       log_info ("resolve_dns_addr failed while checking '%s': %s\n",
350                 name, gpg_strerror (tmperr));
351     }
352   else if (host->pool_len + 1 >= MAX_POOL_SIZE)
353     {
354       log_error ("resolve_dns_addr for '%s': '%s'"
355                  " [index table full - ignored]\n", name, tmphost);
356     }
357   else
358     {
359       if (!is_pool && is_ip_address (name))
360         /* Update the original entry.  */
361         tmpidx = idx;
362       else
363         tmpidx = find_hostinfo (tmphost);
364       log_info ("resolve_dns_addr for '%s': '%s'%s\n",
365                 name, tmphost,
366                 tmpidx == -1? "" : " [already known]");
367
368       if (tmpidx == -1) /* Create a new entry.  */
369         tmpidx = create_new_hostinfo (tmphost);
370
371       if (tmpidx == -1)
372         {
373           log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
374                      name, strerror (errno), tmphost);
375         }
376       else  /* Set or update the entry. */
377         {
378           if (port)
379             hosttable[tmpidx]->port[protocol] = port;
380
381           if (ai->family == AF_INET6)
382             {
383               hosttable[tmpidx]->v6 = 1;
384             }
385           else if (ai->family == AF_INET)
386             {
387               hosttable[tmpidx]->v4 = 1;
388             }
389           else
390             BUG ();
391
392           /* If we updated the main entry, we're done.  */
393           if (idx == tmpidx)
394             goto leave;
395
396           /* If we updated an existing entry, we're done.  */
397           for (i = 0; i < host->pool_len; i++)
398             if (host->pool[i] == tmpidx)
399               goto leave;
400
401           /* Otherwise, we need to add it to the pool.  Check if there
402              is space.  */
403           if (host->pool_len + 1 > host->pool_size)
404             {
405               int *new_pool;
406               size_t new_size;
407
408               if (host->pool_size == 0)
409                 new_size = 4;
410               else
411                 new_size = host->pool_size * 2;
412
413               new_pool = xtryrealloc (host->pool,
414                                       new_size * sizeof *new_pool);
415
416               if (new_pool == NULL)
417                 goto leave;
418
419               host->pool = new_pool;
420               host->pool_size = new_size;
421             }
422
423           /* Finally, add it.  */
424           log_assert (host->pool_len < host->pool_size);
425           host->pool[host->pool_len++] = tmpidx;
426         }
427     }
428  leave:
429   xfree (tmphost);
430 }
431
432
433 /* Sort the pool of the given hostinfo HI.  */
434 static void
435 hostinfo_sort_pool (hostinfo_t hi)
436 {
437   qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
438 }
439
440 /* Map the host name NAME to the actual to be used host name.  This
441  * allows us to manage round robin DNS names.  We use our own strategy
442  * to choose one of the hosts.  For example we skip those hosts which
443  * failed for some time and we stick to one host for a time
444  * independent of DNS retry times.  If FORCE_RESELECT is true a new
445  * host is always selected.  If SRVTAG is NULL no service record
446  * lookup will be done, if it is set that service name is used.  The
447  * selected host is stored as a malloced string at R_HOST; on error
448  * NULL is stored.  If we know the port used by the selected host from
449  * a service record, a string representation is written to R_PORTSTR,
450  * otherwise it is left untouched.  If R_HTTPFLAGS is not NULL it will
451  * receive flags which are to be passed to http_open.  If R_HTTPHOST
452  * is not NULL a malloced name of the host is stored there; this might
453  * be different from R_HOST in case it has been selected from a
454  * pool.  */
455 static gpg_error_t
456 map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
457           enum ks_protocol protocol, char **r_host, char *r_portstr,
458           unsigned int *r_httpflags, char **r_httphost)
459 {
460   gpg_error_t err = 0;
461   hostinfo_t hi;
462   int idx;
463   dns_addrinfo_t aibuf, ai;
464   int is_pool;
465   int new_hosts = 0;
466   char *cname;
467
468   *r_host = NULL;
469   if (r_httpflags)
470     *r_httpflags = 0;
471   if (r_httphost)
472     *r_httphost = NULL;
473
474   /* No hostname means localhost.  */
475   if (!name || !*name)
476     {
477       *r_host = xtrystrdup ("localhost");
478       return *r_host? 0 : gpg_error_from_syserror ();
479     }
480
481   /* See whether the host is in our table.  */
482   idx = find_hostinfo (name);
483   if (idx == -1)
484     {
485       idx = create_new_hostinfo (name);
486       if (idx == -1)
487         return gpg_error_from_syserror ();
488       hi = hosttable[idx];
489       hi->onion = is_onion_address (name);
490     }
491   else
492     hi = hosttable[idx];
493
494   is_pool = hi->pool != NULL;
495
496   if (srvtag && !is_ip_address (name)
497       && ! hi->onion
498       && ! (hi->did_srv_lookup & 1 << protocol))
499     {
500       struct srventry *srvs;
501       unsigned int srvscount;
502
503       /* Check for SRV records.  */
504       err = get_dns_srv (ctrl, name, srvtag, NULL, &srvs, &srvscount);
505       if (err)
506         {
507           if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
508             tor_not_running_p (ctrl);
509           return err;
510         }
511
512       if (srvscount > 0)
513         {
514           int i;
515           if (! is_pool)
516             is_pool = srvscount > 1;
517
518           for (i = 0; i < srvscount; i++)
519             {
520               err = resolve_dns_name (ctrl, srvs[i].target, 0,
521                                       AF_UNSPEC, SOCK_STREAM,
522                                       &ai, &cname);
523               if (err)
524                 continue;
525               dirmngr_tick (ctrl);
526               add_host (ctrl, name, is_pool, ai, protocol, srvs[i].port);
527               new_hosts = 1;
528             }
529
530           xfree (srvs);
531         }
532
533       hi->did_srv_lookup |= 1 << protocol;
534     }
535
536   if (! hi->did_a_lookup
537       && ! hi->onion)
538     {
539       /* Find all A records for this entry and put them into the pool
540          list - if any.  */
541       err = resolve_dns_name (ctrl, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
542       if (err)
543         {
544           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
545           err = 0;
546         }
547       else
548         {
549           /* First figure out whether this is a pool.  For a pool we
550              use a different strategy than for a plain server: We use
551              the canonical name of the pool as the virtual host along
552              with the IP addresses.  If it is not a pool, we use the
553              specified name. */
554           if (! is_pool)
555             is_pool = arecords_is_pool (aibuf);
556           if (is_pool && cname)
557             {
558               hi->cname = cname;
559               cname = NULL;
560             }
561
562           for (ai = aibuf; ai; ai = ai->next)
563             {
564               if (ai->family != AF_INET && ai->family != AF_INET6)
565                 continue;
566               if (opt.disable_ipv4 && ai->family == AF_INET)
567                 continue;
568               if (opt.disable_ipv6 && ai->family == AF_INET6)
569                 continue;
570               dirmngr_tick (ctrl);
571
572               add_host (ctrl, name, is_pool, ai, 0, 0);
573               new_hosts = 1;
574             }
575
576           hi->did_a_lookup = 1;
577         }
578       xfree (cname);
579       free_dns_addrinfo (aibuf);
580     }
581   if (new_hosts)
582     hostinfo_sort_pool (hi);
583
584   if (hi->pool)
585     {
586       /* Deal with the pool name before selecting a host. */
587       if (r_httphost)
588         {
589           *r_httphost = xtrystrdup (hi->name);
590           if (!*r_httphost)
591             return gpg_error_from_syserror ();
592         }
593
594       /* If the currently selected host is now marked dead, force a
595          re-selection .  */
596       if (force_reselect)
597         hi->poolidx = -1;
598       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
599                && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
600         hi->poolidx = -1;
601
602       /* Select a host if needed.  */
603       if (hi->poolidx == -1)
604         {
605           hi->poolidx = select_random_host (hi);
606           if (hi->poolidx == -1)
607             {
608               log_error ("no alive host found in pool '%s'\n", name);
609               if (r_httphost)
610                 {
611                   xfree (*r_httphost);
612                   *r_httphost = NULL;
613                 }
614               return gpg_error (GPG_ERR_NO_KEYSERVER);
615             }
616         }
617
618       assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
619       hi = hosttable[hi->poolidx];
620       assert (hi);
621     }
622   else if (r_httphost && is_ip_address (hi->name))
623     {
624       /* This is a numerical IP address and not a pool.  We want to
625        * find the canonical name so that it can be used in the HTTP
626        * Host header.  Fixme: We should store that name in the
627        * hosttable. */
628       char *host;
629
630       err = resolve_dns_name (ctrl, hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
631       if (!err)
632         {
633           for (ai = aibuf; ai; ai = ai->next)
634             {
635               if ((!opt.disable_ipv6 && ai->family == AF_INET6)
636                   || (!opt.disable_ipv4 && ai->family == AF_INET))
637                 {
638                   err = resolve_dns_addr (ctrl,
639                                           ai->addr, ai->addrlen, 0, &host);
640                   if (!err)
641                     {
642                       /* Okay, we return the first found name.  */
643                       *r_httphost = host;
644                       break;
645                     }
646                 }
647             }
648         }
649       free_dns_addrinfo (aibuf);
650     }
651
652   if (hi->dead)
653     {
654       log_error ("host '%s' marked as dead\n", hi->name);
655       if (r_httphost)
656         {
657           xfree (*r_httphost);
658           *r_httphost = NULL;
659         }
660       return gpg_error (GPG_ERR_NO_KEYSERVER);
661     }
662
663   if (r_httpflags)
664     {
665       /* If the hosttable does not indicate that a certain host
666          supports IPv<N>, we explicit set the corresponding http
667          flags.  The reason for this is that a host might be listed in
668          a pool as not v6 only but actually support v6 when later
669          the name is resolved by our http layer.  */
670       if (!hi->v4)
671         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
672       if (!hi->v6)
673         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
674
675       /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion
676          addresses because the http module detects this itself.  This
677          also allows us to use an onion address without Tor mode being
678          enabled.  */
679     }
680
681   *r_host = xtrystrdup (hi->name);
682   if (!*r_host)
683     {
684       err = gpg_error_from_syserror ();
685       if (r_httphost)
686         {
687           xfree (*r_httphost);
688           *r_httphost = NULL;
689         }
690       return err;
691     }
692   if (hi->port[protocol])
693     snprintf (r_portstr, 6 /* five digits and the sentinel */,
694               "%hu", hi->port[protocol]);
695   return 0;
696 }
697
698
699 /* Mark the host NAME as dead.  NAME may be given as an URL.  Returns
700    true if a host was really marked as dead or was already marked dead
701    (e.g. by a concurrent session).  */
702 static int
703 mark_host_dead (const char *name)
704 {
705   const char *host;
706   char *host_buffer = NULL;
707   parsed_uri_t parsed_uri = NULL;
708   int done = 0;
709
710   if (name && *name && !http_parse_uri (&parsed_uri, name, 1))
711     {
712       if (parsed_uri->v6lit)
713         {
714           host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
715           if (!host_buffer)
716             log_error ("out of core in mark_host_dead");
717           host = host_buffer;
718         }
719       else
720         host = parsed_uri->host;
721     }
722   else
723     host = name;
724
725   if (host && *host && strcmp (host, "localhost"))
726     {
727       hostinfo_t hi;
728       int idx;
729
730       idx = find_hostinfo (host);
731       if (idx != -1)
732         {
733           hi = hosttable[idx];
734           log_info ("marking host '%s' as dead%s\n",
735                     hi->name, hi->dead? " (again)":"");
736           hi->dead = 1;
737           hi->died_at = gnupg_get_time ();
738           if (!hi->died_at)
739             hi->died_at = 1;
740           done = 1;
741         }
742     }
743
744   http_release_parsed_uri (parsed_uri);
745   xfree (host_buffer);
746   return done;
747 }
748
749
750 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
751    alive.  */
752 gpg_error_t
753 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
754 {
755   gpg_error_t err = 0;
756   hostinfo_t hi, hi2;
757   int idx, idx2, idx3, n;
758
759   if (!name || !*name || !strcmp (name, "localhost"))
760     return 0;
761
762   if (npth_mutex_lock (&hosttable_lock))
763     log_fatal ("failed to acquire mutex\n");
764
765   idx = find_hostinfo (name);
766   if (idx == -1)
767     {
768       err = gpg_error (GPG_ERR_NOT_FOUND);
769       goto leave;
770     }
771
772   hi = hosttable[idx];
773   if (alive && hi->dead)
774     {
775       hi->dead = 0;
776       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
777     }
778   else if (!alive && !hi->dead)
779     {
780       hi->dead = 1;
781       hi->died_at = 0; /* Manually set dead.  */
782       err = ks_printf_help (ctrl, "marking '%s' as dead", name);
783     }
784
785   /* If the host is a pool mark all member hosts. */
786   if (!err && hi->pool)
787     {
788       for (idx2 = 0;
789            !err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
790            idx2++)
791         {
792           assert (n >= 0 && n < hosttable_size);
793
794           if (!alive)
795             {
796               /* Do not mark a host from a pool dead if it is also a
797                  member in another pool.  */
798               for (idx3=0; idx3 < hosttable_size; idx3++)
799                 {
800                   if (hosttable[idx3]
801                       && hosttable[idx3]->pool
802                       && idx3 != idx
803                       && host_in_pool_p (hosttable[idx3], n))
804                     break;
805                 }
806               if (idx3 < hosttable_size)
807                 continue;  /* Host is also a member of another pool.  */
808             }
809
810           hi2 = hosttable[n];
811           if (!hi2)
812             ;
813           else if (alive && hi2->dead)
814             {
815               hi2->dead = 0;
816               err = ks_printf_help (ctrl, "marking '%s' as alive",
817                                     hi2->name);
818             }
819           else if (!alive && !hi2->dead)
820             {
821               hi2->dead = 1;
822               hi2->died_at = 0; /* Manually set dead. */
823               err = ks_printf_help (ctrl, "marking '%s' as dead",
824                                     hi2->name);
825             }
826         }
827     }
828
829  leave:
830   if (npth_mutex_unlock (&hosttable_lock))
831     log_fatal ("failed to release mutex\n");
832
833   return err;
834 }
835
836
837 /* Debug function to print the entire hosttable.  */
838 gpg_error_t
839 ks_hkp_print_hosttable (ctrl_t ctrl)
840 {
841   gpg_error_t err;
842   int idx, idx2;
843   hostinfo_t hi;
844   membuf_t mb;
845   time_t curtime;
846   char *p, *died;
847   const char *diedstr;
848
849   err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
850   if (err)
851     return err;
852
853   if (npth_mutex_lock (&hosttable_lock))
854     log_fatal ("failed to acquire mutex\n");
855
856   curtime = gnupg_get_time ();
857   for (idx=0; idx < hosttable_size; idx++)
858     if ((hi=hosttable[idx]))
859       {
860         if (hi->dead && hi->died_at)
861           {
862             died = elapsed_time_string (hi->died_at, curtime);
863             diedstr = died? died : "error";
864           }
865         else
866           diedstr = died = NULL;
867
868         if (!hi->iporname_valid)
869           {
870             char *canon = NULL;
871
872             xfree (hi->iporname);
873             hi->iporname = NULL;
874
875             /* Do a lookup just for the display purpose.  */
876             if (hi->onion || hi->pool)
877               ;
878             else if (is_ip_address (hi->name))
879               {
880                 dns_addrinfo_t aibuf, ai;
881
882                 /* Turn the numerical IP address string into an AI and
883                  * then do a DNS PTR lookup.  */
884                 if (!resolve_dns_name (ctrl, hi->name, 0, 0,
885                                        SOCK_STREAM,
886                                        &aibuf, &canon))
887                   {
888                     if (canon && is_ip_address (canon))
889                       {
890                         xfree (canon);
891                         canon = NULL;
892                       }
893                     for (ai = aibuf; !canon && ai; ai = ai->next)
894                       {
895                         resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
896                                           DNS_WITHBRACKET, &canon);
897                         if (canon && is_ip_address (canon))
898                           {
899                             /* We already have the numeric IP - no need to
900                              * display it a second time.  */
901                             xfree (canon);
902                             canon = NULL;
903                           }
904                       }
905                   }
906                 free_dns_addrinfo (aibuf);
907               }
908             else
909               {
910                 dns_addrinfo_t aibuf, ai;
911
912                 /* Get the IP address as a string from a name.  Note
913                  * that resolve_dns_addr allocates CANON on success
914                  * and thus terminates the loop. */
915                 if (!resolve_dns_name (ctrl, hi->name, 0,
916                                        hi->v6? AF_INET6 : AF_INET,
917                                        SOCK_STREAM,
918                                        &aibuf, NULL))
919                   {
920                     for (ai = aibuf; !canon && ai; ai = ai->next)
921                       {
922                         resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
923                                           DNS_NUMERICHOST|DNS_WITHBRACKET,
924                                           &canon);
925                       }
926                   }
927                 free_dns_addrinfo (aibuf);
928               }
929
930             hi->iporname = canon;
931             hi->iporname_valid = 1;
932           }
933
934         err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s\n",
935                               idx,
936                               hi->onion? "O" : hi->v6? "6":" ",
937                               hi->v4? "4":" ",
938                               hi->dead? "d":" ",
939                               hi->name,
940                               hi->iporname? " (":"",
941                               hi->iporname? hi->iporname : "",
942                               hi->iporname? ")":"",
943                               diedstr? "  (":"",
944                               diedstr? diedstr:"",
945                               diedstr? ")":""   );
946         xfree (died);
947         if (err)
948           goto leave;
949
950         if (hi->cname)
951           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
952         if (err)
953           goto leave;
954
955         if (hi->pool)
956           {
957             init_membuf (&mb, 256);
958             put_membuf_printf (&mb, "  .   -->");
959             for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
960               {
961                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
962                 if (hi->poolidx == hi->pool[idx2])
963                   put_membuf_printf (&mb, "*");
964               }
965             put_membuf( &mb, "", 1);
966             p = get_membuf (&mb, NULL);
967             if (!p)
968               {
969                 err = gpg_error_from_syserror ();
970                 goto leave;
971               }
972             err = ks_print_help (ctrl, p);
973             xfree (p);
974             if (err)
975               goto leave;
976           }
977       }
978
979  leave:
980   if (npth_mutex_unlock (&hosttable_lock))
981     log_fatal ("failed to release mutex\n");
982   return err;
983 }
984
985
986
987 /* Print a help output for the schemata supported by this module. */
988 gpg_error_t
989 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
990 {
991   const char data[] =
992     "Handler for HKP URLs:\n"
993     "  hkp://\n"
994 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
995     "  hkps://\n"
996 #endif
997     "Supported methods: search, get, put\n";
998   gpg_error_t err;
999
1000 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
1001   const char data2[] = "  hkp\n  hkps";
1002 #else
1003   const char data2[] = "  hkp";
1004 #endif
1005
1006   if (!uri)
1007     err = ks_print_help (ctrl, data2);
1008   else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
1009                             || !strcmp (uri->scheme, "hkps")))
1010     err = ks_print_help (ctrl, data);
1011   else
1012     err = 0;
1013
1014   return err;
1015 }
1016
1017
1018 /* Build the remote part of the URL from SCHEME, HOST and an optional
1019  * PORT.  If NO_SRV is set no SRV record lookup will be done.  Returns
1020  * an allocated string at R_HOSTPORT or NULL on failure.  If
1021  * R_HTTPHOST is not NULL it receives a malloced string with the
1022  * hostname; this may be different from HOST if HOST is selected from
1023  * a pool.  */
1024 static gpg_error_t
1025 make_host_part (ctrl_t ctrl,
1026                 const char *scheme, const char *host, unsigned short port,
1027                 int force_reselect, int no_srv,
1028                 char **r_hostport, unsigned int *r_httpflags, char **r_httphost)
1029 {
1030   gpg_error_t err;
1031   const char *srvtag;
1032   char portstr[10];
1033   char *hostname;
1034   enum ks_protocol protocol;
1035
1036   *r_hostport = NULL;
1037
1038   if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
1039     {
1040       scheme = "https";
1041       srvtag = no_srv? NULL : "pgpkey-https";
1042       protocol = KS_PROTOCOL_HKPS;
1043     }
1044   else /* HKP or HTTP.  */
1045     {
1046       scheme = "http";
1047       srvtag = no_srv? NULL : "pgpkey-http";
1048       protocol = KS_PROTOCOL_HKP;
1049     }
1050
1051   if (npth_mutex_lock (&hosttable_lock))
1052     log_fatal ("failed to acquire mutex\n");
1053
1054   portstr[0] = 0;
1055   err = map_host (ctrl, host, srvtag, force_reselect, protocol,
1056                   &hostname, portstr, r_httpflags, r_httphost);
1057
1058   if (npth_mutex_unlock (&hosttable_lock))
1059     log_fatal ("failed to release mutex\n");
1060
1061   if (err)
1062     return err;
1063
1064   /* If map_host did not return a port (from a SRV record) but a port
1065    * has been specified (implicitly or explicitly) then use that port.
1066    * In the case that a port was not specified (which is probably a
1067    * bug in https.c) we will set up defaults.  */
1068   if (*portstr)
1069     ;
1070   else if (!*portstr && port)
1071     snprintf (portstr, sizeof portstr, "%hu", port);
1072   else if (!strcmp (scheme,"https"))
1073     strcpy (portstr, "443");
1074   else
1075     strcpy (portstr, "11371");
1076
1077   if (*hostname != '[' && is_ip_address (hostname) == 6)
1078     *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
1079   else
1080     *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
1081   xfree (hostname);
1082   if (!*r_hostport)
1083     {
1084       if (r_httphost)
1085         {
1086           xfree (*r_httphost);
1087           *r_httphost = NULL;
1088         }
1089       return gpg_error_from_syserror ();
1090     }
1091   return 0;
1092 }
1093
1094
1095 /* Resolve all known keyserver names and update the hosttable.  This
1096    is mainly useful for debugging because the resolving is anyway done
1097    on demand.  */
1098 gpg_error_t
1099 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
1100 {
1101   gpg_error_t err;
1102   char *hostport = NULL;
1103
1104   /* NB: With an explicitly given port we do not want to consult a
1105    * service record because that might be in conflict with the port
1106    * from such a service record.  */
1107   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1108                         1, uri->explicit_port,
1109                         &hostport, NULL, NULL);
1110   if (err)
1111     {
1112       err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
1113                             uri->scheme, uri->host, uri->port,
1114                             gpg_strerror (err));
1115     }
1116   else
1117     {
1118       err = ks_printf_help (ctrl, "%s", hostport);
1119       xfree (hostport);
1120     }
1121   return err;
1122 }
1123
1124
1125 /* Housekeeping function called from the housekeeping thread.  It is
1126    used to mark dead hosts alive so that they may be tried again after
1127    some time.  */
1128 void
1129 ks_hkp_housekeeping (time_t curtime)
1130 {
1131   int idx;
1132   hostinfo_t hi;
1133
1134   if (npth_mutex_lock (&hosttable_lock))
1135     log_fatal ("failed to acquire mutex\n");
1136
1137   for (idx=0; idx < hosttable_size; idx++)
1138     {
1139       hi = hosttable[idx];
1140       if (!hi)
1141         continue;
1142       if (!hi->dead)
1143         continue;
1144       if (!hi->died_at)
1145         continue; /* Do not resurrect manually shot hosts.  */
1146       if (hi->died_at + RESURRECT_INTERVAL <= curtime
1147           || hi->died_at > curtime)
1148         {
1149           hi->dead = 0;
1150           log_info ("resurrected host '%s'", hi->name);
1151         }
1152     }
1153
1154   if (npth_mutex_unlock (&hosttable_lock))
1155     log_fatal ("failed to release mutex\n");
1156 }
1157
1158
1159 /* Reload (SIGHUP) action for this module.  We mark all host alive
1160  * even those which have been manually shot.  */
1161 void
1162 ks_hkp_reload (void)
1163 {
1164   int idx, count;
1165   hostinfo_t hi;
1166
1167   if (npth_mutex_lock (&hosttable_lock))
1168     log_fatal ("failed to acquire mutex\n");
1169
1170   for (idx=count=0; idx < hosttable_size; idx++)
1171     {
1172       hi = hosttable[idx];
1173       if (!hi)
1174         continue;
1175       hi->iporname_valid = 0;
1176       if (!hi->dead)
1177         continue;
1178       hi->dead = 0;
1179       count++;
1180     }
1181   if (count)
1182     log_info ("number of resurrected hosts: %d", count);
1183
1184   if (npth_mutex_unlock (&hosttable_lock))
1185     log_fatal ("failed to release mutex\n");
1186 }
1187
1188
1189 /* Send an HTTP request.  On success returns an estream object at
1190    R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
1191    not NULL it will be used as HTTP "Host" header.  If POST_CB is not
1192    NULL a post request is used and that callback is called to allow
1193    writing the post data.  If R_HTTP_STATUS is not NULL, the http
1194    status code will be stored there.  */
1195 static gpg_error_t
1196 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
1197               const char *httphost, unsigned int httpflags,
1198               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
1199               estream_t *r_fp, unsigned int *r_http_status)
1200 {
1201   gpg_error_t err;
1202   http_session_t session = NULL;
1203   http_t http = NULL;
1204   http_redir_info_t redirinfo = { MAX_REDIRECTS };
1205   estream_t fp = NULL;
1206   char *request_buffer = NULL;
1207   parsed_uri_t uri = NULL;
1208
1209   *r_fp = NULL;
1210
1211   err = http_parse_uri (&uri, request, 0);
1212   if (err)
1213     goto leave;
1214   redirinfo.orig_url   = request;
1215   redirinfo.orig_onion = uri->onion;
1216   redirinfo.allow_downgrade = 1;
1217   /* FIXME: I am not sure whey we allow a downgrade for hkp requests.
1218    * Needs at least an explanation here..  */
1219
1220   err = http_session_new (&session, httphost,
1221                           ((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
1222                            | HTTP_FLAG_TRUST_DEF),
1223                           gnupg_http_tls_verify_cb, ctrl);
1224   if (err)
1225     goto leave;
1226   http_session_set_log_cb (session, cert_log_cb);
1227   http_session_set_timeout (session, ctrl->timeout);
1228
1229  once_more:
1230   err = http_open (ctrl, &http,
1231                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1232                    request,
1233                    httphost,
1234                    /* fixme: AUTH */ NULL,
1235                    (httpflags
1236                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
1237                     |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
1238                     |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
1239                     |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
1240                    ctrl->http_proxy,
1241                    session,
1242                    NULL,
1243                    /*FIXME curl->srvtag*/NULL);
1244   if (!err)
1245     {
1246       fp = http_get_write_ptr (http);
1247       /* Avoid caches to get the most recent copy of the key.  We set
1248          both the Pragma and Cache-Control versions of the header, so
1249          we're good with both HTTP 1.0 and 1.1.  */
1250       es_fputs ("Pragma: no-cache\r\n"
1251                 "Cache-Control: no-cache\r\n", fp);
1252       if (post_cb)
1253         err = post_cb (post_cb_value, http);
1254       if (!err)
1255         {
1256           http_start_data (http);
1257           if (es_ferror (fp))
1258             err = gpg_error_from_syserror ();
1259         }
1260     }
1261   if (err)
1262     {
1263       /* Fixme: After a redirection we show the old host name.  */
1264       log_error (_("error connecting to '%s': %s\n"),
1265                  hostportstr, gpg_strerror (err));
1266       goto leave;
1267     }
1268
1269   /* Wait for the response.  */
1270   dirmngr_tick (ctrl);
1271   err = http_wait_response (http);
1272   if (err)
1273     {
1274       log_error (_("error reading HTTP response for '%s': %s\n"),
1275                  hostportstr, gpg_strerror (err));
1276       goto leave;
1277     }
1278
1279   if (http_get_tls_info (http, NULL))
1280     {
1281       /* Update the httpflags so that a redirect won't fallback to an
1282          unencrypted connection.  */
1283       httpflags |= HTTP_FLAG_FORCE_TLS;
1284     }
1285
1286   if (r_http_status)
1287     *r_http_status = http_get_status_code (http);
1288
1289   switch (http_get_status_code (http))
1290     {
1291     case 200:
1292       err = 0;
1293       break; /* Success.  */
1294
1295     case 301:
1296     case 302:
1297     case 307:
1298       {
1299         xfree (request_buffer);
1300         err = http_prepare_redirect (&redirinfo, http_get_status_code (http),
1301                                      http_get_header (http, "Location"),
1302                                      &request_buffer);
1303         if (err)
1304           goto leave;
1305
1306         request = request_buffer;
1307         http_close (http, 0);
1308         http = NULL;
1309       }
1310       goto once_more;
1311
1312     case 501:
1313       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1314       goto leave;
1315
1316     case 413:  /* Payload too large */
1317       err = gpg_error (GPG_ERR_TOO_LARGE);
1318       goto leave;
1319
1320     default:
1321       log_error (_("error accessing '%s': http status %u\n"),
1322                  request, http_get_status_code (http));
1323       err = gpg_error (GPG_ERR_NO_DATA);
1324       goto leave;
1325     }
1326
1327   /* FIXME: We should register a permanent redirection and whether a
1328      host has ever used TLS so that future calls will always use
1329      TLS. */
1330
1331   fp = http_get_read_ptr (http);
1332   if (!fp)
1333     {
1334       err = gpg_error (GPG_ERR_BUG);
1335       goto leave;
1336     }
1337
1338   /* Return the read stream and close the HTTP context.  */
1339   *r_fp = fp;
1340   http_close (http, 1);
1341   http = NULL;
1342
1343  leave:
1344   http_close (http, 0);
1345   http_session_release (session);
1346   xfree (request_buffer);
1347   http_release_parsed_uri (uri);
1348   return err;
1349 }
1350
1351
1352 /* Helper to evaluate the error code ERR from a send_request() call
1353    with REQUEST.  The function returns true if the caller shall try
1354    again.  TRIES_LEFT points to a variable to track the number of
1355    retries; this function decrements it and won't return true if it is
1356    down to zero. */
1357 static int
1358 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
1359                            unsigned int http_status, unsigned int *tries_left)
1360 {
1361   int retry = 0;
1362
1363   /* Fixme: Should we disable all hosts of a protocol family if a
1364    * request for an address of that family returned ENETDOWN?  */
1365
1366   switch (gpg_err_code (err))
1367     {
1368     case GPG_ERR_ECONNREFUSED:
1369       if (tor_not_running_p (ctrl))
1370         break; /* A retry does not make sense.  */
1371       /* Okay: Tor is up or --use-tor is not used.  */
1372       /*FALLTHRU*/
1373     case GPG_ERR_ENETUNREACH:
1374     case GPG_ERR_ENETDOWN:
1375     case GPG_ERR_UNKNOWN_HOST:
1376     case GPG_ERR_NETWORK:
1377     case GPG_ERR_EIO:  /* Sometimes used by estream cookie functions.  */
1378     case GPG_ERR_EADDRNOTAVAIL:  /* e.g. when IPv6 is disabled */
1379     case GPG_ERR_EAFNOSUPPORT:  /* e.g. when IPv6 is not compiled in */
1380       if (mark_host_dead (request) && *tries_left)
1381         retry = 1;
1382       break;
1383
1384     case GPG_ERR_ETIMEDOUT:
1385       if (*tries_left)
1386         {
1387           log_info ("selecting a different host due to a timeout\n");
1388           retry = 1;
1389         }
1390       break;
1391
1392     case GPG_ERR_EACCES:
1393       if (dirmngr_use_tor ())
1394         {
1395           log_info ("(Tor configuration problem)\n");
1396           dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
1397                           "Please check that the \"SocksPort\" flag "
1398                           "\"IPv6Traffic\" is set in torrc", NULL);
1399         }
1400       break;
1401
1402     case GPG_ERR_NO_DATA:
1403       {
1404         switch (http_status)
1405           {
1406           case 502: /* Bad Gateway  */
1407             log_info ("marking host dead due to a %u (%s)\n",
1408                       http_status, http_status2string (http_status));
1409             if (mark_host_dead (request) && *tries_left)
1410               retry = 1;
1411             break;
1412
1413           case 503: /* Service Unavailable */
1414           case 504: /* Gateway Timeout    */
1415             log_info ("selecting a different host due to a %u (%s)",
1416                       http_status, http_status2string (http_status));
1417             retry = 1;
1418             break;
1419           }
1420       }
1421       break;
1422
1423     default:
1424       break;
1425     }
1426
1427   if (*tries_left)
1428     --*tries_left;
1429
1430   return retry;
1431 }
1432
1433 \f
1434 /* Search the keyserver identified by URI for keys matching PATTERN.
1435    On success R_FP has an open stream to read the data.  If
1436    R_HTTP_STATUS is not NULL, the http status code will be stored
1437    there.  */
1438 gpg_error_t
1439 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1440                estream_t *r_fp, unsigned int *r_http_status)
1441 {
1442   gpg_error_t err;
1443   KEYDB_SEARCH_DESC desc;
1444   char fprbuf[2+64+1];
1445   char *hostport = NULL;
1446   char *request = NULL;
1447   estream_t fp = NULL;
1448   int reselect;
1449   unsigned int httpflags;
1450   char *httphost = NULL;
1451   unsigned int http_status;
1452   unsigned int tries = SEND_REQUEST_RETRIES;
1453
1454   *r_fp = NULL;
1455
1456   /* Remove search type indicator and adjust PATTERN accordingly.
1457      Note that HKP keyservers like the 0x to be present when searching
1458      by keyid.  We need to re-format the fingerprint and keyids so to
1459      remove the gpg specific force-use-of-this-key flag ("!").  */
1460   err = classify_user_id (pattern, &desc, 1);
1461   if (err)
1462     return err;
1463   log_assert (desc.fprlen <= 64);
1464   switch (desc.mode)
1465     {
1466     case KEYDB_SEARCH_MODE_EXACT:
1467     case KEYDB_SEARCH_MODE_SUBSTR:
1468     case KEYDB_SEARCH_MODE_MAIL:
1469     case KEYDB_SEARCH_MODE_MAILSUB:
1470       pattern = desc.u.name;
1471       break;
1472     case KEYDB_SEARCH_MODE_SHORT_KID:
1473       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1474       pattern = fprbuf;
1475       break;
1476     case KEYDB_SEARCH_MODE_LONG_KID:
1477       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1478                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1479       pattern = fprbuf;
1480       break;
1481     case KEYDB_SEARCH_MODE_FPR:
1482       fprbuf[0] = '0';
1483       fprbuf[1] = 'x';
1484       bin2hex (desc.u.fpr, desc.fprlen, fprbuf+2);
1485       pattern = fprbuf;
1486       break;
1487     default:
1488       return gpg_error (GPG_ERR_INV_USER_ID);
1489     }
1490
1491   /* Build the request string.  */
1492   reselect = 0;
1493  again:
1494   {
1495     char *searchkey;
1496
1497     xfree (hostport); hostport = NULL;
1498     xfree (httphost); httphost = NULL;
1499     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1500                           reselect, uri->explicit_port,
1501                           &hostport, &httpflags, &httphost);
1502     if (err)
1503       goto leave;
1504
1505     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1506     if (!searchkey)
1507       {
1508         err = gpg_error_from_syserror ();
1509         goto leave;
1510       }
1511
1512     xfree (request);
1513     request = strconcat (hostport,
1514                          "/pks/lookup?op=index&options=mr&search=",
1515                          searchkey,
1516                          NULL);
1517     xfree (searchkey);
1518     if (!request)
1519       {
1520         err = gpg_error_from_syserror ();
1521         goto leave;
1522       }
1523   }
1524
1525   /* Send the request.  */
1526   err = send_request (ctrl, request, hostport, httphost, httpflags,
1527                       NULL, NULL, &fp, &http_status);
1528   if (handle_send_request_error (ctrl, err, request, http_status, &tries))
1529     {
1530       reselect = 1;
1531       goto again;
1532     }
1533   if (r_http_status)
1534     *r_http_status = http_status;
1535   if (err)
1536     {
1537       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1538         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1539       goto leave;
1540     }
1541
1542   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1543   if (err)
1544     goto leave;
1545
1546   /* Peek at the response.  */
1547   {
1548     int c = es_getc (fp);
1549     if (c == -1)
1550       {
1551         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1552         log_error ("error reading response: %s\n", gpg_strerror (err));
1553         goto leave;
1554       }
1555     if (c == '<')
1556       {
1557         /* The document begins with a '<': Assume a HTML response,
1558            which we don't support.  */
1559         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1560         goto leave;
1561       }
1562     es_ungetc (c, fp);
1563   }
1564
1565   /* Return the read stream.  */
1566   *r_fp = fp;
1567   fp = NULL;
1568
1569  leave:
1570   es_fclose (fp);
1571   xfree (request);
1572   xfree (hostport);
1573   xfree (httphost);
1574   return err;
1575 }
1576
1577
1578 /* Get the key described key the KEYSPEC string from the keyserver
1579    identified by URI.  On success R_FP has an open stream to read the
1580    data.  The data will be provided in a format GnuPG can import
1581    (either a binary OpenPGP message or an armored one).  */
1582 gpg_error_t
1583 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1584 {
1585   gpg_error_t err;
1586   KEYDB_SEARCH_DESC desc;
1587   char kidbuf[2+64+1];
1588   const char *exactname = NULL;
1589   char *searchkey = NULL;
1590   char *hostport = NULL;
1591   char *request = NULL;
1592   estream_t fp = NULL;
1593   int reselect;
1594   char *httphost = NULL;
1595   unsigned int httpflags;
1596   unsigned int http_status;
1597   unsigned int tries = SEND_REQUEST_RETRIES;
1598
1599   *r_fp = NULL;
1600
1601   /* Remove search type indicator and adjust PATTERN accordingly.
1602      Note that HKP keyservers like the 0x to be present when searching
1603      by keyid.  We need to re-format the fingerprint and keyids so to
1604      remove the gpg specific force-use-of-this-key flag ("!").  */
1605   err = classify_user_id (keyspec, &desc, 1);
1606   if (err)
1607     return err;
1608   log_assert (desc.fprlen <= 64);
1609   switch (desc.mode)
1610     {
1611     case KEYDB_SEARCH_MODE_SHORT_KID:
1612       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1613       break;
1614     case KEYDB_SEARCH_MODE_LONG_KID:
1615       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1616                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1617       break;
1618     case KEYDB_SEARCH_MODE_FPR:
1619       if (desc.fprlen < 20)
1620         {
1621           log_error ("HKP keyservers do not support v3 fingerprints\n");
1622           return gpg_error (GPG_ERR_INV_USER_ID);
1623         }
1624       kidbuf[0] = '0';
1625       kidbuf[1] = 'x';
1626       bin2hex (desc.u.fpr, desc.fprlen, kidbuf+2);
1627       break;
1628
1629     case KEYDB_SEARCH_MODE_EXACT:
1630       exactname = desc.u.name;
1631       break;
1632
1633     default:
1634       return gpg_error (GPG_ERR_INV_USER_ID);
1635     }
1636
1637   searchkey = http_escape_string (exactname? exactname : kidbuf,
1638                                   EXTRA_ESCAPE_CHARS);
1639   if (!searchkey)
1640     {
1641       err = gpg_error_from_syserror ();
1642       goto leave;
1643     }
1644
1645   reselect = 0;
1646  again:
1647   /* Build the request string.  */
1648   xfree (hostport); hostport = NULL;
1649   xfree (httphost); httphost = NULL;
1650   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1651                         reselect, uri->explicit_port,
1652                         &hostport, &httpflags, &httphost);
1653   if (err)
1654     goto leave;
1655
1656   xfree (request);
1657   request = strconcat (hostport,
1658                        "/pks/lookup?op=get&options=mr&search=",
1659                        searchkey,
1660                        exactname? "&exact=on":"",
1661                        NULL);
1662   if (!request)
1663     {
1664       err = gpg_error_from_syserror ();
1665       goto leave;
1666     }
1667
1668   /* Send the request.  */
1669   err = send_request (ctrl, request, hostport, httphost, httpflags,
1670                       NULL, NULL, &fp, &http_status);
1671   if (handle_send_request_error (ctrl, err, request, http_status, &tries))
1672     {
1673       reselect = 1;
1674       goto again;
1675     }
1676   if (err)
1677     {
1678       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1679         dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1680       goto leave;
1681     }
1682
1683   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1684   if (err)
1685     goto leave;
1686
1687   /* Return the read stream and close the HTTP context.  */
1688   *r_fp = fp;
1689   fp = NULL;
1690
1691  leave:
1692   es_fclose (fp);
1693   xfree (request);
1694   xfree (hostport);
1695   xfree (httphost);
1696   xfree (searchkey);
1697   return err;
1698 }
1699
1700
1701
1702 \f
1703 /* Callback parameters for put_post_cb.  */
1704 struct put_post_parm_s
1705 {
1706   char *datastring;
1707 };
1708
1709
1710 /* Helper for ks_hkp_put.  */
1711 static gpg_error_t
1712 put_post_cb (void *opaque, http_t http)
1713 {
1714   struct put_post_parm_s *parm = opaque;
1715   gpg_error_t err = 0;
1716   estream_t fp;
1717   size_t len;
1718
1719   fp = http_get_write_ptr (http);
1720   len = strlen (parm->datastring);
1721
1722   es_fprintf (fp,
1723               "Content-Type: application/x-www-form-urlencoded\r\n"
1724               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1725   http_start_data (http);
1726   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1727     err = gpg_error_from_syserror ();
1728   return err;
1729 }
1730
1731
1732 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1733 gpg_error_t
1734 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1735 {
1736   gpg_error_t err;
1737   char *hostport = NULL;
1738   char *request = NULL;
1739   estream_t fp = NULL;
1740   struct put_post_parm_s parm;
1741   char *armored = NULL;
1742   int reselect;
1743   char *httphost = NULL;
1744   unsigned int httpflags;
1745   unsigned int http_status;
1746   unsigned int tries = SEND_REQUEST_RETRIES;
1747
1748   parm.datastring = NULL;
1749
1750   err = armor_data (&armored, data, datalen);
1751   if (err)
1752     goto leave;
1753
1754   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1755   if (!parm.datastring)
1756     {
1757       err = gpg_error_from_syserror ();
1758       goto leave;
1759     }
1760   xfree (armored);
1761   armored = NULL;
1762
1763   /* Build the request string.  */
1764   reselect = 0;
1765  again:
1766   xfree (hostport); hostport = NULL;
1767   xfree (httphost); httphost = NULL;
1768   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1769                         reselect, uri->explicit_port,
1770                         &hostport, &httpflags, &httphost);
1771   if (err)
1772     goto leave;
1773
1774   xfree (request);
1775   request = strconcat (hostport, "/pks/add", NULL);
1776   if (!request)
1777     {
1778       err = gpg_error_from_syserror ();
1779       goto leave;
1780     }
1781
1782   /* Send the request.  */
1783   err = send_request (ctrl, request, hostport, httphost, 0,
1784                       put_post_cb, &parm, &fp, &http_status);
1785   if (handle_send_request_error (ctrl, err, request, http_status, &tries))
1786     {
1787       reselect = 1;
1788       goto again;
1789     }
1790   if (err)
1791     goto leave;
1792
1793  leave:
1794   es_fclose (fp);
1795   xfree (parm.datastring);
1796   xfree (armored);
1797   xfree (request);
1798   xfree (hostport);
1799   xfree (httphost);
1800   return err;
1801 }
1802
1803 void
1804 ks_hkp_init (void)
1805 {
1806   int err;
1807
1808   err = npth_mutex_init (&hosttable_lock, NULL);
1809   if (err)
1810     log_fatal ("error initializing mutex: %s\n", strerror (err));
1811 }