wks: Send only the newest UID to the server.
[gnupg.git] / tools / gpg-wks-client.c
1 /* gpg-wks-client.c - A client for the Web Key Service protocols.
2  * Copyright (C) 2016 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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "../common/util.h"
27 #include "../common/status.h"
28 #include "../common/i18n.h"
29 #include "../common/sysutils.h"
30 #include "../common/init.h"
31 #include "../common/asshelp.h"
32 #include "../common/userids.h"
33 #include "../common/ccparray.h"
34 #include "../common/exectool.h"
35 #include "../common/mbox-util.h"
36 #include "../common/name-value.h"
37 #include "call-dirmngr.h"
38 #include "mime-maker.h"
39 #include "send-mail.h"
40 #include "gpg-wks.h"
41
42
43 /* Constants to identify the commands and options. */
44 enum cmd_and_opt_values
45   {
46     aNull = 0,
47
48     oQuiet      = 'q',
49     oVerbose    = 'v',
50     oOutput     = 'o',
51
52     oDebug      = 500,
53
54     aSupported,
55     aCheck,
56     aCreate,
57     aReceive,
58     aRead,
59
60     oGpgProgram,
61     oSend,
62     oFakeSubmissionAddr,
63     oStatusFD,
64
65     oDummy
66   };
67
68
69 /* The list of commands and options. */
70 static ARGPARSE_OPTS opts[] = {
71   ARGPARSE_group (300, ("@Commands:\n ")),
72
73   ARGPARSE_c (aSupported, "supported",
74               ("check whether provider supports WKS")),
75   ARGPARSE_c (aCheck, "check",
76               ("check whether a key is available")),
77   ARGPARSE_c (aCreate,   "create",
78               ("create a publication request")),
79   ARGPARSE_c (aReceive,   "receive",
80               ("receive a MIME confirmation request")),
81   ARGPARSE_c (aRead,      "read",
82               ("receive a plain text confirmation request")),
83
84   ARGPARSE_group (301, ("@\nOptions:\n ")),
85
86   ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
87   ARGPARSE_s_n (oQuiet, "quiet",  ("be somewhat more quiet")),
88   ARGPARSE_s_s (oDebug, "debug", "@"),
89   ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
90   ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
91   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
92   ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
93
94   ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
95
96   ARGPARSE_end ()
97 };
98
99
100 /* The list of supported debug flags.  */
101 static struct debug_flags_s debug_flags [] =
102   {
103     { DBG_MIME_VALUE   , "mime"    },
104     { DBG_PARSER_VALUE , "parser"  },
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
115 /* Value of the option --fake-submission-addr.  */
116 const char *fake_submission_addr;
117
118
119 static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
120 static gpg_error_t command_supported (char *userid);
121 static gpg_error_t command_check (char *userid);
122 static gpg_error_t command_send (const char *fingerprint, const char *userid);
123 static gpg_error_t encrypt_response (estream_t *r_output, estream_t input,
124                                      const char *addrspec,
125                                      const char *fingerprint);
126 static gpg_error_t read_confirmation_request (estream_t msg);
127 static gpg_error_t command_receive_cb (void *opaque,
128                                        const char *mediatype, estream_t fp,
129                                        unsigned int flags);
130
131
132 \f
133 /* Print usage information and provide strings for help. */
134 static const char *
135 my_strusage( int level )
136 {
137   const char *p;
138
139   switch (level)
140     {
141     case 11: p = "gpg-wks-client"; break;
142     case 12: p = "@GNUPG@"; break;
143     case 13: p = VERSION; break;
144     case 17: p = PRINTABLE_OS_NAME; break;
145     case 19: p = ("Please report bugs to <@EMAIL@>.\n"); break;
146
147     case 1:
148     case 40:
149       p = ("Usage: gpg-wks-client [command] [options] [args] (-h for help)");
150       break;
151     case 41:
152       p = ("Syntax: gpg-wks-client [command] [options] [args]\n"
153            "Client for the Web Key Service\n");
154       break;
155
156     default: p = NULL; break;
157     }
158   return p;
159 }
160
161
162 static void
163 wrong_args (const char *text)
164 {
165   es_fprintf (es_stderr, _("usage: %s [options] %s\n"), strusage (11), text);
166   exit (2);
167 }
168
169
170 \f
171 /* Command line parsing.  */
172 static enum cmd_and_opt_values
173 parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
174 {
175   enum cmd_and_opt_values cmd = 0;
176   int no_more_options = 0;
177
178   while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
179     {
180       switch (pargs->r_opt)
181         {
182         case oQuiet:     opt.quiet = 1; break;
183         case oVerbose:   opt.verbose++; break;
184         case oDebug:
185           if (parse_debug_flag (pargs->r.ret_str, &opt.debug, debug_flags))
186             {
187               pargs->r_opt = ARGPARSE_INVALID_ARG;
188               pargs->err = ARGPARSE_PRINT_ERROR;
189             }
190           break;
191
192         case oGpgProgram:
193           opt.gpg_program = pargs->r.ret_str;
194           break;
195         case oSend:
196           opt.use_sendmail = 1;
197           break;
198         case oOutput:
199           opt.output = pargs->r.ret_str;
200           break;
201         case oFakeSubmissionAddr:
202           fake_submission_addr = pargs->r.ret_str;
203           break;
204         case oStatusFD:
205           wks_set_status_fd (translate_sys2libc_fd_int (pargs->r.ret_int, 1));
206           break;
207
208         case aSupported:
209         case aCreate:
210         case aReceive:
211         case aRead:
212         case aCheck:
213           cmd = pargs->r_opt;
214           break;
215
216         default: pargs->err = 2; break;
217         }
218     }
219
220   return cmd;
221 }
222
223
224 \f
225 /* gpg-wks-client main. */
226 int
227 main (int argc, char **argv)
228 {
229   gpg_error_t err;
230   ARGPARSE_ARGS pargs;
231   enum cmd_and_opt_values cmd;
232
233   gnupg_reopen_std ("gpg-wks-client");
234   set_strusage (my_strusage);
235   log_set_prefix ("gpg-wks-client", GPGRT_LOG_WITH_PREFIX);
236
237   /* Make sure that our subsystems are ready.  */
238   i18n_init();
239   init_common_subsystems (&argc, &argv);
240
241   assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
242   setup_libassuan_logging (&opt.debug, NULL);
243
244   /* Parse the command line. */
245   pargs.argc  = &argc;
246   pargs.argv  = &argv;
247   pargs.flags = ARGPARSE_FLAG_KEEP;
248   cmd = parse_arguments (&pargs, opts);
249
250   if (log_get_errorcount (0))
251     exit (2);
252
253   /* Print a warning if an argument looks like an option.  */
254   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
255     {
256       int i;
257
258       for (i=0; i < argc; i++)
259         if (argv[i][0] == '-' && argv[i][1] == '-')
260           log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
261     }
262
263   /* Set defaults for non given options.  */
264   if (!opt.gpg_program)
265     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
266
267   /* Tell call-dirmngr what options we want.  */
268   set_dirmngr_options (opt.verbose, (opt.debug & DBG_IPC_VALUE), 1);
269
270   /* Run the selected command.  */
271   switch (cmd)
272     {
273     case aSupported:
274       if (argc != 1)
275         wrong_args ("--supported USER-ID");
276       err = command_supported (argv[0]);
277       if (err && gpg_err_code (err) != GPG_ERR_FALSE)
278         log_error ("checking support failed: %s\n", gpg_strerror (err));
279       break;
280
281     case aCreate:
282       if (argc != 2)
283         wrong_args ("--create FINGERPRINT USER-ID");
284       err = command_send (argv[0], argv[1]);
285       if (err)
286         log_error ("creating request failed: %s\n", gpg_strerror (err));
287       break;
288
289     case aReceive:
290       if (argc)
291         wrong_args ("--receive < MIME-DATA");
292       err = wks_receive (es_stdin, command_receive_cb, NULL);
293       if (err)
294         log_error ("processing mail failed: %s\n", gpg_strerror (err));
295       break;
296
297     case aRead:
298       if (argc)
299         wrong_args ("--read < WKS-DATA");
300       err = read_confirmation_request (es_stdin);
301       if (err)
302         log_error ("processing mail failed: %s\n", gpg_strerror (err));
303       break;
304
305     case aCheck:
306       if (argc != 1)
307         wrong_args ("--check USER-ID");
308       err = command_check (argv[0]);
309       break;
310
311     default:
312       usage (1);
313       err = 0;
314       break;
315     }
316
317   if (err)
318     wks_write_status (STATUS_FAILURE, "- %u", err);
319   else if (log_get_errorcount (0))
320     wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
321   else
322     wks_write_status (STATUS_SUCCESS, NULL);
323   return log_get_errorcount (0)? 1:0;
324 }
325
326
327 \f
328 struct get_key_status_parm_s
329 {
330   const char *fpr;
331   int found;
332   int count;
333 };
334
335 static void
336 get_key_status_cb (void *opaque, const char *keyword, char *args)
337 {
338   struct get_key_status_parm_s *parm = opaque;
339
340   /*log_debug ("%s: %s\n", keyword, args);*/
341   if (!strcmp (keyword, "EXPORTED"))
342     {
343       parm->count++;
344       if (!ascii_strcasecmp (args, parm->fpr))
345         parm->found = 1;
346     }
347 }
348
349
350 /* Get a key by fingerprint from gpg's keyring and make sure that the
351  * mail address ADDRSPEC is included in the key.  The key is returned
352  * as a new memory stream at R_KEY.  */
353 static gpg_error_t
354 get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
355 {
356   gpg_error_t err;
357   ccparray_t ccp;
358   const char **argv = NULL;
359   estream_t key = NULL;
360   struct get_key_status_parm_s parm;
361   char *filterexp = NULL;
362
363   memset (&parm, 0, sizeof parm);
364
365   *r_key = NULL;
366
367   key = es_fopenmem (0, "w+b");
368   if (!key)
369     {
370       err = gpg_error_from_syserror ();
371       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
372       goto leave;
373     }
374
375   /* Prefix the key with the MIME content type.  */
376   es_fputs ("Content-Type: application/pgp-keys\n"
377             "\n", key);
378
379   filterexp = es_bsprintf ("keep-uid=mbox = %s", addrspec);
380   if (!filterexp)
381     {
382       err = gpg_error_from_syserror ();
383       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
384       goto leave;
385     }
386
387   ccparray_init (&ccp, 0);
388
389   ccparray_put (&ccp, "--no-options");
390   if (!opt.verbose)
391     ccparray_put (&ccp, "--quiet");
392   else if (opt.verbose > 1)
393     ccparray_put (&ccp, "--verbose");
394   ccparray_put (&ccp, "--batch");
395   ccparray_put (&ccp, "--status-fd=2");
396   ccparray_put (&ccp, "--always-trust");
397   ccparray_put (&ccp, "--armor");
398   ccparray_put (&ccp, "--export-options=export-minimal");
399   ccparray_put (&ccp, "--export-filter");
400   ccparray_put (&ccp, filterexp);
401   ccparray_put (&ccp, "--export");
402   ccparray_put (&ccp, "--");
403   ccparray_put (&ccp, fingerprint);
404
405   ccparray_put (&ccp, NULL);
406   argv = ccparray_get (&ccp, NULL);
407   if (!argv)
408     {
409       err = gpg_error_from_syserror ();
410       goto leave;
411     }
412   parm.fpr = fingerprint;
413   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
414                                 NULL, key,
415                                 get_key_status_cb, &parm);
416   if (!err && parm.count > 1)
417     err = gpg_error (GPG_ERR_TOO_MANY);
418   else if (!err && !parm.found)
419     err = gpg_error (GPG_ERR_NOT_FOUND);
420   if (err)
421     {
422       log_error ("export failed: %s\n", gpg_strerror (err));
423       goto leave;
424     }
425
426   es_rewind (key);
427   *r_key = key;
428   key = NULL;
429
430  leave:
431   es_fclose (key);
432   xfree (argv);
433   xfree (filterexp);
434   return err;
435 }
436
437
438 \f
439 struct decrypt_stream_parm_s
440 {
441   char *fpr;
442   char *mainfpr;
443   int  otrust;
444 };
445
446 static void
447 decrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
448 {
449   struct decrypt_stream_parm_s *decinfo = opaque;
450
451   if (DBG_CRYPTO)
452     log_debug ("gpg status: %s %s\n", keyword, args);
453   if (!strcmp (keyword, "DECRYPTION_KEY") && !decinfo->fpr)
454     {
455       char *fields[3];
456
457       if (split_fields (args, fields, DIM (fields)) >= 3)
458         {
459           decinfo->fpr = xstrdup (fields[0]);
460           decinfo->mainfpr = xstrdup (fields[1]);
461           decinfo->otrust = *fields[2];
462         }
463     }
464 }
465
466 /* Decrypt the INPUT stream to a new stream which is stored at success
467  * at R_OUTPUT.  */
468 static gpg_error_t
469 decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
470                 estream_t input)
471 {
472   gpg_error_t err;
473   ccparray_t ccp;
474   const char **argv;
475   estream_t output;
476
477   *r_output = NULL;
478   memset (decinfo, 0, sizeof *decinfo);
479
480   output = es_fopenmem (0, "w+b");
481   if (!output)
482     {
483       err = gpg_error_from_syserror ();
484       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
485       return err;
486     }
487
488   ccparray_init (&ccp, 0);
489
490   ccparray_put (&ccp, "--no-options");
491   /* We limit the output to 64 KiB to avoid DoS using compression
492    * tricks.  A regular client will anyway only send a minimal key;
493    * that is one w/o key signatures and attribute packets.  */
494   ccparray_put (&ccp, "--max-output=0x10000");
495   if (!opt.verbose)
496     ccparray_put (&ccp, "--quiet");
497   else if (opt.verbose > 1)
498     ccparray_put (&ccp, "--verbose");
499   ccparray_put (&ccp, "--batch");
500   ccparray_put (&ccp, "--status-fd=2");
501   ccparray_put (&ccp, "--decrypt");
502   ccparray_put (&ccp, "--");
503
504   ccparray_put (&ccp, NULL);
505   argv = ccparray_get (&ccp, NULL);
506   if (!argv)
507     {
508       err = gpg_error_from_syserror ();
509       goto leave;
510     }
511   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
512                                 NULL, output,
513                                 decrypt_stream_status_cb, decinfo);
514   if (!err && (!decinfo->fpr || !decinfo->mainfpr || !decinfo->otrust))
515     err = gpg_error (GPG_ERR_INV_ENGINE);
516   if (err)
517     {
518       log_error ("decryption failed: %s\n", gpg_strerror (err));
519       goto leave;
520     }
521   else if (opt.verbose)
522     log_info ("decryption succeeded\n");
523
524   es_rewind (output);
525   *r_output = output;
526   output = NULL;
527
528  leave:
529   if (err)
530     {
531       xfree (decinfo->fpr);
532       xfree (decinfo->mainfpr);
533       memset (decinfo, 0, sizeof *decinfo);
534     }
535   es_fclose (output);
536   xfree (argv);
537   return err;
538 }
539
540
541
542 \f
543 /* Check whether the  provider supports the WKS protocol.  */
544 static gpg_error_t
545 command_supported (char *userid)
546 {
547   gpg_error_t err;
548   char *addrspec = NULL;
549   char *submission_to = NULL;
550
551   if (!strchr (userid, '@'))
552     {
553       char *tmp = xstrconcat ("foo@", userid, NULL);
554       addrspec = mailbox_from_userid (tmp);
555       xfree (tmp);
556     }
557   else
558     addrspec = mailbox_from_userid (userid);
559   if (!addrspec)
560     {
561       log_error (_("\"%s\" is not a proper mail address\n"), userid);
562       err = gpg_error (GPG_ERR_INV_USER_ID);
563       goto leave;
564     }
565
566   /* Get the submission address.  */
567   err = wkd_get_submission_address (addrspec, &submission_to);
568   if (err)
569     {
570       if (gpg_err_code (err) == GPG_ERR_NO_DATA
571           || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST)
572         {
573           if (opt.verbose)
574             log_info ("provider for '%s' does NOT support WKS (%s)\n",
575                       addrspec, gpg_strerror (err));
576           err = gpg_error (GPG_ERR_FALSE);
577           log_inc_errorcount ();
578         }
579       goto leave;
580     }
581   if (opt.verbose)
582     log_info ("provider for '%s' supports WKS\n", addrspec);
583
584  leave:
585   xfree (submission_to);
586   xfree (addrspec);
587   return err;
588 }
589
590
591 \f
592 /* Check whether the key for USERID is available in the WKD.  */
593 static gpg_error_t
594 command_check (char *userid)
595 {
596   gpg_error_t err;
597   char *addrspec = NULL;
598   estream_t key = NULL;
599   char *fpr = NULL;
600   uidinfo_list_t mboxes = NULL;
601   uidinfo_list_t sl;
602   int found = 0;
603
604   addrspec = mailbox_from_userid (userid);
605   if (!addrspec)
606     {
607       log_error (_("\"%s\" is not a proper mail address\n"), userid);
608       err = gpg_error (GPG_ERR_INV_USER_ID);
609       goto leave;
610     }
611
612   /* Get the submission address.  */
613   err = wkd_get_key (addrspec, &key);
614   switch (gpg_err_code (err))
615     {
616     case 0:
617       if (opt.verbose)
618         log_info ("public key for '%s' found via WKD\n", addrspec);
619       /* Fixme: Check that the key contains the user id.  */
620       break;
621
622     case GPG_ERR_NO_DATA: /* No such key.  */
623       if (opt.verbose)
624         log_info ("public key for '%s' NOT found via WKD\n", addrspec);
625       err = gpg_error (GPG_ERR_NO_PUBKEY);
626       log_inc_errorcount ();
627       break;
628
629     case GPG_ERR_UNKNOWN_HOST:
630       if (opt.verbose)
631         log_info ("error looking up '%s' via WKD: %s\n",
632                   addrspec, gpg_strerror (err));
633       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
634       break;
635
636     default:
637       log_error ("error looking up '%s' via WKD: %s\n",
638                  addrspec, gpg_strerror (err));
639       break;
640     }
641
642   if (err)
643     goto leave;
644
645   /* Look closer at the key.  */
646   err = wks_list_key (key, &fpr, &mboxes);
647   if (err)
648     {
649       log_error ("error parsing key: %s\n", gpg_strerror (err));
650       err = gpg_error (GPG_ERR_NO_PUBKEY);
651       goto leave;
652     }
653
654   if (opt.verbose)
655     log_info ("fingerprint: %s\n", fpr);
656
657   for (sl = mboxes; sl; sl = sl->next)
658     {
659       if (sl->mbox && !strcmp (sl->mbox, addrspec))
660         found = 1;
661       if (opt.verbose)
662         {
663           log_info ("    user-id: %s\n", sl->uid);
664           log_info ("    created: %s\n", asctimestamp (sl->created));
665           if (sl->mbox)
666             log_info ("  addr-spec: %s\n", sl->mbox);
667         }
668     }
669   if (!found)
670     {
671       log_error ("public key for '%s' has no user id with the mail address\n",
672                  addrspec);
673       err = gpg_error (GPG_ERR_CERT_REVOKED);
674     }
675
676  leave:
677   xfree (fpr);
678   free_uidinfo_list (mboxes);
679   es_fclose (key);
680   xfree (addrspec);
681   return err;
682 }
683
684
685 \f
686 /* Locate the key by fingerprint and userid and send a publication
687  * request.  */
688 static gpg_error_t
689 command_send (const char *fingerprint, const char *userid)
690 {
691   gpg_error_t err;
692   KEYDB_SEARCH_DESC desc;
693   char *addrspec = NULL;
694   estream_t key = NULL;
695   estream_t keyenc = NULL;
696   char *submission_to = NULL;
697   mime_maker_t mime = NULL;
698   struct policy_flags_s policy;
699   int no_encrypt = 0;
700   int posteo_hack = 0;
701   const char *domain;
702   uidinfo_list_t uidlist = NULL;
703   uidinfo_list_t uid, thisuid;
704   time_t thistime;
705
706   memset (&policy, 0, sizeof policy);
707
708   if (classify_user_id (fingerprint, &desc, 1)
709       || !(desc.mode == KEYDB_SEARCH_MODE_FPR
710            || desc.mode == KEYDB_SEARCH_MODE_FPR20))
711     {
712       log_error (_("\"%s\" is not a fingerprint\n"), fingerprint);
713       err = gpg_error (GPG_ERR_INV_NAME);
714       goto leave;
715     }
716
717   addrspec = mailbox_from_userid (userid);
718   if (!addrspec)
719     {
720       log_error (_("\"%s\" is not a proper mail address\n"), userid);
721       err = gpg_error (GPG_ERR_INV_USER_ID);
722       goto leave;
723     }
724   err = get_key (&key, fingerprint, addrspec);
725   if (err)
726     goto leave;
727
728   domain = strchr (addrspec, '@');
729   log_assert (domain);
730   domain++;
731
732   /* Get the submission address.  */
733   if (fake_submission_addr)
734     {
735       submission_to = xstrdup (fake_submission_addr);
736       err = 0;
737     }
738   else
739     err = wkd_get_submission_address (addrspec, &submission_to);
740   if (err)
741     {
742       log_error (_("error looking up submission address for domain '%s': %s\n"),
743                  domain, gpg_strerror (err));
744       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
745         log_error (_("this domain probably doesn't support WKS.\n"));
746       goto leave;
747     }
748   log_info ("submitting request to '%s'\n", submission_to);
749
750   /* Get the policy flags.  */
751   if (!fake_submission_addr)
752     {
753       estream_t mbuf;
754
755       err = wkd_get_policy_flags (addrspec, &mbuf);
756       if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
757         {
758           log_error ("error reading policy flags for '%s': %s\n",
759                      submission_to, gpg_strerror (err));
760           goto leave;
761         }
762       if (mbuf)
763         {
764           err = wks_parse_policy (&policy, mbuf, 1);
765           es_fclose (mbuf);
766           if (err)
767             goto leave;
768         }
769     }
770
771   if (policy.auth_submit)
772     log_info ("no confirmation required for '%s'\n", addrspec);
773
774   /* In case the key has several uids with the same addr-spec we will
775    * use the newest one.  */
776   err = wks_list_key (key, NULL, &uidlist);
777   if (err)
778     {
779       log_error ("error parsing key: %s\n",gpg_strerror (err));
780       err = gpg_error (GPG_ERR_NO_PUBKEY);
781       goto leave;
782     }
783   thistime = 0;
784   thisuid = NULL;
785   for (uid = uidlist; uid; uid = uid->next)
786     {
787       if (!uid->mbox)
788         continue; /* Should not happen anyway.  */
789       if (uid->created > thistime)
790         {
791           thistime = uid->created;
792           thisuid = uid;
793         }
794     }
795   if (!thisuid)
796     thisuid = uid;  /* This is the case for a missing timestamp.  */
797   if (opt.verbose)
798     log_info ("submitting key with user id '%s'\n", thisuid->uid);
799
800   /* If we have more than one user id we need to filter the key to
801    * include only THISUID.  */
802   if (uidlist->next)
803     {
804       estream_t newkey;
805
806       es_rewind (key);
807       err = wks_filter_uid (&newkey, key, thisuid->uid);
808       if (err)
809         {
810           log_error ("error filtering key: %s\n", gpg_strerror (err));
811           err = gpg_error (GPG_ERR_NO_PUBKEY);
812           goto leave;
813         }
814       es_fclose (key);
815       key = newkey;
816     }
817
818   if (policy.mailbox_only
819       && ascii_strcasecmp (userid, addrspec))
820     {
821       log_info ("Warning: policy requires 'mailbox-only'"
822                 " - creating new user id'\n");
823     }
824
825   /* Hack to support posteo but let them disable this by setting the
826    * new policy-version flag.  */
827   if (policy.protocol_version < 3
828       && !ascii_strcasecmp (domain, "posteo.de"))
829     {
830       log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
831       no_encrypt = 1;
832       posteo_hack = 1;
833     }
834
835   /* Encrypt the key part.  */
836   if (!no_encrypt)
837     {
838       es_rewind (key);
839       err = encrypt_response (&keyenc, key, submission_to, fingerprint);
840       if (err)
841         goto leave;
842       es_fclose (key);
843       key = NULL;
844     }
845
846   /* Send the key.  */
847   err = mime_maker_new (&mime, NULL);
848   if (err)
849     goto leave;
850   err = mime_maker_add_header (mime, "From", addrspec);
851   if (err)
852     goto leave;
853   err = mime_maker_add_header (mime, "To", submission_to);
854   if (err)
855     goto leave;
856   err = mime_maker_add_header (mime, "Subject", "Key publishing request");
857   if (err)
858     goto leave;
859
860   /* Tell server which draft we support.  */
861   err = mime_maker_add_header (mime, "Wks-Draft-Version",
862                                  STR2(WKS_DRAFT_VERSION));
863   if (err)
864     goto leave;
865
866   if (no_encrypt)
867     {
868       void *data;
869       size_t datalen, n;
870
871       if (posteo_hack)
872         {
873           /* Needs a multipart/mixed with one(!) attachment.  It does
874            * not grok a non-multipart mail.  */
875           err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
876           if (err)
877             goto leave;
878           err = mime_maker_add_container (mime);
879           if (err)
880             goto leave;
881         }
882
883       err = mime_maker_add_header (mime, "Content-type",
884                                    "application/pgp-keys");
885       if (err)
886         goto leave;
887
888       if (es_fclose_snatch (key, &data, &datalen))
889         {
890           err = gpg_error_from_syserror ();
891           goto leave;
892         }
893       key = NULL;
894       /* We need to skip over the first line which has a content-type
895        * header not needed here.  */
896       for (n=0; n < datalen ; n++)
897         if (((const char *)data)[n] == '\n')
898           {
899             n++;
900             break;
901           }
902
903       err = mime_maker_add_body_data (mime, (char*)data + n, datalen - n);
904       xfree (data);
905       if (err)
906         goto leave;
907     }
908   else
909     {
910       err = mime_maker_add_header (mime, "Content-Type",
911                                    "multipart/encrypted; "
912                                    "protocol=\"application/pgp-encrypted\"");
913       if (err)
914         goto leave;
915       err = mime_maker_add_container (mime);
916       if (err)
917         goto leave;
918
919       err = mime_maker_add_header (mime, "Content-Type",
920                                    "application/pgp-encrypted");
921       if (err)
922         goto leave;
923       err = mime_maker_add_body (mime, "Version: 1\n");
924       if (err)
925         goto leave;
926       err = mime_maker_add_header (mime, "Content-Type",
927                                    "application/octet-stream");
928       if (err)
929         goto leave;
930
931       err = mime_maker_add_stream (mime, &keyenc);
932       if (err)
933         goto leave;
934     }
935
936   err = wks_send_mime (mime);
937
938  leave:
939   mime_maker_release (mime);
940   xfree (submission_to);
941   free_uidinfo_list (uidlist);
942   es_fclose (keyenc);
943   es_fclose (key);
944   xfree (addrspec);
945   return err;
946 }
947
948
949 \f
950 static void
951 encrypt_response_status_cb (void *opaque, const char *keyword, char *args)
952 {
953   gpg_error_t *failure = opaque;
954   char *fields[2];
955
956   if (DBG_CRYPTO)
957     log_debug ("gpg status: %s %s\n", keyword, args);
958
959   if (!strcmp (keyword, "FAILURE"))
960     {
961       if (split_fields (args, fields, DIM (fields)) >= 2
962           && !strcmp (fields[0], "encrypt"))
963         *failure = strtoul (fields[1], NULL, 10);
964     }
965
966 }
967
968
969 /* Encrypt the INPUT stream to a new stream which is stored at success
970  * at R_OUTPUT.  Encryption is done for ADDRSPEC and for FINGERPRINT
971  * (so that the sent message may later be inspected by the user).  We
972  * currently retrieve that key from the WKD, DANE, or from "local".
973  * "local" is last to prefer the latest key version but use a local
974  * copy in case we are working offline.  It might be useful for the
975  * server to send the fingerprint of its encryption key - or even the
976  * entire key back.  */
977 static gpg_error_t
978 encrypt_response (estream_t *r_output, estream_t input, const char *addrspec,
979                   const char *fingerprint)
980 {
981   gpg_error_t err;
982   ccparray_t ccp;
983   const char **argv;
984   estream_t output;
985   gpg_error_t gpg_err = 0;
986
987   *r_output = NULL;
988
989   output = es_fopenmem (0, "w+b");
990   if (!output)
991     {
992       err = gpg_error_from_syserror ();
993       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
994       return err;
995     }
996
997   ccparray_init (&ccp, 0);
998
999   ccparray_put (&ccp, "--no-options");
1000   if (!opt.verbose)
1001     ccparray_put (&ccp, "--quiet");
1002   else if (opt.verbose > 1)
1003     ccparray_put (&ccp, "--verbose");
1004   ccparray_put (&ccp, "--batch");
1005   ccparray_put (&ccp, "--status-fd=2");
1006   ccparray_put (&ccp, "--always-trust");
1007   ccparray_put (&ccp, "--armor");
1008   if (fake_submission_addr)
1009     ccparray_put (&ccp, "--auto-key-locate=clear,local");
1010   else
1011     ccparray_put (&ccp, "--auto-key-locate=clear,wkd,dane,local");
1012   ccparray_put (&ccp, "--recipient");
1013   ccparray_put (&ccp, addrspec);
1014   ccparray_put (&ccp, "--recipient");
1015   ccparray_put (&ccp, fingerprint);
1016   ccparray_put (&ccp, "--encrypt");
1017   ccparray_put (&ccp, "--");
1018
1019   ccparray_put (&ccp, NULL);
1020   argv = ccparray_get (&ccp, NULL);
1021   if (!argv)
1022     {
1023       err = gpg_error_from_syserror ();
1024       goto leave;
1025     }
1026   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
1027                                 NULL, output,
1028                                 encrypt_response_status_cb, &gpg_err);
1029   if (err)
1030     {
1031       if (gpg_err)
1032         err = gpg_err;
1033       log_error ("encryption failed: %s\n", gpg_strerror (err));
1034       goto leave;
1035     }
1036
1037   es_rewind (output);
1038   *r_output = output;
1039   output = NULL;
1040
1041  leave:
1042   es_fclose (output);
1043   xfree (argv);
1044   return err;
1045 }
1046
1047
1048 static gpg_error_t
1049 send_confirmation_response (const char *sender, const char *address,
1050                             const char *nonce, int encrypt,
1051                             const char *fingerprint)
1052 {
1053   gpg_error_t err;
1054   estream_t body = NULL;
1055   estream_t bodyenc = NULL;
1056   mime_maker_t mime = NULL;
1057
1058   body = es_fopenmem (0, "w+b");
1059   if (!body)
1060     {
1061       err = gpg_error_from_syserror ();
1062       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1063       return err;
1064     }
1065
1066   /* It is fine to use 8 bit encoding because that is encrypted and
1067    * only our client will see it.  */
1068   if (encrypt)
1069     {
1070       es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
1071                 "Content-Transfer-Encoding: 8bit\n"
1072                 "\n",
1073                 body);
1074     }
1075
1076   es_fprintf (body, ("type: confirmation-response\n"
1077                      "sender: %s\n"
1078                      "address: %s\n"
1079                      "nonce: %s\n"),
1080               sender,
1081               address,
1082               nonce);
1083
1084   es_rewind (body);
1085   if (encrypt)
1086     {
1087       err = encrypt_response (&bodyenc, body, sender, fingerprint);
1088       if (err)
1089         goto leave;
1090       es_fclose (body);
1091       body = NULL;
1092     }
1093
1094   err = mime_maker_new (&mime, NULL);
1095   if (err)
1096     goto leave;
1097   err = mime_maker_add_header (mime, "From", address);
1098   if (err)
1099     goto leave;
1100   err = mime_maker_add_header (mime, "To", sender);
1101   if (err)
1102     goto leave;
1103   err = mime_maker_add_header (mime, "Subject", "Key publication confirmation");
1104   if (err)
1105     goto leave;
1106   err = mime_maker_add_header (mime, "Wks-Draft-Version",
1107                                STR2(WKS_DRAFT_VERSION));
1108   if (err)
1109     goto leave;
1110
1111   if (encrypt)
1112     {
1113       err = mime_maker_add_header (mime, "Content-Type",
1114                                    "multipart/encrypted; "
1115                                    "protocol=\"application/pgp-encrypted\"");
1116       if (err)
1117         goto leave;
1118       err = mime_maker_add_container (mime);
1119       if (err)
1120         goto leave;
1121
1122       err = mime_maker_add_header (mime, "Content-Type",
1123                                    "application/pgp-encrypted");
1124       if (err)
1125         goto leave;
1126       err = mime_maker_add_body (mime, "Version: 1\n");
1127       if (err)
1128         goto leave;
1129       err = mime_maker_add_header (mime, "Content-Type",
1130                                    "application/octet-stream");
1131       if (err)
1132         goto leave;
1133
1134       err = mime_maker_add_stream (mime, &bodyenc);
1135       if (err)
1136         goto leave;
1137     }
1138   else
1139     {
1140       err = mime_maker_add_header (mime, "Content-Type",
1141                                    "application/vnd.gnupg.wks");
1142       if (err)
1143         goto leave;
1144       err = mime_maker_add_stream (mime, &body);
1145       if (err)
1146         goto leave;
1147     }
1148
1149   err = wks_send_mime (mime);
1150
1151  leave:
1152   mime_maker_release (mime);
1153   es_fclose (bodyenc);
1154   es_fclose (body);
1155   return err;
1156 }
1157
1158
1159 /* Reply to a confirmation request.  The MSG has already been
1160  * decrypted and we only need to send the nonce back.  MAINFPR is
1161  * either NULL or the primary key fingerprint of the key used to
1162  * decrypt the request.  */
1163 static gpg_error_t
1164 process_confirmation_request (estream_t msg, const char *mainfpr)
1165 {
1166   gpg_error_t err;
1167   nvc_t nvc;
1168   nve_t item;
1169   const char *value, *sender, *address, *fingerprint, *nonce;
1170
1171   err = nvc_parse (&nvc, NULL, msg);
1172   if (err)
1173     {
1174       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1175       goto leave;
1176     }
1177
1178   if (DBG_MIME)
1179     {
1180       log_debug ("request follows:\n");
1181       nvc_write (nvc, log_get_stream ());
1182     }
1183
1184   /* Check that this is a confirmation request.  */
1185   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1186         && !strcmp (value, "confirmation-request")))
1187     {
1188       if (item && value)
1189         log_error ("received unexpected wks message '%s'\n", value);
1190       else
1191         log_error ("received invalid wks message: %s\n", "'type' missing");
1192       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1193       goto leave;
1194     }
1195
1196   /* Get the fingerprint.  */
1197   if (!((item = nvc_lookup (nvc, "fingerprint:"))
1198         && (value = nve_value (item))
1199         && strlen (value) >= 40))
1200     {
1201       log_error ("received invalid wks message: %s\n",
1202                  "'fingerprint' missing or invalid");
1203       err = gpg_error (GPG_ERR_INV_DATA);
1204       goto leave;
1205     }
1206   fingerprint = value;
1207
1208   /* Check that the fingerprint matches the key used to decrypt the
1209    * message.  In --read mode or with the old format we don't have the
1210    * decryption key; thus we can't bail out.  */
1211   if (!mainfpr || ascii_strcasecmp (mainfpr, fingerprint))
1212     {
1213       log_info ("target fingerprint: %s\n", fingerprint);
1214       log_info ("but decrypted with: %s\n", mainfpr);
1215       log_error ("confirmation request not decrypted with target key\n");
1216       if (mainfpr)
1217         {
1218           err = gpg_error (GPG_ERR_INV_DATA);
1219           goto leave;
1220         }
1221     }
1222
1223   /* Get the address.  */
1224   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1225         && is_valid_mailbox (value)))
1226     {
1227       log_error ("received invalid wks message: %s\n",
1228                  "'address' missing or invalid");
1229       err = gpg_error (GPG_ERR_INV_DATA);
1230       goto leave;
1231     }
1232   address = value;
1233   /* FIXME: Check that the "address" matches the User ID we want to
1234    * publish.  */
1235
1236   /* Get the sender.  */
1237   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1238         && is_valid_mailbox (value)))
1239     {
1240       log_error ("received invalid wks message: %s\n",
1241                  "'sender' missing or invalid");
1242       err = gpg_error (GPG_ERR_INV_DATA);
1243       goto leave;
1244     }
1245   sender = value;
1246   /* FIXME: Check that the "sender" matches the From: address.  */
1247
1248   /* Get the nonce.  */
1249   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1250         && strlen (value) > 16))
1251     {
1252       log_error ("received invalid wks message: %s\n",
1253                  "'nonce' missing or too short");
1254       err = gpg_error (GPG_ERR_INV_DATA);
1255       goto leave;
1256     }
1257   nonce = value;
1258
1259   /* Send the confirmation.  If no key was found, try again without
1260    * encryption.  */
1261   err = send_confirmation_response (sender, address, nonce, 1, fingerprint);
1262   if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
1263     {
1264       log_info ("no encryption key found - sending response in the clear\n");
1265       err = send_confirmation_response (sender, address, nonce, 0, NULL);
1266     }
1267
1268  leave:
1269   nvc_release (nvc);
1270   return err;
1271 }
1272
1273
1274 /* Read a confirmation request and decrypt it if needed.  This
1275  * function may not be used with a mail or MIME message but only with
1276  * the actual encrypted or plaintext WKS data.  */
1277 static gpg_error_t
1278 read_confirmation_request (estream_t msg)
1279 {
1280   gpg_error_t err;
1281   int c;
1282   estream_t plaintext = NULL;
1283
1284   /* We take a really simple approach to check whether MSG is
1285    * encrypted: We know that an encrypted message is always armored
1286    * and thus starts with a few dashes.  It is even sufficient to
1287    * check for a single dash, because that can never be a proper first
1288    * WKS data octet.  We need to skip leading spaces, though. */
1289   while ((c = es_fgetc (msg)) == ' ' || c == '\t' || c == '\r' || c == '\n')
1290     ;
1291   if (c == EOF)
1292     {
1293       log_error ("can't process an empty message\n");
1294       return gpg_error (GPG_ERR_INV_DATA);
1295     }
1296   if (es_ungetc (c, msg) != c)
1297     {
1298       log_error ("error ungetting octet from message\n");
1299       return gpg_error (GPG_ERR_INTERNAL);
1300     }
1301
1302   if (c != '-')
1303     err = process_confirmation_request (msg, NULL);
1304   else
1305     {
1306       struct decrypt_stream_parm_s decinfo;
1307
1308       err = decrypt_stream (&plaintext, &decinfo, msg);
1309       if (err)
1310         log_error ("decryption failed: %s\n", gpg_strerror (err));
1311       else if (decinfo.otrust != 'u')
1312         {
1313           err = gpg_error (GPG_ERR_WRONG_SECKEY);
1314           log_error ("key used to decrypt the confirmation request"
1315                      " was not generated by us\n");
1316         }
1317       else
1318         err = process_confirmation_request (plaintext, decinfo.mainfpr);
1319       xfree (decinfo.fpr);
1320       xfree (decinfo.mainfpr);
1321     }
1322
1323   es_fclose (plaintext);
1324   return err;
1325 }
1326
1327
1328 /* Called from the MIME receiver to process the plain text data in MSG.  */
1329 static gpg_error_t
1330 command_receive_cb (void *opaque, const char *mediatype,
1331                     estream_t msg, unsigned int flags)
1332 {
1333   gpg_error_t err;
1334
1335   (void)opaque;
1336   (void)flags;
1337
1338   if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1339     err = read_confirmation_request (msg);
1340   else
1341     {
1342       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1343       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1344     }
1345
1346   return err;
1347 }