scd: Use pipe to kick the loop on NetBSD.
[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   /* First figure out the user id from the key.  */
1139   xfree (ctx->fpr);
1140   free_uidinfo_list (ctx->mboxes);
1141   err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
1142   if (err)
1143     goto leave;
1144   log_assert (ctx->fpr);
1145   log_info ("fingerprint: %s\n", ctx->fpr);
1146   for (sl = ctx->mboxes; sl; sl = sl->next)
1147     {
1148       if (sl->mbox)
1149         log_info ("  addr-spec: %s\n", sl->mbox);
1150     }
1151
1152   /* Walk over all user ids and send confirmation requests for those
1153    * we support.  */
1154   for (sl = ctx->mboxes; sl; sl = sl->next)
1155     {
1156       if (!sl->mbox)
1157         continue;
1158       s = strchr (sl->mbox, '@');
1159       log_assert (s && s[1]);
1160       xfree (dname);
1161       dname = make_filename_try (opt.directory, s+1, NULL);
1162       if (!dname)
1163         {
1164           err = gpg_error_from_syserror ();
1165           goto leave;
1166         }
1167
1168       if (access (dname, W_OK))
1169         {
1170           log_info ("skipping address '%s': Domain not configured\n", sl->mbox);
1171           continue;
1172         }
1173       if (get_policy_flags (&policybuf, sl->mbox))
1174         {
1175           log_info ("skipping address '%s': Bad policy flags\n", sl->mbox);
1176           continue;
1177         }
1178
1179       if (policybuf.auth_submit)
1180         {
1181           /* Bypass the confirmation stuff and publish the key as is.  */
1182           log_info ("publishing address '%s'\n", sl->mbox);
1183           /* FIXME: We need to make sure that we do this only for the
1184            * address in the mail.  */
1185           log_debug ("auth-submit not yet working!\n");
1186         }
1187       else
1188         {
1189           log_info ("storing address '%s'\n", sl->mbox);
1190
1191           xfree (nonce);
1192           xfree (fname);
1193           err = store_key_as_pending (dname, key, &nonce, &fname);
1194           if (err)
1195             goto leave;
1196
1197           err = send_confirmation_request (ctx, sl->mbox, nonce, fname);
1198           if (err)
1199             goto leave;
1200         }
1201     }
1202
1203  leave:
1204   if (nonce)
1205     wipememory (nonce, strlen (nonce));
1206   xfree (nonce);
1207   xfree (fname);
1208   xfree (dname);
1209   return err;
1210 }
1211
1212
1213 \f
1214 /* Send a message to tell the user at MBOX that their key has been
1215  * published.  FNAME the name of the file with the key.  */
1216 static gpg_error_t
1217 send_congratulation_message (const char *mbox, const char *keyfile)
1218 {
1219   gpg_error_t err;
1220   estream_t body = NULL;
1221   estream_t bodyenc = NULL;
1222   mime_maker_t mime = NULL;
1223   char *from_buffer = NULL;
1224   const char *from;
1225   strlist_t sl;
1226
1227   from = from_buffer = get_submission_address (mbox);
1228   if (!from)
1229     {
1230       from = opt.default_from;
1231       if (!from)
1232         {
1233           log_error ("no sender address found for '%s'\n", mbox);
1234           err = gpg_error (GPG_ERR_CONFIGURATION);
1235           goto leave;
1236         }
1237       log_info ("Note: using default sender address '%s'\n", from);
1238     }
1239
1240   body = es_fopenmem (0, "w+b");
1241   if (!body)
1242     {
1243       err = gpg_error_from_syserror ();
1244       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1245       goto leave;
1246     }
1247   /* It is fine to use 8 bit encoding because that is encrypted and
1248    * only our client will see it.  */
1249   es_fputs ("Content-Type: text/plain; charset=utf-8\n"
1250             "Content-Transfer-Encoding: 8bit\n"
1251             "\n",
1252             body);
1253
1254   es_fprintf (body,
1255               "Hello!\n\n"
1256               "The key for your address '%s' has been published\n"
1257               "and can now be retrieved from the Web Key Directory.\n"
1258               "\n"
1259               "For more information on this system see:\n"
1260               "\n"
1261               "  https://gnupg.org/faq/wkd.html\n"
1262               "\n"
1263               "Best regards\n"
1264               "\n"
1265               "  Gnu Key Publisher\n\n\n"
1266               "-- \n"
1267               "The GnuPG Project welcomes donations: %s\n",
1268               mbox, "https://gnupg.org/donate");
1269
1270   es_rewind (body);
1271   err = encrypt_stream (&bodyenc, body, keyfile);
1272   if (err)
1273     goto leave;
1274   es_fclose (body);
1275   body = NULL;
1276
1277   err = mime_maker_new (&mime, NULL);
1278   if (err)
1279     goto leave;
1280   err = mime_maker_add_header (mime, "From", from);
1281   if (err)
1282     goto leave;
1283   err = mime_maker_add_header (mime, "To", mbox);
1284   if (err)
1285     goto leave;
1286   err = mime_maker_add_header (mime, "Subject", "Your key has been published");
1287   if (err)
1288     goto leave;
1289   err = mime_maker_add_header (mime, "Wks-Draft-Version",
1290                                STR2(WKS_DRAFT_VERSION));
1291   if (err)
1292     goto leave;
1293   err = mime_maker_add_header (mime, "WKS-Phase", "done");
1294   if (err)
1295     goto leave;
1296   for (sl = opt.extra_headers; sl; sl = sl->next)
1297     {
1298       err = mime_maker_add_header (mime, sl->d, NULL);
1299       if (err)
1300         goto leave;
1301     }
1302
1303   err = mime_maker_add_header (mime, "Content-Type",
1304                                "multipart/encrypted; "
1305                                "protocol=\"application/pgp-encrypted\"");
1306   if (err)
1307     goto leave;
1308   err = mime_maker_add_container (mime);
1309   if (err)
1310     goto leave;
1311
1312   err = mime_maker_add_header (mime, "Content-Type",
1313                                "application/pgp-encrypted");
1314   if (err)
1315     goto leave;
1316   err = mime_maker_add_body (mime, "Version: 1\n");
1317   if (err)
1318     goto leave;
1319   err = mime_maker_add_header (mime, "Content-Type",
1320                                "application/octet-stream");
1321   if (err)
1322     goto leave;
1323
1324   err = mime_maker_add_stream (mime, &bodyenc);
1325   if (err)
1326     goto leave;
1327
1328   err = wks_send_mime (mime);
1329
1330  leave:
1331   mime_maker_release (mime);
1332   es_fclose (bodyenc);
1333   es_fclose (body);
1334   xfree (from_buffer);
1335   return err;
1336 }
1337
1338
1339 /* Check that we have send a request with NONCE and publish the key.  */
1340 static gpg_error_t
1341 check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
1342 {
1343   gpg_error_t err;
1344   char *fname = NULL;
1345   char *fnewname = NULL;
1346   estream_t key = NULL;
1347   char *hash = NULL;
1348   const char *domain;
1349   const char *s;
1350   uidinfo_list_t sl;
1351   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1352
1353   /* FIXME: There is a bug in name-value.c which adds white space for
1354    * the last pair and thus we strip the nonce here until this has
1355    * been fixed.  */
1356   char *nonce2 = xstrdup (nonce);
1357   trim_trailing_spaces (nonce2);
1358   nonce = nonce2;
1359
1360
1361   domain = strchr (address, '@');
1362   log_assert (domain && domain[1]);
1363   domain++;
1364   fname = make_filename_try (opt.directory, domain, "pending", nonce, NULL);
1365   if (!fname)
1366     {
1367       err = gpg_error_from_syserror ();
1368       goto leave;
1369     }
1370
1371   /* Try to open the file with the key.  */
1372   key = es_fopen (fname, "rb");
1373   if (!key)
1374     {
1375       err = gpg_error_from_syserror ();
1376       if (gpg_err_code (err) == GPG_ERR_ENOENT)
1377         {
1378           log_info ("no pending request for '%s'\n", address);
1379           err = gpg_error (GPG_ERR_NOT_FOUND);
1380         }
1381       else
1382         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
1383       goto leave;
1384     }
1385
1386   /* We need to get the fingerprint from the key.  */
1387   xfree (ctx->fpr);
1388   free_uidinfo_list (ctx->mboxes);
1389   err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
1390   if (err)
1391     goto leave;
1392   log_assert (ctx->fpr);
1393   log_info ("fingerprint: %s\n", ctx->fpr);
1394   for (sl = ctx->mboxes; sl; sl = sl->next)
1395     if (sl->mbox)
1396       log_info ("  addr-spec: %s\n", sl->mbox);
1397
1398   /* Check that the key has 'address' as a user id.  We use
1399    * case-insensitive matching because the client is expected to
1400    * return the address verbatim.  */
1401   for (sl = ctx->mboxes; sl; sl = sl->next)
1402     if (sl->mbox && !strcmp (sl->mbox, address))
1403       break;
1404   if (!sl)
1405     {
1406       log_error ("error publishing key: '%s' is not a user ID of %s\n",
1407                  address, ctx->fpr);
1408       err = gpg_error (GPG_ERR_NO_PUBKEY);
1409       goto leave;
1410     }
1411
1412
1413   /* Hash user ID and create filename.  */
1414   s = strchr (address, '@');
1415   log_assert (s);
1416   gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
1417   hash = zb32_encode (shaxbuf, 8*20);
1418   if (!hash)
1419     {
1420       err = gpg_error_from_syserror ();
1421       goto leave;
1422     }
1423
1424   fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1425   if (!fnewname)
1426     {
1427       err = gpg_error_from_syserror ();
1428       goto leave;
1429     }
1430
1431   /* Publish.  */
1432   err = copy_key_as_binary (fname, fnewname, address);
1433   if (err)
1434     {
1435       err = gpg_error_from_syserror ();
1436       log_error ("copying '%s' to '%s' failed: %s\n",
1437                  fname, fnewname, gpg_strerror (err));
1438       goto leave;
1439     }
1440
1441   /* Make sure it is world readable.  */
1442   if (gnupg_chmod (fnewname, "-rwxr--r--"))
1443     log_error ("can't set permissions of '%s': %s\n",
1444                fnewname, gpg_strerror (gpg_err_code_from_syserror()));
1445
1446   log_info ("key %s published for '%s'\n", ctx->fpr, address);
1447   send_congratulation_message (address, fnewname);
1448
1449   /* Try to publish as DANE record if the DANE directory exists.  */
1450   xfree (fname);
1451   fname = fnewname;
1452   fnewname = make_filename_try (opt.directory, domain, "dane", NULL);
1453   if (!fnewname)
1454     {
1455       err = gpg_error_from_syserror ();
1456       goto leave;
1457     }
1458   if (!access (fnewname, W_OK))
1459     {
1460       /* Yes, we have a dane directory.  */
1461       s = strchr (address, '@');
1462       log_assert (s);
1463       gcry_md_hash_buffer (GCRY_MD_SHA256, shaxbuf, address, s - address);
1464       xfree (hash);
1465       hash = bin2hex (shaxbuf, 28, NULL);
1466       if (!hash)
1467         {
1468           err = gpg_error_from_syserror ();
1469           goto leave;
1470         }
1471       xfree (fnewname);
1472       fnewname = make_filename_try (opt.directory, domain, "dane", hash, NULL);
1473       if (!fnewname)
1474         {
1475           err = gpg_error_from_syserror ();
1476           goto leave;
1477         }
1478       err = copy_key_as_dane (fname, fnewname);
1479       if (err)
1480         goto leave;
1481       log_info ("key %s published for '%s' (DANE record)\n", ctx->fpr, address);
1482     }
1483
1484  leave:
1485   es_fclose (key);
1486   xfree (hash);
1487   xfree (fnewname);
1488   xfree (fname);
1489   xfree (nonce2);
1490   return err;
1491 }
1492
1493
1494 /* Process a confirmation response in MSG.  */
1495 static gpg_error_t
1496 process_confirmation_response (server_ctx_t ctx, estream_t msg)
1497 {
1498   gpg_error_t err;
1499   nvc_t nvc;
1500   nve_t item;
1501   const char *value, *sender, *address, *nonce;
1502
1503   err = nvc_parse (&nvc, NULL, msg);
1504   if (err)
1505     {
1506       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1507       goto leave;
1508     }
1509
1510   if (opt.debug)
1511     {
1512       log_debug ("response follows:\n");
1513       nvc_write (nvc, log_get_stream ());
1514     }
1515
1516   /* Check that this is a confirmation response.  */
1517   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1518         && !strcmp (value, "confirmation-response")))
1519     {
1520       if (item && value)
1521         log_error ("received unexpected wks message '%s'\n", value);
1522       else
1523         log_error ("received invalid wks message: %s\n", "'type' missing");
1524       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1525       goto leave;
1526     }
1527
1528   /* Get the sender.  */
1529   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1530         && is_valid_mailbox (value)))
1531     {
1532       log_error ("received invalid wks message: %s\n",
1533                  "'sender' missing or invalid");
1534       err = gpg_error (GPG_ERR_INV_DATA);
1535       goto leave;
1536     }
1537   sender = value;
1538   (void)sender;
1539   /* FIXME: Do we really need the sender?.  */
1540
1541   /* Get the address.  */
1542   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1543         && is_valid_mailbox (value)))
1544     {
1545       log_error ("received invalid wks message: %s\n",
1546                  "'address' missing or invalid");
1547       err = gpg_error (GPG_ERR_INV_DATA);
1548       goto leave;
1549     }
1550   address = value;
1551
1552   /* Get the nonce.  */
1553   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1554         && strlen (value) > 16))
1555     {
1556       log_error ("received invalid wks message: %s\n",
1557                  "'nonce' missing or too short");
1558       err = gpg_error (GPG_ERR_INV_DATA);
1559       goto leave;
1560     }
1561   nonce = value;
1562
1563   err = check_and_publish (ctx, address, nonce);
1564
1565
1566  leave:
1567   nvc_release (nvc);
1568   return err;
1569 }
1570
1571
1572 \f
1573 /* Called from the MIME receiver to process the plain text data in MSG .  */
1574 static gpg_error_t
1575 command_receive_cb (void *opaque, const char *mediatype,
1576                     estream_t msg, unsigned int flags)
1577 {
1578   gpg_error_t err;
1579   struct server_ctx_s ctx;
1580
1581   (void)opaque;
1582
1583   memset (&ctx, 0, sizeof ctx);
1584   if ((flags & WKS_RECEIVE_DRAFT2))
1585     ctx.draft_version_2 = 1;
1586
1587   if (!strcmp (mediatype, "application/pgp-keys"))
1588     err = process_new_key (&ctx, msg);
1589   else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1590     err = process_confirmation_response (&ctx, msg);
1591   else
1592     {
1593       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1594       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1595     }
1596
1597   xfree (ctx.fpr);
1598   free_uidinfo_list (ctx.mboxes);
1599
1600   return err;
1601 }
1602
1603
1604 \f
1605 /* Return a list of all configured domains.  ECh list element is the
1606  * top directory for the domain.  To figure out the actual domain
1607  * name strrchr(name, '/') can be used.  */
1608 static gpg_error_t
1609 get_domain_list (strlist_t *r_list)
1610 {
1611   gpg_error_t err;
1612   DIR *dir = NULL;
1613   char *fname = NULL;
1614   struct dirent *dentry;
1615   struct stat sb;
1616   strlist_t list = NULL;
1617
1618   *r_list = NULL;
1619
1620   dir = opendir (opt.directory);
1621   if (!dir)
1622     {
1623       err = gpg_error_from_syserror ();
1624       goto leave;
1625     }
1626
1627   while ((dentry = readdir (dir)))
1628     {
1629       if (*dentry->d_name == '.')
1630         continue;
1631       if (!strchr (dentry->d_name, '.'))
1632         continue; /* No dot - can't be a domain subdir.  */
1633
1634       xfree (fname);
1635       fname = make_filename_try (opt.directory, dentry->d_name, NULL);
1636       if (!fname)
1637         {
1638           err = gpg_error_from_syserror ();
1639           log_error ("make_filename failed in %s: %s\n",
1640                      __func__, gpg_strerror (err));
1641           goto leave;
1642         }
1643
1644       if (stat (fname, &sb))
1645         {
1646           err = gpg_error_from_syserror ();
1647           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1648           continue;
1649         }
1650       if (!S_ISDIR(sb.st_mode))
1651         continue;
1652
1653       if (!add_to_strlist_try (&list, fname))
1654         {
1655           err = gpg_error_from_syserror ();
1656           log_error ("add_to_strlist failed in %s: %s\n",
1657                      __func__, gpg_strerror (err));
1658           goto leave;
1659         }
1660     }
1661   err = 0;
1662   *r_list = list;
1663   list = NULL;
1664
1665  leave:
1666   free_strlist (list);
1667   if (dir)
1668     closedir (dir);
1669   xfree (fname);
1670   return err;
1671 }
1672
1673
1674 \f
1675 static gpg_error_t
1676 expire_one_domain (const char *top_dirname, const char *domain)
1677 {
1678   gpg_error_t err;
1679   char *dirname;
1680   char *fname = NULL;
1681   DIR *dir = NULL;
1682   struct dirent *dentry;
1683   struct stat sb;
1684   time_t now = gnupg_get_time ();
1685
1686   dirname = make_filename_try (top_dirname, "pending", NULL);
1687   if (!dirname)
1688     {
1689       err = gpg_error_from_syserror ();
1690       log_error ("make_filename failed in %s: %s\n",
1691                  __func__, gpg_strerror (err));
1692       goto leave;
1693     }
1694
1695   dir = opendir (dirname);
1696   if (!dir)
1697     {
1698       err = gpg_error_from_syserror ();
1699       log_error (("can't access directory '%s': %s\n"),
1700                  dirname, gpg_strerror (err));
1701       goto leave;
1702     }
1703
1704   while ((dentry = readdir (dir)))
1705     {
1706       if (*dentry->d_name == '.')
1707         continue;
1708       xfree (fname);
1709       fname = make_filename_try (dirname, dentry->d_name, NULL);
1710       if (!fname)
1711         {
1712           err = gpg_error_from_syserror ();
1713           log_error ("make_filename failed in %s: %s\n",
1714                      __func__, gpg_strerror (err));
1715           goto leave;
1716         }
1717       if (strlen (dentry->d_name) != 32)
1718         {
1719           log_info ("garbage file '%s' ignored\n", fname);
1720           continue;
1721         }
1722       if (stat (fname, &sb))
1723         {
1724           err = gpg_error_from_syserror ();
1725           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1726           continue;
1727         }
1728       if (S_ISDIR(sb.st_mode))
1729         {
1730           log_info ("garbage directory '%s' ignored\n", fname);
1731           continue;
1732         }
1733       if (sb.st_mtime + PENDING_TTL < now)
1734         {
1735           if (opt.verbose)
1736             log_info ("domain %s: removing pending key '%s'\n",
1737                       domain, dentry->d_name);
1738           if (remove (fname))
1739             {
1740               err = gpg_error_from_syserror ();
1741               /* In case the file has just been renamed or another
1742                * processes is cleaning up, we don't print a diagnostic
1743                * for ENOENT.  */
1744               if (gpg_err_code (err) != GPG_ERR_ENOENT)
1745                 log_error ("error removing '%s': %s\n",
1746                            fname, gpg_strerror (err));
1747             }
1748         }
1749     }
1750   err = 0;
1751
1752  leave:
1753   if (dir)
1754     closedir (dir);
1755   xfree (dirname);
1756   xfree (fname);
1757   return err;
1758
1759 }
1760
1761
1762 /* Scan spool directories and expire too old pending keys.  */
1763 static gpg_error_t
1764 expire_pending_confirmations (strlist_t domaindirs)
1765 {
1766   gpg_error_t err = 0;
1767   strlist_t sl;
1768   const char *domain;
1769
1770   for (sl = domaindirs; sl; sl = sl->next)
1771     {
1772       domain = strrchr (sl->d, '/');
1773       log_assert (domain);
1774       domain++;
1775
1776       expire_one_domain (sl->d, domain);
1777     }
1778
1779   return err;
1780 }
1781
1782
1783 /* List all configured domains.  */
1784 static gpg_error_t
1785 command_list_domains (void)
1786 {
1787   static struct {
1788     const char *name;
1789     const char *perm;
1790   } requireddirs[] = {
1791     { "pending", "-rwx" },
1792     { "hu",      "-rwxr-xr-x" }
1793   };
1794
1795   gpg_error_t err;
1796   strlist_t domaindirs;
1797   strlist_t sl;
1798   const char *domain;
1799   char *fname = NULL;
1800   int i;
1801   estream_t fp;
1802
1803   err = get_domain_list (&domaindirs);
1804   if (err)
1805     {
1806       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1807       return err;
1808     }
1809
1810   for (sl = domaindirs; sl; sl = sl->next)
1811     {
1812       domain = strrchr (sl->d, '/');
1813       log_assert (domain);
1814       domain++;
1815       if (opt_with_dir)
1816         es_printf ("%s %s\n", domain, sl->d);
1817       else
1818         es_printf ("%s\n", domain);
1819
1820
1821       /* Check that the required directories are there.  */
1822       for (i=0; i < DIM (requireddirs); i++)
1823         {
1824           xfree (fname);
1825           fname = make_filename_try (sl->d, requireddirs[i].name, NULL);
1826           if (!fname)
1827             {
1828               err = gpg_error_from_syserror ();
1829               goto leave;
1830             }
1831           if (access (fname, W_OK))
1832             {
1833               err = gpg_error_from_syserror ();
1834               if (gpg_err_code (err) == GPG_ERR_ENOENT)
1835                 {
1836                   if (gnupg_mkdir (fname, requireddirs[i].perm))
1837                     {
1838                       err = gpg_error_from_syserror ();
1839                       log_error ("domain %s: error creating subdir '%s': %s\n",
1840                                  domain, requireddirs[i].name,
1841                                  gpg_strerror (err));
1842                     }
1843                   else
1844                     log_info ("domain %s: subdir '%s' created\n",
1845                               domain, requireddirs[i].name);
1846                 }
1847               else if (err)
1848                 log_error ("domain %s: problem with subdir '%s': %s\n",
1849                            domain, requireddirs[i].name, gpg_strerror (err));
1850             }
1851         }
1852
1853       /* Print a warning if the submission address is not configured.  */
1854       xfree (fname);
1855       fname = make_filename_try (sl->d, "submission-address", NULL);
1856       if (!fname)
1857         {
1858           err = gpg_error_from_syserror ();
1859           goto leave;
1860         }
1861       if (access (fname, F_OK))
1862         {
1863           err = gpg_error_from_syserror ();
1864           if (gpg_err_code (err) == GPG_ERR_ENOENT)
1865             log_error ("domain %s: submission address not configured\n",
1866                        domain);
1867           else
1868             log_error ("domain %s: problem with '%s': %s\n",
1869                        domain, fname, gpg_strerror (err));
1870         }
1871
1872       /* Check the syntax of the optional policy file.  */
1873       xfree (fname);
1874       fname = make_filename_try (sl->d, "policy", NULL);
1875       if (!fname)
1876         {
1877           err = gpg_error_from_syserror ();
1878           goto leave;
1879         }
1880       fp = es_fopen (fname, "r");
1881       if (!fp)
1882         {
1883           err = gpg_error_from_syserror ();
1884           if (gpg_err_code (err) != GPG_ERR_ENOENT)
1885             log_error ("domain %s: error in policy file: %s\n",
1886                        domain, gpg_strerror (err));
1887         }
1888       else
1889         {
1890           struct policy_flags_s policy;
1891           err = wks_parse_policy (&policy, fp, 0);
1892           es_fclose (fp);
1893           if (!err)
1894             {
1895               struct policy_flags_s empty_policy;
1896               memset (&empty_policy, 0, sizeof empty_policy);
1897               if (!memcmp (&empty_policy, &policy, sizeof policy))
1898                 log_error ("domain %s: empty policy file\n", domain);
1899             }
1900         }
1901
1902
1903     }
1904   err = 0;
1905
1906  leave:
1907   xfree (fname);
1908   free_strlist (domaindirs);
1909   return err;
1910 }
1911
1912
1913 /* Run regular maintenance jobs.  */
1914 static gpg_error_t
1915 command_cron (void)
1916 {
1917   gpg_error_t err;
1918   strlist_t domaindirs;
1919
1920   err = get_domain_list (&domaindirs);
1921   if (err)
1922     {
1923       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1924       return err;
1925     }
1926
1927   err = expire_pending_confirmations (domaindirs);
1928
1929   free_strlist (domaindirs);
1930   return err;
1931 }
1932
1933
1934 /* Install a single key into the WKD by reading FNAME.  */
1935 static gpg_error_t
1936 command_install_key (const char *fname)
1937 {
1938   (void)fname;
1939   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1940 }
1941
1942
1943 /* Return the filename and optioanlly the addrspec for USERID at
1944  * R_FNAME and R_ADDRSPEC.  R_ADDRSPEC might also be set on error.  */
1945 static gpg_error_t
1946 fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
1947 {
1948   gpg_error_t err;
1949   char *addrspec = NULL;
1950   const char *domain;
1951   char *hash = NULL;
1952   const char *s;
1953   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1954
1955   *r_fname = NULL;
1956   if (r_addrspec)
1957     *r_addrspec = NULL;
1958
1959   addrspec = mailbox_from_userid (userid);
1960   if (!addrspec)
1961     {
1962       if (opt.verbose)
1963         log_info ("\"%s\" is not a proper mail address\n", userid);
1964       err = gpg_error (GPG_ERR_INV_USER_ID);
1965       goto leave;
1966     }
1967
1968   domain = strchr (addrspec, '@');
1969   log_assert (domain);
1970   domain++;
1971
1972   /* Hash user ID and create filename.  */
1973   s = strchr (addrspec, '@');
1974   log_assert (s);
1975   gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, addrspec, s - addrspec);
1976   hash = zb32_encode (shaxbuf, 8*20);
1977   if (!hash)
1978     {
1979       err = gpg_error_from_syserror ();
1980       goto leave;
1981     }
1982
1983   *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1984   if (!*r_fname)
1985     err = gpg_error_from_syserror ();
1986   else
1987     err = 0;
1988
1989  leave:
1990   if (r_addrspec && addrspec)
1991     *r_addrspec = addrspec;
1992   else
1993     xfree (addrspec);
1994   xfree (hash);
1995   return err;
1996 }
1997
1998
1999 /* Check whether the key with USER_ID is installed.  */
2000 static gpg_error_t
2001 command_check_key (const char *userid)
2002 {
2003   gpg_error_t err;
2004   char *addrspec = NULL;
2005   char *fname = NULL;
2006
2007   err = fname_from_userid (userid, &fname, &addrspec);
2008   if (err)
2009     goto leave;
2010
2011   if (access (fname, R_OK))
2012     {
2013       err = gpg_error_from_syserror ();
2014       if (opt_with_file)
2015         es_printf ("%s n %s\n", addrspec, fname);
2016       if (gpg_err_code (err) == GPG_ERR_ENOENT)
2017         {
2018           if (!opt.quiet)
2019             log_info ("key for '%s' is NOT installed\n", addrspec);
2020           log_inc_errorcount ();
2021           err = 0;
2022         }
2023       else
2024         log_error ("error stating '%s': %s\n", fname, gpg_strerror (err));
2025       goto leave;
2026     }
2027
2028   if (opt_with_file)
2029     es_printf ("%s i %s\n", addrspec, fname);
2030
2031   if (opt.verbose)
2032     log_info ("key for '%s' is installed\n", addrspec);
2033   err = 0;
2034
2035  leave:
2036   xfree (fname);
2037   xfree (addrspec);
2038   return err;
2039 }
2040
2041
2042 /* Remove the key with mail address in USERID.  */
2043 static gpg_error_t
2044 command_remove_key (const char *userid)
2045 {
2046   gpg_error_t err;
2047   char *addrspec = NULL;
2048   char *fname = NULL;
2049
2050   err = fname_from_userid (userid, &fname, &addrspec);
2051   if (err)
2052     goto leave;
2053
2054   if (gnupg_remove (fname))
2055     {
2056       err = gpg_error_from_syserror ();
2057       if (gpg_err_code (err) == GPG_ERR_ENOENT)
2058         {
2059           if (!opt.quiet)
2060             log_info ("key for '%s' is not installed\n", addrspec);
2061           log_inc_errorcount ();
2062           err = 0;
2063         }
2064       else
2065         log_error ("error removing '%s': %s\n", fname, gpg_strerror (err));
2066       goto leave;
2067     }
2068
2069   if (opt.verbose)
2070     log_info ("key for '%s' removed\n", addrspec);
2071   err = 0;
2072
2073  leave:
2074   xfree (fname);
2075   xfree (addrspec);
2076   return err;
2077 }
2078
2079
2080 /* Revoke the key with mail address MAILADDR.  */
2081 static gpg_error_t
2082 command_revoke_key (const char *mailaddr)
2083 {
2084   /* Remove should be different from removing but we have not yet
2085    * defined a suitable way to do this.  */
2086   return command_remove_key (mailaddr);
2087 }