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