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