dirmngr: Use "pgpkey-hkps" and "pgpkey-hkp" for SRV record lookups.
[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   switch (gpg_err_code (err))
1136     {
1137     case GPG_ERR_ECONNREFUSED:
1138     case GPG_ERR_ENETUNREACH:
1139     case GPG_ERR_UNKNOWN_HOST:
1140     case GPG_ERR_NETWORK:
1141       if (mark_host_dead (request) && *tries_left)
1142         retry = 1;
1143       break;
1144
1145     case GPG_ERR_ETIMEDOUT:
1146       if (*tries_left)
1147         {
1148           log_info ("selecting a different host due to a timeout\n");
1149           retry = 1;
1150         }
1151
1152     default:
1153       break;
1154     }
1155
1156   if (*tries_left)
1157     --*tries_left;
1158
1159   return retry;
1160 }
1161
1162 \f
1163 /* Search the keyserver identified by URI for keys matching PATTERN.
1164    On success R_FP has an open stream to read the data.  If
1165    R_HTTP_STATUS is not NULL, the http status code will be stored
1166    there.  */
1167 gpg_error_t
1168 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1169                estream_t *r_fp, unsigned int *r_http_status)
1170 {
1171   gpg_error_t err;
1172   KEYDB_SEARCH_DESC desc;
1173   char fprbuf[2+40+1];
1174   char *hostport = NULL;
1175   char *request = NULL;
1176   estream_t fp = NULL;
1177   int reselect;
1178   unsigned int httpflags;
1179   char *httphost = NULL;
1180   unsigned int tries = SEND_REQUEST_RETRIES;
1181
1182   *r_fp = NULL;
1183
1184   /* Remove search type indicator and adjust PATTERN accordingly.
1185      Note that HKP keyservers like the 0x to be present when searching
1186      by keyid.  We need to re-format the fingerprint and keyids so to
1187      remove the gpg specific force-use-of-this-key flag ("!").  */
1188   err = classify_user_id (pattern, &desc, 1);
1189   if (err)
1190     return err;
1191   switch (desc.mode)
1192     {
1193     case KEYDB_SEARCH_MODE_EXACT:
1194     case KEYDB_SEARCH_MODE_SUBSTR:
1195     case KEYDB_SEARCH_MODE_MAIL:
1196     case KEYDB_SEARCH_MODE_MAILSUB:
1197       pattern = desc.u.name;
1198       break;
1199     case KEYDB_SEARCH_MODE_SHORT_KID:
1200       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1201       pattern = fprbuf;
1202       break;
1203     case KEYDB_SEARCH_MODE_LONG_KID:
1204       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1205                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1206       pattern = fprbuf;
1207       break;
1208     case KEYDB_SEARCH_MODE_FPR16:
1209       fprbuf[0] = '0';
1210       fprbuf[1] = 'x';
1211       bin2hex (desc.u.fpr, 16, fprbuf+2);
1212       pattern = fprbuf;
1213       break;
1214     case KEYDB_SEARCH_MODE_FPR20:
1215     case KEYDB_SEARCH_MODE_FPR:
1216       fprbuf[0] = '0';
1217       fprbuf[1] = 'x';
1218       bin2hex (desc.u.fpr, 20, fprbuf+2);
1219       pattern = fprbuf;
1220       break;
1221     default:
1222       return gpg_error (GPG_ERR_INV_USER_ID);
1223     }
1224
1225   /* Build the request string.  */
1226   reselect = 0;
1227  again:
1228   {
1229     char *searchkey;
1230
1231     xfree (hostport); hostport = NULL;
1232     xfree (httphost); httphost = NULL;
1233     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1234                           reselect, uri->explicit_port,
1235                           &hostport, &httpflags, &httphost);
1236     if (err)
1237       goto leave;
1238
1239     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1240     if (!searchkey)
1241       {
1242         err = gpg_error_from_syserror ();
1243         goto leave;
1244       }
1245
1246     xfree (request);
1247     request = strconcat (hostport,
1248                          "/pks/lookup?op=index&options=mr&search=",
1249                          searchkey,
1250                          NULL);
1251     xfree (searchkey);
1252     if (!request)
1253       {
1254         err = gpg_error_from_syserror ();
1255         goto leave;
1256       }
1257   }
1258
1259   /* Send the request.  */
1260   err = send_request (ctrl, request, hostport, httphost, httpflags,
1261                       NULL, NULL, &fp, r_http_status);
1262   if (handle_send_request_error (err, request, &tries))
1263     {
1264       reselect = 1;
1265       goto again;
1266     }
1267   if (err)
1268     goto leave;
1269
1270   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1271   if (err)
1272     goto leave;
1273
1274   /* Peek at the response.  */
1275   {
1276     int c = es_getc (fp);
1277     if (c == -1)
1278       {
1279         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1280         log_error ("error reading response: %s\n", gpg_strerror (err));
1281         goto leave;
1282       }
1283     if (c == '<')
1284       {
1285         /* The document begins with a '<': Assume a HTML response,
1286            which we don't support.  */
1287         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1288         goto leave;
1289       }
1290     es_ungetc (c, fp);
1291   }
1292
1293   /* Return the read stream.  */
1294   *r_fp = fp;
1295   fp = NULL;
1296
1297  leave:
1298   es_fclose (fp);
1299   xfree (request);
1300   xfree (hostport);
1301   xfree (httphost);
1302   return err;
1303 }
1304
1305
1306 /* Get the key described key the KEYSPEC string from the keyserver
1307    identified by URI.  On success R_FP has an open stream to read the
1308    data.  The data will be provided in a format GnuPG can import
1309    (either a binary OpenPGP message or an armored one).  */
1310 gpg_error_t
1311 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1312 {
1313   gpg_error_t err;
1314   KEYDB_SEARCH_DESC desc;
1315   char kidbuf[2+40+1];
1316   const char *exactname = NULL;
1317   char *searchkey = NULL;
1318   char *hostport = NULL;
1319   char *request = NULL;
1320   estream_t fp = NULL;
1321   int reselect;
1322   char *httphost = NULL;
1323   unsigned int httpflags;
1324   unsigned int tries = SEND_REQUEST_RETRIES;
1325
1326   *r_fp = NULL;
1327
1328   /* Remove search type indicator and adjust PATTERN accordingly.
1329      Note that HKP keyservers like the 0x to be present when searching
1330      by keyid.  We need to re-format the fingerprint and keyids so to
1331      remove the gpg specific force-use-of-this-key flag ("!").  */
1332   err = classify_user_id (keyspec, &desc, 1);
1333   if (err)
1334     return err;
1335   switch (desc.mode)
1336     {
1337     case KEYDB_SEARCH_MODE_SHORT_KID:
1338       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1339       break;
1340     case KEYDB_SEARCH_MODE_LONG_KID:
1341       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1342                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1343       break;
1344     case KEYDB_SEARCH_MODE_FPR20:
1345     case KEYDB_SEARCH_MODE_FPR:
1346       /* This is a v4 fingerprint. */
1347       kidbuf[0] = '0';
1348       kidbuf[1] = 'x';
1349       bin2hex (desc.u.fpr, 20, kidbuf+2);
1350       break;
1351
1352     case KEYDB_SEARCH_MODE_EXACT:
1353       exactname = desc.u.name;
1354       break;
1355
1356     case KEYDB_SEARCH_MODE_FPR16:
1357       log_error ("HKP keyservers do not support v3 fingerprints\n");
1358     default:
1359       return gpg_error (GPG_ERR_INV_USER_ID);
1360     }
1361
1362   searchkey = http_escape_string (exactname? exactname : kidbuf,
1363                                   EXTRA_ESCAPE_CHARS);
1364   if (!searchkey)
1365     {
1366       err = gpg_error_from_syserror ();
1367       goto leave;
1368     }
1369
1370   reselect = 0;
1371  again:
1372   /* Build the request string.  */
1373   xfree (hostport); hostport = NULL;
1374   xfree (httphost); httphost = NULL;
1375   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1376                         reselect, uri->explicit_port,
1377                         &hostport, &httpflags, &httphost);
1378   if (err)
1379     goto leave;
1380
1381   xfree (request);
1382   request = strconcat (hostport,
1383                        "/pks/lookup?op=get&options=mr&search=",
1384                        searchkey,
1385                        exactname? "&exact=on":"",
1386                        NULL);
1387   if (!request)
1388     {
1389       err = gpg_error_from_syserror ();
1390       goto leave;
1391     }
1392
1393   /* Send the request.  */
1394   err = send_request (ctrl, request, hostport, httphost, httpflags,
1395                       NULL, NULL, &fp, NULL);
1396   if (handle_send_request_error (err, request, &tries))
1397     {
1398       reselect = 1;
1399       goto again;
1400     }
1401   if (err)
1402     goto leave;
1403
1404   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1405   if (err)
1406     goto leave;
1407
1408   /* Return the read stream and close the HTTP context.  */
1409   *r_fp = fp;
1410   fp = NULL;
1411
1412  leave:
1413   es_fclose (fp);
1414   xfree (request);
1415   xfree (hostport);
1416   xfree (httphost);
1417   xfree (searchkey);
1418   return err;
1419 }
1420
1421
1422
1423 \f
1424 /* Callback parameters for put_post_cb.  */
1425 struct put_post_parm_s
1426 {
1427   char *datastring;
1428 };
1429
1430
1431 /* Helper for ks_hkp_put.  */
1432 static gpg_error_t
1433 put_post_cb (void *opaque, http_t http)
1434 {
1435   struct put_post_parm_s *parm = opaque;
1436   gpg_error_t err = 0;
1437   estream_t fp;
1438   size_t len;
1439
1440   fp = http_get_write_ptr (http);
1441   len = strlen (parm->datastring);
1442
1443   es_fprintf (fp,
1444               "Content-Type: application/x-www-form-urlencoded\r\n"
1445               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1446   http_start_data (http);
1447   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1448     err = gpg_error_from_syserror ();
1449   return err;
1450 }
1451
1452
1453 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1454 gpg_error_t
1455 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1456 {
1457   gpg_error_t err;
1458   char *hostport = NULL;
1459   char *request = NULL;
1460   estream_t fp = NULL;
1461   struct put_post_parm_s parm;
1462   char *armored = NULL;
1463   int reselect;
1464   char *httphost = NULL;
1465   unsigned int httpflags;
1466   unsigned int tries = SEND_REQUEST_RETRIES;
1467
1468   parm.datastring = NULL;
1469
1470   err = armor_data (&armored, data, datalen);
1471   if (err)
1472     goto leave;
1473
1474   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1475   if (!parm.datastring)
1476     {
1477       err = gpg_error_from_syserror ();
1478       goto leave;
1479     }
1480   xfree (armored);
1481   armored = NULL;
1482
1483   /* Build the request string.  */
1484   reselect = 0;
1485  again:
1486   xfree (hostport); hostport = NULL;
1487   xfree (httphost); httphost = NULL;
1488   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1489                         reselect, uri->explicit_port,
1490                         &hostport, &httpflags, &httphost);
1491   if (err)
1492     goto leave;
1493
1494   xfree (request);
1495   request = strconcat (hostport, "/pks/add", NULL);
1496   if (!request)
1497     {
1498       err = gpg_error_from_syserror ();
1499       goto leave;
1500     }
1501
1502   /* Send the request.  */
1503   err = send_request (ctrl, request, hostport, httphost, 0,
1504                       put_post_cb, &parm, &fp, NULL);
1505   if (handle_send_request_error (err, request, &tries))
1506     {
1507       reselect = 1;
1508       goto again;
1509     }
1510   if (err)
1511     goto leave;
1512
1513  leave:
1514   es_fclose (fp);
1515   xfree (parm.datastring);
1516   xfree (armored);
1517   xfree (request);
1518   xfree (hostport);
1519   xfree (httphost);
1520   return err;
1521 }