dirmngr: Fix license note in server.c
[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 "../common/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 enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
71
72 /* Objects used to maintain information about hosts.  */
73 struct hostinfo_s;
74 typedef struct hostinfo_s *hostinfo_t;
75 struct hostinfo_s
76 {
77   time_t lastfail;   /* Time we tried to connect and failed.  */
78   time_t lastused;   /* Time of last use.  */
79   int *pool;         /* An array with indices into HOSTTABLE or NULL
80                         if NAME is not a pool name.  */
81   size_t pool_len;   /* Length of POOL.  */
82   size_t pool_size;  /* Allocated size of POOL.  */
83 #define MAX_POOL_SIZE   128
84   int poolidx;       /* Index into POOL with the used host.  -1 if not set.  */
85   unsigned int v4:1; /* Host supports AF_INET.  */
86   unsigned int v6:1; /* Host supports AF_INET6.  */
87   unsigned int onion:1;/* NAME is an onion (Tor HS) address.  */
88   unsigned int dead:1; /* Host is currently unresponsive.  */
89   unsigned int iporname_valid:1;  /* The field IPORNAME below is valid */
90                                   /* (but may be NULL) */
91   unsigned int did_a_lookup:1;    /* Have we done an A lookup yet?  */
92   unsigned int did_srv_lookup:2;  /* One bit per protocol indicating
93                                      whether we already did a SRV
94                                      lookup.  */
95   time_t died_at;    /* The time the host was marked dead.  If this is
96                         0 the host has been manually marked dead.  */
97   char *cname;       /* Canonical name of the host.  Only set if this
98                         is a pool or NAME has a numerical IP address.  */
99   char *iporname;    /* Numeric IP address or name for printing.  */
100   unsigned short port[KS_PROTOCOL_MAX];
101                      /* The port used by the host for all protocols, 0
102                         if unknown.  */
103   char name[1];      /* The hostname.  */
104 };
105
106
107 /* An array of hostinfo_t for all hosts requested by the caller or
108    resolved from a pool name and its allocated size.*/
109 static hostinfo_t *hosttable;
110 static int hosttable_size;
111
112 /* The number of host slots we initially allocate for HOSTTABLE.  */
113 #define INITIAL_HOSTTABLE_SIZE 10
114
115
116 /* Create a new hostinfo object, fill in NAME and put it into
117    HOSTTABLE.  Return the index into hosttable on success or -1 on
118    error. */
119 static int
120 create_new_hostinfo (const char *name)
121 {
122   hostinfo_t hi, *newtable;
123   int newsize;
124   int idx, rc;
125
126   hi = xtrymalloc (sizeof *hi + strlen (name));
127   if (!hi)
128     return -1;
129   strcpy (hi->name, name);
130   hi->pool = NULL;
131   hi->pool_len = 0;
132   hi->pool_size = 0;
133   hi->poolidx = -1;
134   hi->lastused = (time_t)(-1);
135   hi->lastfail = (time_t)(-1);
136   hi->v4 = 0;
137   hi->v6 = 0;
138   hi->onion = 0;
139   hi->dead = 0;
140   hi->did_a_lookup = 0;
141   hi->did_srv_lookup = 0;
142   hi->iporname_valid = 0;
143   hi->died_at = 0;
144   hi->cname = NULL;
145   hi->iporname = NULL;
146   hi->port[KS_PROTOCOL_HKP] = 0;
147   hi->port[KS_PROTOCOL_HKPS] = 0;
148
149   /* Add it to the hosttable. */
150   for (idx=0; idx < hosttable_size; idx++)
151     if (!hosttable[idx])
152       {
153         hosttable[idx] = hi;
154         return idx;
155       }
156   /* Need to extend the hosttable.  */
157   newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
158   newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
159   if (!newtable)
160     {
161       xfree (hi);
162       return -1;
163     }
164   hosttable = newtable;
165   idx = hosttable_size;
166   hosttable_size = newsize;
167   rc = idx;
168   hosttable[idx++] = hi;
169   while (idx < hosttable_size)
170     hosttable[idx++] = NULL;
171
172   return rc;
173 }
174
175
176 /* Find the host NAME in our table.  Return the index into the
177    hosttable or -1 if not found.  */
178 static int
179 find_hostinfo (const char *name)
180 {
181   int idx;
182
183   for (idx=0; idx < hosttable_size; idx++)
184     if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
185       return idx;
186   return -1;
187 }
188
189
190 static int
191 sort_hostpool (const void *xa, const void *xb)
192 {
193   int a = *(int *)xa;
194   int b = *(int *)xb;
195
196   assert (a >= 0 && a < hosttable_size);
197   assert (b >= 0 && b < hosttable_size);
198   assert (hosttable[a]);
199   assert (hosttable[b]);
200
201   return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
202 }
203
204
205 /* Return true if the host with the hosttable index TBLIDX is in HI->pool.  */
206 static int
207 host_in_pool_p (hostinfo_t hi, int tblidx)
208 {
209   int i, pidx;
210
211   for (i = 0; i < hi->pool_len && (pidx = hi->pool[i]) != -1; i++)
212     if (pidx == tblidx && hosttable[pidx])
213       return 1;
214   return 0;
215 }
216
217
218 /* Select a random host.  Consult HI->pool which indices into the global
219    hosttable.  Returns index into HI->pool or -1 if no host could be
220    selected.  */
221 static int
222 select_random_host (hostinfo_t hi)
223 {
224   int *tbl;
225   size_t tblsize;
226   int pidx, idx;
227
228   /* We create a new table so that we randomly select only from
229      currently alive hosts.  */
230   for (idx = 0, tblsize = 0;
231        idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
232        idx++)
233     if (hosttable[pidx] && !hosttable[pidx]->dead)
234       tblsize++;
235   if (!tblsize)
236     return -1; /* No hosts.  */
237
238   tbl = xtrymalloc (tblsize * sizeof *tbl);
239   if (!tbl)
240     return -1;
241   for (idx = 0, tblsize = 0;
242        idx < hi->pool_len && (pidx = hi->pool[idx]) != -1;
243        idx++)
244     if (hosttable[pidx] && !hosttable[pidx]->dead)
245       tbl[tblsize++] = pidx;
246
247   if (tblsize == 1)  /* Save a get_uint_nonce.  */
248     pidx = tbl[0];
249   else
250     pidx = tbl[get_uint_nonce () % tblsize];
251
252   xfree (tbl);
253   return pidx;
254 }
255
256
257 /* Figure out if a set of DNS records looks like a pool.  */
258 static int
259 arecords_is_pool (dns_addrinfo_t aibuf)
260 {
261   dns_addrinfo_t ai;
262   int n_v6, n_v4;
263
264   n_v6 = n_v4 = 0;
265   for (ai = aibuf; ai; ai = ai->next)
266     {
267       if (ai->family == AF_INET6)
268         n_v6++;
269       else if (ai->family == AF_INET)
270         n_v4++;
271     }
272
273   return n_v6 > 1 || n_v4 > 1;
274 }
275
276
277 /* Print a warning iff Tor is not running but Tor has been requested.
278  * Also return true if it is not running.  */
279 static int
280 tor_not_running_p (ctrl_t ctrl)
281 {
282   assuan_fd_t sock;
283
284   if (!dirmngr_use_tor ())
285     return 0;
286
287   sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
288   if (sock != ASSUAN_INVALID_FD)
289     {
290       assuan_sock_close (sock);
291       return 0;
292     }
293
294   log_info ("(it seems Tor is not running)\n");
295   dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
296                   "Tor is enabled but the local Tor daemon"
297                   " seems to be down", NULL);
298   return 1;
299 }
300
301
302 /* Add the host AI under the NAME into the HOSTTABLE.  If PORT is not
303    zero, it specifies which port to use to talk to the host for
304    PROTOCOL.  If NAME specifies a pool (as indicated by IS_POOL),
305    update the given reference table accordingly.  */
306 static void
307 add_host (const char *name, int is_pool,
308           const dns_addrinfo_t ai,
309           enum ks_protocol protocol, unsigned short port)
310 {
311   gpg_error_t tmperr;
312   char *tmphost;
313   int idx, tmpidx;
314   hostinfo_t host;
315   int i;
316
317   idx = find_hostinfo (name);
318   host = hosttable[idx];
319
320   if (is_pool)
321     {
322       /* For a pool immediately convert the address to a string.  */
323       tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
324                                  (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
325     }
326   else if (!is_ip_address (name))
327     {
328       /* This is a hostname.  Use the name as given without going
329        * through resolve_dns_addr.  */
330       tmphost = xtrystrdup (name);
331       if (!tmphost)
332         tmperr = gpg_error_from_syserror ();
333       else
334         tmperr = 0;
335     }
336   else
337     {
338       /* Do a PTR lookup on AI.  If a name was not found the function
339        * returns the numeric address (with brackets).  */
340       tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
341                                  DNS_WITHBRACKET, &tmphost);
342     }
343
344   if (tmperr)
345     {
346       log_info ("resolve_dns_addr failed while checking '%s': %s\n",
347                 name, gpg_strerror (tmperr));
348     }
349   else if (host->pool_len + 1 >= MAX_POOL_SIZE)
350     {
351       log_error ("resolve_dns_addr for '%s': '%s'"
352                  " [index table full - ignored]\n", name, tmphost);
353     }
354   else
355     {
356       if (!is_pool && is_ip_address (name))
357         /* Update the original entry.  */
358         tmpidx = idx;
359       else
360         tmpidx = find_hostinfo (tmphost);
361       log_info ("resolve_dns_addr for '%s': '%s'%s\n",
362                 name, tmphost,
363                 tmpidx == -1? "" : " [already known]");
364
365       if (tmpidx == -1) /* Create a new entry.  */
366         tmpidx = create_new_hostinfo (tmphost);
367
368       if (tmpidx == -1)
369         {
370           log_error ("map_host for '%s' problem: %s - '%s' [ignored]\n",
371                      name, strerror (errno), tmphost);
372         }
373       else  /* Set or update the entry. */
374         {
375           if (port)
376             hosttable[tmpidx]->port[protocol] = port;
377
378           if (ai->family == AF_INET6)
379             {
380               hosttable[tmpidx]->v6 = 1;
381             }
382           else if (ai->family == AF_INET)
383             {
384               hosttable[tmpidx]->v4 = 1;
385             }
386           else
387             BUG ();
388
389           /* If we updated the main entry, we're done.  */
390           if (idx == tmpidx)
391             goto leave;
392
393           /* If we updated an existing entry, we're done.  */
394           for (i = 0; i < host->pool_len; i++)
395             if (host->pool[i] == tmpidx)
396               goto leave;
397
398           /* Otherwise, we need to add it to the pool.  Check if there
399              is space.  */
400           if (host->pool_len + 1 > host->pool_size)
401             {
402               int *new_pool;
403               size_t new_size;
404
405               if (host->pool_size == 0)
406                 new_size = 4;
407               else
408                 new_size = host->pool_size * 2;
409
410               new_pool = xtryrealloc (host->pool,
411                                       new_size * sizeof *new_pool);
412
413               if (new_pool == NULL)
414                 goto leave;
415
416               host->pool = new_pool;
417               host->pool_size = new_size;
418             }
419
420           /* Finally, add it.  */
421           log_assert (host->pool_len < host->pool_size);
422           host->pool[host->pool_len++] = tmpidx;
423         }
424     }
425  leave:
426   xfree (tmphost);
427 }
428
429
430 /* Sort the pool of the given hostinfo HI.  */
431 static void
432 hostinfo_sort_pool (hostinfo_t hi)
433 {
434   qsort (hi->pool, hi->pool_len, sizeof *hi->pool, sort_hostpool);
435 }
436
437 /* Map the host name NAME to the actual to be used host name.  This
438  * allows us to manage round robin DNS names.  We use our own strategy
439  * to choose one of the hosts.  For example we skip those hosts which
440  * failed for some time and we stick to one host for a time
441  * independent of DNS retry times.  If FORCE_RESELECT is true a new
442  * host is always selected.  If SRVTAG is NULL no service record
443  * lookup will be done, if it is set that service name is used.  The
444  * selected host is stored as a malloced string at R_HOST; on error
445  * NULL is stored.  If we know the port used by the selected host from
446  * a service record, a string representation is written to R_PORTSTR,
447  * otherwise it is left untouched.  If R_HTTPFLAGS is not NULL it will
448  * receive flags which are to be passed to http_open.  If R_HTTPHOST
449  * is not NULL a malloced name of the host is stored there; this might
450  * be different from R_HOST in case it has been selected from a
451  * pool.  */
452 static gpg_error_t
453 map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
454           enum ks_protocol protocol, char **r_host, char *r_portstr,
455           unsigned int *r_httpflags, char **r_httphost)
456 {
457   gpg_error_t err = 0;
458   hostinfo_t hi;
459   int idx;
460   dns_addrinfo_t aibuf, ai;
461   int is_pool;
462   int new_hosts = 0;
463   char *cname;
464
465   *r_host = NULL;
466   if (r_httpflags)
467     *r_httpflags = 0;
468   if (r_httphost)
469     *r_httphost = NULL;
470
471   /* No hostname means localhost.  */
472   if (!name || !*name)
473     {
474       *r_host = xtrystrdup ("localhost");
475       return *r_host? 0 : gpg_error_from_syserror ();
476     }
477
478   /* See whether the host is in our table.  */
479   idx = find_hostinfo (name);
480   if (idx == -1)
481     {
482       idx = create_new_hostinfo (name);
483       if (idx == -1)
484         return gpg_error_from_syserror ();
485       hi = hosttable[idx];
486       hi->onion = is_onion_address (name);
487     }
488   else
489     hi = hosttable[idx];
490
491   is_pool = hi->pool != NULL;
492
493   if (srvtag && !is_ip_address (name)
494       && ! hi->onion
495       && ! (hi->did_srv_lookup & 1 << protocol))
496     {
497       struct srventry *srvs;
498       unsigned int srvscount;
499
500       /* Check for SRV records.  */
501       err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
502       if (err)
503         {
504           if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
505             tor_not_running_p (ctrl);
506           return err;
507         }
508
509       if (srvscount > 0)
510         {
511           int i;
512           if (! is_pool)
513             is_pool = srvscount > 1;
514
515           for (i = 0; i < srvscount; i++)
516             {
517               err = resolve_dns_name (srvs[i].target, 0,
518                                       AF_UNSPEC, SOCK_STREAM,
519                                       &ai, &cname);
520               if (err)
521                 continue;
522               dirmngr_tick (ctrl);
523               add_host (name, is_pool, ai, protocol, srvs[i].port);
524               new_hosts = 1;
525             }
526
527           xfree (srvs);
528         }
529
530       hi->did_srv_lookup |= 1 << protocol;
531     }
532
533   if (! hi->did_a_lookup
534       && ! hi->onion)
535     {
536       /* Find all A records for this entry and put them into the pool
537          list - if any.  */
538       err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
539       if (err)
540         {
541           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
542           err = 0;
543         }
544       else
545         {
546           /* First figure out whether this is a pool.  For a pool we
547              use a different strategy than for a plain server: We use
548              the canonical name of the pool as the virtual host along
549              with the IP addresses.  If it is not a pool, we use the
550              specified name. */
551           if (! is_pool)
552             is_pool = arecords_is_pool (aibuf);
553           if (is_pool && cname)
554             {
555               hi->cname = cname;
556               cname = NULL;
557             }
558
559           for (ai = aibuf; ai; ai = ai->next)
560             {
561               if (ai->family != AF_INET && ai->family != AF_INET6)
562                 continue;
563               if (opt.disable_ipv4 && ai->family == AF_INET)
564                 continue;
565               if (opt.disable_ipv6 && ai->family == AF_INET6)
566                 continue;
567               dirmngr_tick (ctrl);
568
569               add_host (name, is_pool, ai, 0, 0);
570               new_hosts = 1;
571             }
572
573           hi->did_a_lookup = 1;
574         }
575       xfree (cname);
576       free_dns_addrinfo (aibuf);
577     }
578   if (new_hosts)
579     hostinfo_sort_pool (hi);
580
581   if (hi->pool)
582     {
583       /* Deal with the pool name before selecting a host. */
584       if (r_httphost)
585         {
586           *r_httphost = xtrystrdup (hi->cname? hi->cname : hi->name);
587           if (!*r_httphost)
588             return gpg_error_from_syserror ();
589         }
590
591       /* If the currently selected host is now marked dead, force a
592          re-selection .  */
593       if (force_reselect)
594         hi->poolidx = -1;
595       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
596                && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
597         hi->poolidx = -1;
598
599       /* Select a host if needed.  */
600       if (hi->poolidx == -1)
601         {
602           hi->poolidx = select_random_host (hi);
603           if (hi->poolidx == -1)
604             {
605               log_error ("no alive host found in pool '%s'\n", name);
606               if (r_httphost)
607                 {
608                   xfree (*r_httphost);
609                   *r_httphost = NULL;
610                 }
611               return gpg_error (GPG_ERR_NO_KEYSERVER);
612             }
613         }
614
615       assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
616       hi = hosttable[hi->poolidx];
617       assert (hi);
618     }
619   else if (r_httphost && is_ip_address (hi->name))
620     {
621       /* This is a numerical IP address and not a pool.  We want to
622        * find the canonical name so that it can be used in the HTTP
623        * Host header.  Fixme: We should store that name in the
624        * hosttable. */
625       char *host;
626
627       err = resolve_dns_name (hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
628       if (!err)
629         {
630           for (ai = aibuf; ai; ai = ai->next)
631             {
632               if ((!opt.disable_ipv6 && ai->family == AF_INET6)
633                   || (!opt.disable_ipv4 && ai->family == AF_INET))
634                 {
635                   err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
636                   if (!err)
637                     {
638                       /* Okay, we return the first found name.  */
639                       *r_httphost = host;
640                       break;
641                     }
642                 }
643             }
644         }
645       free_dns_addrinfo (aibuf);
646     }
647
648   if (hi->dead)
649     {
650       log_error ("host '%s' marked as dead\n", hi->name);
651       if (r_httphost)
652         {
653           xfree (*r_httphost);
654           *r_httphost = NULL;
655         }
656       return gpg_error (GPG_ERR_NO_KEYSERVER);
657     }
658
659   if (r_httpflags)
660     {
661       /* If the hosttable does not indicate that a certain host
662          supports IPv<N>, we explicit set the corresponding http
663          flags.  The reason for this is that a host might be listed in
664          a pool as not v6 only but actually support v6 when later
665          the name is resolved by our http layer.  */
666       if (!hi->v4)
667         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
668       if (!hi->v6)
669         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
670
671       /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion
672          addresses because the http module detects this itself.  This
673          also allows us to use an onion address without Tor mode being
674          enabled.  */
675     }
676
677   *r_host = xtrystrdup (hi->name);
678   if (!*r_host)
679     {
680       err = gpg_error_from_syserror ();
681       if (r_httphost)
682         {
683           xfree (*r_httphost);
684           *r_httphost = NULL;
685         }
686       return err;
687     }
688   if (hi->port[protocol])
689     snprintf (r_portstr, 6 /* five digits and the sentinel */,
690               "%hu", hi->port[protocol]);
691   return 0;
692 }
693
694
695 /* Mark the host NAME as dead.  NAME may be given as an URL.  Returns
696    true if a host was really marked as dead or was already marked dead
697    (e.g. by a concurrent session).  */
698 static int
699 mark_host_dead (const char *name)
700 {
701   const char *host;
702   char *host_buffer = NULL;
703   parsed_uri_t parsed_uri = NULL;
704   int done = 0;
705
706   if (name && *name && !http_parse_uri (&parsed_uri, name, 1))
707     {
708       if (parsed_uri->v6lit)
709         {
710           host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
711           if (!host_buffer)
712             log_error ("out of core in mark_host_dead");
713           host = host_buffer;
714         }
715       else
716         host = parsed_uri->host;
717     }
718   else
719     host = name;
720
721   if (host && *host && strcmp (host, "localhost"))
722     {
723       hostinfo_t hi;
724       int idx;
725
726       idx = find_hostinfo (host);
727       if (idx != -1)
728         {
729           hi = hosttable[idx];
730           log_info ("marking host '%s' as dead%s\n",
731                     hi->name, hi->dead? " (again)":"");
732           hi->dead = 1;
733           hi->died_at = gnupg_get_time ();
734           if (!hi->died_at)
735             hi->died_at = 1;
736           done = 1;
737         }
738     }
739
740   http_release_parsed_uri (parsed_uri);
741   xfree (host_buffer);
742   return done;
743 }
744
745
746 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
747    alive.  */
748 gpg_error_t
749 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
750 {
751   gpg_error_t err = 0;
752   hostinfo_t hi, hi2;
753   int idx, idx2, idx3, n;
754
755   if (!name || !*name || !strcmp (name, "localhost"))
756     return 0;
757
758   idx = find_hostinfo (name);
759   if (idx == -1)
760     return gpg_error (GPG_ERR_NOT_FOUND);
761
762   hi = hosttable[idx];
763   if (alive && hi->dead)
764     {
765       hi->dead = 0;
766       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
767     }
768   else if (!alive && !hi->dead)
769     {
770       hi->dead = 1;
771       hi->died_at = 0; /* Manually set dead.  */
772       err = ks_printf_help (ctrl, "marking '%s' as dead", name);
773     }
774
775   /* If the host is a pool mark all member hosts. */
776   if (!err && hi->pool)
777     {
778       for (idx2 = 0;
779            !err && idx2 < hi->pool_len && (n = hi->pool[idx2]) != -1;
780            idx2++)
781         {
782           assert (n >= 0 && n < hosttable_size);
783
784           if (!alive)
785             {
786               /* Do not mark a host from a pool dead if it is also a
787                  member in another pool.  */
788               for (idx3=0; idx3 < hosttable_size; idx3++)
789                 {
790                   if (hosttable[idx3]
791                       && hosttable[idx3]->pool
792                       && idx3 != idx
793                       && host_in_pool_p (hosttable[idx3], n))
794                     break;
795                 }
796               if (idx3 < hosttable_size)
797                 continue;  /* Host is also a member of another pool.  */
798             }
799
800           hi2 = hosttable[n];
801           if (!hi2)
802             ;
803           else if (alive && hi2->dead)
804             {
805               hi2->dead = 0;
806               err = ks_printf_help (ctrl, "marking '%s' as alive",
807                                     hi2->name);
808             }
809           else if (!alive && !hi2->dead)
810             {
811               hi2->dead = 1;
812               hi2->died_at = 0; /* Manually set dead. */
813               err = ks_printf_help (ctrl, "marking '%s' as dead",
814                                     hi2->name);
815             }
816         }
817     }
818
819   return err;
820 }
821
822
823 /* Debug function to print the entire hosttable.  */
824 gpg_error_t
825 ks_hkp_print_hosttable (ctrl_t ctrl)
826 {
827   gpg_error_t err;
828   int idx, idx2;
829   hostinfo_t hi;
830   membuf_t mb;
831   time_t curtime;
832   char *p, *died;
833   const char *diedstr;
834
835   err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
836   if (err)
837     return err;
838
839   /* FIXME: We need a lock for the hosttable.  */
840   curtime = gnupg_get_time ();
841   for (idx=0; idx < hosttable_size; idx++)
842     if ((hi=hosttable[idx]))
843       {
844         if (hi->dead && hi->died_at)
845           {
846             died = elapsed_time_string (hi->died_at, curtime);
847             diedstr = died? died : "error";
848           }
849         else
850           diedstr = died = NULL;
851
852         if (!hi->iporname_valid)
853           {
854             char *canon = NULL;
855
856             xfree (hi->iporname);
857             hi->iporname = NULL;
858
859             /* Do a lookup just for the display purpose.  */
860             if (hi->onion || hi->pool)
861               ;
862             else if (is_ip_address (hi->name))
863               {
864                 dns_addrinfo_t aibuf, ai;
865
866                 /* Turn the numerical IP address string into an AI and
867                  * then do a DNS PTR lookup.  */
868                 if (!resolve_dns_name (hi->name, 0, 0,
869                                        SOCK_STREAM,
870                                        &aibuf, &canon))
871                   {
872                     if (canon && is_ip_address (canon))
873                       {
874                         xfree (canon);
875                         canon = NULL;
876                       }
877                     for (ai = aibuf; !canon && ai; ai = ai->next)
878                       {
879                         resolve_dns_addr (ai->addr, ai->addrlen,
880                                           DNS_WITHBRACKET, &canon);
881                         if (canon && is_ip_address (canon))
882                           {
883                             /* We already have the numeric IP - no need to
884                              * display it a second time.  */
885                             xfree (canon);
886                             canon = NULL;
887                           }
888                       }
889                   }
890                 free_dns_addrinfo (aibuf);
891               }
892             else
893               {
894                 dns_addrinfo_t aibuf, ai;
895
896                 /* Get the IP address as a string from a name.  Note
897                  * that resolve_dns_addr allocates CANON on success
898                  * and thus terminates the loop. */
899                 if (!resolve_dns_name (hi->name, 0,
900                                        hi->v6? AF_INET6 : AF_INET,
901                                        SOCK_STREAM,
902                                        &aibuf, NULL))
903                   {
904                     for (ai = aibuf; !canon && ai; ai = ai->next)
905                       {
906                         resolve_dns_addr (ai->addr, ai->addrlen,
907                                           DNS_NUMERICHOST|DNS_WITHBRACKET,
908                                           &canon);
909                       }
910                   }
911                 free_dns_addrinfo (aibuf);
912               }
913
914             hi->iporname = canon;
915             hi->iporname_valid = 1;
916           }
917
918         err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s\n",
919                               idx,
920                               hi->onion? "O" : hi->v6? "6":" ",
921                               hi->v4? "4":" ",
922                               hi->dead? "d":" ",
923                               hi->name,
924                               hi->iporname? " (":"",
925                               hi->iporname? hi->iporname : "",
926                               hi->iporname? ")":"",
927                               diedstr? "  (":"",
928                               diedstr? diedstr:"",
929                               diedstr? ")":""   );
930         xfree (died);
931         if (err)
932           return err;
933
934         if (hi->cname)
935           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
936         if (err)
937           return err;
938
939         if (hi->pool)
940           {
941             init_membuf (&mb, 256);
942             put_membuf_printf (&mb, "  .   -->");
943             for (idx2 = 0; idx2 < hi->pool_len && hi->pool[idx2] != -1; idx2++)
944               {
945                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
946                 if (hi->poolidx == hi->pool[idx2])
947                   put_membuf_printf (&mb, "*");
948               }
949             put_membuf( &mb, "", 1);
950             p = get_membuf (&mb, NULL);
951             if (!p)
952               return gpg_error_from_syserror ();
953             err = ks_print_help (ctrl, p);
954             xfree (p);
955             if (err)
956               return err;
957           }
958       }
959   return 0;
960 }
961
962
963
964 /* Print a help output for the schemata supported by this module. */
965 gpg_error_t
966 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
967 {
968   const char data[] =
969     "Handler for HKP URLs:\n"
970     "  hkp://\n"
971 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
972     "  hkps://\n"
973 #endif
974     "Supported methods: search, get, put\n";
975   gpg_error_t err;
976
977 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
978   const char data2[] = "  hkp\n  hkps";
979 #else
980   const char data2[] = "  hkp";
981 #endif
982
983   if (!uri)
984     err = ks_print_help (ctrl, data2);
985   else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
986                             || !strcmp (uri->scheme, "hkps")))
987     err = ks_print_help (ctrl, data);
988   else
989     err = 0;
990
991   return err;
992 }
993
994
995 /* Build the remote part of the URL from SCHEME, HOST and an optional
996  * PORT.  If NO_SRV is set no SRV record lookup will be done.  Returns
997  * an allocated string at R_HOSTPORT or NULL on failure.  If
998  * R_HTTPHOST is not NULL it receives a malloced string with the
999  * hostname; this may be different from HOST if HOST is selected from
1000  * a pool.  */
1001 static gpg_error_t
1002 make_host_part (ctrl_t ctrl,
1003                 const char *scheme, const char *host, unsigned short port,
1004                 int force_reselect, int no_srv,
1005                 char **r_hostport, unsigned int *r_httpflags, char **r_httphost)
1006 {
1007   gpg_error_t err;
1008   const char *srvtag;
1009   char portstr[10];
1010   char *hostname;
1011   enum ks_protocol protocol;
1012
1013   *r_hostport = NULL;
1014
1015   if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
1016     {
1017       scheme = "https";
1018       srvtag = no_srv? NULL : "pgpkey-https";
1019       protocol = KS_PROTOCOL_HKPS;
1020     }
1021   else /* HKP or HTTP.  */
1022     {
1023       scheme = "http";
1024       srvtag = no_srv? NULL : "pgpkey-http";
1025       protocol = KS_PROTOCOL_HKP;
1026     }
1027
1028   portstr[0] = 0;
1029   err = map_host (ctrl, host, srvtag, force_reselect, protocol,
1030                   &hostname, portstr, r_httpflags, r_httphost);
1031   if (err)
1032     return err;
1033
1034   /* If map_host did not return a port (from a SRV record) but a port
1035    * has been specified (implicitly or explicitly) then use that port.
1036    * In the case that a port was not specified (which is probably a
1037    * bug in https.c) we will set up defaults.  */
1038   if (*portstr)
1039     ;
1040   else if (!*portstr && port)
1041     snprintf (portstr, sizeof portstr, "%hu", port);
1042   else if (!strcmp (scheme,"https"))
1043     strcpy (portstr, "443");
1044   else
1045     strcpy (portstr, "11371");
1046
1047   if (*hostname != '[' && is_ip_address (hostname) == 6)
1048     *r_hostport = strconcat (scheme, "://[", hostname, "]:", portstr, NULL);
1049   else
1050     *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
1051   xfree (hostname);
1052   if (!*r_hostport)
1053     {
1054       if (r_httphost)
1055         {
1056           xfree (*r_httphost);
1057           *r_httphost = NULL;
1058         }
1059       return gpg_error_from_syserror ();
1060     }
1061   return 0;
1062 }
1063
1064
1065 /* Resolve all known keyserver names and update the hosttable.  This
1066    is mainly useful for debugging because the resolving is anyway done
1067    on demand.  */
1068 gpg_error_t
1069 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
1070 {
1071   gpg_error_t err;
1072   char *hostport = NULL;
1073
1074   /* NB: With an explicitly given port we do not want to consult a
1075    * service record because that might be in conflict with the port
1076    * from such a service record.  */
1077   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1078                         1, uri->explicit_port,
1079                         &hostport, NULL, NULL);
1080   if (err)
1081     {
1082       err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
1083                             uri->scheme, uri->host, uri->port,
1084                             gpg_strerror (err));
1085     }
1086   else
1087     {
1088       err = ks_printf_help (ctrl, "%s", hostport);
1089       xfree (hostport);
1090     }
1091   return err;
1092 }
1093
1094
1095 /* Housekeeping function called from the housekeeping thread.  It is
1096    used to mark dead hosts alive so that they may be tried again after
1097    some time.  */
1098 void
1099 ks_hkp_housekeeping (time_t curtime)
1100 {
1101   int idx;
1102   hostinfo_t hi;
1103
1104   for (idx=0; idx < hosttable_size; idx++)
1105     {
1106       hi = hosttable[idx];
1107       if (!hi)
1108         continue;
1109       if (!hi->dead)
1110         continue;
1111       if (!hi->died_at)
1112         continue; /* Do not resurrect manually shot hosts.  */
1113       if (hi->died_at + RESURRECT_INTERVAL <= curtime
1114           || hi->died_at > curtime)
1115         {
1116           hi->dead = 0;
1117           log_info ("resurrected host '%s'", hi->name);
1118         }
1119     }
1120 }
1121
1122
1123 /* Reload (SIGHUP) action for this module.  We mark all host alive
1124  * even those which have been manually shot.  */
1125 void
1126 ks_hkp_reload (void)
1127 {
1128   int idx, count;
1129   hostinfo_t hi;
1130
1131   for (idx=count=0; idx < hosttable_size; idx++)
1132     {
1133       hi = hosttable[idx];
1134       if (!hi)
1135         continue;
1136       hi->iporname_valid = 0;
1137       if (!hi->dead)
1138         continue;
1139       hi->dead = 0;
1140       count++;
1141     }
1142   if (count)
1143     log_info ("number of resurrected hosts: %d", count);
1144 }
1145
1146
1147 /* Send an HTTP request.  On success returns an estream object at
1148    R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
1149    not NULL it will be used as HTTP "Host" header.  If POST_CB is not
1150    NULL a post request is used and that callback is called to allow
1151    writing the post data.  If R_HTTP_STATUS is not NULL, the http
1152    status code will be stored there.  */
1153 static gpg_error_t
1154 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
1155               const char *httphost, unsigned int httpflags,
1156               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
1157               estream_t *r_fp, unsigned int *r_http_status)
1158 {
1159   gpg_error_t err;
1160   http_session_t session = NULL;
1161   http_t http = NULL;
1162   int redirects_left = MAX_REDIRECTS;
1163   estream_t fp = NULL;
1164   char *request_buffer = NULL;
1165
1166   *r_fp = NULL;
1167
1168   err = http_session_new (&session, httphost,
1169                           ((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0)
1170                            | HTTP_FLAG_TRUST_DEF),
1171                           gnupg_http_tls_verify_cb, ctrl);
1172   if (err)
1173     goto leave;
1174   http_session_set_log_cb (session, cert_log_cb);
1175   http_session_set_timeout (session, ctrl->timeout);
1176
1177  once_more:
1178   err = http_open (&http,
1179                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
1180                    request,
1181                    httphost,
1182                    /* fixme: AUTH */ NULL,
1183                    (httpflags
1184                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
1185                     |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
1186                     |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
1187                     |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
1188                    ctrl->http_proxy,
1189                    session,
1190                    NULL,
1191                    /*FIXME curl->srvtag*/NULL);
1192   if (!err)
1193     {
1194       fp = http_get_write_ptr (http);
1195       /* Avoid caches to get the most recent copy of the key.  We set
1196          both the Pragma and Cache-Control versions of the header, so
1197          we're good with both HTTP 1.0 and 1.1.  */
1198       es_fputs ("Pragma: no-cache\r\n"
1199                 "Cache-Control: no-cache\r\n", fp);
1200       if (post_cb)
1201         err = post_cb (post_cb_value, http);
1202       if (!err)
1203         {
1204           http_start_data (http);
1205           if (es_ferror (fp))
1206             err = gpg_error_from_syserror ();
1207         }
1208     }
1209   if (err)
1210     {
1211       /* Fixme: After a redirection we show the old host name.  */
1212       log_error (_("error connecting to '%s': %s\n"),
1213                  hostportstr, gpg_strerror (err));
1214       goto leave;
1215     }
1216
1217   /* Wait for the response.  */
1218   dirmngr_tick (ctrl);
1219   err = http_wait_response (http);
1220   if (err)
1221     {
1222       log_error (_("error reading HTTP response for '%s': %s\n"),
1223                  hostportstr, gpg_strerror (err));
1224       goto leave;
1225     }
1226
1227   if (http_get_tls_info (http, NULL))
1228     {
1229       /* Update the httpflags so that a redirect won't fallback to an
1230          unencrypted connection.  */
1231       httpflags |= HTTP_FLAG_FORCE_TLS;
1232     }
1233
1234   if (r_http_status)
1235     *r_http_status = http_get_status_code (http);
1236
1237   switch (http_get_status_code (http))
1238     {
1239     case 200:
1240       err = 0;
1241       break; /* Success.  */
1242
1243     case 301:
1244     case 302:
1245     case 307:
1246       {
1247         const char *s = http_get_header (http, "Location");
1248
1249         log_info (_("URL '%s' redirected to '%s' (%u)\n"),
1250                   request, s?s:"[none]", http_get_status_code (http));
1251         if (s && *s && redirects_left-- )
1252           {
1253             xfree (request_buffer);
1254             request_buffer = xtrystrdup (s);
1255             if (request_buffer)
1256               {
1257                 request = request_buffer;
1258                 http_close (http, 0);
1259                 http = NULL;
1260                 goto once_more;
1261               }
1262             err = gpg_error_from_syserror ();
1263           }
1264         else
1265           err = gpg_error (GPG_ERR_NO_DATA);
1266         log_error (_("too many redirections\n"));
1267       }
1268       goto leave;
1269
1270     case 501:
1271       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1272       goto leave;
1273
1274     default:
1275       log_error (_("error accessing '%s': http status %u\n"),
1276                  request, http_get_status_code (http));
1277       err = gpg_error (GPG_ERR_NO_DATA);
1278       goto leave;
1279     }
1280
1281   /* FIXME: We should register a permanent redirection and whether a
1282      host has ever used TLS so that future calls will always use
1283      TLS. */
1284
1285   fp = http_get_read_ptr (http);
1286   if (!fp)
1287     {
1288       err = gpg_error (GPG_ERR_BUG);
1289       goto leave;
1290     }
1291
1292   /* Return the read stream and close the HTTP context.  */
1293   *r_fp = fp;
1294   http_close (http, 1);
1295   http = NULL;
1296
1297  leave:
1298   http_close (http, 0);
1299   http_session_release (session);
1300   xfree (request_buffer);
1301   return err;
1302 }
1303
1304
1305 /* Helper to evaluate the error code ERR from a send_request() call
1306    with REQUEST.  The function returns true if the caller shall try
1307    again.  TRIES_LEFT points to a variable to track the number of
1308    retries; this function decrements it and won't return true if it is
1309    down to zero. */
1310 static int
1311 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
1312                            unsigned int *tries_left)
1313 {
1314   int retry = 0;
1315
1316   /* Fixme: Should we disable all hosts of a protocol family if a
1317    * request for an address of that familiy returned ENETDOWN?  */
1318
1319   switch (gpg_err_code (err))
1320     {
1321     case GPG_ERR_ECONNREFUSED:
1322       if (tor_not_running_p (ctrl))
1323         break; /* A retry does not make sense.  */
1324       /* Okay: Tor is up or --use-tor is not used.  */
1325       /*FALLTHRU*/
1326     case GPG_ERR_ENETUNREACH:
1327     case GPG_ERR_ENETDOWN:
1328     case GPG_ERR_UNKNOWN_HOST:
1329     case GPG_ERR_NETWORK:
1330     case GPG_ERR_EIO:  /* Sometimes used by estream cookie functions.  */
1331       if (mark_host_dead (request) && *tries_left)
1332         retry = 1;
1333       break;
1334
1335     case GPG_ERR_ETIMEDOUT:
1336       if (*tries_left)
1337         {
1338           log_info ("selecting a different host due to a timeout\n");
1339           retry = 1;
1340         }
1341       break;
1342
1343     case GPG_ERR_EACCES:
1344       if (dirmngr_use_tor ())
1345         {
1346           log_info ("(Tor configuration problem)\n");
1347           dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
1348                           "Please check that the \"SocksPort\" flag "
1349                           "\"IPv6Traffic\" is set in torrc", NULL);
1350         }
1351       break;
1352
1353     default:
1354       break;
1355     }
1356
1357   if (*tries_left)
1358     --*tries_left;
1359
1360   return retry;
1361 }
1362
1363 \f
1364 /* Search the keyserver identified by URI for keys matching PATTERN.
1365    On success R_FP has an open stream to read the data.  If
1366    R_HTTP_STATUS is not NULL, the http status code will be stored
1367    there.  */
1368 gpg_error_t
1369 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1370                estream_t *r_fp, unsigned int *r_http_status)
1371 {
1372   gpg_error_t err;
1373   KEYDB_SEARCH_DESC desc;
1374   char fprbuf[2+40+1];
1375   char *hostport = NULL;
1376   char *request = NULL;
1377   estream_t fp = NULL;
1378   int reselect;
1379   unsigned int httpflags;
1380   char *httphost = NULL;
1381   unsigned int tries = SEND_REQUEST_RETRIES;
1382
1383   *r_fp = NULL;
1384
1385   /* Remove search type indicator and adjust PATTERN accordingly.
1386      Note that HKP keyservers like the 0x to be present when searching
1387      by keyid.  We need to re-format the fingerprint and keyids so to
1388      remove the gpg specific force-use-of-this-key flag ("!").  */
1389   err = classify_user_id (pattern, &desc, 1);
1390   if (err)
1391     return err;
1392   switch (desc.mode)
1393     {
1394     case KEYDB_SEARCH_MODE_EXACT:
1395     case KEYDB_SEARCH_MODE_SUBSTR:
1396     case KEYDB_SEARCH_MODE_MAIL:
1397     case KEYDB_SEARCH_MODE_MAILSUB:
1398       pattern = desc.u.name;
1399       break;
1400     case KEYDB_SEARCH_MODE_SHORT_KID:
1401       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1402       pattern = fprbuf;
1403       break;
1404     case KEYDB_SEARCH_MODE_LONG_KID:
1405       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1406                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1407       pattern = fprbuf;
1408       break;
1409     case KEYDB_SEARCH_MODE_FPR16:
1410       fprbuf[0] = '0';
1411       fprbuf[1] = 'x';
1412       bin2hex (desc.u.fpr, 16, fprbuf+2);
1413       pattern = fprbuf;
1414       break;
1415     case KEYDB_SEARCH_MODE_FPR20:
1416     case KEYDB_SEARCH_MODE_FPR:
1417       fprbuf[0] = '0';
1418       fprbuf[1] = 'x';
1419       bin2hex (desc.u.fpr, 20, fprbuf+2);
1420       pattern = fprbuf;
1421       break;
1422     default:
1423       return gpg_error (GPG_ERR_INV_USER_ID);
1424     }
1425
1426   /* Build the request string.  */
1427   reselect = 0;
1428  again:
1429   {
1430     char *searchkey;
1431
1432     xfree (hostport); hostport = NULL;
1433     xfree (httphost); httphost = NULL;
1434     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1435                           reselect, uri->explicit_port,
1436                           &hostport, &httpflags, &httphost);
1437     if (err)
1438       goto leave;
1439
1440     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1441     if (!searchkey)
1442       {
1443         err = gpg_error_from_syserror ();
1444         goto leave;
1445       }
1446
1447     xfree (request);
1448     request = strconcat (hostport,
1449                          "/pks/lookup?op=index&options=mr&search=",
1450                          searchkey,
1451                          NULL);
1452     xfree (searchkey);
1453     if (!request)
1454       {
1455         err = gpg_error_from_syserror ();
1456         goto leave;
1457       }
1458   }
1459
1460   /* Send the request.  */
1461   err = send_request (ctrl, request, hostport, httphost, httpflags,
1462                       NULL, NULL, &fp, r_http_status);
1463   if (handle_send_request_error (ctrl, err, request, &tries))
1464     {
1465       reselect = 1;
1466       goto again;
1467     }
1468   if (err)
1469     goto leave;
1470
1471   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1472   if (err)
1473     goto leave;
1474
1475   /* Peek at the response.  */
1476   {
1477     int c = es_getc (fp);
1478     if (c == -1)
1479       {
1480         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1481         log_error ("error reading response: %s\n", gpg_strerror (err));
1482         goto leave;
1483       }
1484     if (c == '<')
1485       {
1486         /* The document begins with a '<': Assume a HTML response,
1487            which we don't support.  */
1488         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1489         goto leave;
1490       }
1491     es_ungetc (c, fp);
1492   }
1493
1494   /* Return the read stream.  */
1495   *r_fp = fp;
1496   fp = NULL;
1497
1498  leave:
1499   es_fclose (fp);
1500   xfree (request);
1501   xfree (hostport);
1502   xfree (httphost);
1503   return err;
1504 }
1505
1506
1507 /* Get the key described key the KEYSPEC string from the keyserver
1508    identified by URI.  On success R_FP has an open stream to read the
1509    data.  The data will be provided in a format GnuPG can import
1510    (either a binary OpenPGP message or an armored one).  */
1511 gpg_error_t
1512 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1513 {
1514   gpg_error_t err;
1515   KEYDB_SEARCH_DESC desc;
1516   char kidbuf[2+40+1];
1517   const char *exactname = NULL;
1518   char *searchkey = NULL;
1519   char *hostport = NULL;
1520   char *request = NULL;
1521   estream_t fp = NULL;
1522   int reselect;
1523   char *httphost = NULL;
1524   unsigned int httpflags;
1525   unsigned int tries = SEND_REQUEST_RETRIES;
1526
1527   *r_fp = NULL;
1528
1529   /* Remove search type indicator and adjust PATTERN accordingly.
1530      Note that HKP keyservers like the 0x to be present when searching
1531      by keyid.  We need to re-format the fingerprint and keyids so to
1532      remove the gpg specific force-use-of-this-key flag ("!").  */
1533   err = classify_user_id (keyspec, &desc, 1);
1534   if (err)
1535     return err;
1536   switch (desc.mode)
1537     {
1538     case KEYDB_SEARCH_MODE_SHORT_KID:
1539       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1540       break;
1541     case KEYDB_SEARCH_MODE_LONG_KID:
1542       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1543                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1544       break;
1545     case KEYDB_SEARCH_MODE_FPR20:
1546     case KEYDB_SEARCH_MODE_FPR:
1547       /* This is a v4 fingerprint. */
1548       kidbuf[0] = '0';
1549       kidbuf[1] = 'x';
1550       bin2hex (desc.u.fpr, 20, kidbuf+2);
1551       break;
1552
1553     case KEYDB_SEARCH_MODE_EXACT:
1554       exactname = desc.u.name;
1555       break;
1556
1557     case KEYDB_SEARCH_MODE_FPR16:
1558       log_error ("HKP keyservers do not support v3 fingerprints\n");
1559       /* fall through */
1560     default:
1561       return gpg_error (GPG_ERR_INV_USER_ID);
1562     }
1563
1564   searchkey = http_escape_string (exactname? exactname : kidbuf,
1565                                   EXTRA_ESCAPE_CHARS);
1566   if (!searchkey)
1567     {
1568       err = gpg_error_from_syserror ();
1569       goto leave;
1570     }
1571
1572   reselect = 0;
1573  again:
1574   /* Build the request string.  */
1575   xfree (hostport); hostport = NULL;
1576   xfree (httphost); httphost = NULL;
1577   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1578                         reselect, uri->explicit_port,
1579                         &hostport, &httpflags, &httphost);
1580   if (err)
1581     goto leave;
1582
1583   xfree (request);
1584   request = strconcat (hostport,
1585                        "/pks/lookup?op=get&options=mr&search=",
1586                        searchkey,
1587                        exactname? "&exact=on":"",
1588                        NULL);
1589   if (!request)
1590     {
1591       err = gpg_error_from_syserror ();
1592       goto leave;
1593     }
1594
1595   /* Send the request.  */
1596   err = send_request (ctrl, request, hostport, httphost, httpflags,
1597                       NULL, NULL, &fp, NULL);
1598   if (handle_send_request_error (ctrl, err, request, &tries))
1599     {
1600       reselect = 1;
1601       goto again;
1602     }
1603   if (err)
1604     goto leave;
1605
1606   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1607   if (err)
1608     goto leave;
1609
1610   /* Return the read stream and close the HTTP context.  */
1611   *r_fp = fp;
1612   fp = NULL;
1613
1614  leave:
1615   es_fclose (fp);
1616   xfree (request);
1617   xfree (hostport);
1618   xfree (httphost);
1619   xfree (searchkey);
1620   return err;
1621 }
1622
1623
1624
1625 \f
1626 /* Callback parameters for put_post_cb.  */
1627 struct put_post_parm_s
1628 {
1629   char *datastring;
1630 };
1631
1632
1633 /* Helper for ks_hkp_put.  */
1634 static gpg_error_t
1635 put_post_cb (void *opaque, http_t http)
1636 {
1637   struct put_post_parm_s *parm = opaque;
1638   gpg_error_t err = 0;
1639   estream_t fp;
1640   size_t len;
1641
1642   fp = http_get_write_ptr (http);
1643   len = strlen (parm->datastring);
1644
1645   es_fprintf (fp,
1646               "Content-Type: application/x-www-form-urlencoded\r\n"
1647               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1648   http_start_data (http);
1649   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1650     err = gpg_error_from_syserror ();
1651   return err;
1652 }
1653
1654
1655 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1656 gpg_error_t
1657 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1658 {
1659   gpg_error_t err;
1660   char *hostport = NULL;
1661   char *request = NULL;
1662   estream_t fp = NULL;
1663   struct put_post_parm_s parm;
1664   char *armored = NULL;
1665   int reselect;
1666   char *httphost = NULL;
1667   unsigned int httpflags;
1668   unsigned int tries = SEND_REQUEST_RETRIES;
1669
1670   parm.datastring = NULL;
1671
1672   err = armor_data (&armored, data, datalen);
1673   if (err)
1674     goto leave;
1675
1676   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1677   if (!parm.datastring)
1678     {
1679       err = gpg_error_from_syserror ();
1680       goto leave;
1681     }
1682   xfree (armored);
1683   armored = NULL;
1684
1685   /* Build the request string.  */
1686   reselect = 0;
1687  again:
1688   xfree (hostport); hostport = NULL;
1689   xfree (httphost); httphost = NULL;
1690   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port,
1691                         reselect, uri->explicit_port,
1692                         &hostport, &httpflags, &httphost);
1693   if (err)
1694     goto leave;
1695
1696   xfree (request);
1697   request = strconcat (hostport, "/pks/add", NULL);
1698   if (!request)
1699     {
1700       err = gpg_error_from_syserror ();
1701       goto leave;
1702     }
1703
1704   /* Send the request.  */
1705   err = send_request (ctrl, request, hostport, httphost, 0,
1706                       put_post_cb, &parm, &fp, NULL);
1707   if (handle_send_request_error (ctrl, err, request, &tries))
1708     {
1709       reselect = 1;
1710       goto again;
1711     }
1712   if (err)
1713     goto leave;
1714
1715  leave:
1716   es_fclose (fp);
1717   xfree (parm.datastring);
1718   xfree (armored);
1719   xfree (request);
1720   xfree (hostport);
1721   xfree (httphost);
1722   return err;
1723 }