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