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