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