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