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