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