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