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