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