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