gpg: Unfinished support for v5 signatures.
[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 /* Add the user id UID to the key identified by FINGERPRINT.  */
329 static gpg_error_t
330 add_user_id (const char *fingerprint, const char *uid)
331 {
332   gpg_error_t err;
333   ccparray_t ccp;
334   const char **argv = NULL;
335
336   ccparray_init (&ccp, 0);
337
338   ccparray_put (&ccp, "--no-options");
339   if (!opt.verbose)
340     ccparray_put (&ccp, "--quiet");
341   else if (opt.verbose > 1)
342     ccparray_put (&ccp, "--verbose");
343   ccparray_put (&ccp, "--batch");
344   ccparray_put (&ccp, "--always-trust");
345   ccparray_put (&ccp, "--quick-add-uid");
346   ccparray_put (&ccp, fingerprint);
347   ccparray_put (&ccp, uid);
348
349   ccparray_put (&ccp, NULL);
350   argv = ccparray_get (&ccp, NULL);
351   if (!argv)
352     {
353       err = gpg_error_from_syserror ();
354       goto leave;
355     }
356   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
357                                 NULL, NULL,
358                                 NULL, NULL);
359   if (err)
360     {
361       log_error ("adding user id failed: %s\n", gpg_strerror (err));
362       goto leave;
363     }
364
365  leave:
366   xfree (argv);
367   return err;
368 }
369
370
371 \f
372 struct decrypt_stream_parm_s
373 {
374   char *fpr;
375   char *mainfpr;
376   int  otrust;
377 };
378
379 static void
380 decrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
381 {
382   struct decrypt_stream_parm_s *decinfo = opaque;
383
384   if (DBG_CRYPTO)
385     log_debug ("gpg status: %s %s\n", keyword, args);
386   if (!strcmp (keyword, "DECRYPTION_KEY") && !decinfo->fpr)
387     {
388       char *fields[3];
389
390       if (split_fields (args, fields, DIM (fields)) >= 3)
391         {
392           decinfo->fpr = xstrdup (fields[0]);
393           decinfo->mainfpr = xstrdup (fields[1]);
394           decinfo->otrust = *fields[2];
395         }
396     }
397 }
398
399 /* Decrypt the INPUT stream to a new stream which is stored at success
400  * at R_OUTPUT.  */
401 static gpg_error_t
402 decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
403                 estream_t input)
404 {
405   gpg_error_t err;
406   ccparray_t ccp;
407   const char **argv;
408   estream_t output;
409
410   *r_output = NULL;
411   memset (decinfo, 0, sizeof *decinfo);
412
413   output = es_fopenmem (0, "w+b");
414   if (!output)
415     {
416       err = gpg_error_from_syserror ();
417       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
418       return err;
419     }
420
421   ccparray_init (&ccp, 0);
422
423   ccparray_put (&ccp, "--no-options");
424   /* We limit the output to 64 KiB to avoid DoS using compression
425    * tricks.  A regular client will anyway only send a minimal key;
426    * that is one w/o key signatures and attribute packets.  */
427   ccparray_put (&ccp, "--max-output=0x10000");
428   if (!opt.verbose)
429     ccparray_put (&ccp, "--quiet");
430   else if (opt.verbose > 1)
431     ccparray_put (&ccp, "--verbose");
432   ccparray_put (&ccp, "--batch");
433   ccparray_put (&ccp, "--status-fd=2");
434   ccparray_put (&ccp, "--decrypt");
435   ccparray_put (&ccp, "--");
436
437   ccparray_put (&ccp, NULL);
438   argv = ccparray_get (&ccp, NULL);
439   if (!argv)
440     {
441       err = gpg_error_from_syserror ();
442       goto leave;
443     }
444   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
445                                 NULL, output,
446                                 decrypt_stream_status_cb, decinfo);
447   if (!err && (!decinfo->fpr || !decinfo->mainfpr || !decinfo->otrust))
448     err = gpg_error (GPG_ERR_INV_ENGINE);
449   if (err)
450     {
451       log_error ("decryption failed: %s\n", gpg_strerror (err));
452       goto leave;
453     }
454   else if (opt.verbose)
455     log_info ("decryption succeeded\n");
456
457   es_rewind (output);
458   *r_output = output;
459   output = NULL;
460
461  leave:
462   if (err)
463     {
464       xfree (decinfo->fpr);
465       xfree (decinfo->mainfpr);
466       memset (decinfo, 0, sizeof *decinfo);
467     }
468   es_fclose (output);
469   xfree (argv);
470   return err;
471 }
472
473
474
475 \f
476 /* Check whether the  provider supports the WKS protocol.  */
477 static gpg_error_t
478 command_supported (char *userid)
479 {
480   gpg_error_t err;
481   char *addrspec = NULL;
482   char *submission_to = NULL;
483
484   if (!strchr (userid, '@'))
485     {
486       char *tmp = xstrconcat ("foo@", userid, NULL);
487       addrspec = mailbox_from_userid (tmp);
488       xfree (tmp);
489     }
490   else
491     addrspec = mailbox_from_userid (userid);
492   if (!addrspec)
493     {
494       log_error (_("\"%s\" is not a proper mail address\n"), userid);
495       err = gpg_error (GPG_ERR_INV_USER_ID);
496       goto leave;
497     }
498
499   /* Get the submission address.  */
500   err = wkd_get_submission_address (addrspec, &submission_to);
501   if (err)
502     {
503       if (gpg_err_code (err) == GPG_ERR_NO_DATA
504           || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST)
505         {
506           if (opt.verbose)
507             log_info ("provider for '%s' does NOT support WKS (%s)\n",
508                       addrspec, gpg_strerror (err));
509           err = gpg_error (GPG_ERR_FALSE);
510           log_inc_errorcount ();
511         }
512       goto leave;
513     }
514   if (opt.verbose)
515     log_info ("provider for '%s' supports WKS\n", addrspec);
516
517  leave:
518   xfree (submission_to);
519   xfree (addrspec);
520   return err;
521 }
522
523
524 \f
525 /* Check whether the key for USERID is available in the WKD.  */
526 static gpg_error_t
527 command_check (char *userid)
528 {
529   gpg_error_t err;
530   char *addrspec = NULL;
531   estream_t key = NULL;
532   char *fpr = NULL;
533   uidinfo_list_t mboxes = NULL;
534   uidinfo_list_t sl;
535   int found = 0;
536
537   addrspec = mailbox_from_userid (userid);
538   if (!addrspec)
539     {
540       log_error (_("\"%s\" is not a proper mail address\n"), userid);
541       err = gpg_error (GPG_ERR_INV_USER_ID);
542       goto leave;
543     }
544
545   /* Get the submission address.  */
546   err = wkd_get_key (addrspec, &key);
547   switch (gpg_err_code (err))
548     {
549     case 0:
550       if (opt.verbose)
551         log_info ("public key for '%s' found via WKD\n", addrspec);
552       /* Fixme: Check that the key contains the user id.  */
553       break;
554
555     case GPG_ERR_NO_DATA: /* No such key.  */
556       if (opt.verbose)
557         log_info ("public key for '%s' NOT found via WKD\n", addrspec);
558       err = gpg_error (GPG_ERR_NO_PUBKEY);
559       log_inc_errorcount ();
560       break;
561
562     case GPG_ERR_UNKNOWN_HOST:
563       if (opt.verbose)
564         log_info ("error looking up '%s' via WKD: %s\n",
565                   addrspec, gpg_strerror (err));
566       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
567       break;
568
569     default:
570       log_error ("error looking up '%s' via WKD: %s\n",
571                  addrspec, gpg_strerror (err));
572       break;
573     }
574
575   if (err)
576     goto leave;
577
578   /* Look closer at the key.  */
579   err = wks_list_key (key, &fpr, &mboxes);
580   if (err)
581     {
582       log_error ("error parsing key: %s\n", gpg_strerror (err));
583       err = gpg_error (GPG_ERR_NO_PUBKEY);
584       goto leave;
585     }
586
587   if (opt.verbose)
588     log_info ("fingerprint: %s\n", fpr);
589
590   for (sl = mboxes; sl; sl = sl->next)
591     {
592       if (sl->mbox && !strcmp (sl->mbox, addrspec))
593         found = 1;
594       if (opt.verbose)
595         {
596           log_info ("    user-id: %s\n", sl->uid);
597           log_info ("    created: %s\n", asctimestamp (sl->created));
598           if (sl->mbox)
599             log_info ("  addr-spec: %s\n", sl->mbox);
600         }
601     }
602   if (!found)
603     {
604       log_error ("public key for '%s' has no user id with the mail address\n",
605                  addrspec);
606       err = gpg_error (GPG_ERR_CERT_REVOKED);
607     }
608
609  leave:
610   xfree (fpr);
611   free_uidinfo_list (mboxes);
612   es_fclose (key);
613   xfree (addrspec);
614   return err;
615 }
616
617
618 \f
619 /* Locate the key by fingerprint and userid and send a publication
620  * request.  */
621 static gpg_error_t
622 command_send (const char *fingerprint, const char *userid)
623 {
624   gpg_error_t err;
625   KEYDB_SEARCH_DESC desc;
626   char *addrspec = NULL;
627   estream_t key = NULL;
628   estream_t keyenc = NULL;
629   char *submission_to = NULL;
630   mime_maker_t mime = NULL;
631   struct policy_flags_s policy;
632   int no_encrypt = 0;
633   int posteo_hack = 0;
634   const char *domain;
635   uidinfo_list_t uidlist = NULL;
636   uidinfo_list_t uid, thisuid;
637   time_t thistime;
638
639   memset (&policy, 0, sizeof policy);
640
641   if (classify_user_id (fingerprint, &desc, 1)
642       || !(desc.mode == KEYDB_SEARCH_MODE_FPR
643            || desc.mode == KEYDB_SEARCH_MODE_FPR20))
644     {
645       log_error (_("\"%s\" is not a fingerprint\n"), fingerprint);
646       err = gpg_error (GPG_ERR_INV_NAME);
647       goto leave;
648     }
649
650   addrspec = mailbox_from_userid (userid);
651   if (!addrspec)
652     {
653       log_error (_("\"%s\" is not a proper mail address\n"), userid);
654       err = gpg_error (GPG_ERR_INV_USER_ID);
655       goto leave;
656     }
657   err = wks_get_key (&key, fingerprint, addrspec, 0);
658   if (err)
659     goto leave;
660
661   domain = strchr (addrspec, '@');
662   log_assert (domain);
663   domain++;
664
665   /* Get the submission address.  */
666   if (fake_submission_addr)
667     {
668       submission_to = xstrdup (fake_submission_addr);
669       err = 0;
670     }
671   else
672     {
673       /* We first try to get the submission address from the policy
674        * file (this is the new method).  If both are available we
675        * check that they match and print a warning if not.  In the
676        * latter case we keep on using the one from the
677        * submission-address file.  */
678       estream_t mbuf;
679
680       err = wkd_get_policy_flags (addrspec, &mbuf);
681       if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
682         {
683           log_error ("error reading policy flags for '%s': %s\n",
684                      domain, gpg_strerror (err));
685           goto leave;
686         }
687       if (mbuf)
688         {
689           err = wks_parse_policy (&policy, mbuf, 1);
690           es_fclose (mbuf);
691           if (err)
692             goto leave;
693         }
694
695       err = wkd_get_submission_address (addrspec, &submission_to);
696       if (err && !policy.submission_address)
697         {
698           log_error (_("error looking up submission address for domain '%s'"
699                        ": %s\n"), domain, gpg_strerror (err));
700           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
701             log_error (_("this domain probably doesn't support WKS.\n"));
702           goto leave;
703         }
704
705       if (submission_to && policy.submission_address
706           && ascii_strcasecmp (submission_to, policy.submission_address))
707         log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
708                   submission_to, policy.submission_address);
709
710       if (!submission_to)
711         {
712           submission_to = xtrystrdup (policy.submission_address);
713           if (!submission_to)
714             {
715               err = gpg_error_from_syserror ();
716               goto leave;
717             }
718         }
719     }
720
721   log_info ("submitting request to '%s'\n", submission_to);
722
723   if (policy.auth_submit)
724     log_info ("no confirmation required for '%s'\n", addrspec);
725
726   /* In case the key has several uids with the same addr-spec we will
727    * use the newest one.  */
728   err = wks_list_key (key, NULL, &uidlist);
729   if (err)
730     {
731       log_error ("error parsing key: %s\n",gpg_strerror (err));
732       err = gpg_error (GPG_ERR_NO_PUBKEY);
733       goto leave;
734     }
735   thistime = 0;
736   thisuid = NULL;
737   for (uid = uidlist; uid; uid = uid->next)
738     {
739       if (!uid->mbox)
740         continue; /* Should not happen anyway.  */
741       if (policy.mailbox_only
742           && ascii_strcasecmp (uid->uid, uid->mbox))
743         continue; /* UID has more than just the mailbox.  */
744       if (uid->created > thistime)
745         {
746           thistime = uid->created;
747           thisuid = uid;
748         }
749     }
750   if (!thisuid)
751     thisuid = uidlist;  /* This is the case for a missing timestamp.  */
752   if (opt.verbose)
753     log_info ("submitting key with user id '%s'\n", thisuid->uid);
754
755   /* If we have more than one user id we need to filter the key to
756    * include only THISUID.  */
757   if (uidlist->next)
758     {
759       estream_t newkey;
760
761       es_rewind (key);
762       err = wks_filter_uid (&newkey, key, thisuid->uid, 0);
763       if (err)
764         {
765           log_error ("error filtering key: %s\n", gpg_strerror (err));
766           err = gpg_error (GPG_ERR_NO_PUBKEY);
767           goto leave;
768         }
769       es_fclose (key);
770       key = newkey;
771     }
772
773   if (policy.mailbox_only
774       && (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox)))
775     {
776       log_info ("Warning: policy requires 'mailbox-only'"
777                 " - adding user id '%s'\n", addrspec);
778       err = add_user_id (fingerprint, addrspec);
779       if (err)
780         goto leave;
781
782       /* Need to get the key again.  This time we request filtering
783        * for the full user id, so that we do not need check and filter
784        * the key again.  */
785       es_fclose (key);
786       key = NULL;
787       err = wks_get_key (&key, fingerprint, addrspec, 1);
788       if (err)
789         goto leave;
790     }
791
792   /* Hack to support posteo but let them disable this by setting the
793    * new policy-version flag.  */
794   if (policy.protocol_version < 3
795       && !ascii_strcasecmp (domain, "posteo.de"))
796     {
797       log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
798       no_encrypt = 1;
799       posteo_hack = 1;
800     }
801
802   /* Encrypt the key part.  */
803   if (!no_encrypt)
804     {
805       es_rewind (key);
806       err = encrypt_response (&keyenc, key, submission_to, fingerprint);
807       if (err)
808         goto leave;
809       es_fclose (key);
810       key = NULL;
811     }
812
813   /* Send the key.  */
814   err = mime_maker_new (&mime, NULL);
815   if (err)
816     goto leave;
817   err = mime_maker_add_header (mime, "From", addrspec);
818   if (err)
819     goto leave;
820   err = mime_maker_add_header (mime, "To", submission_to);
821   if (err)
822     goto leave;
823   err = mime_maker_add_header (mime, "Subject", "Key publishing request");
824   if (err)
825     goto leave;
826
827   /* Tell server which draft we support.  */
828   err = mime_maker_add_header (mime, "Wks-Draft-Version",
829                                  STR2(WKS_DRAFT_VERSION));
830   if (err)
831     goto leave;
832
833   if (no_encrypt)
834     {
835       void *data;
836       size_t datalen, n;
837
838       if (posteo_hack)
839         {
840           /* Needs a multipart/mixed with one(!) attachment.  It does
841            * not grok a non-multipart mail.  */
842           err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
843           if (err)
844             goto leave;
845           err = mime_maker_add_container (mime);
846           if (err)
847             goto leave;
848         }
849
850       err = mime_maker_add_header (mime, "Content-type",
851                                    "application/pgp-keys");
852       if (err)
853         goto leave;
854
855       if (es_fclose_snatch (key, &data, &datalen))
856         {
857           err = gpg_error_from_syserror ();
858           goto leave;
859         }
860       key = NULL;
861       /* We need to skip over the first line which has a content-type
862        * header not needed here.  */
863       for (n=0; n < datalen ; n++)
864         if (((const char *)data)[n] == '\n')
865           {
866             n++;
867             break;
868           }
869
870       err = mime_maker_add_body_data (mime, (char*)data + n, datalen - n);
871       xfree (data);
872       if (err)
873         goto leave;
874     }
875   else
876     {
877       err = mime_maker_add_header (mime, "Content-Type",
878                                    "multipart/encrypted; "
879                                    "protocol=\"application/pgp-encrypted\"");
880       if (err)
881         goto leave;
882       err = mime_maker_add_container (mime);
883       if (err)
884         goto leave;
885
886       err = mime_maker_add_header (mime, "Content-Type",
887                                    "application/pgp-encrypted");
888       if (err)
889         goto leave;
890       err = mime_maker_add_body (mime, "Version: 1\n");
891       if (err)
892         goto leave;
893       err = mime_maker_add_header (mime, "Content-Type",
894                                    "application/octet-stream");
895       if (err)
896         goto leave;
897
898       err = mime_maker_add_stream (mime, &keyenc);
899       if (err)
900         goto leave;
901     }
902
903   err = wks_send_mime (mime);
904
905  leave:
906   mime_maker_release (mime);
907   xfree (submission_to);
908   free_uidinfo_list (uidlist);
909   es_fclose (keyenc);
910   es_fclose (key);
911   wks_free_policy (&policy);
912   xfree (addrspec);
913   return err;
914 }
915
916
917 \f
918 static void
919 encrypt_response_status_cb (void *opaque, const char *keyword, char *args)
920 {
921   gpg_error_t *failure = opaque;
922   char *fields[2];
923
924   if (DBG_CRYPTO)
925     log_debug ("gpg status: %s %s\n", keyword, args);
926
927   if (!strcmp (keyword, "FAILURE"))
928     {
929       if (split_fields (args, fields, DIM (fields)) >= 2
930           && !strcmp (fields[0], "encrypt"))
931         *failure = strtoul (fields[1], NULL, 10);
932     }
933
934 }
935
936
937 /* Encrypt the INPUT stream to a new stream which is stored at success
938  * at R_OUTPUT.  Encryption is done for ADDRSPEC and for FINGERPRINT
939  * (so that the sent message may later be inspected by the user).  We
940  * currently retrieve that key from the WKD, DANE, or from "local".
941  * "local" is last to prefer the latest key version but use a local
942  * copy in case we are working offline.  It might be useful for the
943  * server to send the fingerprint of its encryption key - or even the
944  * entire key back.  */
945 static gpg_error_t
946 encrypt_response (estream_t *r_output, estream_t input, const char *addrspec,
947                   const char *fingerprint)
948 {
949   gpg_error_t err;
950   ccparray_t ccp;
951   const char **argv;
952   estream_t output;
953   gpg_error_t gpg_err = 0;
954
955   *r_output = NULL;
956
957   output = es_fopenmem (0, "w+b");
958   if (!output)
959     {
960       err = gpg_error_from_syserror ();
961       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
962       return err;
963     }
964
965   ccparray_init (&ccp, 0);
966
967   ccparray_put (&ccp, "--no-options");
968   if (!opt.verbose)
969     ccparray_put (&ccp, "--quiet");
970   else if (opt.verbose > 1)
971     ccparray_put (&ccp, "--verbose");
972   ccparray_put (&ccp, "--batch");
973   ccparray_put (&ccp, "--status-fd=2");
974   ccparray_put (&ccp, "--always-trust");
975   ccparray_put (&ccp, "--armor");
976   if (fake_submission_addr)
977     ccparray_put (&ccp, "--auto-key-locate=clear,local");
978   else
979     ccparray_put (&ccp, "--auto-key-locate=clear,wkd,dane,local");
980   ccparray_put (&ccp, "--recipient");
981   ccparray_put (&ccp, addrspec);
982   ccparray_put (&ccp, "--recipient");
983   ccparray_put (&ccp, fingerprint);
984   ccparray_put (&ccp, "--encrypt");
985   ccparray_put (&ccp, "--");
986
987   ccparray_put (&ccp, NULL);
988   argv = ccparray_get (&ccp, NULL);
989   if (!argv)
990     {
991       err = gpg_error_from_syserror ();
992       goto leave;
993     }
994   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
995                                 NULL, output,
996                                 encrypt_response_status_cb, &gpg_err);
997   if (err)
998     {
999       if (gpg_err)
1000         err = gpg_err;
1001       log_error ("encryption failed: %s\n", gpg_strerror (err));
1002       goto leave;
1003     }
1004
1005   es_rewind (output);
1006   *r_output = output;
1007   output = NULL;
1008
1009  leave:
1010   es_fclose (output);
1011   xfree (argv);
1012   return err;
1013 }
1014
1015
1016 static gpg_error_t
1017 send_confirmation_response (const char *sender, const char *address,
1018                             const char *nonce, int encrypt,
1019                             const char *fingerprint)
1020 {
1021   gpg_error_t err;
1022   estream_t body = NULL;
1023   estream_t bodyenc = NULL;
1024   mime_maker_t mime = NULL;
1025
1026   body = es_fopenmem (0, "w+b");
1027   if (!body)
1028     {
1029       err = gpg_error_from_syserror ();
1030       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1031       return err;
1032     }
1033
1034   /* It is fine to use 8 bit encoding because that is encrypted and
1035    * only our client will see it.  */
1036   if (encrypt)
1037     {
1038       es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
1039                 "Content-Transfer-Encoding: 8bit\n"
1040                 "\n",
1041                 body);
1042     }
1043
1044   es_fprintf (body, ("type: confirmation-response\n"
1045                      "sender: %s\n"
1046                      "address: %s\n"
1047                      "nonce: %s\n"),
1048               sender,
1049               address,
1050               nonce);
1051
1052   es_rewind (body);
1053   if (encrypt)
1054     {
1055       err = encrypt_response (&bodyenc, body, sender, fingerprint);
1056       if (err)
1057         goto leave;
1058       es_fclose (body);
1059       body = NULL;
1060     }
1061
1062   err = mime_maker_new (&mime, NULL);
1063   if (err)
1064     goto leave;
1065   err = mime_maker_add_header (mime, "From", address);
1066   if (err)
1067     goto leave;
1068   err = mime_maker_add_header (mime, "To", sender);
1069   if (err)
1070     goto leave;
1071   err = mime_maker_add_header (mime, "Subject", "Key publication confirmation");
1072   if (err)
1073     goto leave;
1074   err = mime_maker_add_header (mime, "Wks-Draft-Version",
1075                                STR2(WKS_DRAFT_VERSION));
1076   if (err)
1077     goto leave;
1078
1079   if (encrypt)
1080     {
1081       err = mime_maker_add_header (mime, "Content-Type",
1082                                    "multipart/encrypted; "
1083                                    "protocol=\"application/pgp-encrypted\"");
1084       if (err)
1085         goto leave;
1086       err = mime_maker_add_container (mime);
1087       if (err)
1088         goto leave;
1089
1090       err = mime_maker_add_header (mime, "Content-Type",
1091                                    "application/pgp-encrypted");
1092       if (err)
1093         goto leave;
1094       err = mime_maker_add_body (mime, "Version: 1\n");
1095       if (err)
1096         goto leave;
1097       err = mime_maker_add_header (mime, "Content-Type",
1098                                    "application/octet-stream");
1099       if (err)
1100         goto leave;
1101
1102       err = mime_maker_add_stream (mime, &bodyenc);
1103       if (err)
1104         goto leave;
1105     }
1106   else
1107     {
1108       err = mime_maker_add_header (mime, "Content-Type",
1109                                    "application/vnd.gnupg.wks");
1110       if (err)
1111         goto leave;
1112       err = mime_maker_add_stream (mime, &body);
1113       if (err)
1114         goto leave;
1115     }
1116
1117   err = wks_send_mime (mime);
1118
1119  leave:
1120   mime_maker_release (mime);
1121   es_fclose (bodyenc);
1122   es_fclose (body);
1123   return err;
1124 }
1125
1126
1127 /* Reply to a confirmation request.  The MSG has already been
1128  * decrypted and we only need to send the nonce back.  MAINFPR is
1129  * either NULL or the primary key fingerprint of the key used to
1130  * decrypt the request.  */
1131 static gpg_error_t
1132 process_confirmation_request (estream_t msg, const char *mainfpr)
1133 {
1134   gpg_error_t err;
1135   nvc_t nvc;
1136   nve_t item;
1137   const char *value, *sender, *address, *fingerprint, *nonce;
1138
1139   err = nvc_parse (&nvc, NULL, msg);
1140   if (err)
1141     {
1142       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1143       goto leave;
1144     }
1145
1146   if (DBG_MIME)
1147     {
1148       log_debug ("request follows:\n");
1149       nvc_write (nvc, log_get_stream ());
1150     }
1151
1152   /* Check that this is a confirmation request.  */
1153   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1154         && !strcmp (value, "confirmation-request")))
1155     {
1156       if (item && value)
1157         log_error ("received unexpected wks message '%s'\n", value);
1158       else
1159         log_error ("received invalid wks message: %s\n", "'type' missing");
1160       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1161       goto leave;
1162     }
1163
1164   /* Get the fingerprint.  */
1165   if (!((item = nvc_lookup (nvc, "fingerprint:"))
1166         && (value = nve_value (item))
1167         && strlen (value) >= 40))
1168     {
1169       log_error ("received invalid wks message: %s\n",
1170                  "'fingerprint' missing or invalid");
1171       err = gpg_error (GPG_ERR_INV_DATA);
1172       goto leave;
1173     }
1174   fingerprint = value;
1175
1176   /* Check that the fingerprint matches the key used to decrypt the
1177    * message.  In --read mode or with the old format we don't have the
1178    * decryption key; thus we can't bail out.  */
1179   if (!mainfpr || ascii_strcasecmp (mainfpr, fingerprint))
1180     {
1181       log_info ("target fingerprint: %s\n", fingerprint);
1182       log_info ("but decrypted with: %s\n", mainfpr);
1183       log_error ("confirmation request not decrypted with target key\n");
1184       if (mainfpr)
1185         {
1186           err = gpg_error (GPG_ERR_INV_DATA);
1187           goto leave;
1188         }
1189     }
1190
1191   /* Get the address.  */
1192   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1193         && is_valid_mailbox (value)))
1194     {
1195       log_error ("received invalid wks message: %s\n",
1196                  "'address' missing or invalid");
1197       err = gpg_error (GPG_ERR_INV_DATA);
1198       goto leave;
1199     }
1200   address = value;
1201   /* FIXME: Check that the "address" matches the User ID we want to
1202    * publish.  */
1203
1204   /* Get the sender.  */
1205   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1206         && is_valid_mailbox (value)))
1207     {
1208       log_error ("received invalid wks message: %s\n",
1209                  "'sender' missing or invalid");
1210       err = gpg_error (GPG_ERR_INV_DATA);
1211       goto leave;
1212     }
1213   sender = value;
1214   /* FIXME: Check that the "sender" matches the From: address.  */
1215
1216   /* Get the nonce.  */
1217   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1218         && strlen (value) > 16))
1219     {
1220       log_error ("received invalid wks message: %s\n",
1221                  "'nonce' missing or too short");
1222       err = gpg_error (GPG_ERR_INV_DATA);
1223       goto leave;
1224     }
1225   nonce = value;
1226
1227   /* Send the confirmation.  If no key was found, try again without
1228    * encryption.  */
1229   err = send_confirmation_response (sender, address, nonce, 1, fingerprint);
1230   if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
1231     {
1232       log_info ("no encryption key found - sending response in the clear\n");
1233       err = send_confirmation_response (sender, address, nonce, 0, NULL);
1234     }
1235
1236  leave:
1237   nvc_release (nvc);
1238   return err;
1239 }
1240
1241
1242 /* Read a confirmation request and decrypt it if needed.  This
1243  * function may not be used with a mail or MIME message but only with
1244  * the actual encrypted or plaintext WKS data.  */
1245 static gpg_error_t
1246 read_confirmation_request (estream_t msg)
1247 {
1248   gpg_error_t err;
1249   int c;
1250   estream_t plaintext = NULL;
1251
1252   /* We take a really simple approach to check whether MSG is
1253    * encrypted: We know that an encrypted message is always armored
1254    * and thus starts with a few dashes.  It is even sufficient to
1255    * check for a single dash, because that can never be a proper first
1256    * WKS data octet.  We need to skip leading spaces, though. */
1257   while ((c = es_fgetc (msg)) == ' ' || c == '\t' || c == '\r' || c == '\n')
1258     ;
1259   if (c == EOF)
1260     {
1261       log_error ("can't process an empty message\n");
1262       return gpg_error (GPG_ERR_INV_DATA);
1263     }
1264   if (es_ungetc (c, msg) != c)
1265     {
1266       log_error ("error ungetting octet from message\n");
1267       return gpg_error (GPG_ERR_INTERNAL);
1268     }
1269
1270   if (c != '-')
1271     err = process_confirmation_request (msg, NULL);
1272   else
1273     {
1274       struct decrypt_stream_parm_s decinfo;
1275
1276       err = decrypt_stream (&plaintext, &decinfo, msg);
1277       if (err)
1278         log_error ("decryption failed: %s\n", gpg_strerror (err));
1279       else if (decinfo.otrust != 'u')
1280         {
1281           err = gpg_error (GPG_ERR_WRONG_SECKEY);
1282           log_error ("key used to decrypt the confirmation request"
1283                      " was not generated by us\n");
1284         }
1285       else
1286         err = process_confirmation_request (plaintext, decinfo.mainfpr);
1287       xfree (decinfo.fpr);
1288       xfree (decinfo.mainfpr);
1289     }
1290
1291   es_fclose (plaintext);
1292   return err;
1293 }
1294
1295
1296 /* Called from the MIME receiver to process the plain text data in MSG.  */
1297 static gpg_error_t
1298 command_receive_cb (void *opaque, const char *mediatype,
1299                     estream_t msg, unsigned int flags)
1300 {
1301   gpg_error_t err;
1302
1303   (void)opaque;
1304   (void)flags;
1305
1306   if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1307     err = read_confirmation_request (msg);
1308   else
1309     {
1310       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1311       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1312     }
1313
1314   return err;
1315 }