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