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