dirmngr: Change internal SRV lookup API.
[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 "dirmngr.h"
39 #include "misc.h"
40 #include "userids.h"
41 #include "dns-stuff.h"
42 #include "ks-engine.h"
43
44 /* Substitutes for missing Mingw macro.  The EAI_SYSTEM mechanism
45    seems not to be available (probably because there is only one set
46    of error codes anyway).  For now we use WSAEINVAL. */
47 #ifndef EAI_OVERFLOW
48 # define EAI_OVERFLOW EAI_FAIL
49 #endif
50 #ifdef HAVE_W32_SYSTEM
51 # ifndef EAI_SYSTEM
52 #  define EAI_SYSTEM WSAEINVAL
53 # endif
54 #endif
55
56
57 /* Number of seconds after a host is marked as resurrected.  */
58 #define RESURRECT_INTERVAL  (3600*3)  /* 3 hours */
59
60 /* To match the behaviour of our old gpgkeys helper code we escape
61    more characters than actually needed. */
62 #define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
63
64 /* How many redirections do we allow.  */
65 #define MAX_REDIRECTS 2
66
67 /* Number of retries done for a dead host etc.  */
68 #define SEND_REQUEST_RETRIES 3
69
70 /* Objects used to maintain information about hosts.  */
71 struct hostinfo_s;
72 typedef struct hostinfo_s *hostinfo_t;
73 struct hostinfo_s
74 {
75   time_t lastfail;   /* Time we tried to connect and failed.  */
76   time_t lastused;   /* Time of last use.  */
77   int *pool;         /* A -1 terminated array with indices into
78                         HOSTTABLE or NULL if NAME is not a pool
79                         name.  */
80   int poolidx;       /* Index into POOL with the used host.  -1 if not set.  */
81   unsigned int v4:1; /* Host supports AF_INET.  */
82   unsigned int v6:1; /* Host supports AF_INET6.  */
83   unsigned int onion:1;/* NAME is an onion (Tor HS) address.  */
84   unsigned int dead:1; /* Host is currently unresponsive.  */
85   time_t died_at;    /* The time the host was marked dead.  If this is
86                         0 the host has been manually marked dead.  */
87   char *cname;       /* Canonical name of the host.  Only set if this
88                         is a pool.  */
89   char *v4addr;      /* A string with the v4 IP address of the host.
90                         NULL if NAME has a numeric IP address or no v4
91                         address is available.  */
92   char *v6addr;      /* A string with the v6 IP address of the host.
93                         NULL if NAME has a numeric IP address or no v6
94                         address is available.  */
95   unsigned short port; /* The port used by the host, 0 if unknown.  */
96   char name[1];      /* The hostname.  */
97 };
98
99
100 /* An array of hostinfo_t for all hosts requested by the caller or
101    resolved from a pool name and its allocated size.*/
102 static hostinfo_t *hosttable;
103 static int hosttable_size;
104
105 /* The number of host slots we initially allocate for HOSTTABLE.  */
106 #define INITIAL_HOSTTABLE_SIZE 10
107
108
109 /* Create a new hostinfo object, fill in NAME and put it into
110    HOSTTABLE.  Return the index into hosttable on success or -1 on
111    error. */
112 static int
113 create_new_hostinfo (const char *name)
114 {
115   hostinfo_t hi, *newtable;
116   int newsize;
117   int idx, rc;
118
119   hi = xtrymalloc (sizeof *hi + strlen (name));
120   if (!hi)
121     return -1;
122   strcpy (hi->name, name);
123   hi->pool = NULL;
124   hi->poolidx = -1;
125   hi->lastused = (time_t)(-1);
126   hi->lastfail = (time_t)(-1);
127   hi->v4 = 0;
128   hi->v6 = 0;
129   hi->onion = 0;
130   hi->dead = 0;
131   hi->died_at = 0;
132   hi->cname = NULL;
133   hi->v4addr = NULL;
134   hi->v6addr = NULL;
135   hi->port = 0;
136
137   /* Add it to the hosttable. */
138   for (idx=0; idx < hosttable_size; idx++)
139     if (!hosttable[idx])
140       {
141         hosttable[idx] = hi;
142         return idx;
143       }
144   /* Need to extend the hosttable.  */
145   newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
146   newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
147   if (!newtable)
148     {
149       xfree (hi);
150       return -1;
151     }
152   hosttable = newtable;
153   idx = hosttable_size;
154   hosttable_size = newsize;
155   rc = idx;
156   hosttable[idx++] = hi;
157   while (idx < hosttable_size)
158     hosttable[idx++] = NULL;
159
160   return rc;
161 }
162
163
164 /* Find the host NAME in our table.  Return the index into the
165    hosttable or -1 if not found.  */
166 static int
167 find_hostinfo (const char *name)
168 {
169   int idx;
170
171   for (idx=0; idx < hosttable_size; idx++)
172     if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
173       return idx;
174   return -1;
175 }
176
177
178 static int
179 sort_hostpool (const void *xa, const void *xb)
180 {
181   int a = *(int *)xa;
182   int b = *(int *)xb;
183
184   assert (a >= 0 && a < hosttable_size);
185   assert (b >= 0 && b < hosttable_size);
186   assert (hosttable[a]);
187   assert (hosttable[b]);
188
189   return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
190 }
191
192
193 /* Return true if the host with the hosttable index TBLIDX is in POOL.  */
194 static int
195 host_in_pool_p (int *pool, int tblidx)
196 {
197   int i, pidx;
198
199   for (i=0; (pidx = pool[i]) != -1; i++)
200     if (pidx == tblidx && hosttable[pidx])
201       return 1;
202   return 0;
203 }
204
205
206 /* Select a random host.  Consult TABLE which indices into the global
207    hosttable.  Returns index into TABLE or -1 if no host could be
208    selected.  */
209 static int
210 select_random_host (int *table)
211 {
212   int *tbl;
213   size_t tblsize;
214   int pidx, idx;
215
216   /* We create a new table so that we randomly select only from
217      currently alive hosts.  */
218   for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
219     if (hosttable[pidx] && !hosttable[pidx]->dead)
220       tblsize++;
221   if (!tblsize)
222     return -1; /* No hosts.  */
223
224   tbl = xtrymalloc (tblsize * sizeof *tbl);
225   if (!tbl)
226     return -1;
227   for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
228     if (hosttable[pidx] && !hosttable[pidx]->dead)
229       tbl[tblsize++] = pidx;
230
231   if (tblsize == 1)  /* Save a get_uint_nonce.  */
232     pidx = tbl[0];
233   else
234     pidx = tbl[get_uint_nonce () % tblsize];
235
236   xfree (tbl);
237   return pidx;
238 }
239
240
241 /* Figure out if a set of DNS records looks like a pool.  */
242 static int
243 arecords_is_pool (dns_addrinfo_t aibuf)
244 {
245   dns_addrinfo_t ai;
246   int n_v6, n_v4;
247
248   n_v6 = n_v4 = 0;
249   for (ai = aibuf; ai; ai = ai->next)
250     {
251       if (ai->family == AF_INET6)
252         n_v6++;
253       else if (ai->family == AF_INET)
254         n_v4++;
255     }
256
257   return n_v6 > 1 || n_v4 > 1;
258 }
259
260
261 /* Add the host AI under the NAME into the HOSTTABLE.  If PORT is not
262    zero, it specifies which port to use to talk to the host.  If NAME
263    specifies a pool (as indicated by IS_POOL), update the given
264    reference table accordingly.  */
265 static void
266 add_host (const char *name, int is_pool,
267           const dns_addrinfo_t ai, unsigned short port,
268           int *reftbl, size_t reftblsize, int *refidx)
269 {
270   gpg_error_t tmperr;
271   char *tmphost;
272   int idx, tmpidx;
273   int is_numeric = 0;
274   int i;
275
276   idx = find_hostinfo (name);
277
278   if (!is_pool && !is_ip_address (name))
279     {
280       /* This is a hostname but not a pool.  Use the name
281          as given without going through resolve_dns_addr.  */
282       tmphost = xtrystrdup (name);
283       if (!tmphost)
284         tmperr = gpg_error_from_syserror ();
285       else
286         tmperr = 0;
287     }
288   else
289     {
290       tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
291                                  DNS_WITHBRACKET, &tmphost);
292       if (tmphost && is_ip_address (tmphost))
293         is_numeric = 1;
294     }
295
296   if (tmperr)
297     {
298       log_info ("resolve_dns_addr failed while checking '%s': %s\n",
299                 name, gpg_strerror (tmperr));
300     }
301   else if ((*refidx) + 1 >= reftblsize)
302     {
303       log_error ("resolve_dns_addr for '%s': '%s'"
304                  " [index table full - ignored]\n", name, tmphost);
305     }
306   else
307     {
308       if (!is_pool && is_ip_address (name))
309         /* Update the original entry.  */
310         tmpidx = idx;
311       else
312         tmpidx = find_hostinfo (tmphost);
313       log_info ("resolve_dns_addr for '%s': '%s'%s\n",
314                 name, tmphost,
315                 tmpidx == -1? "" : " [already known]");
316
317       if (tmpidx == -1) /* Create a new entry.  */
318         tmpidx = create_new_hostinfo (tmphost);
319
320       if (tmpidx == -1)
321         {
322           log_error ("map_host for '%s' problem: %s - '%s'"
323                      " [ignored]\n",
324                      name, strerror (errno), tmphost);
325         }
326       else  /* Set or update the entry. */
327         {
328           char *ipaddr = NULL;
329
330           if (port)
331             hosttable[tmpidx]->port = port;
332
333           if (!is_numeric)
334             {
335               xfree (tmphost);
336               tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
337                                          (DNS_NUMERICHOST
338                                           | DNS_WITHBRACKET),
339                                          &tmphost);
340               if (tmperr)
341                 log_info ("resolve_dns_addr failed: %s\n",
342                           gpg_strerror (tmperr));
343               else
344                 {
345                   ipaddr = tmphost;
346                   tmphost = NULL;
347                 }
348             }
349
350           if (ai->family == AF_INET6)
351             {
352               hosttable[tmpidx]->v6 = 1;
353               xfree (hosttable[tmpidx]->v6addr);
354               hosttable[tmpidx]->v6addr = ipaddr;
355             }
356           else if (ai->family == AF_INET)
357             {
358               hosttable[tmpidx]->v4 = 1;
359               xfree (hosttable[tmpidx]->v4addr);
360               hosttable[tmpidx]->v4addr = ipaddr;
361             }
362           else
363             BUG ();
364
365           for (i=0; i < *refidx; i++)
366             if (reftbl[i] == tmpidx)
367               break;
368           if (!(i < *refidx) && tmpidx != idx)
369             reftbl[(*refidx)++] = tmpidx;
370         }
371     }
372   xfree (tmphost);
373 }
374
375
376 /* Map the host name NAME to the actual to be used host name.  This
377    allows us to manage round robin DNS names.  We use our own strategy
378    to choose one of the hosts.  For example we skip those hosts which
379    failed for some time and we stick to one host for a time
380    independent of DNS retry times.  If FORCE_RESELECT is true a new
381    host is always selected.  The selected host is stored as a malloced
382    string at R_HOST; on error NULL is stored.  If we know the port
383    used by the selected host, a string representation is written to
384    R_PORTSTR, otherwise it is left untouched.  If R_HTTPFLAGS is not
385    NULL it will receive flags which are to be passed to http_open.  If
386    R_POOLNAME is not NULL a malloced name of the pool is stored or
387    NULL if it is not a pool. */
388 static gpg_error_t
389 map_host (ctrl_t ctrl, const char *name, int force_reselect,
390           char **r_host, char *r_portstr,
391           unsigned int *r_httpflags, char **r_poolname)
392 {
393   gpg_error_t err = 0;
394   hostinfo_t hi;
395   int idx;
396
397   *r_host = NULL;
398   if (r_httpflags)
399     *r_httpflags = 0;
400   if (r_poolname)
401     *r_poolname = NULL;
402
403   /* No hostname means localhost.  */
404   if (!name || !*name)
405     {
406       *r_host = xtrystrdup ("localhost");
407       return *r_host? 0 : gpg_error_from_syserror ();
408     }
409
410   /* See whether the host is in our table.  */
411   idx = find_hostinfo (name);
412   if (idx == -1 && is_onion_address (name))
413     {
414       idx = create_new_hostinfo (name);
415       if (idx == -1)
416         return gpg_error_from_syserror ();
417       hi = hosttable[idx];
418       hi->onion = 1;
419     }
420   else if (idx == -1)
421     {
422       /* We never saw this host.  Allocate a new entry.  */
423       dns_addrinfo_t aibuf, ai;
424       int *reftbl;
425       size_t reftblsize;
426       int refidx;
427       int is_pool = 0;
428       char *cname;
429       struct srventry *srvs;
430       unsigned int srvscount;
431
432       reftblsize = 100;
433       reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
434       if (!reftbl)
435         return gpg_error_from_syserror ();
436       refidx = 0;
437
438       idx = create_new_hostinfo (name);
439       if (idx == -1)
440         {
441           err = gpg_error_from_syserror ();
442           xfree (reftbl);
443           return err;
444         }
445       hi = hosttable[idx];
446
447       if (!is_ip_address (name))
448         {
449           /* Check for SRV records.  */
450           err = get_dns_srv (name, "hkp", NULL, &srvs, &srvscount);
451           if (err)
452             {
453               xfree (reftbl);
454               return err;
455             }
456
457           if (srvscount > 0)
458             {
459               int i;
460               is_pool = srvscount > 1;
461
462               for (i = 0; i < srvscount; i++)
463                 {
464                   err = resolve_dns_name (srvs[i].target, 0,
465                                           AF_UNSPEC, SOCK_STREAM,
466                                           &ai, &cname);
467                   if (err)
468                     continue;
469                   dirmngr_tick (ctrl);
470                   add_host (name, is_pool, ai, srvs[i].port,
471                             reftbl, reftblsize, &refidx);
472                 }
473
474               xfree (srvs);
475             }
476         }
477
478       /* Find all A records for this entry and put them into the pool
479          list - if any.  */
480       err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
481       if (err)
482         {
483           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
484           err = 0;
485         }
486       else
487         {
488           /* First figure out whether this is a pool.  For a pool we
489              use a different strategy than for a plain server: We use
490              the canonical name of the pool as the virtual host along
491              with the IP addresses.  If it is not a pool, we use the
492              specified name. */
493           if (! is_pool)
494             is_pool = arecords_is_pool (aibuf);
495           if (is_pool && cname)
496             {
497               hi->cname = cname;
498               cname = NULL;
499             }
500
501           for (ai = aibuf; ai; ai = ai->next)
502             {
503               if (ai->family != AF_INET && ai->family != AF_INET6)
504                 continue;
505               dirmngr_tick (ctrl);
506
507               add_host (name, is_pool, ai, 0, reftbl, reftblsize, &refidx);
508             }
509         }
510       reftbl[refidx] = -1;
511       xfree (cname);
512       free_dns_addrinfo (aibuf);
513
514       if (refidx && is_pool)
515         {
516           assert (!hi->pool);
517           hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
518           if (!hi->pool)
519             {
520               err = gpg_error_from_syserror ();
521               log_error ("shrinking index table in map_host failed: %s\n",
522                          gpg_strerror (err));
523               xfree (reftbl);
524               return err;
525             }
526           qsort (hi->pool, refidx, sizeof *reftbl, sort_hostpool);
527         }
528       else
529         xfree (reftbl);
530     }
531
532   hi = hosttable[idx];
533   if (hi->pool)
534     {
535       /* Deal with the pool name before selecting a host. */
536       if (r_poolname)
537         {
538           *r_poolname = xtrystrdup (hi->cname? hi->cname : hi->name);
539           if (!*r_poolname)
540             return gpg_error_from_syserror ();
541         }
542
543       /* If the currently selected host is now marked dead, force a
544          re-selection .  */
545       if (force_reselect)
546         hi->poolidx = -1;
547       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
548                && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
549         hi->poolidx = -1;
550
551       /* Select a host if needed.  */
552       if (hi->poolidx == -1)
553         {
554           hi->poolidx = select_random_host (hi->pool);
555           if (hi->poolidx == -1)
556             {
557               log_error ("no alive host found in pool '%s'\n", name);
558               if (r_poolname)
559                 {
560                   xfree (*r_poolname);
561                   *r_poolname = NULL;
562                 }
563               return gpg_error (GPG_ERR_NO_KEYSERVER);
564             }
565         }
566
567       assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
568       hi = hosttable[hi->poolidx];
569       assert (hi);
570     }
571
572   if (hi->dead)
573     {
574       log_error ("host '%s' marked as dead\n", hi->name);
575       if (r_poolname)
576         {
577           xfree (*r_poolname);
578           *r_poolname = NULL;
579         }
580       return gpg_error (GPG_ERR_NO_KEYSERVER);
581     }
582
583   if (r_httpflags)
584     {
585       /* If the hosttable does not indicate that a certain host
586          supports IPv<N>, we explicit set the corresponding http
587          flags.  The reason for this is that a host might be listed in
588          a pool as not v6 only but actually support v6 when later
589          the name is resolved by our http layer.  */
590       if (!hi->v4)
591         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
592       if (!hi->v6)
593         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
594
595       /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion
596          addresses because the http module detects this itself.  This
597          also allows us to use an onion address without Tor mode being
598          enabled.  */
599     }
600
601   *r_host = xtrystrdup (hi->name);
602   if (!*r_host)
603     {
604       err = gpg_error_from_syserror ();
605       if (r_poolname)
606         {
607           xfree (*r_poolname);
608           *r_poolname = NULL;
609         }
610       return err;
611     }
612   if (hi->port)
613     snprintf (r_portstr, 6 /* five digits and the sentinel */,
614               "%hu", hi->port);
615   return 0;
616 }
617
618
619 /* Mark the host NAME as dead.  NAME may be given as an URL.  Returns
620    true if a host was really marked as dead or was already marked dead
621    (e.g. by a concurrent session).  */
622 static int
623 mark_host_dead (const char *name)
624 {
625   const char *host;
626   char *host_buffer = NULL;
627   parsed_uri_t parsed_uri = NULL;
628   int done = 0;
629
630   if (name && *name && !http_parse_uri (&parsed_uri, name, 1))
631     {
632       if (parsed_uri->v6lit)
633         {
634           host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
635           if (!host_buffer)
636             log_error ("out of core in mark_host_dead");
637           host = host_buffer;
638         }
639       else
640         host = parsed_uri->host;
641     }
642   else
643     host = name;
644
645   if (host && *host && strcmp (host, "localhost"))
646     {
647       hostinfo_t hi;
648       int idx;
649
650       idx = find_hostinfo (host);
651       if (idx != -1)
652         {
653           hi = hosttable[idx];
654           log_info ("marking host '%s' as dead%s\n",
655                     hi->name, hi->dead? " (again)":"");
656           hi->dead = 1;
657           hi->died_at = gnupg_get_time ();
658           if (!hi->died_at)
659             hi->died_at = 1;
660           done = 1;
661         }
662     }
663
664   http_release_parsed_uri (parsed_uri);
665   xfree (host_buffer);
666   return done;
667 }
668
669
670 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
671    alive.  */
672 gpg_error_t
673 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
674 {
675   gpg_error_t err = 0;
676   hostinfo_t hi, hi2;
677   int idx, idx2, idx3, n;
678
679   if (!name || !*name || !strcmp (name, "localhost"))
680     return 0;
681
682   idx = find_hostinfo (name);
683   if (idx == -1)
684     return gpg_error (GPG_ERR_NOT_FOUND);
685
686   hi = hosttable[idx];
687   if (alive && hi->dead)
688     {
689       hi->dead = 0;
690       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
691     }
692   else if (!alive && !hi->dead)
693     {
694       hi->dead = 1;
695       hi->died_at = 0; /* Manually set dead.  */
696       err = ks_printf_help (ctrl, "marking '%s' as dead", name);
697     }
698
699   /* If the host is a pool mark all member hosts. */
700   if (!err && hi->pool)
701     {
702       for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
703         {
704           assert (n >= 0 && n < hosttable_size);
705
706           if (!alive)
707             {
708               /* Do not mark a host from a pool dead if it is also a
709                  member in another pool.  */
710               for (idx3=0; idx3 < hosttable_size; idx3++)
711                 {
712                   if (hosttable[idx3]
713                       && hosttable[idx3]->pool
714                       && idx3 != idx
715                       && host_in_pool_p (hosttable[idx3]->pool, n))
716                     break;
717                 }
718               if (idx3 < hosttable_size)
719                 continue;  /* Host is also a member of another pool.  */
720             }
721
722           hi2 = hosttable[n];
723           if (!hi2)
724             ;
725           else if (alive && hi2->dead)
726             {
727               hi2->dead = 0;
728               err = ks_printf_help (ctrl, "marking '%s' as alive",
729                                     hi2->name);
730             }
731           else if (!alive && !hi2->dead)
732             {
733               hi2->dead = 1;
734               hi2->died_at = 0; /* Manually set dead. */
735               err = ks_printf_help (ctrl, "marking '%s' as dead",
736                                     hi2->name);
737             }
738         }
739     }
740
741   return err;
742 }
743
744
745 /* Debug function to print the entire hosttable.  */
746 gpg_error_t
747 ks_hkp_print_hosttable (ctrl_t ctrl)
748 {
749   gpg_error_t err;
750   int idx, idx2;
751   hostinfo_t hi;
752   membuf_t mb;
753   time_t curtime;
754   char *p, *died;
755   const char *diedstr;
756
757   err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
758   if (err)
759     return err;
760
761   curtime = gnupg_get_time ();
762   for (idx=0; idx < hosttable_size; idx++)
763     if ((hi=hosttable[idx]))
764       {
765         if (hi->dead && hi->died_at)
766           {
767             died = elapsed_time_string (hi->died_at, curtime);
768             diedstr = died? died : "error";
769           }
770         else
771           diedstr = died = NULL;
772         err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n",
773                               idx,
774                               hi->onion? "O" : hi->v6? "6":" ",
775                               hi->v4? "4":" ",
776                               hi->dead? "d":" ",
777                               hi->name,
778                               hi->v6addr? " v6=":"",
779                               hi->v6addr? hi->v6addr:"",
780                               hi->v4addr? " v4=":"",
781                               hi->v4addr? hi->v4addr:"",
782                               diedstr? "  (":"",
783                               diedstr? diedstr:"",
784                               diedstr? ")":""   );
785         xfree (died);
786         if (err)
787           return err;
788
789         if (hi->cname)
790           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
791         if (err)
792           return err;
793
794         if (hi->pool)
795           {
796             init_membuf (&mb, 256);
797             put_membuf_printf (&mb, "  .   -->");
798             for (idx2=0; hi->pool[idx2] != -1; idx2++)
799               {
800                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
801                 if (hi->poolidx == hi->pool[idx2])
802                   put_membuf_printf (&mb, "*");
803               }
804             put_membuf( &mb, "", 1);
805             p = get_membuf (&mb, NULL);
806             if (!p)
807               return gpg_error_from_syserror ();
808             err = ks_print_help (ctrl, p);
809             xfree (p);
810             if (err)
811               return err;
812           }
813       }
814   return 0;
815 }
816
817
818
819 /* Print a help output for the schemata supported by this module. */
820 gpg_error_t
821 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
822 {
823   const char const data[] =
824     "Handler for HKP URLs:\n"
825     "  hkp://\n"
826 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
827     "  hkps://\n"
828 #endif
829     "Supported methods: search, get, put\n";
830   gpg_error_t err;
831
832 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
833   const char data2[] = "  hkp\n  hkps";
834 #else
835   const char data2[] = "  hkp";
836 #endif
837
838   if (!uri)
839     err = ks_print_help (ctrl, data2);
840   else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
841                             || !strcmp (uri->scheme, "hkps")))
842     err = ks_print_help (ctrl, data);
843   else
844     err = 0;
845
846   return err;
847 }
848
849
850 /* Build the remote part of the URL from SCHEME, HOST and an optional
851    PORT.  Returns an allocated string at R_HOSTPORT or NULL on failure
852    If R_POOLNAME is not NULL it receives a malloced string with the
853    poolname.  */
854 static gpg_error_t
855 make_host_part (ctrl_t ctrl,
856                 const char *scheme, const char *host, unsigned short port,
857                 int force_reselect,
858                 char **r_hostport, unsigned int *r_httpflags, char **r_poolname)
859 {
860   gpg_error_t err;
861   char portstr[10];
862   char *hostname;
863
864   *r_hostport = NULL;
865
866   portstr[0] = 0;
867   err = map_host (ctrl, host, force_reselect,
868                   &hostname, portstr, r_httpflags, r_poolname);
869   if (err)
870     return err;
871
872   /* Map scheme and port.  */
873   if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
874     {
875       scheme = "https";
876       if (! *portstr)
877         strcpy (portstr, "443");
878     }
879   else /* HKP or HTTP.  */
880     {
881       scheme = "http";
882       if (! *portstr)
883         strcpy (portstr, "11371");
884     }
885   if (port)
886     snprintf (portstr, sizeof portstr, "%hu", port);
887   else
888     {
889       /*fixme_do_srv_lookup ()*/
890     }
891
892   *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
893   xfree (hostname);
894   if (!*r_hostport)
895     {
896       if (r_poolname)
897         {
898           xfree (*r_poolname);
899           *r_poolname = NULL;
900         }
901       return gpg_error_from_syserror ();
902     }
903   return 0;
904 }
905
906
907 /* Resolve all known keyserver names and update the hosttable.  This
908    is mainly useful for debugging because the resolving is anyway done
909    on demand.  */
910 gpg_error_t
911 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
912 {
913   gpg_error_t err;
914   char *hostport = NULL;
915
916   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1,
917                         &hostport, NULL, NULL);
918   if (err)
919     {
920       err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
921                             uri->scheme, uri->host, uri->port,
922                             gpg_strerror (err));
923     }
924   else
925     {
926       err = ks_printf_help (ctrl, "%s", hostport);
927       xfree (hostport);
928     }
929   return err;
930 }
931
932
933 /* Housekeeping function called from the housekeeping thread.  It is
934    used to mark dead hosts alive so that they may be tried again after
935    some time.  */
936 void
937 ks_hkp_housekeeping (time_t curtime)
938 {
939   int idx;
940   hostinfo_t hi;
941
942   for (idx=0; idx < hosttable_size; idx++)
943     {
944       hi = hosttable[idx];
945       if (!hi)
946         continue;
947       if (!hi->dead)
948         continue;
949       if (!hi->died_at)
950         continue; /* Do not resurrect manually shot hosts.  */
951       if (hi->died_at + RESURRECT_INTERVAL <= curtime
952           || hi->died_at > curtime)
953         {
954           hi->dead = 0;
955           log_info ("resurrected host '%s'", hi->name);
956         }
957     }
958 }
959
960
961 /* Send an HTTP request.  On success returns an estream object at
962    R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
963    not NULL it will be used as HTTP "Host" header.  If POST_CB is not
964    NULL a post request is used and that callback is called to allow
965    writing the post data.  If R_HTTP_STATUS is not NULL, the http
966    status code will be stored there.  */
967 static gpg_error_t
968 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
969               const char *httphost, unsigned int httpflags,
970               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
971               estream_t *r_fp, unsigned int *r_http_status)
972 {
973   gpg_error_t err;
974   http_session_t session = NULL;
975   http_t http = NULL;
976   int redirects_left = MAX_REDIRECTS;
977   estream_t fp = NULL;
978   char *request_buffer = NULL;
979
980   *r_fp = NULL;
981
982   err = http_session_new (&session, NULL, httphost, HTTP_FLAG_TRUST_DEF);
983   if (err)
984     goto leave;
985   http_session_set_log_cb (session, cert_log_cb);
986
987  once_more:
988   err = http_open (&http,
989                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
990                    request,
991                    httphost,
992                    /* fixme: AUTH */ NULL,
993                    (httpflags
994                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
995                     |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
996                    ctrl->http_proxy,
997                    session,
998                    NULL,
999                    /*FIXME curl->srvtag*/NULL);
1000   if (!err)
1001     {
1002       fp = http_get_write_ptr (http);
1003       /* Avoid caches to get the most recent copy of the key.  We set
1004          both the Pragma and Cache-Control versions of the header, so
1005          we're good with both HTTP 1.0 and 1.1.  */
1006       es_fputs ("Pragma: no-cache\r\n"
1007                 "Cache-Control: no-cache\r\n", fp);
1008       if (post_cb)
1009         err = post_cb (post_cb_value, http);
1010       if (!err)
1011         {
1012           http_start_data (http);
1013           if (es_ferror (fp))
1014             err = gpg_error_from_syserror ();
1015         }
1016     }
1017   if (err)
1018     {
1019       /* Fixme: After a redirection we show the old host name.  */
1020       log_error (_("error connecting to '%s': %s\n"),
1021                  hostportstr, gpg_strerror (err));
1022       goto leave;
1023     }
1024
1025   /* Wait for the response.  */
1026   dirmngr_tick (ctrl);
1027   err = http_wait_response (http);
1028   if (err)
1029     {
1030       log_error (_("error reading HTTP response for '%s': %s\n"),
1031                  hostportstr, gpg_strerror (err));
1032       goto leave;
1033     }
1034
1035   if (http_get_tls_info (http, NULL))
1036     {
1037       /* Update the httpflags so that a redirect won't fallback to an
1038          unencrypted connection.  */
1039       httpflags |= HTTP_FLAG_FORCE_TLS;
1040     }
1041
1042   if (r_http_status)
1043     *r_http_status = http_get_status_code (http);
1044
1045   switch (http_get_status_code (http))
1046     {
1047     case 200:
1048       err = 0;
1049       break; /* Success.  */
1050
1051     case 301:
1052     case 302:
1053     case 307:
1054       {
1055         const char *s = http_get_header (http, "Location");
1056
1057         log_info (_("URL '%s' redirected to '%s' (%u)\n"),
1058                   request, s?s:"[none]", http_get_status_code (http));
1059         if (s && *s && redirects_left-- )
1060           {
1061             xfree (request_buffer);
1062             request_buffer = xtrystrdup (s);
1063             if (request_buffer)
1064               {
1065                 request = request_buffer;
1066                 http_close (http, 0);
1067                 http = NULL;
1068                 goto once_more;
1069               }
1070             err = gpg_error_from_syserror ();
1071           }
1072         else
1073           err = gpg_error (GPG_ERR_NO_DATA);
1074         log_error (_("too many redirections\n"));
1075       }
1076       goto leave;
1077
1078     case 501:
1079       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1080       goto leave;
1081
1082     default:
1083       log_error (_("error accessing '%s': http status %u\n"),
1084                  request, http_get_status_code (http));
1085       err = gpg_error (GPG_ERR_NO_DATA);
1086       goto leave;
1087     }
1088
1089   /* FIXME: We should register a permanent redirection and whether a
1090      host has ever used TLS so that future calls will always use
1091      TLS. */
1092
1093   fp = http_get_read_ptr (http);
1094   if (!fp)
1095     {
1096       err = gpg_error (GPG_ERR_BUG);
1097       goto leave;
1098     }
1099
1100   /* Return the read stream and close the HTTP context.  */
1101   *r_fp = fp;
1102   http_close (http, 1);
1103   http = NULL;
1104
1105  leave:
1106   http_close (http, 0);
1107   http_session_release (session);
1108   xfree (request_buffer);
1109   return err;
1110 }
1111
1112
1113 /* Helper to evaluate the error code ERR form a send_request() call
1114    with REQUEST.  The function returns true if the caller shall try
1115    again.  TRIES_LEFT points to a variable to track the number of
1116    retries; this function decrements it and won't return true if it is
1117    down to zero. */
1118 static int
1119 handle_send_request_error (gpg_error_t err, const char *request,
1120                            unsigned int *tries_left)
1121 {
1122   int retry = 0;
1123
1124   switch (gpg_err_code (err))
1125     {
1126     case GPG_ERR_ECONNREFUSED:
1127     case GPG_ERR_ENETUNREACH:
1128     case GPG_ERR_UNKNOWN_HOST:
1129     case GPG_ERR_NETWORK:
1130       if (mark_host_dead (request) && *tries_left)
1131         retry = 1;
1132       break;
1133
1134     case GPG_ERR_ETIMEDOUT:
1135       if (*tries_left)
1136         {
1137           log_info ("selecting a different host due to a timeout\n");
1138           retry = 1;
1139         }
1140
1141     default:
1142       break;
1143     }
1144
1145   if (*tries_left)
1146     --*tries_left;
1147
1148   return retry;
1149 }
1150
1151 \f
1152 /* Search the keyserver identified by URI for keys matching PATTERN.
1153    On success R_FP has an open stream to read the data.  If
1154    R_HTTP_STATUS is not NULL, the http status code will be stored
1155    there.  */
1156 gpg_error_t
1157 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1158                estream_t *r_fp, unsigned int *r_http_status)
1159 {
1160   gpg_error_t err;
1161   KEYDB_SEARCH_DESC desc;
1162   char fprbuf[2+40+1];
1163   char *hostport = NULL;
1164   char *request = NULL;
1165   estream_t fp = NULL;
1166   int reselect;
1167   unsigned int httpflags;
1168   char *httphost = NULL;
1169   unsigned int tries = SEND_REQUEST_RETRIES;
1170
1171   *r_fp = NULL;
1172
1173   /* Remove search type indicator and adjust PATTERN accordingly.
1174      Note that HKP keyservers like the 0x to be present when searching
1175      by keyid.  We need to re-format the fingerprint and keyids so to
1176      remove the gpg specific force-use-of-this-key flag ("!").  */
1177   err = classify_user_id (pattern, &desc, 1);
1178   if (err)
1179     return err;
1180   switch (desc.mode)
1181     {
1182     case KEYDB_SEARCH_MODE_EXACT:
1183     case KEYDB_SEARCH_MODE_SUBSTR:
1184     case KEYDB_SEARCH_MODE_MAIL:
1185     case KEYDB_SEARCH_MODE_MAILSUB:
1186       pattern = desc.u.name;
1187       break;
1188     case KEYDB_SEARCH_MODE_SHORT_KID:
1189       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1190       pattern = fprbuf;
1191       break;
1192     case KEYDB_SEARCH_MODE_LONG_KID:
1193       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1194                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1195       pattern = fprbuf;
1196       break;
1197     case KEYDB_SEARCH_MODE_FPR16:
1198       fprbuf[0] = '0';
1199       fprbuf[1] = 'x';
1200       bin2hex (desc.u.fpr, 16, fprbuf+2);
1201       pattern = fprbuf;
1202       break;
1203     case KEYDB_SEARCH_MODE_FPR20:
1204     case KEYDB_SEARCH_MODE_FPR:
1205       fprbuf[0] = '0';
1206       fprbuf[1] = 'x';
1207       bin2hex (desc.u.fpr, 20, fprbuf+2);
1208       pattern = fprbuf;
1209       break;
1210     default:
1211       return gpg_error (GPG_ERR_INV_USER_ID);
1212     }
1213
1214   /* Build the request string.  */
1215   reselect = 0;
1216  again:
1217   {
1218     char *searchkey;
1219
1220     xfree (hostport); hostport = NULL;
1221     xfree (httphost); httphost = NULL;
1222     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1223                           &hostport, &httpflags, &httphost);
1224     if (err)
1225       goto leave;
1226
1227     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1228     if (!searchkey)
1229       {
1230         err = gpg_error_from_syserror ();
1231         goto leave;
1232       }
1233
1234     xfree (request);
1235     request = strconcat (hostport,
1236                          "/pks/lookup?op=index&options=mr&search=",
1237                          searchkey,
1238                          NULL);
1239     xfree (searchkey);
1240     if (!request)
1241       {
1242         err = gpg_error_from_syserror ();
1243         goto leave;
1244       }
1245   }
1246
1247   /* Send the request.  */
1248   err = send_request (ctrl, request, hostport, httphost, httpflags,
1249                       NULL, NULL, &fp, r_http_status);
1250   if (handle_send_request_error (err, request, &tries))
1251     {
1252       reselect = 1;
1253       goto again;
1254     }
1255   if (err)
1256     goto leave;
1257
1258   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1259   if (err)
1260     goto leave;
1261
1262   /* Peek at the response.  */
1263   {
1264     int c = es_getc (fp);
1265     if (c == -1)
1266       {
1267         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1268         log_error ("error reading response: %s\n", gpg_strerror (err));
1269         goto leave;
1270       }
1271     if (c == '<')
1272       {
1273         /* The document begins with a '<': Assume a HTML response,
1274            which we don't support.  */
1275         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1276         goto leave;
1277       }
1278     es_ungetc (c, fp);
1279   }
1280
1281   /* Return the read stream.  */
1282   *r_fp = fp;
1283   fp = NULL;
1284
1285  leave:
1286   es_fclose (fp);
1287   xfree (request);
1288   xfree (hostport);
1289   xfree (httphost);
1290   return err;
1291 }
1292
1293
1294 /* Get the key described key the KEYSPEC string from the keyserver
1295    identified by URI.  On success R_FP has an open stream to read the
1296    data.  The data will be provided in a format GnuPG can import
1297    (either a binary OpenPGP message or an armored one).  */
1298 gpg_error_t
1299 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1300 {
1301   gpg_error_t err;
1302   KEYDB_SEARCH_DESC desc;
1303   char kidbuf[2+40+1];
1304   const char *exactname = NULL;
1305   char *searchkey = NULL;
1306   char *hostport = NULL;
1307   char *request = NULL;
1308   estream_t fp = NULL;
1309   int reselect;
1310   char *httphost = NULL;
1311   unsigned int httpflags;
1312   unsigned int tries = SEND_REQUEST_RETRIES;
1313
1314   *r_fp = NULL;
1315
1316   /* Remove search type indicator and adjust PATTERN accordingly.
1317      Note that HKP keyservers like the 0x to be present when searching
1318      by keyid.  We need to re-format the fingerprint and keyids so to
1319      remove the gpg specific force-use-of-this-key flag ("!").  */
1320   err = classify_user_id (keyspec, &desc, 1);
1321   if (err)
1322     return err;
1323   switch (desc.mode)
1324     {
1325     case KEYDB_SEARCH_MODE_SHORT_KID:
1326       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1327       break;
1328     case KEYDB_SEARCH_MODE_LONG_KID:
1329       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1330                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1331       break;
1332     case KEYDB_SEARCH_MODE_FPR20:
1333     case KEYDB_SEARCH_MODE_FPR:
1334       /* This is a v4 fingerprint. */
1335       kidbuf[0] = '0';
1336       kidbuf[1] = 'x';
1337       bin2hex (desc.u.fpr, 20, kidbuf+2);
1338       break;
1339
1340     case KEYDB_SEARCH_MODE_EXACT:
1341       exactname = desc.u.name;
1342       break;
1343
1344     case KEYDB_SEARCH_MODE_FPR16:
1345       log_error ("HKP keyservers do not support v3 fingerprints\n");
1346     default:
1347       return gpg_error (GPG_ERR_INV_USER_ID);
1348     }
1349
1350   searchkey = http_escape_string (exactname? exactname : kidbuf,
1351                                   EXTRA_ESCAPE_CHARS);
1352   if (!searchkey)
1353     {
1354       err = gpg_error_from_syserror ();
1355       goto leave;
1356     }
1357
1358   reselect = 0;
1359  again:
1360   /* Build the request string.  */
1361   xfree (hostport); hostport = NULL;
1362   xfree (httphost); httphost = NULL;
1363   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1364                         &hostport, &httpflags, &httphost);
1365   if (err)
1366     goto leave;
1367
1368   xfree (request);
1369   request = strconcat (hostport,
1370                        "/pks/lookup?op=get&options=mr&search=",
1371                        searchkey,
1372                        exactname? "&exact=on":"",
1373                        NULL);
1374   if (!request)
1375     {
1376       err = gpg_error_from_syserror ();
1377       goto leave;
1378     }
1379
1380   /* Send the request.  */
1381   err = send_request (ctrl, request, hostport, httphost, httpflags,
1382                       NULL, NULL, &fp, NULL);
1383   if (handle_send_request_error (err, request, &tries))
1384     {
1385       reselect = 1;
1386       goto again;
1387     }
1388   if (err)
1389     goto leave;
1390
1391   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1392   if (err)
1393     goto leave;
1394
1395   /* Return the read stream and close the HTTP context.  */
1396   *r_fp = fp;
1397   fp = NULL;
1398
1399  leave:
1400   es_fclose (fp);
1401   xfree (request);
1402   xfree (hostport);
1403   xfree (httphost);
1404   xfree (searchkey);
1405   return err;
1406 }
1407
1408
1409
1410 \f
1411 /* Callback parameters for put_post_cb.  */
1412 struct put_post_parm_s
1413 {
1414   char *datastring;
1415 };
1416
1417
1418 /* Helper for ks_hkp_put.  */
1419 static gpg_error_t
1420 put_post_cb (void *opaque, http_t http)
1421 {
1422   struct put_post_parm_s *parm = opaque;
1423   gpg_error_t err = 0;
1424   estream_t fp;
1425   size_t len;
1426
1427   fp = http_get_write_ptr (http);
1428   len = strlen (parm->datastring);
1429
1430   es_fprintf (fp,
1431               "Content-Type: application/x-www-form-urlencoded\r\n"
1432               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1433   http_start_data (http);
1434   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1435     err = gpg_error_from_syserror ();
1436   return err;
1437 }
1438
1439
1440 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1441 gpg_error_t
1442 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1443 {
1444   gpg_error_t err;
1445   char *hostport = NULL;
1446   char *request = NULL;
1447   estream_t fp = NULL;
1448   struct put_post_parm_s parm;
1449   char *armored = NULL;
1450   int reselect;
1451   char *httphost = NULL;
1452   unsigned int httpflags;
1453   unsigned int tries = SEND_REQUEST_RETRIES;
1454
1455   parm.datastring = NULL;
1456
1457   err = armor_data (&armored, data, datalen);
1458   if (err)
1459     goto leave;
1460
1461   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1462   if (!parm.datastring)
1463     {
1464       err = gpg_error_from_syserror ();
1465       goto leave;
1466     }
1467   xfree (armored);
1468   armored = NULL;
1469
1470   /* Build the request string.  */
1471   reselect = 0;
1472  again:
1473   xfree (hostport); hostport = NULL;
1474   xfree (httphost); httphost = NULL;
1475   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1476                         &hostport, &httpflags, &httphost);
1477   if (err)
1478     goto leave;
1479
1480   xfree (request);
1481   request = strconcat (hostport, "/pks/add", NULL);
1482   if (!request)
1483     {
1484       err = gpg_error_from_syserror ();
1485       goto leave;
1486     }
1487
1488   /* Send the request.  */
1489   err = send_request (ctrl, request, hostport, httphost, 0,
1490                       put_post_cb, &parm, &fp, NULL);
1491   if (handle_send_request_error (err, request, &tries))
1492     {
1493       reselect = 1;
1494       goto again;
1495     }
1496   if (err)
1497     goto leave;
1498
1499  leave:
1500   es_fclose (fp);
1501   xfree (parm.datastring);
1502   xfree (armored);
1503   xfree (request);
1504   xfree (hostport);
1505   xfree (httphost);
1506   return err;
1507 }