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