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