dirmngr: Add workaround for broken getaddrinfo.
[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 <http://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 dead:1; /* Host is currently unresponsive.  */
84   time_t died_at;    /* The time the host was marked dead.  If this is
85                         0 the host has been manually marked dead.  */
86   char *cname;       /* Canonical name of the host.  Only set if this
87                         is a pool.  */
88   char *v4addr;      /* A string with the v4 IP address of the host.
89                         NULL if NAME has a numeric IP address or no v4
90                         address is available.  */
91   char *v6addr;      /* A string with the v6 IP address of the host.
92                         NULL if NAME has a numeric IP address or no v4
93                         address is available.  */
94   char name[1];      /* The hostname.  */
95 };
96
97
98 /* An array of hostinfo_t for all hosts requested by the caller or
99    resolved from a pool name and its allocated size.*/
100 static hostinfo_t *hosttable;
101 static int hosttable_size;
102
103 /* The number of host slots we initally allocate for HOSTTABLE.  */
104 #define INITIAL_HOSTTABLE_SIZE 10
105
106
107 /* Create a new hostinfo object, fill in NAME and put it into
108    HOSTTABLE.  Return the index into hosttable on success or -1 on
109    error. */
110 static int
111 create_new_hostinfo (const char *name)
112 {
113   hostinfo_t hi, *newtable;
114   int newsize;
115   int idx, rc;
116
117   hi = xtrymalloc (sizeof *hi + strlen (name));
118   if (!hi)
119     return -1;
120   strcpy (hi->name, name);
121   hi->pool = NULL;
122   hi->poolidx = -1;
123   hi->lastused = (time_t)(-1);
124   hi->lastfail = (time_t)(-1);
125   hi->v4 = 0;
126   hi->v6 = 0;
127   hi->dead = 0;
128   hi->died_at = 0;
129   hi->cname = NULL;
130   hi->v4addr = NULL;
131   hi->v6addr = NULL;
132
133   /* Add it to the hosttable. */
134   for (idx=0; idx < hosttable_size; idx++)
135     if (!hosttable[idx])
136       {
137         hosttable[idx] = hi;
138         return idx;
139       }
140   /* Need to extend the hosttable.  */
141   newsize = hosttable_size + INITIAL_HOSTTABLE_SIZE;
142   newtable = xtryrealloc (hosttable, newsize * sizeof *hosttable);
143   if (!newtable)
144     {
145       xfree (hi);
146       return -1;
147     }
148   hosttable = newtable;
149   idx = hosttable_size;
150   hosttable_size = newsize;
151   rc = idx;
152   hosttable[idx++] = hi;
153   while (idx < hosttable_size)
154     hosttable[idx++] = NULL;
155
156   return rc;
157 }
158
159
160 /* Find the host NAME in our table.  Return the index into the
161    hosttable or -1 if not found.  */
162 static int
163 find_hostinfo (const char *name)
164 {
165   int idx;
166
167   for (idx=0; idx < hosttable_size; idx++)
168     if (hosttable[idx] && !ascii_strcasecmp (hosttable[idx]->name, name))
169       return idx;
170   return -1;
171 }
172
173
174 static int
175 sort_hostpool (const void *xa, const void *xb)
176 {
177   int a = *(int *)xa;
178   int b = *(int *)xb;
179
180   assert (a >= 0 && a < hosttable_size);
181   assert (b >= 0 && b < hosttable_size);
182   assert (hosttable[a]);
183   assert (hosttable[b]);
184
185   return ascii_strcasecmp (hosttable[a]->name, hosttable[b]->name);
186 }
187
188
189 /* Return true if the host with the hosttable index TBLIDX is in POOL.  */
190 static int
191 host_in_pool_p (int *pool, int tblidx)
192 {
193   int i, pidx;
194
195   for (i=0; (pidx = pool[i]) != -1; i++)
196     if (pidx == tblidx && hosttable[pidx])
197       return 1;
198   return 0;
199 }
200
201
202 /* Select a random host.  Consult TABLE which indices into the global
203    hosttable.  Returns index into TABLE or -1 if no host could be
204    selected.  */
205 static int
206 select_random_host (int *table)
207 {
208   int *tbl;
209   size_t tblsize;
210   int pidx, idx;
211
212   /* We create a new table so that we randomly select only from
213      currently alive hosts.  */
214   for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
215     if (hosttable[pidx] && !hosttable[pidx]->dead)
216       tblsize++;
217   if (!tblsize)
218     return -1; /* No hosts.  */
219
220   tbl = xtrymalloc (tblsize * sizeof *tbl);
221   if (!tbl)
222     return -1;
223   for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
224     if (hosttable[pidx] && !hosttable[pidx]->dead)
225       tbl[tblsize++] = pidx;
226
227   if (tblsize == 1)  /* Save a get_uint_nonce.  */
228     pidx = tbl[0];
229   else
230     pidx = tbl[get_uint_nonce () % tblsize];
231
232   xfree (tbl);
233   return pidx;
234 }
235
236
237 /* Map the host name NAME to the actual to be used host name.  This
238    allows us to manage round robin DNS names.  We use our own strategy
239    to choose one of the hosts.  For example we skip those hosts which
240    failed for some time and we stick to one host for a time
241    independent of DNS retry times.  If FORCE_RESELECT is true a new
242    host is always selected.  The selected host is stored as a malloced
243    string at R_HOST; on error NULL is stored.  If R_HTTPFLAGS is not
244    NULL it will receive flags which are to be passed to http_open.  If
245    R_POOLNAME is not NULL a malloced name of the pool is stored or
246    NULL if it is not a pool. */
247 static gpg_error_t
248 map_host (ctrl_t ctrl, const char *name, int force_reselect,
249           char **r_host, unsigned int *r_httpflags, char **r_poolname)
250 {
251   gpg_error_t err = 0;
252   hostinfo_t hi;
253   int idx;
254
255   *r_host = NULL;
256   if (r_httpflags)
257     *r_httpflags = 0;
258   if (r_poolname)
259     *r_poolname = NULL;
260
261   /* No hostname means localhost.  */
262   if (!name || !*name)
263     {
264       *r_host = xtrystrdup ("localhost");
265       return *r_host? 0 : gpg_error_from_syserror ();
266     }
267
268   /* See whether the host is in our table.  */
269   idx = find_hostinfo (name);
270   if (idx == -1)
271     {
272       /* We never saw this host.  Allocate a new entry.  */
273       dns_addrinfo_t aibuf, ai;
274       int *reftbl;
275       size_t reftblsize;
276       int refidx;
277       int is_pool = 0;
278       char *cname;
279
280       reftblsize = 100;
281       reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
282       if (!reftbl)
283         return gpg_error_from_syserror ();
284       refidx = 0;
285
286       idx = create_new_hostinfo (name);
287       if (idx == -1)
288         {
289           err = gpg_error_from_syserror ();
290           xfree (reftbl);
291           return err;
292         }
293       hi = hosttable[idx];
294
295       /* Find all A records for this entry and put them into the pool
296          list - if any.  */
297       err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
298       if (err)
299         {
300           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
301           err = 0;
302         }
303       else
304         {
305           int n_v6, n_v4;
306
307           /* First figure out whether this is a pool.  For a pool we
308              use a different strategy than for a plain server: We use
309              the canonical name of the pool as the virtual host along
310              with the IP addresses.  If it is not a pool, we use the
311              specified name. */
312           n_v6 = n_v4 = 0;
313           for (ai = aibuf; ai; ai = ai->next)
314             {
315               if (ai->family != AF_INET6)
316                 n_v6++;
317               else if (ai->family != AF_INET)
318                 n_v4++;
319             }
320           if (n_v6 > 1 || n_v4 > 1)
321             is_pool = 1;
322           if (is_pool && cname)
323             {
324               hi->cname = cname;
325               cname = NULL;
326             }
327
328           for (ai = aibuf; ai; ai = ai->next)
329             {
330               gpg_error_t tmperr;
331               char *tmphost;
332               int tmpidx;
333               int is_numeric = 0;
334               int i;
335
336               if (ai->family != AF_INET && ai->family != AF_INET6)
337                 continue;
338
339               dirmngr_tick (ctrl);
340
341               if (!is_pool && !is_ip_address (name))
342                 {
343                   /* This is a hostname but not a pool.  Use the name
344                      as given without going through resolve_dns_addr.  */
345                   tmphost = xtrystrdup (name);
346                   if (!tmphost)
347                     tmperr = gpg_error_from_syserror ();
348                   else
349                     tmperr = 0;
350                 }
351               else
352                 {
353                   tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
354                                              DNS_WITHBRACKET, &tmphost);
355                   if (tmphost && is_ip_address (tmphost))
356                     is_numeric = 1;
357                 }
358
359               if (tmperr)
360                 {
361                   log_info ("resolve_dns_addr failed while checking '%s': %s\n",
362                             name, gpg_strerror (tmperr));
363                 }
364               else if (refidx+1 >= reftblsize)
365                 {
366                   log_error ("resolve_dns_addr for '%s': '%s'"
367                              " [index table full - ignored]\n", name, tmphost);
368                 }
369               else
370                 {
371                   tmpidx = find_hostinfo (tmphost);
372                   log_info ("resolve_dns_addr for '%s': '%s'%s\n",
373                             name, tmphost,
374                             tmpidx == -1? "" : " [already known]");
375
376                   if (tmpidx == -1) /* Create a new entry.  */
377                     tmpidx = create_new_hostinfo (tmphost);
378
379                   if (tmpidx == -1)
380                     {
381                       log_error ("map_host for '%s' problem: %s - '%s'"
382                                  " [ignored]\n",
383                                  name, strerror (errno), tmphost);
384                     }
385                   else  /* Set or update the entry. */
386                     {
387                       char *ipaddr = NULL;
388
389                       if (!is_numeric)
390                         {
391                           xfree (tmphost);
392                           tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
393                                                      (DNS_NUMERICHOST
394                                                       | DNS_WITHBRACKET),
395                                                      &tmphost);
396                           if (tmperr)
397                             log_info ("resolve_dns_addr failed: %s\n",
398                                       gpg_strerror (tmperr));
399                           else
400                             {
401                               ipaddr = tmphost;
402                               tmphost = NULL;
403                             }
404                         }
405
406                       if (ai->family == AF_INET6)
407                         {
408                           hosttable[tmpidx]->v6 = 1;
409                           xfree (hosttable[tmpidx]->v6addr);
410                           hosttable[tmpidx]->v6addr = ipaddr;
411                         }
412                       else if (ai->family == AF_INET)
413                         {
414                           hosttable[tmpidx]->v4 = 1;
415                           xfree (hosttable[tmpidx]->v4addr);
416                           hosttable[tmpidx]->v4addr = ipaddr;
417                         }
418                       else
419                         BUG ();
420
421                       for (i=0; i < refidx; i++)
422                         if (reftbl[i] == tmpidx)
423                           break;
424                       if (!(i < refidx) && tmpidx != idx)
425                         reftbl[refidx++] = tmpidx;
426                     }
427                 }
428               xfree (tmphost);
429             }
430         }
431       reftbl[refidx] = -1;
432       xfree (cname);
433       free_dns_addrinfo (aibuf);
434
435       if (refidx && is_pool)
436         {
437           assert (!hi->pool);
438           hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
439           if (!hi->pool)
440             {
441               err = gpg_error_from_syserror ();
442               log_error ("shrinking index table in map_host failed: %s\n",
443                          gpg_strerror (err));
444               xfree (reftbl);
445               return err;
446             }
447           qsort (hi->pool, refidx, sizeof *reftbl, sort_hostpool);
448         }
449       else
450         xfree (reftbl);
451     }
452
453   hi = hosttable[idx];
454   if (hi->pool)
455     {
456       /* Deal with the pool name before selecting a host. */
457       if (r_poolname && hi->cname)
458         {
459           *r_poolname = xtrystrdup (hi->cname);
460           if (!*r_poolname)
461             return gpg_error_from_syserror ();
462         }
463
464       /* If the currently selected host is now marked dead, force a
465          re-selection .  */
466       if (force_reselect)
467         hi->poolidx = -1;
468       else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
469                && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
470         hi->poolidx = -1;
471
472       /* Select a host if needed.  */
473       if (hi->poolidx == -1)
474         {
475           hi->poolidx = select_random_host (hi->pool);
476           if (hi->poolidx == -1)
477             {
478               log_error ("no alive host found in pool '%s'\n", name);
479               if (r_poolname)
480                 {
481                   xfree (*r_poolname);
482                   *r_poolname = NULL;
483                 }
484               return gpg_error (GPG_ERR_NO_KEYSERVER);
485             }
486         }
487
488       assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
489       hi = hosttable[hi->poolidx];
490       assert (hi);
491     }
492
493   if (hi->dead)
494     {
495       log_error ("host '%s' marked as dead\n", hi->name);
496       if (r_poolname)
497         {
498           xfree (*r_poolname);
499           *r_poolname = NULL;
500         }
501       return gpg_error (GPG_ERR_NO_KEYSERVER);
502     }
503
504   if (r_httpflags)
505     {
506       /* If the hosttable does not indicate that a certain host
507          supports IPv<N>, we explicit set the corresponding http
508          flags.  The reason for this is that a host might be listed in
509          a pool as not v6 only but actually support v6 when later
510          the name is resolved by our http layer.  */
511       if (!hi->v4)
512         *r_httpflags |= HTTP_FLAG_IGNORE_IPv4;
513       if (!hi->v6)
514         *r_httpflags |= HTTP_FLAG_IGNORE_IPv6;
515     }
516
517   *r_host = xtrystrdup (hi->name);
518   if (!*r_host)
519     {
520       err = gpg_error_from_syserror ();
521       if (r_poolname)
522         {
523           xfree (*r_poolname);
524           *r_poolname = NULL;
525         }
526       return err;
527     }
528   return 0;
529 }
530
531
532 /* Mark the host NAME as dead.  NAME may be given as an URL.  Returns
533    true if a host was really marked as dead or was already marked dead
534    (e.g. by a concurrent session).  */
535 static int
536 mark_host_dead (const char *name)
537 {
538   const char *host;
539   char *host_buffer = NULL;
540   parsed_uri_t parsed_uri = NULL;
541   int done = 0;
542
543   if (name && *name && !http_parse_uri (&parsed_uri, name, 1))
544     {
545       if (parsed_uri->v6lit)
546         {
547           host_buffer = strconcat ("[", parsed_uri->host, "]", NULL);
548           if (!host_buffer)
549             log_error ("out of core in mark_host_dead");
550           host = host_buffer;
551         }
552       else
553         host = parsed_uri->host;
554     }
555   else
556     host = name;
557
558   if (host && *host && strcmp (host, "localhost"))
559     {
560       hostinfo_t hi;
561       int idx;
562
563       idx = find_hostinfo (host);
564       if (idx != -1)
565         {
566           hi = hosttable[idx];
567           log_info ("marking host '%s' as dead%s\n",
568                     hi->name, hi->dead? " (again)":"");
569           hi->dead = 1;
570           hi->died_at = gnupg_get_time ();
571           if (!hi->died_at)
572             hi->died_at = 1;
573           done = 1;
574         }
575     }
576
577   http_release_parsed_uri (parsed_uri);
578   xfree (host_buffer);
579   return done;
580 }
581
582
583 /* Mark a host in the hosttable as dead or - if ALIVE is true - as
584    alive.  */
585 gpg_error_t
586 ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
587 {
588   gpg_error_t err = 0;
589   hostinfo_t hi, hi2;
590   int idx, idx2, idx3, n;
591
592   if (!name || !*name || !strcmp (name, "localhost"))
593     return 0;
594
595   idx = find_hostinfo (name);
596   if (idx == -1)
597     return gpg_error (GPG_ERR_NOT_FOUND);
598
599   hi = hosttable[idx];
600   if (alive && hi->dead)
601     {
602       hi->dead = 0;
603       err = ks_printf_help (ctrl, "marking '%s' as alive", name);
604     }
605   else if (!alive && !hi->dead)
606     {
607       hi->dead = 1;
608       hi->died_at = 0; /* Manually set dead.  */
609       err = ks_printf_help (ctrl, "marking '%s' as dead", name);
610     }
611
612   /* If the host is a pool mark all member hosts. */
613   if (!err && hi->pool)
614     {
615       for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
616         {
617           assert (n >= 0 && n < hosttable_size);
618
619           if (!alive)
620             {
621               /* Do not mark a host from a pool dead if it is also a
622                  member in another pool.  */
623               for (idx3=0; idx3 < hosttable_size; idx3++)
624                 {
625                   if (hosttable[idx3]
626                       && hosttable[idx3]->pool
627                       && idx3 != idx
628                       && host_in_pool_p (hosttable[idx3]->pool, n))
629                     break;
630                 }
631               if (idx3 < hosttable_size)
632                 continue;  /* Host is also a member of another pool.  */
633             }
634
635           hi2 = hosttable[n];
636           if (!hi2)
637             ;
638           else if (alive && hi2->dead)
639             {
640               hi2->dead = 0;
641               err = ks_printf_help (ctrl, "marking '%s' as alive",
642                                     hi2->name);
643             }
644           else if (!alive && !hi2->dead)
645             {
646               hi2->dead = 1;
647               hi2->died_at = 0; /* Manually set dead. */
648               err = ks_printf_help (ctrl, "marking '%s' as dead",
649                                     hi2->name);
650             }
651         }
652     }
653
654   return err;
655 }
656
657
658 /* Debug function to print the entire hosttable.  */
659 gpg_error_t
660 ks_hkp_print_hosttable (ctrl_t ctrl)
661 {
662   gpg_error_t err;
663   int idx, idx2;
664   hostinfo_t hi;
665   membuf_t mb;
666   time_t curtime;
667   char *p, *died;
668   const char *diedstr;
669
670   err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):");
671   if (err)
672     return err;
673
674   curtime = gnupg_get_time ();
675   for (idx=0; idx < hosttable_size; idx++)
676     if ((hi=hosttable[idx]))
677       {
678         if (hi->dead && hi->died_at)
679           {
680             died = elapsed_time_string (hi->died_at, curtime);
681             diedstr = died? died : "error";
682           }
683         else
684           diedstr = died = NULL;
685         err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n",
686                               idx, hi->v6? "6":" ", hi->v4? "4":" ",
687                               hi->dead? "d":" ",
688                               hi->name,
689                               hi->v6addr? " v6=":"",
690                               hi->v6addr? hi->v6addr:"",
691                               hi->v4addr? " v4=":"",
692                               hi->v4addr? hi->v4addr:"",
693                               diedstr? "  (":"",
694                               diedstr? diedstr:"",
695                               diedstr? ")":""   );
696         xfree (died);
697         if (err)
698           return err;
699
700         if (hi->cname)
701           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
702         if (err)
703           return err;
704
705         if (hi->pool)
706           {
707             init_membuf (&mb, 256);
708             put_membuf_printf (&mb, "  .   -->");
709             for (idx2=0; hi->pool[idx2] != -1; idx2++)
710               {
711                 put_membuf_printf (&mb, " %d", hi->pool[idx2]);
712                 if (hi->poolidx == hi->pool[idx2])
713                   put_membuf_printf (&mb, "*");
714               }
715             put_membuf( &mb, "", 1);
716             p = get_membuf (&mb, NULL);
717             if (!p)
718               return gpg_error_from_syserror ();
719             err = ks_print_help (ctrl, p);
720             xfree (p);
721             if (err)
722               return err;
723           }
724       }
725   return 0;
726 }
727
728
729
730 /* Print a help output for the schemata supported by this module. */
731 gpg_error_t
732 ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
733 {
734   const char const data[] =
735     "Handler for HKP URLs:\n"
736     "  hkp://\n"
737 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
738     "  hkps://\n"
739 #endif
740     "Supported methods: search, get, put\n";
741   gpg_error_t err;
742
743 #if  HTTP_USE_GNUTLS || HTTP_USE_NTBTLS
744   const char data2[] = "  hkp\n  hkps";
745 #else
746   const char data2[] = "  hkp";
747 #endif
748
749   if (!uri)
750     err = ks_print_help (ctrl, data2);
751   else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
752                             || !strcmp (uri->scheme, "hkps")))
753     err = ks_print_help (ctrl, data);
754   else
755     err = 0;
756
757   return err;
758 }
759
760
761 /* Build the remote part of the URL from SCHEME, HOST and an optional
762    PORT.  Returns an allocated string at R_HOSTPORT or NULL on failure
763    If R_POOLNAME is not NULL it receives a malloced string with the
764    poolname.  */
765 static gpg_error_t
766 make_host_part (ctrl_t ctrl,
767                 const char *scheme, const char *host, unsigned short port,
768                 int force_reselect,
769                 char **r_hostport, unsigned int *r_httpflags, char **r_poolname)
770 {
771   gpg_error_t err;
772   char portstr[10];
773   char *hostname;
774
775   *r_hostport = NULL;
776
777   /* Map scheme and port.  */
778   if (!strcmp (scheme, "hkps") || !strcmp (scheme,"https"))
779     {
780       scheme = "https";
781       strcpy (portstr, "443");
782     }
783   else /* HKP or HTTP.  */
784     {
785       scheme = "http";
786       strcpy (portstr, "11371");
787     }
788   if (port)
789     snprintf (portstr, sizeof portstr, "%hu", port);
790   else
791     {
792       /*fixme_do_srv_lookup ()*/
793     }
794
795   err = map_host (ctrl, host, force_reselect,
796                   &hostname, r_httpflags, r_poolname);
797   if (err)
798     return err;
799
800   *r_hostport = strconcat (scheme, "://", hostname, ":", portstr, NULL);
801   xfree (hostname);
802   if (!*r_hostport)
803     {
804       if (r_poolname)
805         {
806           xfree (*r_poolname);
807           *r_poolname = NULL;
808         }
809       return gpg_error_from_syserror ();
810     }
811   return 0;
812 }
813
814
815 /* Resolve all known keyserver names and update the hosttable.  This
816    is mainly useful for debugging because the resolving is anyway done
817    on demand.  */
818 gpg_error_t
819 ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
820 {
821   gpg_error_t err;
822   char *hostport = NULL;
823
824   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1,
825                         &hostport, NULL, NULL);
826   if (err)
827     {
828       err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
829                             uri->scheme, uri->host, uri->port,
830                             gpg_strerror (err));
831     }
832   else
833     {
834       err = ks_printf_help (ctrl, "%s", hostport);
835       xfree (hostport);
836     }
837   return err;
838 }
839
840
841 /* Housekeeping function called from the housekeeping thread.  It is
842    used to mark dead hosts alive so that they may be tried again after
843    some time.  */
844 void
845 ks_hkp_housekeeping (time_t curtime)
846 {
847   int idx;
848   hostinfo_t hi;
849
850   for (idx=0; idx < hosttable_size; idx++)
851     {
852       hi = hosttable[idx];
853       if (!hi)
854         continue;
855       if (!hi->dead)
856         continue;
857       if (!hi->died_at)
858         continue; /* Do not resurrect manually shot hosts.  */
859       if (hi->died_at + RESURRECT_INTERVAL <= curtime
860           || hi->died_at > curtime)
861         {
862           hi->dead = 0;
863           log_info ("resurrected host '%s'", hi->name);
864         }
865     }
866 }
867
868
869 /* Send an HTTP request.  On success returns an estream object at
870    R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
871    not NULL it will be used as HTTP "Host" header.  If POST_CB is not
872    NULL a post request is used and that callback is called to allow
873    writing the post data.  */
874 static gpg_error_t
875 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
876               const char *httphost, unsigned int httpflags,
877               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
878               estream_t *r_fp)
879 {
880   gpg_error_t err;
881   http_session_t session = NULL;
882   http_t http = NULL;
883   int redirects_left = MAX_REDIRECTS;
884   estream_t fp = NULL;
885   char *request_buffer = NULL;
886
887   *r_fp = NULL;
888
889   err = http_session_new (&session, NULL);
890   if (err)
891     goto leave;
892   http_session_set_log_cb (session, cert_log_cb);
893
894  once_more:
895   err = http_open (&http,
896                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
897                    request,
898                    httphost,
899                    /* fixme: AUTH */ NULL,
900                    (httpflags
901                     |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
902                     |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)),
903                    ctrl->http_proxy,
904                    session,
905                    NULL,
906                    /*FIXME curl->srvtag*/NULL);
907   if (!err)
908     {
909       fp = http_get_write_ptr (http);
910       /* Avoid caches to get the most recent copy of the key.  We set
911          both the Pragma and Cache-Control versions of the header, so
912          we're good with both HTTP 1.0 and 1.1.  */
913       es_fputs ("Pragma: no-cache\r\n"
914                 "Cache-Control: no-cache\r\n", fp);
915       if (post_cb)
916         err = post_cb (post_cb_value, http);
917       if (!err)
918         {
919           http_start_data (http);
920           if (es_ferror (fp))
921             err = gpg_error_from_syserror ();
922         }
923     }
924   if (err)
925     {
926       /* Fixme: After a redirection we show the old host name.  */
927       log_error (_("error connecting to '%s': %s\n"),
928                  hostportstr, gpg_strerror (err));
929       goto leave;
930     }
931
932   /* Wait for the response.  */
933   dirmngr_tick (ctrl);
934   err = http_wait_response (http);
935   if (err)
936     {
937       log_error (_("error reading HTTP response for '%s': %s\n"),
938                  hostportstr, gpg_strerror (err));
939       goto leave;
940     }
941
942   if (http_get_tls_info (http, NULL))
943     {
944       /* Update the httpflags so that a redirect won't fallback to an
945          unencrypted connection.  */
946       httpflags |= HTTP_FLAG_FORCE_TLS;
947     }
948
949   switch (http_get_status_code (http))
950     {
951     case 200:
952       err = 0;
953       break; /* Success.  */
954
955     case 301:
956     case 302:
957     case 307:
958       {
959         const char *s = http_get_header (http, "Location");
960
961         log_info (_("URL '%s' redirected to '%s' (%u)\n"),
962                   request, s?s:"[none]", http_get_status_code (http));
963         if (s && *s && redirects_left-- )
964           {
965             xfree (request_buffer);
966             request_buffer = xtrystrdup (s);
967             if (request_buffer)
968               {
969                 request = request_buffer;
970                 http_close (http, 0);
971                 http = NULL;
972                 goto once_more;
973               }
974             err = gpg_error_from_syserror ();
975           }
976         else
977           err = gpg_error (GPG_ERR_NO_DATA);
978         log_error (_("too many redirections\n"));
979       }
980       goto leave;
981
982     default:
983       log_error (_("error accessing '%s': http status %u\n"),
984                  request, http_get_status_code (http));
985       err = gpg_error (GPG_ERR_NO_DATA);
986       goto leave;
987     }
988
989   /* FIXME: We should register a permanent redirection and whether a
990      host has ever used TLS so that future calls will always use
991      TLS. */
992
993   fp = http_get_read_ptr (http);
994   if (!fp)
995     {
996       err = gpg_error (GPG_ERR_BUG);
997       goto leave;
998     }
999
1000   /* Return the read stream and close the HTTP context.  */
1001   *r_fp = fp;
1002   http_close (http, 1);
1003   http = NULL;
1004
1005  leave:
1006   http_close (http, 0);
1007   http_session_release (session);
1008   xfree (request_buffer);
1009   return err;
1010 }
1011
1012
1013 /* Helper to evaluate the error code ERR form a send_request() call
1014    with REQUEST.  The function returns true if the caller shall try
1015    again.  TRIES_LEFT points to a variable to track the number of
1016    retries; this function decrements it and won't return true if it is
1017    down to zero. */
1018 static int
1019 handle_send_request_error (gpg_error_t err, const char *request,
1020                            unsigned int *tries_left)
1021 {
1022   int retry = 0;
1023
1024   switch (gpg_err_code (err))
1025     {
1026     case GPG_ERR_ECONNREFUSED:
1027     case GPG_ERR_ENETUNREACH:
1028     case GPG_ERR_UNKNOWN_HOST:
1029     case GPG_ERR_NETWORK:
1030       if (mark_host_dead (request) && *tries_left)
1031         retry = 1;
1032       break;
1033
1034     case GPG_ERR_ETIMEDOUT:
1035       if (*tries_left)
1036         {
1037           log_info ("selecting a different host due to a timeout\n");
1038           retry = 1;
1039         }
1040
1041     default:
1042       break;
1043     }
1044
1045   if (*tries_left)
1046     --*tries_left;
1047
1048   return retry;
1049 }
1050
1051 \f
1052 /* Search the keyserver identified by URI for keys matching PATTERN.
1053    On success R_FP has an open stream to read the data.  */
1054 gpg_error_t
1055 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1056                estream_t *r_fp)
1057 {
1058   gpg_error_t err;
1059   KEYDB_SEARCH_DESC desc;
1060   char fprbuf[2+40+1];
1061   char *hostport = NULL;
1062   char *request = NULL;
1063   estream_t fp = NULL;
1064   int reselect;
1065   unsigned int httpflags;
1066   char *httphost = NULL;
1067   unsigned int tries = SEND_REQUEST_RETRIES;
1068
1069   *r_fp = NULL;
1070
1071   /* Remove search type indicator and adjust PATTERN accordingly.
1072      Note that HKP keyservers like the 0x to be present when searching
1073      by keyid.  We need to re-format the fingerprint and keyids so to
1074      remove the gpg specific force-use-of-this-key flag ("!").  */
1075   err = classify_user_id (pattern, &desc, 1);
1076   if (err)
1077     return err;
1078   switch (desc.mode)
1079     {
1080     case KEYDB_SEARCH_MODE_EXACT:
1081     case KEYDB_SEARCH_MODE_SUBSTR:
1082     case KEYDB_SEARCH_MODE_MAIL:
1083     case KEYDB_SEARCH_MODE_MAILSUB:
1084       pattern = desc.u.name;
1085       break;
1086     case KEYDB_SEARCH_MODE_SHORT_KID:
1087       snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1088       pattern = fprbuf;
1089       break;
1090     case KEYDB_SEARCH_MODE_LONG_KID:
1091       snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
1092                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1093       pattern = fprbuf;
1094       break;
1095     case KEYDB_SEARCH_MODE_FPR16:
1096       bin2hex (desc.u.fpr, 16, fprbuf);
1097       pattern = fprbuf;
1098       break;
1099     case KEYDB_SEARCH_MODE_FPR20:
1100     case KEYDB_SEARCH_MODE_FPR:
1101       bin2hex (desc.u.fpr, 20, fprbuf);
1102       pattern = fprbuf;
1103       break;
1104     default:
1105       return gpg_error (GPG_ERR_INV_USER_ID);
1106     }
1107
1108   /* Build the request string.  */
1109   reselect = 0;
1110  again:
1111   {
1112     char *searchkey;
1113
1114     xfree (hostport); hostport = NULL;
1115     xfree (httphost); httphost = NULL;
1116     err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1117                           &hostport, &httpflags, &httphost);
1118     if (err)
1119       goto leave;
1120
1121     searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
1122     if (!searchkey)
1123       {
1124         err = gpg_error_from_syserror ();
1125         goto leave;
1126       }
1127
1128     xfree (request);
1129     request = strconcat (hostport,
1130                          "/pks/lookup?op=index&options=mr&search=",
1131                          searchkey,
1132                          NULL);
1133     xfree (searchkey);
1134     if (!request)
1135       {
1136         err = gpg_error_from_syserror ();
1137         goto leave;
1138       }
1139   }
1140
1141   /* Send the request.  */
1142   err = send_request (ctrl, request, hostport, httphost, httpflags,
1143                       NULL, NULL, &fp);
1144   if (handle_send_request_error (err, request, &tries))
1145     {
1146       reselect = 1;
1147       goto again;
1148     }
1149   if (err)
1150     goto leave;
1151
1152   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1153   if (err)
1154     goto leave;
1155
1156   /* Peek at the response.  */
1157   {
1158     int c = es_getc (fp);
1159     if (c == -1)
1160       {
1161         err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
1162         log_error ("error reading response: %s\n", gpg_strerror (err));
1163         goto leave;
1164       }
1165     if (c == '<')
1166       {
1167         /* The document begins with a '<': Assume a HTML response,
1168            which we don't support.  */
1169         err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1170         goto leave;
1171       }
1172     es_ungetc (c, fp);
1173   }
1174
1175   /* Return the read stream.  */
1176   *r_fp = fp;
1177   fp = NULL;
1178
1179  leave:
1180   es_fclose (fp);
1181   xfree (request);
1182   xfree (hostport);
1183   xfree (httphost);
1184   return err;
1185 }
1186
1187
1188 /* Get the key described key the KEYSPEC string from the keyserver
1189    identified by URI.  On success R_FP has an open stream to read the
1190    data.  The data will be provided in a format GnuPG can import
1191    (either a binary OpenPGP message or an armored one).  */
1192 gpg_error_t
1193 ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
1194 {
1195   gpg_error_t err;
1196   KEYDB_SEARCH_DESC desc;
1197   char kidbuf[2+40+1];
1198   const char *exactname = NULL;
1199   char *searchkey = NULL;
1200   char *hostport = NULL;
1201   char *request = NULL;
1202   estream_t fp = NULL;
1203   int reselect;
1204   char *httphost = NULL;
1205   unsigned int httpflags;
1206   unsigned int tries = SEND_REQUEST_RETRIES;
1207
1208   *r_fp = NULL;
1209
1210   /* Remove search type indicator and adjust PATTERN accordingly.
1211      Note that HKP keyservers like the 0x to be present when searching
1212      by keyid.  We need to re-format the fingerprint and keyids so to
1213      remove the gpg specific force-use-of-this-key flag ("!").  */
1214   err = classify_user_id (keyspec, &desc, 1);
1215   if (err)
1216     return err;
1217   switch (desc.mode)
1218     {
1219     case KEYDB_SEARCH_MODE_SHORT_KID:
1220       snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
1221       break;
1222     case KEYDB_SEARCH_MODE_LONG_KID:
1223       snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
1224                 (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
1225       break;
1226     case KEYDB_SEARCH_MODE_FPR20:
1227     case KEYDB_SEARCH_MODE_FPR:
1228       /* This is a v4 fingerprint. */
1229       kidbuf[0] = '0';
1230       kidbuf[1] = 'x';
1231       bin2hex (desc.u.fpr, 20, kidbuf+2);
1232       break;
1233
1234     case KEYDB_SEARCH_MODE_EXACT:
1235       exactname = desc.u.name;
1236       break;
1237
1238     case KEYDB_SEARCH_MODE_FPR16:
1239       log_error ("HKP keyservers do not support v3 fingerprints\n");
1240     default:
1241       return gpg_error (GPG_ERR_INV_USER_ID);
1242     }
1243
1244   searchkey = http_escape_string (exactname? exactname : kidbuf,
1245                                   EXTRA_ESCAPE_CHARS);
1246   if (!searchkey)
1247     {
1248       err = gpg_error_from_syserror ();
1249       goto leave;
1250     }
1251
1252   reselect = 0;
1253  again:
1254   /* Build the request string.  */
1255   xfree (hostport); hostport = NULL;
1256   xfree (httphost); httphost = NULL;
1257   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1258                         &hostport, &httpflags, &httphost);
1259   if (err)
1260     goto leave;
1261
1262   xfree (request);
1263   request = strconcat (hostport,
1264                        "/pks/lookup?op=get&options=mr&search=",
1265                        searchkey,
1266                        exactname? "&exact=on":"",
1267                        NULL);
1268   if (!request)
1269     {
1270       err = gpg_error_from_syserror ();
1271       goto leave;
1272     }
1273
1274   /* Send the request.  */
1275   err = send_request (ctrl, request, hostport, httphost, httpflags,
1276                       NULL, NULL, &fp);
1277   if (handle_send_request_error (err, request, &tries))
1278     {
1279       reselect = 1;
1280       goto again;
1281     }
1282   if (err)
1283     goto leave;
1284
1285   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
1286   if (err)
1287     goto leave;
1288
1289   /* Return the read stream and close the HTTP context.  */
1290   *r_fp = fp;
1291   fp = NULL;
1292
1293  leave:
1294   es_fclose (fp);
1295   xfree (request);
1296   xfree (hostport);
1297   xfree (httphost);
1298   xfree (searchkey);
1299   return err;
1300 }
1301
1302
1303
1304 \f
1305 /* Callback parameters for put_post_cb.  */
1306 struct put_post_parm_s
1307 {
1308   char *datastring;
1309 };
1310
1311
1312 /* Helper for ks_hkp_put.  */
1313 static gpg_error_t
1314 put_post_cb (void *opaque, http_t http)
1315 {
1316   struct put_post_parm_s *parm = opaque;
1317   gpg_error_t err = 0;
1318   estream_t fp;
1319   size_t len;
1320
1321   fp = http_get_write_ptr (http);
1322   len = strlen (parm->datastring);
1323
1324   es_fprintf (fp,
1325               "Content-Type: application/x-www-form-urlencoded\r\n"
1326               "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
1327   http_start_data (http);
1328   if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
1329     err = gpg_error_from_syserror ();
1330   return err;
1331 }
1332
1333
1334 /* Send the key in {DATA,DATALEN} to the keyserver identified by URI.  */
1335 gpg_error_t
1336 ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
1337 {
1338   gpg_error_t err;
1339   char *hostport = NULL;
1340   char *request = NULL;
1341   estream_t fp = NULL;
1342   struct put_post_parm_s parm;
1343   char *armored = NULL;
1344   int reselect;
1345   char *httphost = NULL;
1346   unsigned int httpflags;
1347   unsigned int tries = SEND_REQUEST_RETRIES;
1348
1349   parm.datastring = NULL;
1350
1351   err = armor_data (&armored, data, datalen);
1352   if (err)
1353     goto leave;
1354
1355   parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS);
1356   if (!parm.datastring)
1357     {
1358       err = gpg_error_from_syserror ();
1359       goto leave;
1360     }
1361   xfree (armored);
1362   armored = NULL;
1363
1364   /* Build the request string.  */
1365   reselect = 0;
1366  again:
1367   xfree (hostport); hostport = NULL;
1368   xfree (httphost); httphost = NULL;
1369   err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
1370                         &hostport, &httpflags, &httphost);
1371   if (err)
1372     goto leave;
1373
1374   xfree (request);
1375   request = strconcat (hostport, "/pks/add", NULL);
1376   if (!request)
1377     {
1378       err = gpg_error_from_syserror ();
1379       goto leave;
1380     }
1381
1382   /* Send the request.  */
1383   err = send_request (ctrl, request, hostport, httphost, 0,
1384                       put_post_cb, &parm, &fp);
1385   if (handle_send_request_error (err, request, &tries))
1386     {
1387       reselect = 1;
1388       goto again;
1389     }
1390   if (err)
1391     goto leave;
1392
1393  leave:
1394   es_fclose (fp);
1395   xfree (parm.datastring);
1396   xfree (armored);
1397   xfree (request);
1398   xfree (hostport);
1399   xfree (httphost);
1400   return err;
1401 }