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