wks: New server command --list-domains
[gnupg.git] / tools / gpg-wks-server.c
1 /* gpg-wks-server.c - A server for the Web Key Service protocols.
2  * Copyright (C) 2016 Werner Koch
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* The Web Key Service I-D defines an update protocol to stpre a
21  * public key in the Web Key Directory.  The current specification is
22  * draft-koch-openpgp-webkey-service-01.txt.
23  */
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33
34 #include "util.h"
35 #include "init.h"
36 #include "sysutils.h"
37 #include "ccparray.h"
38 #include "exectool.h"
39 #include "zb32.h"
40 #include "mbox-util.h"
41 #include "name-value.h"
42 #include "mime-maker.h"
43 #include "send-mail.h"
44 #include "gpg-wks.h"
45
46
47 /* The time we wait for a confirmation response.  */
48 #define PENDING_TTL (86400 * 3)  /* 3 days.  */
49
50
51 /* Constants to identify the commands and options. */
52 enum cmd_and_opt_values
53   {
54     aNull = 0,
55
56     oQuiet      = 'q',
57     oVerbose    = 'v',
58     oOutput     = 'o',
59
60     oDebug      = 500,
61
62     aReceive,
63     aCron,
64     aListDomains,
65
66     oGpgProgram,
67     oSend,
68     oFrom,
69     oHeader,
70
71     oDummy
72   };
73
74
75 /* The list of commands and options. */
76 static ARGPARSE_OPTS opts[] = {
77   ARGPARSE_group (300, ("@Commands:\n ")),
78
79   ARGPARSE_c (aReceive,   "receive",
80               ("receive a submission or confirmation")),
81   ARGPARSE_c (aCron,      "cron",
82               ("run regular jobs")),
83   ARGPARSE_c (aListDomains, "list-domains",
84               ("list configured domains")),
85
86   ARGPARSE_group (301, ("@\nOptions:\n ")),
87
88   ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
89   ARGPARSE_s_n (oQuiet, "quiet",  ("be somewhat more quiet")),
90   ARGPARSE_s_s (oDebug, "debug", "@"),
91   ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
92   ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
93   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
94   ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"),
95   ARGPARSE_s_s (oHeader, "header" ,
96                 "|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"),
97
98   ARGPARSE_end ()
99 };
100
101
102 /* The list of supported debug flags.  */
103 static struct debug_flags_s debug_flags [] =
104   {
105     { DBG_CRYPTO_VALUE , "crypto"  },
106     { DBG_MEMORY_VALUE , "memory"  },
107     { DBG_MEMSTAT_VALUE, "memstat" },
108     { DBG_IPC_VALUE    , "ipc"     },
109     { DBG_EXTPROG_VALUE, "extprog" },
110     { 0, NULL }
111   };
112
113
114 /* State for processing a message.  */
115 struct server_ctx_s
116 {
117   char *fpr;
118   strlist_t mboxes;  /* List of addr-specs taken from the UIDs.  */
119 };
120 typedef struct server_ctx_s *server_ctx_t;
121
122 /* Prototypes.  */
123 static gpg_error_t get_domain_list (strlist_t *r_list);
124
125 static gpg_error_t command_receive_cb (void *opaque,
126                                        const char *mediatype, estream_t fp);
127 static gpg_error_t command_list_domains (void);
128 static gpg_error_t command_cron (void);
129
130
131 \f
132 /* Print usage information and and provide strings for help. */
133 static const char *
134 my_strusage( int level )
135 {
136   const char *p;
137
138   switch (level)
139     {
140     case 11: p = "gpg-wks-server (@GNUPG@)";
141       break;
142     case 13: p = VERSION; break;
143     case 17: p = PRINTABLE_OS_NAME; break;
144     case 19: p = ("Please report bugs to <@EMAIL@>.\n"); break;
145
146     case 1:
147     case 40:
148       p = ("Usage: gpg-wks-server command [options] (-h for help)");
149       break;
150     case 41:
151       p = ("Syntax: gpg-wks-server command [options]\n"
152            "Server for the Web Key Service protocol\n");
153       break;
154
155     default: p = NULL; break;
156     }
157   return p;
158 }
159
160
161 static void
162 wrong_args (const char *text)
163 {
164   es_fprintf (es_stderr, "usage: %s [options] %s\n", strusage (11), text);
165   exit (2);
166 }
167
168
169 \f
170 /* Command line parsing.  */
171 static enum cmd_and_opt_values
172 parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
173 {
174   enum cmd_and_opt_values cmd = 0;
175   int no_more_options = 0;
176
177   while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
178     {
179       switch (pargs->r_opt)
180         {
181         case oQuiet:     opt.quiet = 1; break;
182         case oVerbose:   opt.verbose++; break;
183         case oDebug:
184           if (parse_debug_flag (pargs->r.ret_str, &opt.debug, debug_flags))
185             {
186               pargs->r_opt = ARGPARSE_INVALID_ARG;
187               pargs->err = ARGPARSE_PRINT_ERROR;
188             }
189           break;
190
191         case oGpgProgram:
192           opt.gpg_program = pargs->r.ret_str;
193           break;
194         case oFrom:
195           opt.default_from = pargs->r.ret_str;
196           break;
197         case oHeader:
198           append_to_strlist (&opt.extra_headers, pargs->r.ret_str);
199           break;
200         case oSend:
201           opt.use_sendmail = 1;
202           break;
203         case oOutput:
204           opt.output = pargs->r.ret_str;
205           break;
206
207         case aReceive:
208         case aCron:
209         case aListDomains:
210           cmd = pargs->r_opt;
211           break;
212
213         default: pargs->err = 2; break;
214         }
215     }
216
217   return cmd;
218 }
219
220
221 \f
222 /* gpg-wks-server main. */
223 int
224 main (int argc, char **argv)
225 {
226   gpg_error_t err;
227   ARGPARSE_ARGS pargs;
228   enum cmd_and_opt_values cmd;
229
230   gnupg_reopen_std ("gpg-wks-server");
231   set_strusage (my_strusage);
232   log_set_prefix ("gpg-wks-server", GPGRT_LOG_WITH_PREFIX);
233
234   /* Make sure that our subsystems are ready.  */
235   init_common_subsystems (&argc, &argv);
236
237   /* Parse the command line. */
238   pargs.argc  = &argc;
239   pargs.argv  = &argv;
240   pargs.flags = ARGPARSE_FLAG_KEEP;
241   cmd = parse_arguments (&pargs, opts);
242
243   if (log_get_errorcount (0))
244     exit (2);
245
246   /* Print a warning if an argument looks like an option.  */
247   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
248     {
249       int i;
250
251       for (i=0; i < argc; i++)
252         if (argv[i][0] == '-' && argv[i][1] == '-')
253           log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
254     }
255
256   /* Set defaults for non given options.  */
257   if (!opt.gpg_program)
258     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
259
260   if (!opt.directory)
261     opt.directory = "/var/lib/gnupg/wks";
262
263   /* Check for syntax errors in the --header option to avoid later
264    * error messages with a not easy to find cause */
265   if (opt.extra_headers)
266     {
267       strlist_t sl;
268
269       for (sl = opt.extra_headers; sl; sl = sl->next)
270         {
271           err = mime_maker_add_header (NULL, sl->d, NULL);
272           if (err)
273             log_error ("syntax error in \"--header %s\": %s\n",
274                        sl->d, gpg_strerror (err));
275         }
276     }
277
278   if (log_get_errorcount (0))
279     exit (2);
280
281
282   /* Check that we have a working directory.  */
283 #if defined(HAVE_STAT)
284   {
285     struct stat sb;
286
287     if (stat (opt.directory, &sb))
288       {
289         err = gpg_error_from_syserror ();
290         log_error ("error accessing directory '%s': %s\n",
291                    opt.directory, gpg_strerror (err));
292         exit (2);
293       }
294     if (!S_ISDIR(sb.st_mode))
295       {
296         log_error ("error accessing directory '%s': %s\n",
297                    opt.directory, "not a directory");
298         exit (2);
299       }
300     if (sb.st_uid != getuid())
301       {
302         log_error ("directory '%s' not owned by user\n", opt.directory);
303         exit (2);
304       }
305     if ((sb.st_mode & S_IRWXO))
306       {
307         log_error ("directory '%s' has too relaxed permissions\n",
308                    opt.directory);
309         exit (2);
310       }
311   }
312 #else /*!HAVE_STAT*/
313   log_fatal ("program build w/o stat() call\n");
314 #endif /*!HAVE_STAT*/
315
316   /* Run the selected command.  */
317   switch (cmd)
318     {
319     case aReceive:
320       if (argc)
321         wrong_args ("--receive");
322       err = wks_receive (es_stdin, command_receive_cb, NULL);
323       break;
324
325     case aCron:
326       if (argc)
327         wrong_args ("--cron");
328       err = command_cron ();
329       break;
330
331     case aListDomains:
332       err = command_list_domains ();
333       break;
334
335     default:
336       usage (1);
337       err = gpg_error (GPG_ERR_BUG);
338       break;
339     }
340
341   if (err)
342     log_error ("command failed: %s\n", gpg_strerror (err));
343   return log_get_errorcount (0)? 1:0;
344 }
345
346
347 \f
348 static void
349 list_key_status_cb (void *opaque, const char *keyword, char *args)
350 {
351   server_ctx_t ctx = opaque;
352   (void)ctx;
353   if (opt.debug)
354     log_debug ("%s: %s\n", keyword, args);
355 }
356
357
358 static gpg_error_t
359 list_key (server_ctx_t ctx, estream_t key)
360 {
361   gpg_error_t err;
362   ccparray_t ccp;
363   const char **argv;
364   estream_t listing;
365   char *line = NULL;
366   size_t length_of_line = 0;
367   size_t  maxlen;
368   ssize_t len;
369   char **fields = NULL;
370   int nfields;
371   int lnr;
372   char *mbox = NULL;
373
374   /* We store our results in the context - clear it first.  */
375   xfree (ctx->fpr);
376   ctx->fpr = NULL;
377   free_strlist (ctx->mboxes);
378   ctx->mboxes = NULL;
379
380   /* Open a memory stream.  */
381   listing = es_fopenmem (0, "w+b");
382   if (!listing)
383     {
384       err = gpg_error_from_syserror ();
385       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
386       return err;
387     }
388
389   ccparray_init (&ccp, 0);
390
391   ccparray_put (&ccp, "--no-options");
392   if (!opt.verbose)
393     ccparray_put (&ccp, "--quiet");
394   else if (opt.verbose > 1)
395     ccparray_put (&ccp, "--verbose");
396   ccparray_put (&ccp, "--batch");
397   ccparray_put (&ccp, "--status-fd=2");
398   ccparray_put (&ccp, "--always-trust");
399   ccparray_put (&ccp, "--with-colons");
400   ccparray_put (&ccp, "--dry-run");
401   ccparray_put (&ccp, "--import-options=import-minimal,import-show");
402   ccparray_put (&ccp, "--import");
403
404   ccparray_put (&ccp, NULL);
405   argv = ccparray_get (&ccp, NULL);
406   if (!argv)
407     {
408       err = gpg_error_from_syserror ();
409       goto leave;
410     }
411   err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
412                                 NULL, listing,
413                                 list_key_status_cb, ctx);
414   if (err)
415     {
416       log_error ("import failed: %s\n", gpg_strerror (err));
417       goto leave;
418     }
419
420   es_rewind (listing);
421   lnr = 0;
422   maxlen = 2048; /* Set limit.  */
423   while ((len = es_read_line (listing, &line, &length_of_line, &maxlen)) > 0)
424     {
425       lnr++;
426       if (!maxlen)
427         {
428           log_error ("received line too long\n");
429           err = gpg_error (GPG_ERR_LINE_TOO_LONG);
430           goto leave;
431         }
432       /* Strip newline and carriage return, if present.  */
433       while (len > 0
434              && (line[len - 1] == '\n' || line[len - 1] == '\r'))
435         line[--len] = '\0';
436       /* log_debug ("line '%s'\n", line); */
437
438       xfree (fields);
439       fields = strtokenize (line, ":");
440       if (!fields)
441         {
442           err = gpg_error_from_syserror ();
443           log_error ("strtokenize failed: %s\n", gpg_strerror (err));
444           goto leave;
445         }
446       for (nfields = 0; fields[nfields]; nfields++)
447         ;
448       if (!nfields)
449         {
450           err = gpg_error (GPG_ERR_INV_ENGINE);
451           goto leave;
452         }
453       if (!strcmp (fields[0], "sec"))
454         {
455           /* gpg may return "sec" as the first record - but we do not
456            * accept secret keys.  */
457           err = gpg_error (GPG_ERR_NO_PUBKEY);
458           goto leave;
459         }
460       if (lnr == 1 && strcmp (fields[0], "pub"))
461         {
462           /* First record is not a public key.  */
463           err = gpg_error (GPG_ERR_INV_ENGINE);
464           goto leave;
465         }
466       if (lnr > 1 && !strcmp (fields[0], "pub"))
467         {
468           /* More than one public key.  */
469           err = gpg_error (GPG_ERR_TOO_MANY);
470           goto leave;
471         }
472       if (!strcmp (fields[0], "sub") || !strcmp (fields[0], "ssb"))
473         break; /* We can stop parsing here.  */
474
475       if (!strcmp (fields[0], "fpr") && nfields > 9 && !ctx->fpr)
476         {
477           ctx->fpr = xtrystrdup (fields[9]);
478           if (!ctx->fpr)
479             {
480               err = gpg_error_from_syserror ();
481               goto leave;
482             }
483         }
484       else if (!strcmp (fields[0], "uid") && nfields > 9)
485         {
486           /* Fixme: Unescape fields[9] */
487           xfree (mbox);
488           mbox = mailbox_from_userid (fields[9]);
489           if (mbox && !append_to_strlist_try (&ctx->mboxes, mbox))
490             {
491               err = gpg_error_from_syserror ();
492               goto leave;
493             }
494         }
495     }
496   if (len < 0 || es_ferror (listing))
497     log_error ("error reading memory stream\n");
498
499  leave:
500   xfree (mbox);
501   xfree (fields);
502   es_free (line);
503   xfree (argv);
504   es_fclose (listing);
505   return err;
506 }
507
508
509 /* Take the key in KEYFILE and write it to DANEFILE using the DANE
510  * output format. */
511 static gpg_error_t
512 copy_key_as_dane (const char *keyfile, const char *danefile)
513 {
514   gpg_error_t err;
515   ccparray_t ccp;
516   const char **argv;
517
518   ccparray_init (&ccp, 0);
519
520   ccparray_put (&ccp, "--no-options");
521   if (!opt.verbose)
522     ccparray_put (&ccp, "--quiet");
523   else if (opt.verbose > 1)
524     ccparray_put (&ccp, "--verbose");
525   ccparray_put (&ccp, "--batch");
526   ccparray_put (&ccp, "--yes");
527   ccparray_put (&ccp, "--always-trust");
528   ccparray_put (&ccp, "--no-keyring");
529   ccparray_put (&ccp, "--output");
530   ccparray_put (&ccp, danefile);
531   ccparray_put (&ccp, "--export-options=export-dane");
532   ccparray_put (&ccp, "--import-options=import-export");
533   ccparray_put (&ccp, "--import");
534   ccparray_put (&ccp, "--");
535   ccparray_put (&ccp, keyfile);
536
537   ccparray_put (&ccp, NULL);
538   argv = ccparray_get (&ccp, NULL);
539   if (!argv)
540     {
541       err = gpg_error_from_syserror ();
542       goto leave;
543     }
544   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
545                                 NULL, NULL, NULL, NULL);
546   if (err)
547     {
548       log_error ("%s failed: %s\n", __func__, gpg_strerror (err));
549       goto leave;
550     }
551
552  leave:
553   xfree (argv);
554   return err;
555 }
556
557
558 static void
559 encrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
560 {
561   (void)opaque;
562
563   if (opt.debug)
564     log_debug ("%s: %s\n", keyword, args);
565 }
566
567
568 /* Encrypt the INPUT stream to a new stream which is stored at success
569  * at R_OUTPUT.  Encryption is done for the key in file KEYFIL.  */
570 static gpg_error_t
571 encrypt_stream (estream_t *r_output, estream_t input, const char *keyfile)
572 {
573   gpg_error_t err;
574   ccparray_t ccp;
575   const char **argv;
576   estream_t output;
577
578   *r_output = NULL;
579
580   output = es_fopenmem (0, "w+b");
581   if (!output)
582     {
583       err = gpg_error_from_syserror ();
584       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
585       return err;
586     }
587
588   ccparray_init (&ccp, 0);
589
590   ccparray_put (&ccp, "--no-options");
591   if (!opt.verbose)
592     ccparray_put (&ccp, "--quiet");
593   else if (opt.verbose > 1)
594     ccparray_put (&ccp, "--verbose");
595   ccparray_put (&ccp, "--batch");
596   ccparray_put (&ccp, "--status-fd=2");
597   ccparray_put (&ccp, "--always-trust");
598   ccparray_put (&ccp, "--no-keyring");
599   ccparray_put (&ccp, "--armor");
600   ccparray_put (&ccp, "--recipient-file");
601   ccparray_put (&ccp, keyfile);
602   ccparray_put (&ccp, "--encrypt");
603   ccparray_put (&ccp, "--");
604
605   ccparray_put (&ccp, NULL);
606   argv = ccparray_get (&ccp, NULL);
607   if (!argv)
608     {
609       err = gpg_error_from_syserror ();
610       goto leave;
611     }
612   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
613                                 NULL, output,
614                                 encrypt_stream_status_cb, NULL);
615   if (err)
616     {
617       log_error ("encryption failed: %s\n", gpg_strerror (err));
618       goto leave;
619     }
620
621   es_rewind (output);
622   *r_output = output;
623   output = NULL;
624
625  leave:
626   es_fclose (output);
627   xfree (argv);
628   return err;
629 }
630
631
632 /* Get the submission address for address MBOX.  Caller must free the
633  * value.  If no address can be found NULL is returned.  */
634 static char *
635 get_submission_address (const char *mbox)
636 {
637   gpg_error_t err;
638   const char *domain;
639   char *fname, *line, *p;
640   size_t n;
641   estream_t fp;
642
643   domain = strchr (mbox, '@');
644   if (!domain)
645     return NULL;
646   domain++;
647
648   fname = make_filename_try (opt.directory, domain, "submission-address", NULL);
649   if (!fname)
650     {
651       err = gpg_error_from_syserror ();
652       log_error ("make_filename failed in %s: %s\n",
653                  __func__, gpg_strerror (err));
654       return NULL;
655     }
656
657   fp = es_fopen (fname, "r");
658   if (!fp)
659     {
660       err = gpg_error_from_syserror ();
661       if (gpg_err_code (err) == GPG_ERR_ENOENT)
662         log_info ("Note: no specific submission address configured"
663                   " for domain '%s'\n", domain);
664       else
665         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
666       xfree (fname);
667       return NULL;
668     }
669
670   line = NULL;
671   n = 0;
672   if (es_getline (&line, &n, fp) < 0)
673     {
674       err = gpg_error_from_syserror ();
675       log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
676       xfree (line);
677       es_fclose (fp);
678       xfree (fname);
679       return NULL;
680     }
681   es_fclose (fp);
682   xfree (fname);
683
684   p = strchr (line, '\n');
685   if (p)
686     *p = 0;
687   trim_spaces (line);
688   if (!is_valid_mailbox (line))
689     {
690       log_error ("invalid submission address for domain '%s' detected\n",
691                  domain);
692       xfree (line);
693       return NULL;
694     }
695
696   return line;
697 }
698
699
700 /* We store the key under the name of the nonce we will then send to
701  * the user.  On success the nonce is stored at R_NONCE and the file
702  * name at R_FNAME.  */
703 static gpg_error_t
704 store_key_as_pending (const char *dir, estream_t key,
705                       char **r_nonce, char **r_fname)
706 {
707   gpg_error_t err;
708   char *dname = NULL;
709   char *fname = NULL;
710   char *nonce = NULL;
711   estream_t outfp = NULL;
712   char buffer[1024];
713   size_t nbytes, nwritten;
714
715   *r_nonce = NULL;
716   *r_fname = NULL;
717
718   dname = make_filename_try (dir, "pending", NULL);
719   if (!dname)
720     {
721       err = gpg_error_from_syserror ();
722       goto leave;
723     }
724
725   /* Create the nonce.  We use 20 bytes so that we don't waste a
726    * character in our zBase-32 encoding.  Using the gcrypt's nonce
727    * function is faster than using the strong random function; this is
728    * Good Enough for our purpose.  */
729   log_assert (sizeof buffer > 20);
730   gcry_create_nonce (buffer, 20);
731   nonce = zb32_encode (buffer, 8 * 20);
732   memset (buffer, 0, 20);  /* Not actually needed but it does not harm. */
733   if (!nonce)
734     {
735       err = gpg_error_from_syserror ();
736       goto leave;
737     }
738
739   fname = strconcat (dname, "/", nonce, NULL);
740   if (!fname)
741     {
742       err = gpg_error_from_syserror ();
743       goto leave;
744     }
745
746   /* With 128 bits of random we can expect that no other file exists
747    * under this name.  We use "x" to detect internal errors.  */
748   outfp = es_fopen (fname, "wbx,mode=-rw");
749   if (!outfp)
750     {
751       err = gpg_error_from_syserror ();
752       log_error ("error creating '%s': %s\n", fname, gpg_strerror (err));
753       goto leave;
754     }
755   es_rewind (key);
756   for (;;)
757     {
758       if (es_read (key, buffer, sizeof buffer, &nbytes))
759         {
760           err = gpg_error_from_syserror ();
761           log_error ("error reading '%s': %s\n",
762                      es_fname_get (key), gpg_strerror (err));
763           break;
764         }
765
766       if (!nbytes)
767         {
768           err = 0;
769           goto leave; /* Ready.  */
770         }
771       if (es_write (outfp, buffer, nbytes, &nwritten))
772         {
773           err = gpg_error_from_syserror ();
774           log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
775           goto leave;
776         }
777       else if (nwritten != nbytes)
778         {
779           err = gpg_error (GPG_ERR_EIO);
780           log_error ("error writing '%s': %s\n", fname, "short write");
781           goto leave;
782         }
783     }
784
785  leave:
786   if (err)
787     {
788       es_fclose (outfp);
789       gnupg_remove (fname);
790     }
791   else if (es_fclose (outfp))
792     {
793       err = gpg_error_from_syserror ();
794       log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
795     }
796
797   if (!err)
798     {
799       *r_nonce = nonce;
800       *r_fname = fname;
801     }
802   else
803     {
804       xfree (nonce);
805       xfree (fname);
806     }
807   xfree (dname);
808   return err;
809 }
810
811
812 /* Send a confirmation rewqyest.  DIR is the directory used for the
813  * address MBOX.  NONCE is the nonce we want to see in the response to
814  * this mail.  FNAME the name of the file with the key.  */
815 static gpg_error_t
816 send_confirmation_request (server_ctx_t ctx,
817                            const char *mbox, const char *nonce,
818                            const char *keyfile)
819 {
820   gpg_error_t err;
821   estream_t body = NULL;
822   estream_t bodyenc = NULL;
823   mime_maker_t mime = NULL;
824   char *from_buffer = NULL;
825   const char *from;
826   strlist_t sl;
827
828   from = from_buffer = get_submission_address (mbox);
829   if (!from)
830     {
831       from = opt.default_from;
832       if (!from)
833         {
834           log_error ("no sender address found for '%s'\n", mbox);
835           err = gpg_error (GPG_ERR_CONFIGURATION);
836           goto leave;
837         }
838       log_info ("Note: using default sender address '%s'\n", from);
839     }
840
841   body = es_fopenmem (0, "w+b");
842   if (!body)
843     {
844       err = gpg_error_from_syserror ();
845       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
846       goto leave;
847     }
848   /* It is fine to use 8 bit encoding because that is encrypted and
849    * only our client will see it.  */
850   es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
851             "Content-Transfer-Encoding: 8bit\n"
852             "\n",
853             body);
854
855   es_fprintf (body, ("type: confirmation-request\n"
856                      "sender: %s\n"
857                      "address: %s\n"
858                      "fingerprint: %s\n"
859                      "nonce: %s\n"),
860               from,
861               mbox,
862               ctx->fpr,
863               nonce);
864
865   es_rewind (body);
866   err = encrypt_stream (&bodyenc, body, keyfile);
867   if (err)
868     goto leave;
869   es_fclose (body);
870   body = NULL;
871
872
873   err = mime_maker_new (&mime, NULL);
874   if (err)
875     goto leave;
876   err = mime_maker_add_header (mime, "From", from);
877   if (err)
878     goto leave;
879   err = mime_maker_add_header (mime, "To", mbox);
880   if (err)
881     goto leave;
882   err = mime_maker_add_header (mime, "Subject", "Confirm your key publication");
883   if (err)
884     goto leave;
885   for (sl = opt.extra_headers; sl; sl = sl->next)
886     {
887       err = mime_maker_add_header (mime, sl->d, NULL);
888       if (err)
889         goto leave;
890     }
891
892   err = mime_maker_add_header (mime, "Content-Type",
893                                "multipart/encrypted; "
894                                "protocol=\"application/pgp-encrypted\"");
895   if (err)
896     goto leave;
897   err = mime_maker_add_container (mime, "multipart/encrypted");
898   if (err)
899     goto leave;
900
901   err = mime_maker_add_header (mime, "Content-Type",
902                                "application/pgp-encrypted");
903   if (err)
904     goto leave;
905   err = mime_maker_add_body (mime, "Version: 1\n");
906   if (err)
907     goto leave;
908   err = mime_maker_add_header (mime, "Content-Type",
909                                "application/octet-stream");
910   if (err)
911     goto leave;
912
913   err = mime_maker_add_stream (mime, &bodyenc);
914   if (err)
915     goto leave;
916
917   err = wks_send_mime (mime);
918
919  leave:
920   mime_maker_release (mime);
921   es_fclose (bodyenc);
922   es_fclose (body);
923   xfree (from_buffer);
924   return err;
925 }
926
927
928 /* Store the key given by KEY into the pending directory and send a
929  * confirmation requests.  */
930 static gpg_error_t
931 process_new_key (server_ctx_t ctx, estream_t key)
932 {
933   gpg_error_t err;
934   strlist_t sl;
935   const char *s;
936   char *dname = NULL;
937   char *nonce = NULL;
938   char *fname = NULL;
939
940   /* First figure out the user id from the key.  */
941   err = list_key (ctx, key);
942   if (err)
943     goto leave;
944   if (!ctx->fpr)
945     {
946       log_error ("error parsing key (no fingerprint)\n");
947       err = gpg_error (GPG_ERR_NO_PUBKEY);
948       goto leave;
949     }
950   log_info ("fingerprint: %s\n", ctx->fpr);
951   for (sl = ctx->mboxes; sl; sl = sl->next)
952     {
953       log_info ("  addr-spec: %s\n", sl->d);
954     }
955
956   /* Walk over all user ids and send confirmation requests for those
957    * we support.  */
958   for (sl = ctx->mboxes; sl; sl = sl->next)
959     {
960       s = strchr (sl->d, '@');
961       log_assert (s && s[1]);
962       xfree (dname);
963       dname = make_filename_try (opt.directory, s+1, NULL);
964       if (!dname)
965         {
966           err = gpg_error_from_syserror ();
967           goto leave;
968         }
969       /* Fixme: check for proper directory permissions.  */
970       if (access (dname, W_OK))
971         {
972           log_info ("skipping address '%s': Domain not configured\n", sl->d);
973           continue;
974         }
975       log_info ("storing address '%s'\n", sl->d);
976
977       xfree (nonce);
978       xfree (fname);
979       err = store_key_as_pending (dname, key, &nonce, &fname);
980       if (err)
981         goto leave;
982
983       err = send_confirmation_request (ctx, sl->d, nonce, fname);
984       if (err)
985         goto leave;
986     }
987
988  leave:
989   if (nonce)
990     wipememory (nonce, strlen (nonce));
991   xfree (nonce);
992   xfree (fname);
993   xfree (dname);
994   return err;
995 }
996
997
998 \f
999 /* Check that we have send a request with NONCE and publish the key.  */
1000 static gpg_error_t
1001 check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
1002 {
1003   gpg_error_t err;
1004   char *fname = NULL;
1005   char *fnewname = NULL;
1006   estream_t key = NULL;
1007   char *hash = NULL;
1008   const char *domain;
1009   const char *s;
1010   strlist_t sl;
1011   char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1012
1013   /* FIXME: There is a bug in name-value.c which adds white space for
1014    * the last pair and thus we strip the nonce here until this has
1015    * been fixed.  */
1016   char *nonce2 = xstrdup (nonce);
1017   trim_trailing_spaces (nonce2);
1018   nonce = nonce2;
1019
1020
1021   domain = strchr (address, '@');
1022   log_assert (domain && domain[1]);
1023   domain++;
1024   fname = make_filename_try (opt.directory, domain, "pending", nonce, NULL);
1025   if (!fname)
1026     {
1027       err = gpg_error_from_syserror ();
1028       goto leave;
1029     }
1030
1031   /* Try to open the file with the key.  */
1032   key = es_fopen (fname, "rb");
1033   if (!key)
1034     {
1035       err = gpg_error_from_syserror ();
1036       if (gpg_err_code (err) == GPG_ERR_ENOENT)
1037         {
1038           log_info ("no pending request for '%s'\n", address);
1039           err = gpg_error (GPG_ERR_NOT_FOUND);
1040         }
1041       else
1042         log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
1043       goto leave;
1044     }
1045
1046   /* We need to get the fingerprint from the key.  */
1047   err = list_key (ctx, key);
1048   if (err)
1049     goto leave;
1050   if (!ctx->fpr)
1051     {
1052       log_error ("error parsing key (no fingerprint)\n");
1053       err = gpg_error (GPG_ERR_NO_PUBKEY);
1054       goto leave;
1055     }
1056   log_info ("fingerprint: %s\n", ctx->fpr);
1057   for (sl = ctx->mboxes; sl; sl = sl->next)
1058     log_info ("  addr-spec: %s\n", sl->d);
1059
1060   /* Check that the key has 'address' as a user id.  We use
1061    * case-insensitive matching because the client is expected to
1062    * return the address verbatim.  */
1063   for (sl = ctx->mboxes; sl; sl = sl->next)
1064     if (!strcmp (sl->d, address))
1065       break;
1066   if (!sl)
1067     {
1068       log_error ("error publishing key: '%s' is not a user ID of %s\n",
1069                  address, ctx->fpr);
1070       err = gpg_error (GPG_ERR_NO_PUBKEY);
1071       goto leave;
1072     }
1073
1074
1075   /* Hash user ID and create filename.  */
1076   s = strchr (address, '@');
1077   log_assert (s);
1078   gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
1079   hash = zb32_encode (shaxbuf, 8*20);
1080   if (!hash)
1081     {
1082       err = gpg_error_from_syserror ();
1083       goto leave;
1084     }
1085
1086   fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1087   if (!fnewname)
1088     {
1089       err = gpg_error_from_syserror ();
1090       goto leave;
1091     }
1092
1093   /* Publish.  */
1094   if (rename (fname, fnewname))
1095     {
1096       err = gpg_error_from_syserror ();
1097       log_error ("renaming '%s' to '%s' failed: %s\n",
1098                  fname, fnewname, gpg_strerror (err));
1099       goto leave;
1100     }
1101
1102   log_info ("key %s published for '%s'\n", ctx->fpr, address);
1103
1104
1105   /* Try to publish as DANE record if the DANE directory exists.  */
1106   xfree (fname);
1107   fname = fnewname;
1108   fnewname = make_filename_try (opt.directory, domain, "dane", NULL);
1109   if (!fnewname)
1110     {
1111       err = gpg_error_from_syserror ();
1112       goto leave;
1113     }
1114   if (!access (fnewname, W_OK))
1115     {
1116       /* Yes, we have a dane directory.  */
1117       s = strchr (address, '@');
1118       log_assert (s);
1119       gcry_md_hash_buffer (GCRY_MD_SHA256, shaxbuf, address, s - address);
1120       xfree (hash);
1121       hash = bin2hex (shaxbuf, 28, NULL);
1122       if (!hash)
1123         {
1124           err = gpg_error_from_syserror ();
1125           goto leave;
1126         }
1127       xfree (fnewname);
1128       fnewname = make_filename_try (opt.directory, domain, "dane", hash, NULL);
1129       if (!fnewname)
1130         {
1131           err = gpg_error_from_syserror ();
1132           goto leave;
1133         }
1134       err = copy_key_as_dane (fname, fnewname);
1135       if (err)
1136         goto leave;
1137       log_info ("key %s published for '%s' (DANE record)\n", ctx->fpr, address);
1138     }
1139
1140
1141  leave:
1142   es_fclose (key);
1143   xfree (hash);
1144   xfree (fnewname);
1145   xfree (fname);
1146   xfree (nonce2);
1147   return err;
1148 }
1149
1150
1151 /* Process a confirmation response in MSG.  */
1152 static gpg_error_t
1153 process_confirmation_response (server_ctx_t ctx, estream_t msg)
1154 {
1155   gpg_error_t err;
1156   nvc_t nvc;
1157   nve_t item;
1158   const char *value, *sender, *address, *nonce;
1159
1160   err = nvc_parse (&nvc, NULL, msg);
1161   if (err)
1162     {
1163       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1164       goto leave;
1165     }
1166
1167   if (opt.debug)
1168     {
1169       log_debug ("response follows:\n");
1170       nvc_write (nvc, log_get_stream ());
1171     }
1172
1173   /* Check that this is a confirmation response.  */
1174   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1175         && !strcmp (value, "confirmation-response")))
1176     {
1177       if (item && value)
1178         log_error ("received unexpected wks message '%s'\n", value);
1179       else
1180         log_error ("received invalid wks message: %s\n", "'type' missing");
1181       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1182       goto leave;
1183     }
1184
1185   /* Get the sender.  */
1186   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1187         && is_valid_mailbox (value)))
1188     {
1189       log_error ("received invalid wks message: %s\n",
1190                  "'sender' missing or invalid");
1191       err = gpg_error (GPG_ERR_INV_DATA);
1192       goto leave;
1193     }
1194   sender = value;
1195   (void)sender;
1196   /* FIXME: Do we really need the sender?.  */
1197
1198   /* Get the address.  */
1199   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1200         && is_valid_mailbox (value)))
1201     {
1202       log_error ("received invalid wks message: %s\n",
1203                  "'address' missing or invalid");
1204       err = gpg_error (GPG_ERR_INV_DATA);
1205       goto leave;
1206     }
1207   address = value;
1208
1209   /* Get the nonce.  */
1210   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1211         && strlen (value) > 16))
1212     {
1213       log_error ("received invalid wks message: %s\n",
1214                  "'nonce' missing or too short");
1215       err = gpg_error (GPG_ERR_INV_DATA);
1216       goto leave;
1217     }
1218   nonce = value;
1219
1220   err = check_and_publish (ctx, address, nonce);
1221
1222
1223  leave:
1224   nvc_release (nvc);
1225   return err;
1226 }
1227
1228
1229 \f
1230 /* Called from the MIME receiver to process the plain text data in MSG .  */
1231 static gpg_error_t
1232 command_receive_cb (void *opaque, const char *mediatype, estream_t msg)
1233 {
1234   gpg_error_t err;
1235   struct server_ctx_s ctx;
1236
1237   memset (&ctx, 0, sizeof ctx);
1238
1239   (void)opaque;
1240
1241   if (!strcmp (mediatype, "application/pgp-keys"))
1242     err = process_new_key (&ctx, msg);
1243   else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1244     err = process_confirmation_response (&ctx, msg);
1245   else
1246     {
1247       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1248       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1249     }
1250
1251   xfree (ctx.fpr);
1252   free_strlist (ctx.mboxes);
1253
1254   return err;
1255 }
1256
1257
1258 \f
1259 /* Return a list of all configured domains.  ECh list element is the
1260  * top directory for for the domain.  To figure out the actual domain
1261  * name strrchr(name, '/') can be used.  */
1262 static gpg_error_t
1263 get_domain_list (strlist_t *r_list)
1264 {
1265   gpg_error_t err;
1266   DIR *dir = NULL;
1267   char *fname = NULL;
1268   struct dirent *dentry;
1269   struct stat sb;
1270   strlist_t list = NULL;
1271
1272   *r_list = NULL;
1273
1274   dir = opendir (opt.directory);
1275   if (!dir)
1276     {
1277       err = gpg_error_from_syserror ();
1278       goto leave;
1279     }
1280
1281   while ((dentry = readdir (dir)))
1282     {
1283       if (*dentry->d_name == '.')
1284         continue;
1285       if (!strchr (dentry->d_name, '.'))
1286         continue; /* No dot - can't be a domain subdir.  */
1287
1288       xfree (fname);
1289       fname = make_filename_try (opt.directory, dentry->d_name, NULL);
1290       if (!fname)
1291         {
1292           err = gpg_error_from_syserror ();
1293           log_error ("make_filename failed in %s: %s\n",
1294                      __func__, gpg_strerror (err));
1295           goto leave;
1296         }
1297
1298       if (stat (fname, &sb))
1299         {
1300           err = gpg_error_from_syserror ();
1301           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1302           continue;
1303         }
1304       if (!S_ISDIR(sb.st_mode))
1305         continue;
1306
1307       if (!add_to_strlist_try (&list, fname))
1308         {
1309           err = gpg_error_from_syserror ();
1310           log_error ("add_to_strlist failed in %s: %s\n",
1311                      __func__, gpg_strerror (err));
1312           goto leave;
1313         }
1314     }
1315   err = 0;
1316   *r_list = list;
1317   list = NULL;
1318
1319  leave:
1320   free_strlist (list);
1321   if (dir)
1322     closedir (dir);
1323   xfree (fname);
1324   return err;
1325 }
1326
1327
1328 \f
1329 static gpg_error_t
1330 expire_one_domain (const char *top_dirname, const char *domain)
1331 {
1332   gpg_error_t err;
1333   char *dirname;
1334   char *fname = NULL;
1335   DIR *dir = NULL;
1336   struct dirent *dentry;
1337   struct stat sb;
1338   time_t now = gnupg_get_time ();
1339
1340   dirname = make_filename_try (top_dirname, "pending", NULL);
1341   if (!dirname)
1342     {
1343       err = gpg_error_from_syserror ();
1344       log_error ("make_filename failed in %s: %s\n",
1345                  __func__, gpg_strerror (err));
1346       goto leave;
1347     }
1348
1349   dir = opendir (dirname);
1350   if (!dir)
1351     {
1352       err = gpg_error_from_syserror ();
1353       log_error (("can't access directory '%s': %s\n"),
1354                  dirname, gpg_strerror (err));
1355       goto leave;
1356     }
1357
1358   while ((dentry = readdir (dir)))
1359     {
1360       if (*dentry->d_name == '.')
1361         continue;
1362       xfree (fname);
1363       fname = make_filename_try (dirname, dentry->d_name, NULL);
1364       if (!fname)
1365         {
1366           err = gpg_error_from_syserror ();
1367           log_error ("make_filename failed in %s: %s\n",
1368                      __func__, gpg_strerror (err));
1369           goto leave;
1370         }
1371       if (strlen (dentry->d_name) != 32)
1372         {
1373           log_info ("garbage file '%s' ignored\n", fname);
1374           continue;
1375         }
1376       if (stat (fname, &sb))
1377         {
1378           err = gpg_error_from_syserror ();
1379           log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1380           continue;
1381         }
1382       if (S_ISDIR(sb.st_mode))
1383         {
1384           log_info ("garbage directory '%s' ignored\n", fname);
1385           continue;
1386         }
1387       if (sb.st_mtime + PENDING_TTL < now)
1388         {
1389           if (opt.verbose)
1390             log_info ("domain %s: removing pending key '%s'\n",
1391                       domain, dentry->d_name);
1392           if (remove (fname))
1393             {
1394               err = gpg_error_from_syserror ();
1395               /* In case the file has just been renamed or another
1396                * processes is cleaning up, we don't print a diagnostic
1397                * for ENOENT.  */
1398               if (gpg_err_code (err) != GPG_ERR_ENOENT)
1399                 log_error ("error removing '%s': %s\n",
1400                            fname, gpg_strerror (err));
1401             }
1402         }
1403     }
1404   err = 0;
1405
1406  leave:
1407   if (dir)
1408     closedir (dir);
1409   xfree (dirname);
1410   xfree (fname);
1411   return err;
1412
1413 }
1414
1415
1416 /* Scan spool directories and expire too old pending keys.  */
1417 static gpg_error_t
1418 expire_pending_confirmations (strlist_t domaindirs)
1419 {
1420   gpg_error_t err = 0;
1421   strlist_t sl;
1422   const char *domain;
1423
1424   for (sl = domaindirs; sl; sl = sl->next)
1425     {
1426       domain = strrchr (sl->d, '/');
1427       log_assert (domain);
1428       domain++;
1429
1430       expire_one_domain (sl->d, domain);
1431     }
1432
1433   return err;
1434 }
1435
1436
1437 /* List all configured domains.  */
1438 static gpg_error_t
1439 command_list_domains (void)
1440 {
1441   static struct {
1442     const char *name;
1443     const char *perm;
1444   } requireddirs[] = {
1445     { "pending", "-rwx" },
1446     { "hu",      "-rwxr-xr-x" }
1447   };
1448
1449   gpg_error_t err;
1450   strlist_t domaindirs;
1451   strlist_t sl;
1452   const char *domain;
1453   char *fname = NULL;
1454   int i;
1455
1456   err = get_domain_list (&domaindirs);
1457   if (err)
1458     {
1459       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1460       return err;
1461     }
1462
1463   for (sl = domaindirs; sl; sl = sl->next)
1464     {
1465       domain = strrchr (sl->d, '/');
1466       log_assert (domain);
1467       domain++;
1468       es_printf ("%s\n", domain);
1469
1470       /* Check that the required directories are there.  */
1471       for (i=0; i < DIM (requireddirs); i++)
1472         {
1473           xfree (fname);
1474           fname = make_filename_try (sl->d, requireddirs[i].name, NULL);
1475           if (!fname)
1476             {
1477               err = gpg_error_from_syserror ();
1478               goto leave;
1479             }
1480           if (access (fname, W_OK))
1481             {
1482               err = gpg_error_from_syserror ();
1483               if (gpg_err_code (err) == GPG_ERR_ENOENT)
1484                 {
1485                   if (gnupg_mkdir (fname, requireddirs[i].perm))
1486                     {
1487                       err = gpg_error_from_syserror ();
1488                       log_error ("domain %s: error creating subdir '%s': %s\n",
1489                                  domain, requireddirs[i].name,
1490                                  gpg_strerror (err));
1491                     }
1492                   else
1493                     log_info ("domain %s: subdir '%s' created\n",
1494                               domain, requireddirs[i].name);
1495                 }
1496               else if (err)
1497                 log_error ("domain %s: problem with subdir '%s': %s\n",
1498                            domain, requireddirs[i].name, gpg_strerror (err));
1499             }
1500         }
1501
1502       /* Print a warning if the sumbission address is not configured.  */
1503       xfree (fname);
1504       fname = make_filename_try (sl->d, "submission-address", NULL);
1505       if (!fname)
1506         {
1507           err = gpg_error_from_syserror ();
1508           goto leave;
1509         }
1510       if (access (fname, F_OK))
1511         {
1512           err = gpg_error_from_syserror ();
1513           if (gpg_err_code (err) == GPG_ERR_ENOENT)
1514             log_error ("domain %s: submission address not configured\n",
1515                        domain);
1516           else
1517             log_error ("domain %s: problem with '%s': %s\n",
1518                        domain, fname, gpg_strerror (err));
1519         }
1520     }
1521   err = 0;
1522
1523  leave:
1524   xfree (fname);
1525   free_strlist (domaindirs);
1526   return err;
1527 }
1528
1529
1530 /* Run regular maintenance jobs.  */
1531 static gpg_error_t
1532 command_cron (void)
1533 {
1534   gpg_error_t err;
1535   strlist_t domaindirs;
1536
1537   err = get_domain_list (&domaindirs);
1538   if (err)
1539     {
1540       log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1541       return err;
1542     }
1543
1544   err = expire_pending_confirmations (domaindirs);
1545
1546   free_strlist (domaindirs);
1547   return err;
1548 }