wks: Implement server command --install-key.
[gnupg.git] / tools / gpg-wks-server.c
1 /* gpg-wks-server.c - A server for the Web Key Service protocols.
2  * Copyright (C) 2016, 2018 Werner Koch
3  * Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 /* The Web Key Service I-D defines an update protocol to store a
22  * public key in the Web Key Directory.  The current specification is
23  * draft-koch-openpgp-webkey-service-05.txt.
24  */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <dirent.h>
34
35 #include "../common/util.h"
36 #include "../common/init.h"
37 #include "../common/sysutils.h"
38 #include "../common/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, const char *userid);
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 != 2)
380         wrong_args ("--install-key FILE USER-ID");
381       err = command_install_key (*argv, argv[1]);
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 /* Write the content of SRC to the new file FNAME.  */
1343 static gpg_error_t
1344 write_to_file (estream_t src, const char *fname)
1345 {
1346   gpg_error_t err;
1347   estream_t dst;
1348   char buffer[4096];
1349   size_t nread, written;
1350
1351   dst = es_fopen (fname, "wb");
1352   if (!dst)
1353     return gpg_error_from_syserror ();
1354
1355   do
1356     {
1357       nread = es_fread (buffer, 1, sizeof buffer, src);
1358       if (!nread)
1359         break;
1360       written = es_fwrite (buffer, 1, nread, dst);
1361       if (written != nread)
1362         break;
1363     }
1364   while (!es_feof (src) && !es_ferror (src) && !es_ferror (dst));
1365   if (!es_feof (src) || es_ferror (src) || es_ferror (dst))
1366     {
1367       err = gpg_error_from_syserror ();
1368       es_fclose (dst);
1369       gnupg_remove (fname);
1370       return err;
1371     }
1372
1373   if (es_fclose (dst))
1374     {
1375       err = gpg_error_from_syserror ();
1376       log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
1377       return err;
1378     }
1379
1380   return 0;
1381 }
1382
1383
1384 /* Compute the the full file name for the key with ADDRSPEC and return
1385  * it at R_FNAME.  */
1386 static gpg_error_t
1387 compute_hu_fname (char **r_fname, const char *addrspec)
1388 {
1389   gpg_error_t err;
1390   char *hash;
1391   const char *domain;
1392   char sha1buf[20];
1393
1394   *r_fname = NULL;
1395
1396   domain = strchr (addrspec, '@');
1397   if (!domain || !domain[1] || domain == addrspec)
1398     return gpg_error (GPG_ERR_INV_ARG);
1399   domain++;
1400
1401   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, addrspec, domain - addrspec - 1);
1402   hash = zb32_encode (sha1buf, 8*20);
1403   if (!hash)
1404     return gpg_error_from_syserror ();
1405
1406   *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1407   if (!*r_fname)
1408     err = gpg_error_from_syserror ();
1409   else
1410     err = 0;
1411
1412   xfree (hash);
1413   return err;
1414 }
1415
1416
1417 /* Check that we have send a request with NONCE and publish the key.  */
1418 static gpg_error_t
1419 check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
1420 {
1421   gpg_error_t err;
1422   char *fname = NULL;
1423   char *fnewname = NULL;
1424   estream_t key = NULL;
1425   char *hash = NULL;
1426   const char *domain;
1427   const char *s;
1428   uidinfo_list_t sl;
1429   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1430
1431   /* FIXME: There is a bug in name-value.c which adds white space for
1432    * the last pair and thus we strip the nonce here until this has
1433    * been fixed.  */
1434   char *nonce2 = xstrdup (nonce);
1435   trim_trailing_spaces (nonce2);
1436   nonce = nonce2;
1437
1438
1439   domain = strchr (address, '@');
1440   log_assert (domain && domain[1]);
1441   domain++;
1442   fname = make_filename_try (opt.directory, domain, "pending", nonce, NULL);
1443   if (!fname)
1444     {
1445       err = gpg_error_from_syserror ();
1446       goto leave;
1447     }
1448
1449   /* Try to open the file with the key.  */
1450   key = es_fopen (fname, "rb");
1451   if (!key)
1452     {
1453       err = gpg_error_from_syserror ();
1454       if (gpg_err_code (err) == GPG_ERR_ENOENT)
1455         {
1456           log_info ("no pending request for '%s'\n", address);
1457           err = gpg_error (GPG_ERR_NOT_FOUND);
1458         }
1459       else
1460         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
1461       goto leave;
1462     }
1463
1464   /* We need to get the fingerprint from the key.  */
1465   xfree (ctx->fpr);
1466   free_uidinfo_list (ctx->mboxes);
1467   err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
1468   if (err)
1469     goto leave;
1470   log_assert (ctx->fpr);
1471   log_info ("fingerprint: %s\n", ctx->fpr);
1472   for (sl = ctx->mboxes; sl; sl = sl->next)
1473     if (sl->mbox)
1474       log_info ("  addr-spec: %s\n", sl->mbox);
1475
1476   /* Check that the key has 'address' as a user id.  We use
1477    * case-insensitive matching because the client is expected to
1478    * return the address verbatim.  */
1479   for (sl = ctx->mboxes; sl; sl = sl->next)
1480     if (sl->mbox && !strcmp (sl->mbox, address))
1481       break;
1482   if (!sl)
1483     {
1484       log_error ("error publishing key: '%s' is not a user ID of %s\n",
1485                  address, ctx->fpr);
1486       err = gpg_error (GPG_ERR_NO_PUBKEY);
1487       goto leave;
1488     }
1489
1490   /* Hash user ID and create filename.  */
1491   err = compute_hu_fname (&fnewname, address);
1492   if (err)
1493     goto leave;
1494
1495   /* Publish.  */
1496   err = copy_key_as_binary (fname, fnewname, address);
1497   if (err)
1498     {
1499       err = gpg_error_from_syserror ();
1500       log_error ("copying '%s' to '%s' failed: %s\n",
1501                  fname, fnewname, gpg_strerror (err));
1502       goto leave;
1503     }
1504
1505   /* Make sure it is world readable.  */
1506   if (gnupg_chmod (fnewname, "-rwxr--r--"))
1507     log_error ("can't set permissions of '%s': %s\n",
1508                fnewname, gpg_strerror (gpg_err_code_from_syserror()));
1509
1510   log_info ("key %s published for '%s'\n", ctx->fpr, address);
1511   send_congratulation_message (address, fnewname);
1512
1513   /* Try to publish as DANE record if the DANE directory exists.  */
1514   xfree (fname);
1515   fname = fnewname;
1516   fnewname = make_filename_try (opt.directory, domain, "dane", NULL);
1517   if (!fnewname)
1518     {
1519       err = gpg_error_from_syserror ();
1520       goto leave;
1521     }
1522   if (!access (fnewname, W_OK))
1523     {
1524       /* Yes, we have a dane directory.  */
1525       s = strchr (address, '@');
1526       log_assert (s);
1527       gcry_md_hash_buffer (GCRY_MD_SHA256, shaxbuf, address, s - address);
1528       xfree (hash);
1529       hash = bin2hex (shaxbuf, 28, NULL);
1530       if (!hash)
1531         {
1532           err = gpg_error_from_syserror ();
1533           goto leave;
1534         }
1535       xfree (fnewname);
1536       fnewname = make_filename_try (opt.directory, domain, "dane", hash, NULL);
1537       if (!fnewname)
1538         {
1539           err = gpg_error_from_syserror ();
1540           goto leave;
1541         }
1542       err = copy_key_as_dane (fname, fnewname);
1543       if (err)
1544         goto leave;
1545       log_info ("key %s published for '%s' (DANE record)\n", ctx->fpr, address);
1546     }
1547
1548  leave:
1549   es_fclose (key);
1550   xfree (hash);
1551   xfree (fnewname);
1552   xfree (fname);
1553   xfree (nonce2);
1554   return err;
1555 }
1556
1557
1558 /* Process a confirmation response in MSG.  */
1559 static gpg_error_t
1560 process_confirmation_response (server_ctx_t ctx, estream_t msg)
1561 {
1562   gpg_error_t err;
1563   nvc_t nvc;
1564   nve_t item;
1565   const char *value, *sender, *address, *nonce;
1566
1567   err = nvc_parse (&nvc, NULL, msg);
1568   if (err)
1569     {
1570       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1571       goto leave;
1572     }
1573
1574   if (opt.debug)
1575     {
1576       log_debug ("response follows:\n");
1577       nvc_write (nvc, log_get_stream ());
1578     }
1579
1580   /* Check that this is a confirmation response.  */
1581   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1582         && !strcmp (value, "confirmation-response")))
1583     {
1584       if (item && value)
1585         log_error ("received unexpected wks message '%s'\n", value);
1586       else
1587         log_error ("received invalid wks message: %s\n", "'type' missing");
1588       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1589       goto leave;
1590     }
1591
1592   /* Get the sender.  */
1593   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1594         && is_valid_mailbox (value)))
1595     {
1596       log_error ("received invalid wks message: %s\n",
1597                  "'sender' missing or invalid");
1598       err = gpg_error (GPG_ERR_INV_DATA);
1599       goto leave;
1600     }
1601   sender = value;
1602   (void)sender;
1603   /* FIXME: Do we really need the sender?.  */
1604
1605   /* Get the address.  */
1606   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1607         && is_valid_mailbox (value)))
1608     {
1609       log_error ("received invalid wks message: %s\n",
1610                  "'address' missing or invalid");
1611       err = gpg_error (GPG_ERR_INV_DATA);
1612       goto leave;
1613     }
1614   address = value;
1615
1616   /* Get the nonce.  */
1617   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1618         && strlen (value) > 16))
1619     {
1620       log_error ("received invalid wks message: %s\n",
1621                  "'nonce' missing or too short");
1622       err = gpg_error (GPG_ERR_INV_DATA);
1623       goto leave;
1624     }
1625   nonce = value;
1626
1627   err = check_and_publish (ctx, address, nonce);
1628
1629
1630  leave:
1631   nvc_release (nvc);
1632   return err;
1633 }
1634
1635
1636 \f
1637 /* Called from the MIME receiver to process the plain text data in MSG .  */
1638 static gpg_error_t
1639 command_receive_cb (void *opaque, const char *mediatype,
1640                     estream_t msg, unsigned int flags)
1641 {
1642   gpg_error_t err;
1643   struct server_ctx_s ctx;
1644
1645   (void)opaque;
1646
1647   memset (&ctx, 0, sizeof ctx);
1648   if ((flags & WKS_RECEIVE_DRAFT2))
1649     ctx.draft_version_2 = 1;
1650
1651   if (!strcmp (mediatype, "application/pgp-keys"))
1652     err = process_new_key (&ctx, msg);
1653   else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1654     err = process_confirmation_response (&ctx, msg);
1655   else
1656     {
1657       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1658       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1659     }
1660
1661   xfree (ctx.fpr);
1662   free_uidinfo_list (ctx.mboxes);
1663
1664   return err;
1665 }
1666
1667
1668 \f
1669 /* Return a list of all configured domains.  ECh list element is the
1670  * top directory for the domain.  To figure out the actual domain
1671  * name strrchr(name, '/') can be used.  */
1672 static gpg_error_t
1673 get_domain_list (strlist_t *r_list)
1674 {
1675   gpg_error_t err;
1676   DIR *dir = NULL;
1677   char *fname = NULL;
1678   struct dirent *dentry;
1679   struct stat sb;
1680   strlist_t list = NULL;
1681
1682   *r_list = NULL;
1683
1684   dir = opendir (opt.directory);
1685   if (!dir)
1686     {
1687       err = gpg_error_from_syserror ();
1688       goto leave;
1689     }
1690
1691   while ((dentry = readdir (dir)))
1692     {
1693       if (*dentry->d_name == '.')
1694         continue;
1695       if (!strchr (dentry->d_name, '.'))
1696         continue; /* No dot - can't be a domain subdir.  */
1697
1698       xfree (fname);
1699       fname = make_filename_try (opt.directory, dentry->d_name, NULL);
1700       if (!fname)
1701         {
1702           err = gpg_error_from_syserror ();
1703           log_error ("make_filename failed in %s: %s\n",
1704                      __func__, gpg_strerror (err));
1705           goto leave;
1706         }
1707
1708       if (stat (fname, &sb))
1709         {
1710           err = gpg_error_from_syserror ();
1711           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1712           continue;
1713         }
1714       if (!S_ISDIR(sb.st_mode))
1715         continue;
1716
1717       if (!add_to_strlist_try (&list, fname))
1718         {
1719           err = gpg_error_from_syserror ();
1720           log_error ("add_to_strlist failed in %s: %s\n",
1721                      __func__, gpg_strerror (err));
1722           goto leave;
1723         }
1724     }
1725   err = 0;
1726   *r_list = list;
1727   list = NULL;
1728
1729  leave:
1730   free_strlist (list);
1731   if (dir)
1732     closedir (dir);
1733   xfree (fname);
1734   return err;
1735 }
1736
1737
1738 \f
1739 static gpg_error_t
1740 expire_one_domain (const char *top_dirname, const char *domain)
1741 {
1742   gpg_error_t err;
1743   char *dirname;
1744   char *fname = NULL;
1745   DIR *dir = NULL;
1746   struct dirent *dentry;
1747   struct stat sb;
1748   time_t now = gnupg_get_time ();
1749
1750   dirname = make_filename_try (top_dirname, "pending", NULL);
1751   if (!dirname)
1752     {
1753       err = gpg_error_from_syserror ();
1754       log_error ("make_filename failed in %s: %s\n",
1755                  __func__, gpg_strerror (err));
1756       goto leave;
1757     }
1758
1759   dir = opendir (dirname);
1760   if (!dir)
1761     {
1762       err = gpg_error_from_syserror ();
1763       log_error (("can't access directory '%s': %s\n"),
1764                  dirname, gpg_strerror (err));
1765       goto leave;
1766     }
1767
1768   while ((dentry = readdir (dir)))
1769     {
1770       if (*dentry->d_name == '.')
1771         continue;
1772       xfree (fname);
1773       fname = make_filename_try (dirname, dentry->d_name, NULL);
1774       if (!fname)
1775         {
1776           err = gpg_error_from_syserror ();
1777           log_error ("make_filename failed in %s: %s\n",
1778                      __func__, gpg_strerror (err));
1779           goto leave;
1780         }
1781       if (strlen (dentry->d_name) != 32)
1782         {
1783           log_info ("garbage file '%s' ignored\n", fname);
1784           continue;
1785         }
1786       if (stat (fname, &sb))
1787         {
1788           err = gpg_error_from_syserror ();
1789           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1790           continue;
1791         }
1792       if (S_ISDIR(sb.st_mode))
1793         {
1794           log_info ("garbage directory '%s' ignored\n", fname);
1795           continue;
1796         }
1797       if (sb.st_mtime + PENDING_TTL < now)
1798         {
1799           if (opt.verbose)
1800             log_info ("domain %s: removing pending key '%s'\n",
1801                       domain, dentry->d_name);
1802           if (remove (fname))
1803             {
1804               err = gpg_error_from_syserror ();
1805               /* In case the file has just been renamed or another
1806                * processes is cleaning up, we don't print a diagnostic
1807                * for ENOENT.  */
1808               if (gpg_err_code (err) != GPG_ERR_ENOENT)
1809                 log_error ("error removing '%s': %s\n",
1810                            fname, gpg_strerror (err));
1811             }
1812         }
1813     }
1814   err = 0;
1815
1816  leave:
1817   if (dir)
1818     closedir (dir);
1819   xfree (dirname);
1820   xfree (fname);
1821   return err;
1822
1823 }
1824
1825
1826 /* Scan spool directories and expire too old pending keys.  */
1827 static gpg_error_t
1828 expire_pending_confirmations (strlist_t domaindirs)
1829 {
1830   gpg_error_t err = 0;
1831   strlist_t sl;
1832   const char *domain;
1833
1834   for (sl = domaindirs; sl; sl = sl->next)
1835     {
1836       domain = strrchr (sl->d, '/');
1837       log_assert (domain);
1838       domain++;
1839
1840       expire_one_domain (sl->d, domain);
1841     }
1842
1843   return err;
1844 }
1845
1846
1847 /* List all configured domains.  */
1848 static gpg_error_t
1849 command_list_domains (void)
1850 {
1851   static struct {
1852     const char *name;
1853     const char *perm;
1854   } requireddirs[] = {
1855     { "pending", "-rwx" },
1856     { "hu",      "-rwxr-xr-x" }
1857   };
1858
1859   gpg_error_t err;
1860   strlist_t domaindirs;
1861   strlist_t sl;
1862   const char *domain;
1863   char *fname = NULL;
1864   int i;
1865   estream_t fp;
1866
1867   err = get_domain_list (&domaindirs);
1868   if (err)
1869     {
1870       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1871       return err;
1872     }
1873
1874   for (sl = domaindirs; sl; sl = sl->next)
1875     {
1876       domain = strrchr (sl->d, '/');
1877       log_assert (domain);
1878       domain++;
1879       if (opt_with_dir)
1880         es_printf ("%s %s\n", domain, sl->d);
1881       else
1882         es_printf ("%s\n", domain);
1883
1884
1885       /* Check that the required directories are there.  */
1886       for (i=0; i < DIM (requireddirs); i++)
1887         {
1888           xfree (fname);
1889           fname = make_filename_try (sl->d, requireddirs[i].name, NULL);
1890           if (!fname)
1891             {
1892               err = gpg_error_from_syserror ();
1893               goto leave;
1894             }
1895           if (access (fname, W_OK))
1896             {
1897               err = gpg_error_from_syserror ();
1898               if (gpg_err_code (err) == GPG_ERR_ENOENT)
1899                 {
1900                   if (gnupg_mkdir (fname, requireddirs[i].perm))
1901                     {
1902                       err = gpg_error_from_syserror ();
1903                       log_error ("domain %s: error creating subdir '%s': %s\n",
1904                                  domain, requireddirs[i].name,
1905                                  gpg_strerror (err));
1906                     }
1907                   else
1908                     log_info ("domain %s: subdir '%s' created\n",
1909                               domain, requireddirs[i].name);
1910                 }
1911               else if (err)
1912                 log_error ("domain %s: problem with subdir '%s': %s\n",
1913                            domain, requireddirs[i].name, gpg_strerror (err));
1914             }
1915         }
1916
1917       /* Print a warning if the submission address is not configured.  */
1918       xfree (fname);
1919       fname = make_filename_try (sl->d, "submission-address", NULL);
1920       if (!fname)
1921         {
1922           err = gpg_error_from_syserror ();
1923           goto leave;
1924         }
1925       if (access (fname, F_OK))
1926         {
1927           err = gpg_error_from_syserror ();
1928           if (gpg_err_code (err) == GPG_ERR_ENOENT)
1929             log_error ("domain %s: submission address not configured\n",
1930                        domain);
1931           else
1932             log_error ("domain %s: problem with '%s': %s\n",
1933                        domain, fname, gpg_strerror (err));
1934         }
1935
1936       /* Check the syntax of the optional policy file.  */
1937       xfree (fname);
1938       fname = make_filename_try (sl->d, "policy", NULL);
1939       if (!fname)
1940         {
1941           err = gpg_error_from_syserror ();
1942           goto leave;
1943         }
1944       fp = es_fopen (fname, "r");
1945       if (!fp)
1946         {
1947           err = gpg_error_from_syserror ();
1948           if (gpg_err_code (err) != GPG_ERR_ENOENT)
1949             log_error ("domain %s: error in policy file: %s\n",
1950                        domain, gpg_strerror (err));
1951         }
1952       else
1953         {
1954           struct policy_flags_s policy;
1955           err = wks_parse_policy (&policy, fp, 0);
1956           es_fclose (fp);
1957           if (!err)
1958             {
1959               struct policy_flags_s empty_policy;
1960               memset (&empty_policy, 0, sizeof empty_policy);
1961               if (!memcmp (&empty_policy, &policy, sizeof policy))
1962                 log_error ("domain %s: empty policy file\n", domain);
1963             }
1964           wks_free_policy (&policy);
1965         }
1966
1967
1968     }
1969   err = 0;
1970
1971  leave:
1972   xfree (fname);
1973   free_strlist (domaindirs);
1974   return err;
1975 }
1976
1977
1978 /* Run regular maintenance jobs.  */
1979 static gpg_error_t
1980 command_cron (void)
1981 {
1982   gpg_error_t err;
1983   strlist_t domaindirs;
1984
1985   err = get_domain_list (&domaindirs);
1986   if (err)
1987     {
1988       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1989       return err;
1990     }
1991
1992   err = expire_pending_confirmations (domaindirs);
1993
1994   free_strlist (domaindirs);
1995   return err;
1996 }
1997
1998
1999 /* Install a single key into the WKD by reading FNAME and extracting
2000  * USERID.  */
2001 static gpg_error_t
2002 command_install_key (const char *fname, const char *userid)
2003 {
2004   gpg_error_t err;
2005   estream_t fp;
2006   char *addrspec = NULL;
2007   char *fpr = NULL;
2008   uidinfo_list_t uidlist = NULL;
2009   uidinfo_list_t uid, thisuid;
2010   time_t thistime;
2011   char *huname = NULL;
2012   int any;
2013
2014   fp = es_fopen (fname, "rb");
2015   if (!fp)
2016     {
2017       err = gpg_error_from_syserror ();
2018       log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
2019       goto leave;
2020     }
2021
2022   addrspec = mailbox_from_userid (userid);
2023   if (!addrspec)
2024     {
2025       log_error ("\"%s\" is not a proper mail address\n", userid);
2026       err = gpg_error (GPG_ERR_INV_USER_ID);
2027       goto leave;
2028     }
2029
2030   /* List the key so that we can figure out the newest UID with the
2031    * requested addrspec.  */
2032   err = wks_list_key (fp, &fpr, &uidlist);
2033   if (err)
2034     {
2035       log_error ("error parsing key: %s\n", gpg_strerror (err));
2036       err = gpg_error (GPG_ERR_NO_PUBKEY);
2037       goto leave;
2038     }
2039   thistime = 0;
2040   thisuid = NULL;
2041   any = 0;
2042   for (uid = uidlist; uid; uid = uid->next)
2043     {
2044       if (!uid->mbox)
2045         continue; /* Should not happen anyway.  */
2046       if (ascii_strcasecmp (uid->mbox, addrspec))
2047         continue; /* Not the requested addrspec.  */
2048       any = 1;
2049       if (uid->created > thistime)
2050         {
2051           thistime = uid->created;
2052           thisuid = uid;
2053         }
2054     }
2055   if (!thisuid)
2056     thisuid = uidlist;  /* This is the case for a missing timestamp.  */
2057   if (!any)
2058     {
2059       log_error ("public key in '%s' has no mail address '%s'\n",
2060                  fname, addrspec);
2061       err = gpg_error (GPG_ERR_INV_USER_ID);
2062       goto leave;
2063     }
2064
2065   if (opt.verbose)
2066     log_info ("using key with user id '%s'\n", thisuid->uid);
2067
2068   {
2069     estream_t fp2;
2070
2071     es_rewind (fp);
2072     err = wks_filter_uid (&fp2, fp, thisuid->uid, 1);
2073     if (err)
2074       {
2075         log_error ("error filtering key: %s\n", gpg_strerror (err));
2076         err = gpg_error (GPG_ERR_NO_PUBKEY);
2077         goto leave;
2078       }
2079     es_fclose (fp);
2080     fp = fp2;
2081   }
2082
2083   /* Hash user ID and create filename.  */
2084   err = compute_hu_fname (&huname, addrspec);
2085   if (err)
2086     goto leave;
2087
2088   /* Publish.  */
2089   err = write_to_file (fp, huname);
2090   if (err)
2091     {
2092       log_error ("copying key to '%s' failed: %s\n", huname,gpg_strerror (err));
2093       goto leave;
2094     }
2095
2096   /* Make sure it is world readable.  */
2097   if (gnupg_chmod (huname, "-rwxr--r--"))
2098     log_error ("can't set permissions of '%s': %s\n",
2099                huname, gpg_strerror (gpg_err_code_from_syserror()));
2100
2101   if (!opt.quiet)
2102     log_info ("key %s published for '%s'\n", fpr, addrspec);
2103
2104  leave:
2105   xfree (huname);
2106   free_uidinfo_list (uidlist);
2107   xfree (fpr);
2108   xfree (addrspec);
2109   es_fclose (fp);
2110   return err;
2111 }
2112
2113
2114 /* Return the filename and optionally the addrspec for USERID at
2115  * R_FNAME and R_ADDRSPEC.  R_ADDRSPEC might also be set on error.  */
2116 static gpg_error_t
2117 fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
2118 {
2119   gpg_error_t err;
2120   char *addrspec = NULL;
2121   const char *domain;
2122   char *hash = NULL;
2123   const char *s;
2124   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
2125
2126   *r_fname = NULL;
2127   if (r_addrspec)
2128     *r_addrspec = NULL;
2129
2130   addrspec = mailbox_from_userid (userid);
2131   if (!addrspec)
2132     {
2133       if (opt.verbose)
2134         log_info ("\"%s\" is not a proper mail address\n", userid);
2135       err = gpg_error (GPG_ERR_INV_USER_ID);
2136       goto leave;
2137     }
2138
2139   domain = strchr (addrspec, '@');
2140   log_assert (domain);
2141   domain++;
2142
2143   /* Hash user ID and create filename.  */
2144   s = strchr (addrspec, '@');
2145   log_assert (s);
2146   gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, addrspec, s - addrspec);
2147   hash = zb32_encode (shaxbuf, 8*20);
2148   if (!hash)
2149     {
2150       err = gpg_error_from_syserror ();
2151       goto leave;
2152     }
2153
2154   *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
2155   if (!*r_fname)
2156     err = gpg_error_from_syserror ();
2157   else
2158     err = 0;
2159
2160  leave:
2161   if (r_addrspec && addrspec)
2162     *r_addrspec = addrspec;
2163   else
2164     xfree (addrspec);
2165   xfree (hash);
2166   return err;
2167 }
2168
2169
2170 /* Check whether the key with USER_ID is installed.  */
2171 static gpg_error_t
2172 command_check_key (const char *userid)
2173 {
2174   gpg_error_t err;
2175   char *addrspec = NULL;
2176   char *fname = NULL;
2177
2178   err = fname_from_userid (userid, &fname, &addrspec);
2179   if (err)
2180     goto leave;
2181
2182   if (access (fname, R_OK))
2183     {
2184       err = gpg_error_from_syserror ();
2185       if (opt_with_file)
2186         es_printf ("%s n %s\n", addrspec, fname);
2187       if (gpg_err_code (err) == GPG_ERR_ENOENT)
2188         {
2189           if (!opt.quiet)
2190             log_info ("key for '%s' is NOT installed\n", addrspec);
2191           log_inc_errorcount ();
2192           err = 0;
2193         }
2194       else
2195         log_error ("error stating '%s': %s\n", fname, gpg_strerror (err));
2196       goto leave;
2197     }
2198
2199   if (opt_with_file)
2200     es_printf ("%s i %s\n", addrspec, fname);
2201
2202   if (opt.verbose)
2203     log_info ("key for '%s' is installed\n", addrspec);
2204   err = 0;
2205
2206  leave:
2207   xfree (fname);
2208   xfree (addrspec);
2209   return err;
2210 }
2211
2212
2213 /* Remove the key with mail address in USERID.  */
2214 static gpg_error_t
2215 command_remove_key (const char *userid)
2216 {
2217   gpg_error_t err;
2218   char *addrspec = NULL;
2219   char *fname = NULL;
2220
2221   err = fname_from_userid (userid, &fname, &addrspec);
2222   if (err)
2223     goto leave;
2224
2225   if (gnupg_remove (fname))
2226     {
2227       err = gpg_error_from_syserror ();
2228       if (gpg_err_code (err) == GPG_ERR_ENOENT)
2229         {
2230           if (!opt.quiet)
2231             log_info ("key for '%s' is not installed\n", addrspec);
2232           log_inc_errorcount ();
2233           err = 0;
2234         }
2235       else
2236         log_error ("error removing '%s': %s\n", fname, gpg_strerror (err));
2237       goto leave;
2238     }
2239
2240   if (opt.verbose)
2241     log_info ("key for '%s' removed\n", addrspec);
2242   err = 0;
2243
2244  leave:
2245   xfree (fname);
2246   xfree (addrspec);
2247   return err;
2248 }
2249
2250
2251 /* Revoke the key with mail address MAILADDR.  */
2252 static gpg_error_t
2253 command_revoke_key (const char *mailaddr)
2254 {
2255   /* Remove should be different from removing but we have not yet
2256    * defined a suitable way to do this.  */
2257   return command_remove_key (mailaddr);
2258 }