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