678000c8042510b12b542177ee2f2cf813a5778b
[gnupg.git] / tools / gpg-wks-server.c
1 /* gpg-wks-server.c - A server for the Web Key Service protocols.
2  * Copyright (C) 2016 Werner Koch
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* The Web Key Service I-D defines an update protocol to store a
21  * public key in the Web Key Directory.  The current specification is
22  * draft-koch-openpgp-webkey-service-01.txt.
23  */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33
34 #include "util.h"
35 #include "init.h"
36 #include "sysutils.h"
37 #include "ccparray.h"
38 #include "exectool.h"
39 #include "zb32.h"
40 #include "mbox-util.h"
41 #include "name-value.h"
42 #include "mime-maker.h"
43 #include "send-mail.h"
44 #include "gpg-wks.h"
45
46
47 /* The time we wait for a confirmation response.  */
48 #define PENDING_TTL (86400 * 3)  /* 3 days.  */
49
50
51 /* Constants to identify the commands and options. */
52 enum cmd_and_opt_values
53   {
54     aNull = 0,
55
56     oQuiet      = 'q',
57     oVerbose    = 'v',
58     oOutput     = 'o',
59
60     oDebug      = 500,
61
62     aReceive,
63     aCron,
64     aListDomains,
65
66     oGpgProgram,
67     oSend,
68     oFrom,
69     oHeader,
70
71     oDummy
72   };
73
74
75 /* The list of commands and options. */
76 static ARGPARSE_OPTS opts[] = {
77   ARGPARSE_group (300, ("@Commands:\n ")),
78
79   ARGPARSE_c (aReceive,   "receive",
80               ("receive a submission or confirmation")),
81   ARGPARSE_c (aCron,      "cron",
82               ("run regular jobs")),
83   ARGPARSE_c (aListDomains, "list-domains",
84               ("list configured domains")),
85
86   ARGPARSE_group (301, ("@\nOptions:\n ")),
87
88   ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
89   ARGPARSE_s_n (oQuiet, "quiet",  ("be somewhat more quiet")),
90   ARGPARSE_s_s (oDebug, "debug", "@"),
91   ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
92   ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
93   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
94   ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"),
95   ARGPARSE_s_s (oHeader, "header" ,
96                 "|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"),
97
98   ARGPARSE_end ()
99 };
100
101
102 /* The list of supported debug flags.  */
103 static struct debug_flags_s debug_flags [] =
104   {
105     { DBG_CRYPTO_VALUE , "crypto"  },
106     { DBG_MEMORY_VALUE , "memory"  },
107     { DBG_MEMSTAT_VALUE, "memstat" },
108     { DBG_IPC_VALUE    , "ipc"     },
109     { DBG_EXTPROG_VALUE, "extprog" },
110     { 0, NULL }
111   };
112
113
114 /* State for processing a message.  */
115 struct server_ctx_s
116 {
117   char *fpr;
118   strlist_t mboxes;  /* List of addr-specs taken from the UIDs.  */
119 };
120 typedef struct server_ctx_s *server_ctx_t;
121
122 /* Prototypes.  */
123 static gpg_error_t get_domain_list (strlist_t *r_list);
124
125 static gpg_error_t command_receive_cb (void *opaque,
126                                        const char *mediatype, estream_t fp);
127 static gpg_error_t command_list_domains (void);
128 static gpg_error_t command_cron (void);
129
130
131 \f
132 /* Print usage information and and provide strings for help. */
133 static const char *
134 my_strusage( int level )
135 {
136   const char *p;
137
138   switch (level)
139     {
140     case 11: p = "gpg-wks-server (@GNUPG@)";
141       break;
142     case 13: p = VERSION; break;
143     case 17: p = PRINTABLE_OS_NAME; break;
144     case 19: p = ("Please report bugs to <@EMAIL@>.\n"); break;
145
146     case 1:
147     case 40:
148       p = ("Usage: gpg-wks-server command [options] (-h for help)");
149       break;
150     case 41:
151       p = ("Syntax: gpg-wks-server command [options]\n"
152            "Server for the Web Key Service protocol\n");
153       break;
154
155     default: p = NULL; break;
156     }
157   return p;
158 }
159
160
161 static void
162 wrong_args (const char *text)
163 {
164   es_fprintf (es_stderr, "usage: %s [options] %s\n", strusage (11), text);
165   exit (2);
166 }
167
168
169 \f
170 /* Command line parsing.  */
171 static enum cmd_and_opt_values
172 parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
173 {
174   enum cmd_and_opt_values cmd = 0;
175   int no_more_options = 0;
176
177   while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
178     {
179       switch (pargs->r_opt)
180         {
181         case oQuiet:     opt.quiet = 1; break;
182         case oVerbose:   opt.verbose++; break;
183         case oDebug:
184           if (parse_debug_flag (pargs->r.ret_str, &opt.debug, debug_flags))
185             {
186               pargs->r_opt = ARGPARSE_INVALID_ARG;
187               pargs->err = ARGPARSE_PRINT_ERROR;
188             }
189           break;
190
191         case oGpgProgram:
192           opt.gpg_program = pargs->r.ret_str;
193           break;
194         case oFrom:
195           opt.default_from = pargs->r.ret_str;
196           break;
197         case oHeader:
198           append_to_strlist (&opt.extra_headers, pargs->r.ret_str);
199           break;
200         case oSend:
201           opt.use_sendmail = 1;
202           break;
203         case oOutput:
204           opt.output = pargs->r.ret_str;
205           break;
206
207         case aReceive:
208         case aCron:
209         case aListDomains:
210           cmd = pargs->r_opt;
211           break;
212
213         default: pargs->err = 2; break;
214         }
215     }
216
217   return cmd;
218 }
219
220
221 \f
222 /* gpg-wks-server main. */
223 int
224 main (int argc, char **argv)
225 {
226   gpg_error_t err;
227   ARGPARSE_ARGS pargs;
228   enum cmd_and_opt_values cmd;
229
230   gnupg_reopen_std ("gpg-wks-server");
231   set_strusage (my_strusage);
232   log_set_prefix ("gpg-wks-server", GPGRT_LOG_WITH_PREFIX);
233
234   /* Make sure that our subsystems are ready.  */
235   init_common_subsystems (&argc, &argv);
236
237   /* Parse the command line. */
238   pargs.argc  = &argc;
239   pargs.argv  = &argv;
240   pargs.flags = ARGPARSE_FLAG_KEEP;
241   cmd = parse_arguments (&pargs, opts);
242
243   if (log_get_errorcount (0))
244     exit (2);
245
246   /* Print a warning if an argument looks like an option.  */
247   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
248     {
249       int i;
250
251       for (i=0; i < argc; i++)
252         if (argv[i][0] == '-' && argv[i][1] == '-')
253           log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
254     }
255
256   /* Set defaults for non given options.  */
257   if (!opt.gpg_program)
258     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
259
260   if (!opt.directory)
261     opt.directory = "/var/lib/gnupg/wks";
262
263   /* Check for syntax errors in the --header option to avoid later
264    * error messages with a not easy to find cause */
265   if (opt.extra_headers)
266     {
267       strlist_t sl;
268
269       for (sl = opt.extra_headers; sl; sl = sl->next)
270         {
271           err = mime_maker_add_header (NULL, sl->d, NULL);
272           if (err)
273             log_error ("syntax error in \"--header %s\": %s\n",
274                        sl->d, gpg_strerror (err));
275         }
276     }
277
278   if (log_get_errorcount (0))
279     exit (2);
280
281
282   /* Check that we have a working directory.  */
283 #if defined(HAVE_STAT)
284   {
285     struct stat sb;
286
287     if (stat (opt.directory, &sb))
288       {
289         err = gpg_error_from_syserror ();
290         log_error ("error accessing directory '%s': %s\n",
291                    opt.directory, gpg_strerror (err));
292         exit (2);
293       }
294     if (!S_ISDIR(sb.st_mode))
295       {
296         log_error ("error accessing directory '%s': %s\n",
297                    opt.directory, "not a directory");
298         exit (2);
299       }
300     if (sb.st_uid != getuid())
301       {
302         log_error ("directory '%s' not owned by user\n", opt.directory);
303         exit (2);
304       }
305     if ((sb.st_mode & (S_IROTH|S_IWOTH)))
306       {
307         log_error ("directory '%s' has too relaxed permissions\n",
308                    opt.directory);
309         exit (2);
310       }
311   }
312 #else /*!HAVE_STAT*/
313   log_fatal ("program build w/o stat() call\n");
314 #endif /*!HAVE_STAT*/
315
316   /* Run the selected command.  */
317   switch (cmd)
318     {
319     case aReceive:
320       if (argc)
321         wrong_args ("--receive");
322       err = wks_receive (es_stdin, command_receive_cb, NULL);
323       break;
324
325     case aCron:
326       if (argc)
327         wrong_args ("--cron");
328       err = command_cron ();
329       break;
330
331     case aListDomains:
332       err = command_list_domains ();
333       break;
334
335     default:
336       usage (1);
337       err = gpg_error (GPG_ERR_BUG);
338       break;
339     }
340
341   if (err)
342     log_error ("command failed: %s\n", gpg_strerror (err));
343   return log_get_errorcount (0)? 1:0;
344 }
345
346
347 \f
348 static void
349 list_key_status_cb (void *opaque, const char *keyword, char *args)
350 {
351   server_ctx_t ctx = opaque;
352   (void)ctx;
353   if (opt.debug)
354     log_debug ("%s: %s\n", keyword, args);
355 }
356
357
358 static gpg_error_t
359 list_key (server_ctx_t ctx, estream_t key)
360 {
361   gpg_error_t err;
362   ccparray_t ccp;
363   const char **argv;
364   estream_t listing;
365   char *line = NULL;
366   size_t length_of_line = 0;
367   size_t  maxlen;
368   ssize_t len;
369   char **fields = NULL;
370   int nfields;
371   int lnr;
372   char *mbox = NULL;
373
374   /* We store our results in the context - clear it first.  */
375   xfree (ctx->fpr);
376   ctx->fpr = NULL;
377   free_strlist (ctx->mboxes);
378   ctx->mboxes = NULL;
379
380   /* Open a memory stream.  */
381   listing = es_fopenmem (0, "w+b");
382   if (!listing)
383     {
384       err = gpg_error_from_syserror ();
385       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
386       return err;
387     }
388
389   ccparray_init (&ccp, 0);
390
391   ccparray_put (&ccp, "--no-options");
392   if (!opt.verbose)
393     ccparray_put (&ccp, "--quiet");
394   else if (opt.verbose > 1)
395     ccparray_put (&ccp, "--verbose");
396   ccparray_put (&ccp, "--batch");
397   ccparray_put (&ccp, "--status-fd=2");
398   ccparray_put (&ccp, "--always-trust");
399   ccparray_put (&ccp, "--with-colons");
400   ccparray_put (&ccp, "--dry-run");
401   ccparray_put (&ccp, "--import-options=import-minimal,import-show");
402   ccparray_put (&ccp, "--import");
403
404   ccparray_put (&ccp, NULL);
405   argv = ccparray_get (&ccp, NULL);
406   if (!argv)
407     {
408       err = gpg_error_from_syserror ();
409       goto leave;
410     }
411   err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
412                                 NULL, listing,
413                                 list_key_status_cb, ctx);
414   if (err)
415     {
416       log_error ("import failed: %s\n", gpg_strerror (err));
417       goto leave;
418     }
419
420   es_rewind (listing);
421   lnr = 0;
422   maxlen = 2048; /* Set limit.  */
423   while ((len = es_read_line (listing, &line, &length_of_line, &maxlen)) > 0)
424     {
425       lnr++;
426       if (!maxlen)
427         {
428           log_error ("received line too long\n");
429           err = gpg_error (GPG_ERR_LINE_TOO_LONG);
430           goto leave;
431         }
432       /* Strip newline and carriage return, if present.  */
433       while (len > 0
434              && (line[len - 1] == '\n' || line[len - 1] == '\r'))
435         line[--len] = '\0';
436       /* log_debug ("line '%s'\n", line); */
437
438       xfree (fields);
439       fields = strtokenize (line, ":");
440       if (!fields)
441         {
442           err = gpg_error_from_syserror ();
443           log_error ("strtokenize failed: %s\n", gpg_strerror (err));
444           goto leave;
445         }
446       for (nfields = 0; fields[nfields]; nfields++)
447         ;
448       if (!nfields)
449         {
450           err = gpg_error (GPG_ERR_INV_ENGINE);
451           goto leave;
452         }
453       if (!strcmp (fields[0], "sec"))
454         {
455           /* gpg may return "sec" as the first record - but we do not
456            * accept secret keys.  */
457           err = gpg_error (GPG_ERR_NO_PUBKEY);
458           goto leave;
459         }
460       if (lnr == 1 && strcmp (fields[0], "pub"))
461         {
462           /* First record is not a public key.  */
463           err = gpg_error (GPG_ERR_INV_ENGINE);
464           goto leave;
465         }
466       if (lnr > 1 && !strcmp (fields[0], "pub"))
467         {
468           /* More than one public key.  */
469           err = gpg_error (GPG_ERR_TOO_MANY);
470           goto leave;
471         }
472       if (!strcmp (fields[0], "sub") || !strcmp (fields[0], "ssb"))
473         break; /* We can stop parsing here.  */
474
475       if (!strcmp (fields[0], "fpr") && nfields > 9 && !ctx->fpr)
476         {
477           ctx->fpr = xtrystrdup (fields[9]);
478           if (!ctx->fpr)
479             {
480               err = gpg_error_from_syserror ();
481               goto leave;
482             }
483         }
484       else if (!strcmp (fields[0], "uid") && nfields > 9)
485         {
486           /* Fixme: Unescape fields[9] */
487           xfree (mbox);
488           mbox = mailbox_from_userid (fields[9]);
489           if (mbox && !append_to_strlist_try (&ctx->mboxes, mbox))
490             {
491               err = gpg_error_from_syserror ();
492               goto leave;
493             }
494         }
495     }
496   if (len < 0 || es_ferror (listing))
497     log_error ("error reading memory stream\n");
498
499  leave:
500   xfree (mbox);
501   xfree (fields);
502   es_free (line);
503   xfree (argv);
504   es_fclose (listing);
505   return err;
506 }
507
508
509 /* Take the key in KEYFILE and write it to OUTFILE in binary encoding.
510  * If ADDRSPEC is given only matching user IDs are included in the
511  * output.  */
512 static gpg_error_t
513 copy_key_as_binary (const char *keyfile, const char *outfile,
514                     const char *addrspec)
515 {
516   gpg_error_t err;
517   ccparray_t ccp;
518   const char **argv;
519   char *filterexp = NULL;
520
521   if (addrspec)
522     {
523       filterexp = es_bsprintf ("keep-uid=mbox = %s", addrspec);
524       if (!filterexp)
525         {
526           err = gpg_error_from_syserror ();
527           log_error ("error allocating memory buffer: %s\n",
528                      gpg_strerror (err));
529           goto leave;
530         }
531     }
532
533   ccparray_init (&ccp, 0);
534
535   ccparray_put (&ccp, "--no-options");
536   if (!opt.verbose)
537     ccparray_put (&ccp, "--quiet");
538   else if (opt.verbose > 1)
539     ccparray_put (&ccp, "--verbose");
540   ccparray_put (&ccp, "--batch");
541   ccparray_put (&ccp, "--yes");
542   ccparray_put (&ccp, "--always-trust");
543   ccparray_put (&ccp, "--no-keyring");
544   ccparray_put (&ccp, "--output");
545   ccparray_put (&ccp, outfile);
546   ccparray_put (&ccp, "--import-options=import-export");
547   if (filterexp)
548     {
549       ccparray_put (&ccp, "--import-filter");
550       ccparray_put (&ccp, filterexp);
551     }
552   ccparray_put (&ccp, "--import");
553   ccparray_put (&ccp, "--");
554   ccparray_put (&ccp, keyfile);
555
556   ccparray_put (&ccp, NULL);
557   argv = ccparray_get (&ccp, NULL);
558   if (!argv)
559     {
560       err = gpg_error_from_syserror ();
561       goto leave;
562     }
563   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
564                                 NULL, NULL, NULL, NULL);
565   if (err)
566     {
567       log_error ("%s failed: %s\n", __func__, gpg_strerror (err));
568       goto leave;
569     }
570
571  leave:
572   xfree (filterexp);
573   xfree (argv);
574   return err;
575 }
576
577
578 /* Take the key in KEYFILE and write it to DANEFILE using the DANE
579  * output format. */
580 static gpg_error_t
581 copy_key_as_dane (const char *keyfile, const char *danefile)
582 {
583   gpg_error_t err;
584   ccparray_t ccp;
585   const char **argv;
586
587   ccparray_init (&ccp, 0);
588
589   ccparray_put (&ccp, "--no-options");
590   if (!opt.verbose)
591     ccparray_put (&ccp, "--quiet");
592   else if (opt.verbose > 1)
593     ccparray_put (&ccp, "--verbose");
594   ccparray_put (&ccp, "--batch");
595   ccparray_put (&ccp, "--yes");
596   ccparray_put (&ccp, "--always-trust");
597   ccparray_put (&ccp, "--no-keyring");
598   ccparray_put (&ccp, "--output");
599   ccparray_put (&ccp, danefile);
600   ccparray_put (&ccp, "--export-options=export-dane");
601   ccparray_put (&ccp, "--import-options=import-export");
602   ccparray_put (&ccp, "--import");
603   ccparray_put (&ccp, "--");
604   ccparray_put (&ccp, keyfile);
605
606   ccparray_put (&ccp, NULL);
607   argv = ccparray_get (&ccp, NULL);
608   if (!argv)
609     {
610       err = gpg_error_from_syserror ();
611       goto leave;
612     }
613   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
614                                 NULL, NULL, NULL, NULL);
615   if (err)
616     {
617       log_error ("%s failed: %s\n", __func__, gpg_strerror (err));
618       goto leave;
619     }
620
621  leave:
622   xfree (argv);
623   return err;
624 }
625
626
627 static void
628 encrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
629 {
630   (void)opaque;
631
632   if (opt.debug)
633     log_debug ("%s: %s\n", keyword, args);
634 }
635
636
637 /* Encrypt the INPUT stream to a new stream which is stored at success
638  * at R_OUTPUT.  Encryption is done for the key in file KEYFIL.  */
639 static gpg_error_t
640 encrypt_stream (estream_t *r_output, estream_t input, const char *keyfile)
641 {
642   gpg_error_t err;
643   ccparray_t ccp;
644   const char **argv;
645   estream_t output;
646
647   *r_output = NULL;
648
649   output = es_fopenmem (0, "w+b");
650   if (!output)
651     {
652       err = gpg_error_from_syserror ();
653       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
654       return err;
655     }
656
657   ccparray_init (&ccp, 0);
658
659   ccparray_put (&ccp, "--no-options");
660   if (!opt.verbose)
661     ccparray_put (&ccp, "--quiet");
662   else if (opt.verbose > 1)
663     ccparray_put (&ccp, "--verbose");
664   ccparray_put (&ccp, "--batch");
665   ccparray_put (&ccp, "--status-fd=2");
666   ccparray_put (&ccp, "--always-trust");
667   ccparray_put (&ccp, "--no-keyring");
668   ccparray_put (&ccp, "--armor");
669   ccparray_put (&ccp, "--recipient-file");
670   ccparray_put (&ccp, keyfile);
671   ccparray_put (&ccp, "--encrypt");
672   ccparray_put (&ccp, "--");
673
674   ccparray_put (&ccp, NULL);
675   argv = ccparray_get (&ccp, NULL);
676   if (!argv)
677     {
678       err = gpg_error_from_syserror ();
679       goto leave;
680     }
681   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
682                                 NULL, output,
683                                 encrypt_stream_status_cb, NULL);
684   if (err)
685     {
686       log_error ("encryption failed: %s\n", gpg_strerror (err));
687       goto leave;
688     }
689
690   es_rewind (output);
691   *r_output = output;
692   output = NULL;
693
694  leave:
695   es_fclose (output);
696   xfree (argv);
697   return err;
698 }
699
700
701 /* Get the submission address for address MBOX.  Caller must free the
702  * value.  If no address can be found NULL is returned.  */
703 static char *
704 get_submission_address (const char *mbox)
705 {
706   gpg_error_t err;
707   const char *domain;
708   char *fname, *line, *p;
709   size_t n;
710   estream_t fp;
711
712   domain = strchr (mbox, '@');
713   if (!domain)
714     return NULL;
715   domain++;
716
717   fname = make_filename_try (opt.directory, domain, "submission-address", NULL);
718   if (!fname)
719     {
720       err = gpg_error_from_syserror ();
721       log_error ("make_filename failed in %s: %s\n",
722                  __func__, gpg_strerror (err));
723       return NULL;
724     }
725
726   fp = es_fopen (fname, "r");
727   if (!fp)
728     {
729       err = gpg_error_from_syserror ();
730       if (gpg_err_code (err) == GPG_ERR_ENOENT)
731         log_info ("Note: no specific submission address configured"
732                   " for domain '%s'\n", domain);
733       else
734         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
735       xfree (fname);
736       return NULL;
737     }
738
739   line = NULL;
740   n = 0;
741   if (es_getline (&line, &n, fp) < 0)
742     {
743       err = gpg_error_from_syserror ();
744       log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
745       xfree (line);
746       es_fclose (fp);
747       xfree (fname);
748       return NULL;
749     }
750   es_fclose (fp);
751   xfree (fname);
752
753   p = strchr (line, '\n');
754   if (p)
755     *p = 0;
756   trim_spaces (line);
757   if (!is_valid_mailbox (line))
758     {
759       log_error ("invalid submission address for domain '%s' detected\n",
760                  domain);
761       xfree (line);
762       return NULL;
763     }
764
765   return line;
766 }
767
768
769 /* Get the policy flags for address MBOX and store them in POLICY.  */
770 static gpg_error_t
771 get_policy_flags (policy_flags_t policy, const char *mbox)
772 {
773   gpg_error_t err;
774   const char *domain;
775   char *fname;
776   estream_t fp;
777
778   memset (policy, 0, sizeof *policy);
779
780   domain = strchr (mbox, '@');
781   if (!domain)
782     return gpg_error (GPG_ERR_INV_USER_ID);
783   domain++;
784
785   fname = make_filename_try (opt.directory, domain, "policy", NULL);
786   if (!fname)
787     {
788       err = gpg_error_from_syserror ();
789       log_error ("make_filename failed in %s: %s\n",
790                  __func__, gpg_strerror (err));
791       return err;
792     }
793
794   fp = es_fopen (fname, "r");
795   if (!fp)
796     {
797       err = gpg_error_from_syserror ();
798       if (gpg_err_code (err) == GPG_ERR_ENOENT)
799         err = 0;
800       else
801         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
802       xfree (fname);
803       return err;
804     }
805
806   err = wks_parse_policy (policy, fp, 0);
807   es_fclose (fp);
808   xfree (fname);
809   return err;
810 }
811
812
813 /* We store the key under the name of the nonce we will then send to
814  * the user.  On success the nonce is stored at R_NONCE and the file
815  * name at R_FNAME.  */
816 static gpg_error_t
817 store_key_as_pending (const char *dir, estream_t key,
818                       char **r_nonce, char **r_fname)
819 {
820   gpg_error_t err;
821   char *dname = NULL;
822   char *fname = NULL;
823   char *nonce = NULL;
824   estream_t outfp = NULL;
825   char buffer[1024];
826   size_t nbytes, nwritten;
827
828   *r_nonce = NULL;
829   *r_fname = NULL;
830
831   dname = make_filename_try (dir, "pending", NULL);
832   if (!dname)
833     {
834       err = gpg_error_from_syserror ();
835       goto leave;
836     }
837
838   /* Create the nonce.  We use 20 bytes so that we don't waste a
839    * character in our zBase-32 encoding.  Using the gcrypt's nonce
840    * function is faster than using the strong random function; this is
841    * Good Enough for our purpose.  */
842   log_assert (sizeof buffer > 20);
843   gcry_create_nonce (buffer, 20);
844   nonce = zb32_encode (buffer, 8 * 20);
845   memset (buffer, 0, 20);  /* Not actually needed but it does not harm. */
846   if (!nonce)
847     {
848       err = gpg_error_from_syserror ();
849       goto leave;
850     }
851
852   fname = strconcat (dname, "/", nonce, NULL);
853   if (!fname)
854     {
855       err = gpg_error_from_syserror ();
856       goto leave;
857     }
858
859   /* With 128 bits of random we can expect that no other file exists
860    * under this name.  We use "x" to detect internal errors.  */
861   outfp = es_fopen (fname, "wbx,mode=-rw");
862   if (!outfp)
863     {
864       err = gpg_error_from_syserror ();
865       log_error ("error creating '%s': %s\n", fname, gpg_strerror (err));
866       goto leave;
867     }
868   es_rewind (key);
869   for (;;)
870     {
871       if (es_read (key, buffer, sizeof buffer, &nbytes))
872         {
873           err = gpg_error_from_syserror ();
874           log_error ("error reading '%s': %s\n",
875                      es_fname_get (key), gpg_strerror (err));
876           break;
877         }
878
879       if (!nbytes)
880         {
881           err = 0;
882           goto leave; /* Ready.  */
883         }
884       if (es_write (outfp, buffer, nbytes, &nwritten))
885         {
886           err = gpg_error_from_syserror ();
887           log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
888           goto leave;
889         }
890       else if (nwritten != nbytes)
891         {
892           err = gpg_error (GPG_ERR_EIO);
893           log_error ("error writing '%s': %s\n", fname, "short write");
894           goto leave;
895         }
896     }
897
898  leave:
899   if (err)
900     {
901       es_fclose (outfp);
902       gnupg_remove (fname);
903     }
904   else if (es_fclose (outfp))
905     {
906       err = gpg_error_from_syserror ();
907       log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
908     }
909
910   if (!err)
911     {
912       *r_nonce = nonce;
913       *r_fname = fname;
914     }
915   else
916     {
917       xfree (nonce);
918       xfree (fname);
919     }
920   xfree (dname);
921   return err;
922 }
923
924
925 /* Send a confirmation request.  DIR is the directory used for the
926  * address MBOX.  NONCE is the nonce we want to see in the response to
927  * this mail.  FNAME the name of the file with the key.  */
928 static gpg_error_t
929 send_confirmation_request (server_ctx_t ctx,
930                            const char *mbox, const char *nonce,
931                            const char *keyfile)
932 {
933   gpg_error_t err;
934   estream_t body = NULL;
935   estream_t bodyenc = NULL;
936   mime_maker_t mime = NULL;
937   char *from_buffer = NULL;
938   const char *from;
939   strlist_t sl;
940
941   from = from_buffer = get_submission_address (mbox);
942   if (!from)
943     {
944       from = opt.default_from;
945       if (!from)
946         {
947           log_error ("no sender address found for '%s'\n", mbox);
948           err = gpg_error (GPG_ERR_CONFIGURATION);
949           goto leave;
950         }
951       log_info ("Note: using default sender address '%s'\n", from);
952     }
953
954   body = es_fopenmem (0, "w+b");
955   if (!body)
956     {
957       err = gpg_error_from_syserror ();
958       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
959       goto leave;
960     }
961   /* It is fine to use 8 bit encoding because that is encrypted and
962    * only our client will see it.  */
963   es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
964             "Content-Transfer-Encoding: 8bit\n"
965             "\n",
966             body);
967
968   es_fprintf (body, ("type: confirmation-request\n"
969                      "sender: %s\n"
970                      "address: %s\n"
971                      "fingerprint: %s\n"
972                      "nonce: %s\n"),
973               from,
974               mbox,
975               ctx->fpr,
976               nonce);
977
978   es_rewind (body);
979   err = encrypt_stream (&bodyenc, body, keyfile);
980   if (err)
981     goto leave;
982   es_fclose (body);
983   body = NULL;
984
985
986   err = mime_maker_new (&mime, NULL);
987   if (err)
988     goto leave;
989   err = mime_maker_add_header (mime, "From", from);
990   if (err)
991     goto leave;
992   err = mime_maker_add_header (mime, "To", mbox);
993   if (err)
994     goto leave;
995   err = mime_maker_add_header (mime, "Subject", "Confirm your key publication");
996   if (err)
997     goto leave;
998   for (sl = opt.extra_headers; sl; sl = sl->next)
999     {
1000       err = mime_maker_add_header (mime, sl->d, NULL);
1001       if (err)
1002         goto leave;
1003     }
1004
1005   err = mime_maker_add_header (mime, "Content-Type",
1006                                "multipart/encrypted; "
1007                                "protocol=\"application/pgp-encrypted\"");
1008   if (err)
1009     goto leave;
1010   err = mime_maker_add_container (mime, "multipart/encrypted");
1011   if (err)
1012     goto leave;
1013
1014   err = mime_maker_add_header (mime, "Content-Type",
1015                                "application/pgp-encrypted");
1016   if (err)
1017     goto leave;
1018   err = mime_maker_add_body (mime, "Version: 1\n");
1019   if (err)
1020     goto leave;
1021   err = mime_maker_add_header (mime, "Content-Type",
1022                                "application/octet-stream");
1023   if (err)
1024     goto leave;
1025
1026   err = mime_maker_add_stream (mime, &bodyenc);
1027   if (err)
1028     goto leave;
1029
1030   err = wks_send_mime (mime);
1031
1032  leave:
1033   mime_maker_release (mime);
1034   es_fclose (bodyenc);
1035   es_fclose (body);
1036   xfree (from_buffer);
1037   return err;
1038 }
1039
1040
1041 /* Store the key given by KEY into the pending directory and send a
1042  * confirmation requests.  */
1043 static gpg_error_t
1044 process_new_key (server_ctx_t ctx, estream_t key)
1045 {
1046   gpg_error_t err;
1047   strlist_t sl;
1048   const char *s;
1049   char *dname = NULL;
1050   char *nonce = NULL;
1051   char *fname = NULL;
1052   struct policy_flags_s policybuf;
1053
1054   /* First figure out the user id from the key.  */
1055   err = list_key (ctx, key);
1056   if (err)
1057     goto leave;
1058   if (!ctx->fpr)
1059     {
1060       log_error ("error parsing key (no fingerprint)\n");
1061       err = gpg_error (GPG_ERR_NO_PUBKEY);
1062       goto leave;
1063     }
1064   log_info ("fingerprint: %s\n", ctx->fpr);
1065   for (sl = ctx->mboxes; sl; sl = sl->next)
1066     {
1067       log_info ("  addr-spec: %s\n", sl->d);
1068     }
1069
1070   /* Walk over all user ids and send confirmation requests for those
1071    * we support.  */
1072   for (sl = ctx->mboxes; sl; sl = sl->next)
1073     {
1074       s = strchr (sl->d, '@');
1075       log_assert (s && s[1]);
1076       xfree (dname);
1077       dname = make_filename_try (opt.directory, s+1, NULL);
1078       if (!dname)
1079         {
1080           err = gpg_error_from_syserror ();
1081           goto leave;
1082         }
1083
1084       if (access (dname, W_OK))
1085         {
1086           log_info ("skipping address '%s': Domain not configured\n", sl->d);
1087           continue;
1088         }
1089       if (get_policy_flags (&policybuf, sl->d))
1090         {
1091           log_info ("skipping address '%s': Bad policy flags\n", sl->d);
1092           continue;
1093         }
1094
1095       if (policybuf.auth_submit)
1096         {
1097           /* Bypass the confirmation stuff and publish the the key as is.  */
1098           log_info ("publishing address '%s'\n", sl->d);
1099           /* FIXME: We need to make sure that we do this only for the
1100            * address in the mail.  */
1101           log_debug ("auth-submit not yet working!\n");
1102         }
1103       else
1104         {
1105           log_info ("storing address '%s'\n", sl->d);
1106
1107           xfree (nonce);
1108           xfree (fname);
1109           err = store_key_as_pending (dname, key, &nonce, &fname);
1110           if (err)
1111             goto leave;
1112
1113           err = send_confirmation_request (ctx, sl->d, nonce, fname);
1114           if (err)
1115             goto leave;
1116         }
1117     }
1118
1119  leave:
1120   if (nonce)
1121     wipememory (nonce, strlen (nonce));
1122   xfree (nonce);
1123   xfree (fname);
1124   xfree (dname);
1125   return err;
1126 }
1127
1128
1129 \f
1130 /* Send a message to tell the user at MBOX that their key has been
1131  * published.  FNAME the name of the file with the key.  */
1132 static gpg_error_t
1133 send_congratulation_message (const char *mbox, const char *keyfile)
1134 {
1135   gpg_error_t err;
1136   estream_t body = NULL;
1137   estream_t bodyenc = NULL;
1138   mime_maker_t mime = NULL;
1139   char *from_buffer = NULL;
1140   const char *from;
1141   strlist_t sl;
1142
1143   from = from_buffer = get_submission_address (mbox);
1144   if (!from)
1145     {
1146       from = opt.default_from;
1147       if (!from)
1148         {
1149           log_error ("no sender address found for '%s'\n", mbox);
1150           err = gpg_error (GPG_ERR_CONFIGURATION);
1151           goto leave;
1152         }
1153       log_info ("Note: using default sender address '%s'\n", from);
1154     }
1155
1156   body = es_fopenmem (0, "w+b");
1157   if (!body)
1158     {
1159       err = gpg_error_from_syserror ();
1160       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1161       goto leave;
1162     }
1163   /* It is fine to use 8 bit encoding because that is encrypted and
1164    * only our client will see it.  */
1165   es_fputs ("Content-Type: text/plain; charset=utf-8\n"
1166             "Content-Transfer-Encoding: 8bit\n"
1167             "\n",
1168             body);
1169
1170   es_fprintf (body,
1171               "Hello!\n\n"
1172               "The key for your address '%s' has been published\n"
1173               "and can now be retrieved from the Web Key Directory.\n"
1174               "\n"
1175               "For more information on this system see:\n"
1176               "\n"
1177               "  https://gnupg.org/faq/wkd.html\n"
1178               "\n"
1179               "Best regards\n"
1180               "\n"
1181               "  Gnu Key Publisher\n\n\n"
1182               "-- \n"
1183               "The GnuPG Project welcomes donations: %s\n",
1184               mbox, "https://gnupg.org/donate");
1185
1186   es_rewind (body);
1187   err = encrypt_stream (&bodyenc, body, keyfile);
1188   if (err)
1189     goto leave;
1190   es_fclose (body);
1191   body = NULL;
1192
1193   err = mime_maker_new (&mime, NULL);
1194   if (err)
1195     goto leave;
1196   err = mime_maker_add_header (mime, "From", from);
1197   if (err)
1198     goto leave;
1199   err = mime_maker_add_header (mime, "To", mbox);
1200   if (err)
1201     goto leave;
1202   err = mime_maker_add_header (mime, "Subject", "Your key has been published");
1203   if (err)
1204     goto leave;
1205   for (sl = opt.extra_headers; sl; sl = sl->next)
1206     {
1207       err = mime_maker_add_header (mime, sl->d, NULL);
1208       if (err)
1209         goto leave;
1210     }
1211
1212   err = mime_maker_add_header (mime, "Content-Type",
1213                                "multipart/encrypted; "
1214                                "protocol=\"application/pgp-encrypted\"");
1215   if (err)
1216     goto leave;
1217   err = mime_maker_add_container (mime, "multipart/encrypted");
1218   if (err)
1219     goto leave;
1220
1221   err = mime_maker_add_header (mime, "Content-Type",
1222                                "application/pgp-encrypted");
1223   if (err)
1224     goto leave;
1225   err = mime_maker_add_body (mime, "Version: 1\n");
1226   if (err)
1227     goto leave;
1228   err = mime_maker_add_header (mime, "Content-Type",
1229                                "application/octet-stream");
1230   if (err)
1231     goto leave;
1232
1233   err = mime_maker_add_stream (mime, &bodyenc);
1234   if (err)
1235     goto leave;
1236
1237   err = wks_send_mime (mime);
1238
1239  leave:
1240   mime_maker_release (mime);
1241   es_fclose (bodyenc);
1242   es_fclose (body);
1243   xfree (from_buffer);
1244   return err;
1245 }
1246
1247
1248 /* Check that we have send a request with NONCE and publish the key.  */
1249 static gpg_error_t
1250 check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
1251 {
1252   gpg_error_t err;
1253   char *fname = NULL;
1254   char *fnewname = NULL;
1255   estream_t key = NULL;
1256   char *hash = NULL;
1257   const char *domain;
1258   const char *s;
1259   strlist_t sl;
1260   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1261
1262   /* FIXME: There is a bug in name-value.c which adds white space for
1263    * the last pair and thus we strip the nonce here until this has
1264    * been fixed.  */
1265   char *nonce2 = xstrdup (nonce);
1266   trim_trailing_spaces (nonce2);
1267   nonce = nonce2;
1268
1269
1270   domain = strchr (address, '@');
1271   log_assert (domain && domain[1]);
1272   domain++;
1273   fname = make_filename_try (opt.directory, domain, "pending", nonce, NULL);
1274   if (!fname)
1275     {
1276       err = gpg_error_from_syserror ();
1277       goto leave;
1278     }
1279
1280   /* Try to open the file with the key.  */
1281   key = es_fopen (fname, "rb");
1282   if (!key)
1283     {
1284       err = gpg_error_from_syserror ();
1285       if (gpg_err_code (err) == GPG_ERR_ENOENT)
1286         {
1287           log_info ("no pending request for '%s'\n", address);
1288           err = gpg_error (GPG_ERR_NOT_FOUND);
1289         }
1290       else
1291         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
1292       goto leave;
1293     }
1294
1295   /* We need to get the fingerprint from the key.  */
1296   err = list_key (ctx, key);
1297   if (err)
1298     goto leave;
1299   if (!ctx->fpr)
1300     {
1301       log_error ("error parsing key (no fingerprint)\n");
1302       err = gpg_error (GPG_ERR_NO_PUBKEY);
1303       goto leave;
1304     }
1305   log_info ("fingerprint: %s\n", ctx->fpr);
1306   for (sl = ctx->mboxes; sl; sl = sl->next)
1307     log_info ("  addr-spec: %s\n", sl->d);
1308
1309   /* Check that the key has 'address' as a user id.  We use
1310    * case-insensitive matching because the client is expected to
1311    * return the address verbatim.  */
1312   for (sl = ctx->mboxes; sl; sl = sl->next)
1313     if (!strcmp (sl->d, address))
1314       break;
1315   if (!sl)
1316     {
1317       log_error ("error publishing key: '%s' is not a user ID of %s\n",
1318                  address, ctx->fpr);
1319       err = gpg_error (GPG_ERR_NO_PUBKEY);
1320       goto leave;
1321     }
1322
1323
1324   /* Hash user ID and create filename.  */
1325   s = strchr (address, '@');
1326   log_assert (s);
1327   gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
1328   hash = zb32_encode (shaxbuf, 8*20);
1329   if (!hash)
1330     {
1331       err = gpg_error_from_syserror ();
1332       goto leave;
1333     }
1334
1335   fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1336   if (!fnewname)
1337     {
1338       err = gpg_error_from_syserror ();
1339       goto leave;
1340     }
1341
1342   /* Publish.  */
1343   err = copy_key_as_binary (fname, fnewname, address);
1344   if (err)
1345     {
1346       err = gpg_error_from_syserror ();
1347       log_error ("copying '%s' to '%s' failed: %s\n",
1348                  fname, fnewname, gpg_strerror (err));
1349       goto leave;
1350     }
1351
1352   log_info ("key %s published for '%s'\n", ctx->fpr, address);
1353   send_congratulation_message (address, fnewname);
1354
1355   /* Try to publish as DANE record if the DANE directory exists.  */
1356   xfree (fname);
1357   fname = fnewname;
1358   fnewname = make_filename_try (opt.directory, domain, "dane", NULL);
1359   if (!fnewname)
1360     {
1361       err = gpg_error_from_syserror ();
1362       goto leave;
1363     }
1364   if (!access (fnewname, W_OK))
1365     {
1366       /* Yes, we have a dane directory.  */
1367       s = strchr (address, '@');
1368       log_assert (s);
1369       gcry_md_hash_buffer (GCRY_MD_SHA256, shaxbuf, address, s - address);
1370       xfree (hash);
1371       hash = bin2hex (shaxbuf, 28, NULL);
1372       if (!hash)
1373         {
1374           err = gpg_error_from_syserror ();
1375           goto leave;
1376         }
1377       xfree (fnewname);
1378       fnewname = make_filename_try (opt.directory, domain, "dane", hash, NULL);
1379       if (!fnewname)
1380         {
1381           err = gpg_error_from_syserror ();
1382           goto leave;
1383         }
1384       err = copy_key_as_dane (fname, fnewname);
1385       if (err)
1386         goto leave;
1387       log_info ("key %s published for '%s' (DANE record)\n", ctx->fpr, address);
1388     }
1389
1390  leave:
1391   es_fclose (key);
1392   xfree (hash);
1393   xfree (fnewname);
1394   xfree (fname);
1395   xfree (nonce2);
1396   return err;
1397 }
1398
1399
1400 /* Process a confirmation response in MSG.  */
1401 static gpg_error_t
1402 process_confirmation_response (server_ctx_t ctx, estream_t msg)
1403 {
1404   gpg_error_t err;
1405   nvc_t nvc;
1406   nve_t item;
1407   const char *value, *sender, *address, *nonce;
1408
1409   err = nvc_parse (&nvc, NULL, msg);
1410   if (err)
1411     {
1412       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1413       goto leave;
1414     }
1415
1416   if (opt.debug)
1417     {
1418       log_debug ("response follows:\n");
1419       nvc_write (nvc, log_get_stream ());
1420     }
1421
1422   /* Check that this is a confirmation response.  */
1423   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1424         && !strcmp (value, "confirmation-response")))
1425     {
1426       if (item && value)
1427         log_error ("received unexpected wks message '%s'\n", value);
1428       else
1429         log_error ("received invalid wks message: %s\n", "'type' missing");
1430       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1431       goto leave;
1432     }
1433
1434   /* Get the sender.  */
1435   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1436         && is_valid_mailbox (value)))
1437     {
1438       log_error ("received invalid wks message: %s\n",
1439                  "'sender' missing or invalid");
1440       err = gpg_error (GPG_ERR_INV_DATA);
1441       goto leave;
1442     }
1443   sender = value;
1444   (void)sender;
1445   /* FIXME: Do we really need the sender?.  */
1446
1447   /* Get the address.  */
1448   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1449         && is_valid_mailbox (value)))
1450     {
1451       log_error ("received invalid wks message: %s\n",
1452                  "'address' missing or invalid");
1453       err = gpg_error (GPG_ERR_INV_DATA);
1454       goto leave;
1455     }
1456   address = value;
1457
1458   /* Get the nonce.  */
1459   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1460         && strlen (value) > 16))
1461     {
1462       log_error ("received invalid wks message: %s\n",
1463                  "'nonce' missing or too short");
1464       err = gpg_error (GPG_ERR_INV_DATA);
1465       goto leave;
1466     }
1467   nonce = value;
1468
1469   err = check_and_publish (ctx, address, nonce);
1470
1471
1472  leave:
1473   nvc_release (nvc);
1474   return err;
1475 }
1476
1477
1478 \f
1479 /* Called from the MIME receiver to process the plain text data in MSG .  */
1480 static gpg_error_t
1481 command_receive_cb (void *opaque, const char *mediatype, estream_t msg)
1482 {
1483   gpg_error_t err;
1484   struct server_ctx_s ctx;
1485
1486   memset (&ctx, 0, sizeof ctx);
1487
1488   (void)opaque;
1489
1490   if (!strcmp (mediatype, "application/pgp-keys"))
1491     err = process_new_key (&ctx, msg);
1492   else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1493     err = process_confirmation_response (&ctx, msg);
1494   else
1495     {
1496       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1497       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1498     }
1499
1500   xfree (ctx.fpr);
1501   free_strlist (ctx.mboxes);
1502
1503   return err;
1504 }
1505
1506
1507 \f
1508 /* Return a list of all configured domains.  ECh list element is the
1509  * top directory for for the domain.  To figure out the actual domain
1510  * name strrchr(name, '/') can be used.  */
1511 static gpg_error_t
1512 get_domain_list (strlist_t *r_list)
1513 {
1514   gpg_error_t err;
1515   DIR *dir = NULL;
1516   char *fname = NULL;
1517   struct dirent *dentry;
1518   struct stat sb;
1519   strlist_t list = NULL;
1520
1521   *r_list = NULL;
1522
1523   dir = opendir (opt.directory);
1524   if (!dir)
1525     {
1526       err = gpg_error_from_syserror ();
1527       goto leave;
1528     }
1529
1530   while ((dentry = readdir (dir)))
1531     {
1532       if (*dentry->d_name == '.')
1533         continue;
1534       if (!strchr (dentry->d_name, '.'))
1535         continue; /* No dot - can't be a domain subdir.  */
1536
1537       xfree (fname);
1538       fname = make_filename_try (opt.directory, dentry->d_name, NULL);
1539       if (!fname)
1540         {
1541           err = gpg_error_from_syserror ();
1542           log_error ("make_filename failed in %s: %s\n",
1543                      __func__, gpg_strerror (err));
1544           goto leave;
1545         }
1546
1547       if (stat (fname, &sb))
1548         {
1549           err = gpg_error_from_syserror ();
1550           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1551           continue;
1552         }
1553       if (!S_ISDIR(sb.st_mode))
1554         continue;
1555
1556       if (!add_to_strlist_try (&list, fname))
1557         {
1558           err = gpg_error_from_syserror ();
1559           log_error ("add_to_strlist failed in %s: %s\n",
1560                      __func__, gpg_strerror (err));
1561           goto leave;
1562         }
1563     }
1564   err = 0;
1565   *r_list = list;
1566   list = NULL;
1567
1568  leave:
1569   free_strlist (list);
1570   if (dir)
1571     closedir (dir);
1572   xfree (fname);
1573   return err;
1574 }
1575
1576
1577 \f
1578 static gpg_error_t
1579 expire_one_domain (const char *top_dirname, const char *domain)
1580 {
1581   gpg_error_t err;
1582   char *dirname;
1583   char *fname = NULL;
1584   DIR *dir = NULL;
1585   struct dirent *dentry;
1586   struct stat sb;
1587   time_t now = gnupg_get_time ();
1588
1589   dirname = make_filename_try (top_dirname, "pending", NULL);
1590   if (!dirname)
1591     {
1592       err = gpg_error_from_syserror ();
1593       log_error ("make_filename failed in %s: %s\n",
1594                  __func__, gpg_strerror (err));
1595       goto leave;
1596     }
1597
1598   dir = opendir (dirname);
1599   if (!dir)
1600     {
1601       err = gpg_error_from_syserror ();
1602       log_error (("can't access directory '%s': %s\n"),
1603                  dirname, gpg_strerror (err));
1604       goto leave;
1605     }
1606
1607   while ((dentry = readdir (dir)))
1608     {
1609       if (*dentry->d_name == '.')
1610         continue;
1611       xfree (fname);
1612       fname = make_filename_try (dirname, dentry->d_name, NULL);
1613       if (!fname)
1614         {
1615           err = gpg_error_from_syserror ();
1616           log_error ("make_filename failed in %s: %s\n",
1617                      __func__, gpg_strerror (err));
1618           goto leave;
1619         }
1620       if (strlen (dentry->d_name) != 32)
1621         {
1622           log_info ("garbage file '%s' ignored\n", fname);
1623           continue;
1624         }
1625       if (stat (fname, &sb))
1626         {
1627           err = gpg_error_from_syserror ();
1628           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1629           continue;
1630         }
1631       if (S_ISDIR(sb.st_mode))
1632         {
1633           log_info ("garbage directory '%s' ignored\n", fname);
1634           continue;
1635         }
1636       if (sb.st_mtime + PENDING_TTL < now)
1637         {
1638           if (opt.verbose)
1639             log_info ("domain %s: removing pending key '%s'\n",
1640                       domain, dentry->d_name);
1641           if (remove (fname))
1642             {
1643               err = gpg_error_from_syserror ();
1644               /* In case the file has just been renamed or another
1645                * processes is cleaning up, we don't print a diagnostic
1646                * for ENOENT.  */
1647               if (gpg_err_code (err) != GPG_ERR_ENOENT)
1648                 log_error ("error removing '%s': %s\n",
1649                            fname, gpg_strerror (err));
1650             }
1651         }
1652     }
1653   err = 0;
1654
1655  leave:
1656   if (dir)
1657     closedir (dir);
1658   xfree (dirname);
1659   xfree (fname);
1660   return err;
1661
1662 }
1663
1664
1665 /* Scan spool directories and expire too old pending keys.  */
1666 static gpg_error_t
1667 expire_pending_confirmations (strlist_t domaindirs)
1668 {
1669   gpg_error_t err = 0;
1670   strlist_t sl;
1671   const char *domain;
1672
1673   for (sl = domaindirs; sl; sl = sl->next)
1674     {
1675       domain = strrchr (sl->d, '/');
1676       log_assert (domain);
1677       domain++;
1678
1679       expire_one_domain (sl->d, domain);
1680     }
1681
1682   return err;
1683 }
1684
1685
1686 /* List all configured domains.  */
1687 static gpg_error_t
1688 command_list_domains (void)
1689 {
1690   static struct {
1691     const char *name;
1692     const char *perm;
1693   } requireddirs[] = {
1694     { "pending", "-rwx" },
1695     { "hu",      "-rwxr-xr-x" }
1696   };
1697
1698   gpg_error_t err;
1699   strlist_t domaindirs;
1700   strlist_t sl;
1701   const char *domain;
1702   char *fname = NULL;
1703   int i;
1704   estream_t fp;
1705
1706   err = get_domain_list (&domaindirs);
1707   if (err)
1708     {
1709       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1710       return err;
1711     }
1712
1713   for (sl = domaindirs; sl; sl = sl->next)
1714     {
1715       domain = strrchr (sl->d, '/');
1716       log_assert (domain);
1717       domain++;
1718       es_printf ("%s\n", domain);
1719
1720       /* Check that the required directories are there.  */
1721       for (i=0; i < DIM (requireddirs); i++)
1722         {
1723           xfree (fname);
1724           fname = make_filename_try (sl->d, requireddirs[i].name, NULL);
1725           if (!fname)
1726             {
1727               err = gpg_error_from_syserror ();
1728               goto leave;
1729             }
1730           if (access (fname, W_OK))
1731             {
1732               err = gpg_error_from_syserror ();
1733               if (gpg_err_code (err) == GPG_ERR_ENOENT)
1734                 {
1735                   if (gnupg_mkdir (fname, requireddirs[i].perm))
1736                     {
1737                       err = gpg_error_from_syserror ();
1738                       log_error ("domain %s: error creating subdir '%s': %s\n",
1739                                  domain, requireddirs[i].name,
1740                                  gpg_strerror (err));
1741                     }
1742                   else
1743                     log_info ("domain %s: subdir '%s' created\n",
1744                               domain, requireddirs[i].name);
1745                 }
1746               else if (err)
1747                 log_error ("domain %s: problem with subdir '%s': %s\n",
1748                            domain, requireddirs[i].name, gpg_strerror (err));
1749             }
1750         }
1751
1752       /* Print a warning if the submission address is not configured.  */
1753       xfree (fname);
1754       fname = make_filename_try (sl->d, "submission-address", NULL);
1755       if (!fname)
1756         {
1757           err = gpg_error_from_syserror ();
1758           goto leave;
1759         }
1760       if (access (fname, F_OK))
1761         {
1762           err = gpg_error_from_syserror ();
1763           if (gpg_err_code (err) == GPG_ERR_ENOENT)
1764             log_error ("domain %s: submission address not configured\n",
1765                        domain);
1766           else
1767             log_error ("domain %s: problem with '%s': %s\n",
1768                        domain, fname, gpg_strerror (err));
1769         }
1770
1771       /* Check the syntax of the optional policy file.  */
1772       xfree (fname);
1773       fname = make_filename_try (sl->d, "policy", NULL);
1774       if (!fname)
1775         {
1776           err = gpg_error_from_syserror ();
1777           goto leave;
1778         }
1779       fp = es_fopen (fname, "r");
1780       if (!fp)
1781         {
1782           err = gpg_error_from_syserror ();
1783           if (gpg_err_code (err) != GPG_ERR_ENOENT)
1784             log_error ("domain %s: error in policy file: %s\n",
1785                        domain, gpg_strerror (err));
1786         }
1787       else
1788         {
1789           struct policy_flags_s policy;
1790           err = wks_parse_policy (&policy, fp, 0);
1791           es_fclose (fp);
1792           if (!err)
1793             {
1794               struct policy_flags_s empty_policy;
1795               memset (&empty_policy, 0, sizeof empty_policy);
1796               if (!memcmp (&empty_policy, &policy, sizeof policy))
1797                 log_error ("domain %s: empty policy file\n", domain);
1798             }
1799         }
1800
1801
1802     }
1803   err = 0;
1804
1805  leave:
1806   xfree (fname);
1807   free_strlist (domaindirs);
1808   return err;
1809 }
1810
1811
1812 /* Run regular maintenance jobs.  */
1813 static gpg_error_t
1814 command_cron (void)
1815 {
1816   gpg_error_t err;
1817   strlist_t domaindirs;
1818
1819   err = get_domain_list (&domaindirs);
1820   if (err)
1821     {
1822       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1823       return err;
1824     }
1825
1826   err = expire_pending_confirmations (domaindirs);
1827
1828   free_strlist (domaindirs);
1829   return err;
1830 }