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