c603cc043f2e0e6040d1872d0b620d7146ac201a
[platform/upstream/gpg2.git] / tools / gpg-wks-client.c
1 /* gpg-wks-client.c - A client for the Web Key Service protocols.
2  * Copyright (C) 2016, 2022 g10 Code GmbH
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  * SPDX-License-Identifier: LGPL-2.1-or-later
20  */
21
22 #include <config.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29
30 #define INCLUDED_BY_MAIN_MODULE 1
31 #include "../common/util.h"
32 #include "../common/status.h"
33 #include "../common/i18n.h"
34 #include "../common/sysutils.h"
35 #include "../common/init.h"
36 #include "../common/asshelp.h"
37 #include "../common/userids.h"
38 #include "../common/ccparray.h"
39 #include "../common/exectool.h"
40 #include "../common/mbox-util.h"
41 #include "../common/name-value.h"
42 #include "../common/comopt.h"
43 #include "call-dirmngr.h"
44 #include "mime-maker.h"
45 #include "send-mail.h"
46 #include "gpg-wks.h"
47
48
49 /* Constants to identify the commands and options. */
50 enum cmd_and_opt_values
51   {
52     aNull = 0,
53
54     oQuiet      = 'q',
55     oVerbose    = 'v',
56     oOutput     = 'o',
57     oDirectory  = 'C',
58
59     oDebug      = 500,
60
61     aSupported,
62     aCheck,
63     aCreate,
64     aReceive,
65     aRead,
66     aMirror,
67     aInstallKey,
68     aRemoveKey,
69     aPrintWKDHash,
70     aPrintWKDURL,
71
72     oGpgProgram,
73     oSend,
74     oFakeSubmissionAddr,
75     oStatusFD,
76     oWithColons,
77     oBlacklist,
78     oNoAutostart,
79     oAddRevocs,
80
81     oDummy
82   };
83
84
85 /* The list of commands and options. */
86 static gpgrt_opt_t opts[] = {
87   ARGPARSE_group (300, ("@Commands:\n ")),
88
89   ARGPARSE_c (aSupported, "supported",
90               ("check whether provider supports WKS")),
91   ARGPARSE_c (aCheck, "check",
92               ("check whether a key is available")),
93   ARGPARSE_c (aCreate,   "create",
94               ("create a publication request")),
95   ARGPARSE_c (aReceive,   "receive",
96               ("receive a MIME confirmation request")),
97   ARGPARSE_c (aRead,      "read",
98               ("receive a plain text confirmation request")),
99   ARGPARSE_c (aMirror, "mirror",
100               "mirror an LDAP directory"),
101   ARGPARSE_c (aInstallKey, "install-key",
102               "install a key into a directory"),
103   ARGPARSE_c (aRemoveKey, "remove-key",
104               "remove a key from a directory"),
105   ARGPARSE_c (aPrintWKDHash, "print-wkd-hash",
106               "print the WKD identifier for the given user ids"),
107   ARGPARSE_c (aPrintWKDURL, "print-wkd-url",
108               "print the WKD URL for the given user id"),
109
110   ARGPARSE_group (301, ("@\nOptions:\n ")),
111
112   ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
113   ARGPARSE_s_n (oQuiet, "quiet",  ("be somewhat more quiet")),
114   ARGPARSE_s_s (oDebug, "debug", "@"),
115   ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
116   ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
117   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
118   ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
119   ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
120   ARGPARSE_s_n (oWithColons, "with-colons", "@"),
121   ARGPARSE_s_s (oBlacklist, "blacklist", "@"),
122   ARGPARSE_s_s (oDirectory, "directory", "@"),
123   ARGPARSE_s_n (oAddRevocs, "add-revocs", "add revocation certificates"),
124
125   ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
126
127   ARGPARSE_end ()
128 };
129
130
131 /* The list of supported debug flags.  */
132 static struct debug_flags_s debug_flags [] =
133   {
134     { DBG_MIME_VALUE   , "mime"    },
135     { DBG_PARSER_VALUE , "parser"  },
136     { DBG_CRYPTO_VALUE , "crypto"  },
137     { DBG_MEMORY_VALUE , "memory"  },
138     { DBG_MEMSTAT_VALUE, "memstat" },
139     { DBG_IPC_VALUE    , "ipc"     },
140     { DBG_EXTPROG_VALUE, "extprog" },
141     { 0, NULL }
142   };
143
144
145
146 /* Value of the option --fake-submission-addr.  */
147 const char *fake_submission_addr;
148
149 /* An array with blacklisted addresses and its length.  Use
150  * is_in_blacklist to check.  */
151 static char **blacklist_array;
152 static size_t blacklist_array_len;
153
154
155 static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
156 static void add_blacklist (const char *fname);
157 static gpg_error_t proc_userid_from_stdin (gpg_error_t (*func)(const char *),
158                                            const char *text);
159 static gpg_error_t command_supported (char *userid);
160 static gpg_error_t command_check (char *userid);
161 static gpg_error_t command_send (const char *fingerprint, const char *userid);
162 static gpg_error_t encrypt_response (estream_t *r_output, estream_t input,
163                                      const char *addrspec,
164                                      const char *fingerprint);
165 static gpg_error_t read_confirmation_request (estream_t msg);
166 static gpg_error_t command_receive_cb (void *opaque,
167                                        const char *mediatype, estream_t fp,
168                                        unsigned int flags);
169 static gpg_error_t command_mirror (char *domain[]);
170
171
172 \f
173 /* Print usage information and provide strings for help. */
174 static const char *
175 my_strusage( int level )
176 {
177   const char *p;
178
179   switch (level)
180     {
181     case  9: p = "LGPL-2.1-or-later"; break;
182     case 11: p = "gpg-wks-client"; break;
183     case 12: p = "@GNUPG@"; break;
184     case 13: p = VERSION; break;
185     case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
186     case 17: p = PRINTABLE_OS_NAME; break;
187     case 19: p = ("Please report bugs to <@EMAIL@>.\n"); break;
188
189     case 1:
190     case 40:
191       p = ("Usage: gpg-wks-client [command] [options] [args] (-h for help)");
192       break;
193     case 41:
194       p = ("Syntax: gpg-wks-client [command] [options] [args]\n"
195            "Client for the Web Key Service\n");
196       break;
197
198     default: p = NULL; break;
199     }
200   return p;
201 }
202
203
204 static void
205 wrong_args (const char *text)
206 {
207   es_fprintf (es_stderr, _("usage: %s [options] %s\n"),
208               gpgrt_strusage (11), text);
209   exit (2);
210 }
211
212
213 \f
214 /* Command line parsing.  */
215 static enum cmd_and_opt_values
216 parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts)
217 {
218   enum cmd_and_opt_values cmd = 0;
219   int no_more_options = 0;
220
221   while (!no_more_options && gpgrt_argparse (NULL, pargs, popts))
222     {
223       switch (pargs->r_opt)
224         {
225         case oQuiet:     opt.quiet = 1; break;
226         case oVerbose:   opt.verbose++; break;
227         case oDebug:
228           if (parse_debug_flag (pargs->r.ret_str, &opt.debug, debug_flags))
229             {
230               pargs->r_opt = ARGPARSE_INVALID_ARG;
231               pargs->err = ARGPARSE_PRINT_ERROR;
232             }
233           break;
234
235         case oGpgProgram:
236           opt.gpg_program = pargs->r.ret_str;
237           break;
238         case oDirectory:
239           opt.directory = pargs->r.ret_str;
240           break;
241         case oSend:
242           opt.use_sendmail = 1;
243           break;
244         case oOutput:
245           opt.output = pargs->r.ret_str;
246           break;
247         case oFakeSubmissionAddr:
248           fake_submission_addr = pargs->r.ret_str;
249           break;
250         case oStatusFD:
251           wks_set_status_fd (translate_sys2libc_fd_int (pargs->r.ret_int, 1));
252           break;
253         case oWithColons:
254           opt.with_colons = 1;
255           break;
256         case oNoAutostart:
257           opt.no_autostart = 1;
258           break;
259         case oBlacklist:
260           add_blacklist (pargs->r.ret_str);
261           break;
262         case oAddRevocs:
263           opt.add_revocs = 1;
264           break;
265
266         case aSupported:
267         case aCreate:
268         case aReceive:
269         case aRead:
270         case aCheck:
271         case aMirror:
272         case aInstallKey:
273         case aRemoveKey:
274         case aPrintWKDHash:
275         case aPrintWKDURL:
276           cmd = pargs->r_opt;
277           break;
278
279         default: pargs->err = ARGPARSE_PRINT_ERROR; break;
280         }
281     }
282
283   return cmd;
284 }
285
286
287 \f
288 /* gpg-wks-client main. */
289 int
290 main (int argc, char **argv)
291 {
292   gpg_error_t err, delayed_err;
293   gpgrt_argparse_t pargs;
294   enum cmd_and_opt_values cmd;
295
296   gnupg_reopen_std ("gpg-wks-client");
297   gpgrt_set_strusage (my_strusage);
298   log_set_prefix ("gpg-wks-client", GPGRT_LOG_WITH_PREFIX);
299
300   /* Make sure that our subsystems are ready.  */
301   i18n_init();
302   init_common_subsystems (&argc, &argv);
303
304   assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
305   setup_libassuan_logging (&opt.debug, NULL);
306
307   /* Parse the command line. */
308   pargs.argc  = &argc;
309   pargs.argv  = &argv;
310   pargs.flags = ARGPARSE_FLAG_KEEP;
311   cmd = parse_arguments (&pargs, opts);
312   gpgrt_argparse (NULL, &pargs, NULL);
313
314   /* Check if gpg is build with sendmail support */
315   if (opt.use_sendmail && !NAME_OF_SENDMAIL[0])
316     {
317       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
318       log_error ("sending mail is not supported in this build: %s\n",
319                 gpg_strerror (err));
320     }
321
322   if (log_get_errorcount (0))
323     exit (2);
324
325   /* Process common component options.  Note that we set the config
326    * dir only here so that --homedir will have an effect.  */
327   gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
328   gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
329   if (parse_comopt (GNUPG_MODULE_NAME_CONNECT_AGENT, opt.verbose > 1))
330     exit(2);
331   if (comopt.no_autostart)
332      opt.no_autostart = 1;
333
334   /* Print a warning if an argument looks like an option.  */
335   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
336     {
337       int i;
338
339       for (i=0; i < argc; i++)
340         if (argv[i][0] == '-' && argv[i][1] == '-')
341           log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
342     }
343
344   /* Set defaults for non given options.  */
345   if (!opt.gpg_program)
346     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
347
348   if (!opt.directory)
349     opt.directory = "openpgpkey";
350
351   /* Tell call-dirmngr what options we want.  */
352   set_dirmngr_options (opt.verbose, (opt.debug & DBG_IPC_VALUE),
353                        !opt.no_autostart);
354
355
356   /* Check that the top directory exists.  */
357   if (cmd == aInstallKey || cmd == aRemoveKey || cmd == aMirror)
358     {
359       struct stat sb;
360
361       if (gnupg_stat (opt.directory, &sb))
362         {
363           err = gpg_error_from_syserror ();
364           log_error ("error accessing directory '%s': %s\n",
365                      opt.directory, gpg_strerror (err));
366           goto leave;
367         }
368       if (!S_ISDIR(sb.st_mode))
369         {
370           log_error ("error accessing directory '%s': %s\n",
371                      opt.directory, "not a directory");
372           err = gpg_error (GPG_ERR_ENOENT);
373           goto leave;
374         }
375     }
376
377   /* Run the selected command.  */
378   switch (cmd)
379     {
380     case aSupported:
381       if (opt.with_colons)
382         {
383           for (; argc; argc--, argv++)
384             command_supported (*argv);
385           err = 0;
386         }
387       else
388         {
389           if (argc != 1)
390             wrong_args ("--supported DOMAIN");
391           err = command_supported (argv[0]);
392           if (err && gpg_err_code (err) != GPG_ERR_FALSE)
393             log_error ("checking support failed: %s\n", gpg_strerror (err));
394         }
395       break;
396
397     case aCreate:
398       if (argc != 2)
399         wrong_args ("--create FINGERPRINT USER-ID");
400       err = command_send (argv[0], argv[1]);
401       if (err)
402         log_error ("creating request failed: %s\n", gpg_strerror (err));
403       break;
404
405     case aReceive:
406       if (argc)
407         wrong_args ("--receive < MIME-DATA");
408       err = wks_receive (es_stdin, command_receive_cb, NULL);
409       if (err)
410         log_error ("processing mail failed: %s\n", gpg_strerror (err));
411       break;
412
413     case aRead:
414       if (argc)
415         wrong_args ("--read < WKS-DATA");
416       err = read_confirmation_request (es_stdin);
417       if (err)
418         log_error ("processing mail failed: %s\n", gpg_strerror (err));
419       break;
420
421     case aCheck:
422       if (argc != 1)
423         wrong_args ("--check USER-ID");
424       err = command_check (argv[0]);
425       break;
426
427     case aMirror:
428       if (!argc)
429         err = command_mirror (NULL);
430       else
431         err = command_mirror (argv);
432       break;
433
434     case aInstallKey:
435       if (!argc)
436         err = wks_cmd_install_key (NULL, NULL);
437       else if (argc == 2)
438         err = wks_cmd_install_key (*argv, argv[1]);
439       else
440         wrong_args ("--install-key [FILE|FINGERPRINT USER-ID]");
441       break;
442
443     case aRemoveKey:
444       if (argc != 1)
445         wrong_args ("--remove-key USER-ID");
446       err = wks_cmd_remove_key (*argv);
447       break;
448
449     case aPrintWKDHash:
450     case aPrintWKDURL:
451       if (!argc)
452         {
453           if (cmd == aPrintWKDHash)
454             err = proc_userid_from_stdin (wks_cmd_print_wkd_hash,
455                                           "printing WKD hash");
456           else
457             err = proc_userid_from_stdin (wks_cmd_print_wkd_url,
458                                           "printing WKD URL");
459         }
460       else
461         {
462           for (err = delayed_err = 0; !err && argc; argc--, argv++)
463             {
464               if (cmd == aPrintWKDHash)
465                 err = wks_cmd_print_wkd_hash (*argv);
466               else
467                 err = wks_cmd_print_wkd_url (*argv);
468               if (gpg_err_code (err) == GPG_ERR_INV_USER_ID)
469                 {
470                   /* Diagnostic already printed.  */
471                   delayed_err = err;
472                   err = 0;
473                 }
474               else if (err)
475                 log_error ("printing hash failed: %s\n", gpg_strerror (err));
476             }
477           if (!err)
478             err = delayed_err;
479         }
480       break;
481
482     default:
483       gpgrt_usage (1);
484       err = 0;
485       break;
486     }
487
488  leave:
489   if (err)
490     wks_write_status (STATUS_FAILURE, "- %u", err);
491   else if (log_get_errorcount (0))
492     wks_write_status (STATUS_FAILURE, "- %u", GPG_ERR_GENERAL);
493   else
494     wks_write_status (STATUS_SUCCESS, NULL);
495   return (err || log_get_errorcount (0))? 1:0;
496 }
497
498
499
500 /* Read a file FNAME into a buffer and return that malloced buffer.
501  * Caller must free the buffer.  On error NULL is returned, on success
502  * the valid length of the buffer is stored at R_LENGTH.  The returned
503  * buffer is guaranteed to be Nul terminated.  */
504 static char *
505 read_file (const char *fname, size_t *r_length)
506 {
507   estream_t fp;
508   char *buf;
509   size_t buflen;
510
511   if (!strcmp (fname, "-"))
512     {
513       size_t nread, bufsize = 0;
514
515       fp = es_stdin;
516       es_set_binary (fp);
517       buf = NULL;
518       buflen = 0;
519 #define NCHUNK 32767
520       do
521         {
522           bufsize += NCHUNK;
523           if (!buf)
524             buf = xmalloc (bufsize+1);
525           else
526             buf = xrealloc (buf, bufsize+1);
527
528           nread = es_fread (buf+buflen, 1, NCHUNK, fp);
529           if (nread < NCHUNK && es_ferror (fp))
530             {
531               log_error ("error reading '[stdin]': %s\n", strerror (errno));
532               xfree (buf);
533               return NULL;
534             }
535           buflen += nread;
536         }
537       while (nread == NCHUNK);
538 #undef NCHUNK
539     }
540   else
541     {
542       struct stat st;
543
544       fp = es_fopen (fname, "rb");
545       if (!fp)
546         {
547           log_error ("can't open '%s': %s\n", fname, strerror (errno));
548           return NULL;
549         }
550
551       if (fstat (es_fileno (fp), &st))
552         {
553           log_error ("can't stat '%s': %s\n", fname, strerror (errno));
554           es_fclose (fp);
555           return NULL;
556         }
557
558       buflen = st.st_size;
559       buf = xmalloc (buflen+1);
560       if (es_fread (buf, buflen, 1, fp) != 1)
561         {
562           log_error ("error reading '%s': %s\n", fname, strerror (errno));
563           es_fclose (fp);
564           xfree (buf);
565           return NULL;
566         }
567       es_fclose (fp);
568     }
569   buf[buflen] = 0;
570   if (r_length)
571     *r_length = buflen;
572   return buf;
573 }
574
575
576 static int
577 cmp_blacklist (const void *arg_a, const void *arg_b)
578 {
579   const char *a = *(const char **)arg_a;
580   const char *b = *(const char **)arg_b;
581   return strcmp (a, b);
582 }
583
584
585 /* Add a blacklist to our global table.  This is called during option
586  * parsing and thus any use of log_error will eventually stop further
587  * processing.  */
588 static void
589 add_blacklist (const char *fname)
590 {
591   char *buffer;
592   char *p, *pend;
593   char **array;
594   size_t arraysize, arrayidx;
595
596   buffer = read_file (fname, NULL);
597   if (!buffer)
598     return;
599
600   /* Estimate the number of entries by counting the non-comment lines.  */
601   arraysize = 2; /* For the first and an extra NULL item.  */
602   for (p=buffer; *p; p++)
603     if (*p == '\n' && p[1] && p[1] != '#')
604       arraysize++;
605
606   array = xcalloc (arraysize, sizeof *array);
607   arrayidx = 0;
608
609   /* Loop over all lines.  */
610   for (p = buffer; p && *p; p = pend)
611     {
612       pend = strchr (p, '\n');
613       if (pend)
614         *pend++ = 0;
615       trim_spaces (p);
616       if (!*p || *p == '#' )
617         continue;
618       ascii_strlwr (p);
619       log_assert (arrayidx < arraysize);
620       array[arrayidx] = p;
621       arrayidx++;
622     }
623   log_assert (arrayidx < arraysize);
624
625   qsort (array, arrayidx, sizeof *array, cmp_blacklist);
626
627   blacklist_array = array;
628   blacklist_array_len = arrayidx;
629   gpgrt_annotate_leaked_object (buffer);
630   gpgrt_annotate_leaked_object (blacklist_array);
631 }
632
633
634 /* Return true if NAME is in a blacklist.  */
635 static int
636 is_in_blacklist (const char *name)
637 {
638   if (!name || !blacklist_array)
639     return 0;
640   return !!bsearch (&name, blacklist_array, blacklist_array_len,
641                     sizeof *blacklist_array, cmp_blacklist);
642 }
643
644
645 \f
646 /* Read user ids from stdin and call FUNC for each user id.  TEXT is
647  * used for error messages.  */
648 static gpg_error_t
649 proc_userid_from_stdin (gpg_error_t (*func)(const char *), const char *text)
650 {
651   gpg_error_t err = 0;
652   gpg_error_t delayed_err = 0;
653   char line[2048];
654   size_t n = 0;
655
656   /* If we are on a terminal disable buffering to get direct response.  */
657   if (gnupg_isatty (es_fileno (es_stdin))
658       && gnupg_isatty (es_fileno (es_stdout)))
659     {
660       es_setvbuf (es_stdin, NULL, _IONBF, 0);
661       es_setvbuf (es_stdout, NULL, _IOLBF, 0);
662     }
663
664   while (es_fgets (line, sizeof line - 1, es_stdin))
665     {
666       n = strlen (line);
667       if (!n || line[n-1] != '\n')
668         {
669           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
670                            : GPG_ERR_INCOMPLETE_LINE);
671           log_error ("error reading stdin: %s\n", gpg_strerror (err));
672           break;
673         }
674       trim_spaces (line);
675       err = func (line);
676       if (gpg_err_code (err) == GPG_ERR_INV_USER_ID)
677         {
678           delayed_err = err;
679           err = 0;
680         }
681       else if (err)
682         log_error ("%s failed: %s\n", text, gpg_strerror (err));
683     }
684   if (es_ferror (es_stdin))
685     {
686       err = gpg_error_from_syserror ();
687       log_error ("error reading stdin: %s\n", gpg_strerror (err));
688       goto leave;
689     }
690
691  leave:
692   if (!err)
693     err = delayed_err;
694   return err;
695 }
696
697
698
699 \f
700 /* Add the user id UID to the key identified by FINGERPRINT.  */
701 static gpg_error_t
702 add_user_id (const char *fingerprint, const char *uid)
703 {
704   gpg_error_t err;
705   ccparray_t ccp;
706   const char **argv = NULL;
707
708   ccparray_init (&ccp, 0);
709
710   ccparray_put (&ccp, "--no-options");
711   if (opt.verbose < 2)
712     ccparray_put (&ccp, "--quiet");
713   else
714     ccparray_put (&ccp, "--verbose");
715   ccparray_put (&ccp, "--batch");
716   ccparray_put (&ccp, "--always-trust");
717   ccparray_put (&ccp, "--quick-add-uid");
718   ccparray_put (&ccp, fingerprint);
719   ccparray_put (&ccp, uid);
720
721   ccparray_put (&ccp, NULL);
722   argv = ccparray_get (&ccp, NULL);
723   if (!argv)
724     {
725       err = gpg_error_from_syserror ();
726       goto leave;
727     }
728   err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
729                                 NULL, NULL,
730                                 NULL, NULL);
731   if (err)
732     {
733       log_error ("adding user id failed: %s\n", gpg_strerror (err));
734       goto leave;
735     }
736
737  leave:
738   xfree (argv);
739   return err;
740 }
741
742
743 \f
744 struct decrypt_stream_parm_s
745 {
746   char *fpr;
747   char *mainfpr;
748   int  otrust;
749 };
750
751 static void
752 decrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
753 {
754   struct decrypt_stream_parm_s *decinfo = opaque;
755
756   if (DBG_CRYPTO)
757     log_debug ("gpg status: %s %s\n", keyword, args);
758   if (!strcmp (keyword, "DECRYPTION_KEY") && !decinfo->fpr)
759     {
760       const char *fields[3];
761
762       if (split_fields (args, fields, DIM (fields)) >= 3)
763         {
764           decinfo->fpr = xstrdup (fields[0]);
765           decinfo->mainfpr = xstrdup (fields[1]);
766           decinfo->otrust = *fields[2];
767         }
768     }
769 }
770
771 /* Decrypt the INPUT stream to a new stream which is stored at success
772  * at R_OUTPUT.  */
773 static gpg_error_t
774 decrypt_stream (estream_t *r_output, struct decrypt_stream_parm_s *decinfo,
775                 estream_t input)
776 {
777   gpg_error_t err;
778   ccparray_t ccp;
779   const char **argv;
780   estream_t output;
781
782   *r_output = NULL;
783   memset (decinfo, 0, sizeof *decinfo);
784
785   output = es_fopenmem (0, "w+b");
786   if (!output)
787     {
788       err = gpg_error_from_syserror ();
789       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
790       return err;
791     }
792
793   ccparray_init (&ccp, 0);
794
795   ccparray_put (&ccp, "--no-options");
796   /* We limit the output to 64 KiB to avoid DoS using compression
797    * tricks.  A regular client will anyway only send a minimal key;
798    * that is one w/o key signatures and attribute packets.  */
799   ccparray_put (&ccp, "--max-output=0x10000");
800   if (opt.verbose < 2)
801     ccparray_put (&ccp, "--quiet");
802   else
803     ccparray_put (&ccp, "--verbose");
804   ccparray_put (&ccp, "--batch");
805   ccparray_put (&ccp, "--status-fd=2");
806   ccparray_put (&ccp, "--decrypt");
807   ccparray_put (&ccp, "--");
808
809   ccparray_put (&ccp, NULL);
810   argv = ccparray_get (&ccp, NULL);
811   if (!argv)
812     {
813       err = gpg_error_from_syserror ();
814       goto leave;
815     }
816   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
817                                 NULL, output,
818                                 decrypt_stream_status_cb, decinfo);
819   if (!err && (!decinfo->fpr || !decinfo->mainfpr || !decinfo->otrust))
820     err = gpg_error (GPG_ERR_INV_ENGINE);
821   if (err)
822     {
823       log_error ("decryption failed: %s\n", gpg_strerror (err));
824       goto leave;
825     }
826   else if (opt.verbose)
827     log_info ("decryption succeeded\n");
828
829   es_rewind (output);
830   *r_output = output;
831   output = NULL;
832
833  leave:
834   if (err)
835     {
836       xfree (decinfo->fpr);
837       xfree (decinfo->mainfpr);
838       memset (decinfo, 0, sizeof *decinfo);
839     }
840   es_fclose (output);
841   xfree (argv);
842   return err;
843 }
844
845
846 /* Return the submission address for the address or just the domain in
847  * ADDRSPEC.  The submission address is stored as a malloced string at
848  * R_SUBMISSION_ADDRESS.  At R_POLICY the policy flags of the domain
849  * are stored.  The caller needs to free them with wks_free_policy.
850  * The function returns an error code on failure to find a submission
851  * address or policy file.  Note: The function may store NULL at
852  * R_SUBMISSION_ADDRESS but return success to indicate that the web
853  * key directory is supported but not the web key service.  As per WKD
854  * specs a policy file is always required and will thus be return on
855  * success.  */
856 static gpg_error_t
857 get_policy_and_sa (const char *addrspec, int silent,
858                    policy_flags_t *r_policy, char **r_submission_address)
859 {
860   gpg_error_t err;
861   estream_t mbuf = NULL;
862   const char *domain;
863   const char *s;
864   policy_flags_t policy = NULL;
865   char *submission_to = NULL;
866
867   *r_submission_address = NULL;
868   *r_policy = NULL;
869
870   domain = strchr (addrspec, '@');
871   if (domain)
872     domain++;
873
874   if (opt.with_colons)
875     {
876       s = domain? domain : addrspec;
877       es_write_sanitized (es_stdout, s, strlen (s), ":", NULL);
878       es_putc (':', es_stdout);
879     }
880
881   /* We first try to get the submission address from the policy file
882    * (this is the new method).  If both are available we check that
883    * they match and print a warning if not.  In the latter case we
884    * keep on using the one from the submission-address file.    */
885   err = wkd_get_policy_flags (addrspec, &mbuf);
886   if (err && gpg_err_code (err) != GPG_ERR_NO_DATA
887       && gpg_err_code (err) != GPG_ERR_NO_NAME)
888     {
889       if (!opt.with_colons)
890         log_error ("error reading policy flags for '%s': %s\n",
891                    domain, gpg_strerror (err));
892       goto leave;
893     }
894   if (!mbuf)
895     {
896       if (!opt.with_colons)
897         log_error ("provider for '%s' does NOT support the Web Key Directory\n",
898                    addrspec);
899       err = gpg_error (GPG_ERR_FALSE);
900       goto leave;
901     }
902
903   policy = xtrycalloc (1, sizeof *policy);
904   if (!policy)
905     err = gpg_error_from_syserror ();
906   else
907     err = wks_parse_policy (policy, mbuf, 1);
908   es_fclose (mbuf);
909   mbuf = NULL;
910   if (err)
911     goto leave;
912
913   err = wkd_get_submission_address (addrspec, &submission_to);
914   if (err && !policy->submission_address)
915     {
916       if (!silent && !opt.with_colons)
917         log_error (_("error looking up submission address for domain '%s'"
918                      ": %s\n"), domain, gpg_strerror (err));
919       if (!silent && gpg_err_code (err) == GPG_ERR_NO_DATA && !opt.with_colons)
920         log_error (_("this domain probably doesn't support WKS.\n"));
921       goto leave;
922     }
923
924   if (submission_to && policy->submission_address
925       && ascii_strcasecmp (submission_to, policy->submission_address))
926     log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
927               submission_to, policy->submission_address);
928
929   if (!submission_to && policy->submission_address)
930     {
931       submission_to = xtrystrdup (policy->submission_address);
932       if (!submission_to)
933         {
934           err = gpg_error_from_syserror ();
935           goto leave;
936         }
937     }
938
939  leave:
940   *r_submission_address = submission_to;
941   submission_to = NULL;
942   *r_policy = policy;
943   policy = NULL;
944
945   if (opt.with_colons)
946     {
947       if (*r_policy && !*r_submission_address)
948         es_fprintf (es_stdout, "1:0::");
949       else if (*r_policy && *r_submission_address)
950         es_fprintf (es_stdout, "1:1::");
951       else if (err && !(gpg_err_code (err) == GPG_ERR_FALSE
952                         || gpg_err_code (err) == GPG_ERR_NO_DATA
953                         || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST))
954         es_fprintf (es_stdout, "0:0:%d:", err);
955       else
956         es_fprintf (es_stdout, "0:0::");
957       if (*r_policy)
958         {
959           es_fprintf (es_stdout, "%u:%u:%u:",
960                       (*r_policy)->protocol_version,
961                       (*r_policy)->auth_submit,
962                       (*r_policy)->mailbox_only);
963         }
964       es_putc ('\n', es_stdout);
965     }
966
967   xfree (submission_to);
968   wks_free_policy (policy);
969   xfree (policy);
970   es_fclose (mbuf);
971   return err;
972 }
973
974
975 \f
976 /* Check whether the  provider supports the WKS protocol.  */
977 static gpg_error_t
978 command_supported (char *userid)
979 {
980   gpg_error_t err;
981   char *addrspec = NULL;
982   char *submission_to = NULL;
983   policy_flags_t policy = NULL;
984
985   if (!strchr (userid, '@'))
986     {
987       char *tmp = xstrconcat ("foo@", userid, NULL);
988       addrspec = mailbox_from_userid (tmp, 0);
989       xfree (tmp);
990     }
991   else
992     addrspec = mailbox_from_userid (userid, 0);
993   if (!addrspec)
994     {
995       log_error (_("\"%s\" is not a proper mail address\n"), userid);
996       err = gpg_error (GPG_ERR_INV_USER_ID);
997       goto leave;
998     }
999
1000   /* Get the submission address.  */
1001   err = get_policy_and_sa (addrspec, 1, &policy, &submission_to);
1002   if (err || !submission_to)
1003     {
1004       if (!submission_to
1005           || gpg_err_code (err) == GPG_ERR_FALSE
1006           || gpg_err_code (err) == GPG_ERR_NO_DATA
1007           || gpg_err_code (err) == GPG_ERR_UNKNOWN_HOST
1008           )
1009         {
1010           /* FALSE is returned if we already figured out that even the
1011            * Web Key Directory is not supported and thus printed an
1012            * error message.  */
1013           if (opt.verbose && gpg_err_code (err) != GPG_ERR_FALSE
1014               && !opt.with_colons)
1015             {
1016               if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1017                 log_info ("provider for '%s' does NOT support WKS\n",
1018                           addrspec);
1019               else
1020                 log_info ("provider for '%s' does NOT support WKS (%s)\n",
1021                           addrspec, gpg_strerror (err));
1022             }
1023           err = gpg_error (GPG_ERR_FALSE);
1024           if (!opt.with_colons)
1025             log_inc_errorcount ();
1026         }
1027       goto leave;
1028     }
1029
1030   if (opt.verbose && !opt.with_colons)
1031     log_info ("provider for '%s' supports WKS\n", addrspec);
1032
1033  leave:
1034   wks_free_policy (policy);
1035   xfree (policy);
1036   xfree (submission_to);
1037   xfree (addrspec);
1038   return err;
1039 }
1040
1041
1042 \f
1043 /* Check whether the key for USERID is available in the WKD.  */
1044 static gpg_error_t
1045 command_check (char *userid)
1046 {
1047   gpg_error_t err;
1048   char *addrspec = NULL;
1049   estream_t key = NULL;
1050   char *fpr = NULL;
1051   uidinfo_list_t mboxes = NULL;
1052   uidinfo_list_t sl;
1053   int found = 0;
1054
1055   addrspec = mailbox_from_userid (userid, 0);
1056   if (!addrspec)
1057     {
1058       log_error (_("\"%s\" is not a proper mail address\n"), userid);
1059       err = gpg_error (GPG_ERR_INV_USER_ID);
1060       goto leave;
1061     }
1062
1063   /* Get the submission address.  */
1064   err = wkd_get_key (addrspec, &key);
1065   switch (gpg_err_code (err))
1066     {
1067     case 0:
1068       if (opt.verbose)
1069         log_info ("public key for '%s' found via WKD\n", addrspec);
1070       /* Fixme: Check that the key contains the user id.  */
1071       break;
1072
1073     case GPG_ERR_NO_DATA: /* No such key.  */
1074       if (opt.verbose)
1075         log_info ("public key for '%s' NOT found via WKD\n", addrspec);
1076       err = gpg_error (GPG_ERR_NO_PUBKEY);
1077       log_inc_errorcount ();
1078       break;
1079
1080     case GPG_ERR_UNKNOWN_HOST:
1081       if (opt.verbose)
1082         log_info ("error looking up '%s' via WKD: %s\n",
1083                   addrspec, gpg_strerror (err));
1084       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1085       break;
1086
1087     default:
1088       log_error ("error looking up '%s' via WKD: %s\n",
1089                  addrspec, gpg_strerror (err));
1090       break;
1091     }
1092
1093   if (err)
1094     goto leave;
1095
1096   /* Look closer at the key.  */
1097   err = wks_list_key (key, &fpr, &mboxes);
1098   if (err)
1099     {
1100       log_error ("error parsing key: %s\n", gpg_strerror (err));
1101       err = gpg_error (GPG_ERR_NO_PUBKEY);
1102       goto leave;
1103     }
1104
1105   if (opt.verbose)
1106     log_info ("fingerprint: %s\n", fpr);
1107
1108   for (sl = mboxes; sl; sl = sl->next)
1109     {
1110       if (sl->mbox && !strcmp (sl->mbox, addrspec))
1111         found = 1;
1112       if (opt.verbose)
1113         {
1114           log_info ("    user-id: %s\n", sl->uid);
1115           log_info ("    created: %s\n", asctimestamp (sl->created));
1116           if (sl->mbox)
1117             log_info ("  addr-spec: %s\n", sl->mbox);
1118           if (sl->expired || sl->revoked)
1119             log_info ("    flags:%s%s\n",
1120                       sl->expired? " expired":"", sl->revoked?" revoked":"");
1121         }
1122     }
1123   if (!found)
1124     {
1125       log_error ("public key for '%s' has no user id with the mail address\n",
1126                  addrspec);
1127       err = gpg_error (GPG_ERR_CERT_REVOKED);
1128     }
1129
1130  leave:
1131   xfree (fpr);
1132   free_uidinfo_list (mboxes);
1133   es_fclose (key);
1134   xfree (addrspec);
1135   return err;
1136 }
1137
1138
1139 \f
1140 /* Locate the key by fingerprint and userid and send a publication
1141  * request.  */
1142 static gpg_error_t
1143 command_send (const char *fingerprint, const char *userid)
1144 {
1145   gpg_error_t err;
1146   KEYDB_SEARCH_DESC desc;
1147   char *addrspec = NULL;
1148   estream_t key = NULL;
1149   estream_t keyenc = NULL;
1150   char *submission_to = NULL;
1151   mime_maker_t mime = NULL;
1152   policy_flags_t policy = NULL;
1153   int no_encrypt = 0;
1154   int posteo_hack = 0;
1155   const char *domain;
1156   uidinfo_list_t uidlist = NULL;
1157   uidinfo_list_t uid, thisuid;
1158   time_t thistime;
1159   int any;
1160
1161   if (classify_user_id (fingerprint, &desc, 1)
1162       || desc.mode != KEYDB_SEARCH_MODE_FPR)
1163     {
1164       log_error (_("\"%s\" is not a fingerprint\n"), fingerprint);
1165       err = gpg_error (GPG_ERR_INV_NAME);
1166       goto leave;
1167     }
1168
1169   addrspec = mailbox_from_userid (userid, 0);
1170   if (!addrspec)
1171     {
1172       log_error (_("\"%s\" is not a proper mail address\n"), userid);
1173       err = gpg_error (GPG_ERR_INV_USER_ID);
1174       goto leave;
1175     }
1176   err = wks_get_key (&key, fingerprint, addrspec, 0, 1);
1177   if (err)
1178     goto leave;
1179
1180   domain = strchr (addrspec, '@');
1181   log_assert (domain);
1182   domain++;
1183
1184   /* Get the submission address.  */
1185   if (fake_submission_addr)
1186     {
1187       policy = xcalloc (1, sizeof *policy);
1188       submission_to = xstrdup (fake_submission_addr);
1189       err = 0;
1190     }
1191   else
1192     {
1193       err = get_policy_and_sa (addrspec, 0, &policy, &submission_to);
1194       if (err)
1195         goto leave;
1196       if (!submission_to)
1197         {
1198           log_error (_("this domain probably doesn't support WKS.\n"));
1199           err = gpg_error (GPG_ERR_NO_DATA);
1200           goto leave;
1201         }
1202     }
1203
1204   log_info ("submitting request to '%s'\n", submission_to);
1205
1206   if (policy->auth_submit)
1207     log_info ("no confirmation required for '%s'\n", addrspec);
1208
1209   /* In case the key has several uids with the same addr-spec we will
1210    * use the newest one.  */
1211   err = wks_list_key (key, NULL, &uidlist);
1212   if (err)
1213     {
1214       log_error ("error parsing key: %s\n",gpg_strerror (err));
1215       err = gpg_error (GPG_ERR_NO_PUBKEY);
1216       goto leave;
1217     }
1218   thistime = 0;
1219   thisuid = NULL;
1220   any = 0;
1221   for (uid = uidlist; uid; uid = uid->next)
1222     {
1223       if (!uid->mbox)
1224         continue; /* Should not happen anyway.  */
1225       if (policy->mailbox_only && ascii_strcasecmp (uid->uid, uid->mbox))
1226         continue; /* UID has more than just the mailbox.  */
1227       if (uid->expired)
1228         {
1229           if (opt.verbose)
1230             log_info ("ignoring expired user id '%s'\n", uid->uid);
1231           continue;
1232         }
1233       any = 1;
1234       if (uid->created > thistime)
1235         {
1236           thistime = uid->created;
1237           thisuid = uid;
1238         }
1239     }
1240   if (!thisuid)
1241     thisuid = uidlist;  /* This is the case for a missing timestamp.  */
1242   if (!any)
1243     {
1244       log_error ("public key %s has no mail address '%s'\n",
1245                  fingerprint, addrspec);
1246       err = gpg_error (GPG_ERR_INV_USER_ID);
1247       goto leave;
1248     }
1249
1250   if (opt.verbose)
1251     log_info ("submitting key with user id '%s'\n", thisuid->uid);
1252
1253   /* If we have more than one user id we need to filter the key to
1254    * include only THISUID.  */
1255   if (uidlist->next)
1256     {
1257       estream_t newkey;
1258
1259       es_rewind (key);
1260       err = wks_filter_uid (&newkey, key, thisuid->uid, 1);
1261       if (err)
1262         {
1263           log_error ("error filtering key: %s\n", gpg_strerror (err));
1264           err = gpg_error (GPG_ERR_NO_PUBKEY);
1265           goto leave;
1266         }
1267       es_fclose (key);
1268       key = newkey;
1269     }
1270
1271   if (policy->mailbox_only
1272       && (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox)))
1273     {
1274       log_info ("Warning: policy requires 'mailbox-only'"
1275                 " - adding user id '%s'\n", addrspec);
1276       err = add_user_id (fingerprint, addrspec);
1277       if (err)
1278         goto leave;
1279
1280       /* Need to get the key again.  This time we request filtering
1281        * for the full user id, so that we do not need check and filter
1282        * the key again.  */
1283       es_fclose (key);
1284       key = NULL;
1285       err = wks_get_key (&key, fingerprint, addrspec, 1, 1);
1286       if (err)
1287         goto leave;
1288     }
1289
1290   if (opt.add_revocs)
1291     {
1292       if (es_fseek (key, 0, SEEK_END))
1293         {
1294           err = gpg_error_from_syserror ();
1295           log_error ("error seeking stream: %s\n", gpg_strerror (err));
1296           goto leave;
1297         }
1298       err = wks_find_add_revocs (key, addrspec);
1299       if (err)
1300         {
1301           log_error ("error finding revocations for '%s': %s\n",
1302                      addrspec, gpg_strerror (err));
1303           goto leave;
1304         }
1305     }
1306
1307
1308   /* Now put the armor around the key.  */
1309   {
1310     estream_t newkey;
1311
1312     es_rewind (key);
1313     err = wks_armor_key (&newkey, key,
1314                          no_encrypt? NULL
1315                          /* */    : ("Content-Type: application/pgp-keys\n"
1316                                      "\n"));
1317     if (err)
1318       {
1319         log_error ("error armoring key: %s\n", gpg_strerror (err));
1320         goto leave;
1321       }
1322     es_fclose (key);
1323     key = newkey;
1324   }
1325
1326   /* Hack to support posteo but let them disable this by setting the
1327    * new policy-version flag.  */
1328   if (policy->protocol_version < 3
1329       && !ascii_strcasecmp (domain, "posteo.de"))
1330     {
1331       log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
1332       no_encrypt = 1;
1333       posteo_hack = 1;
1334     }
1335
1336   /* Encrypt the key part.  */
1337   if (!no_encrypt)
1338     {
1339       es_rewind (key);
1340       err = encrypt_response (&keyenc, key, submission_to, fingerprint);
1341       if (err)
1342         goto leave;
1343       es_fclose (key);
1344       key = NULL;
1345     }
1346
1347   /* Send the key.  */
1348   err = mime_maker_new (&mime, NULL);
1349   if (err)
1350     goto leave;
1351   err = mime_maker_add_header (mime, "From", addrspec);
1352   if (err)
1353     goto leave;
1354   err = mime_maker_add_header (mime, "To", submission_to);
1355   if (err)
1356     goto leave;
1357   err = mime_maker_add_header (mime, "Subject", "Key publishing request");
1358   if (err)
1359     goto leave;
1360
1361   /* Tell server which draft we support.  */
1362   err = mime_maker_add_header (mime, "Wks-Draft-Version",
1363                                  STR2(WKS_DRAFT_VERSION));
1364   if (err)
1365     goto leave;
1366
1367   if (no_encrypt)
1368     {
1369       void *data;
1370       size_t datalen;
1371
1372       if (posteo_hack)
1373         {
1374           /* Needs a multipart/mixed with one(!) attachment.  It does
1375            * not grok a non-multipart mail.  */
1376           err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
1377           if (err)
1378             goto leave;
1379           err = mime_maker_add_container (mime);
1380           if (err)
1381             goto leave;
1382         }
1383
1384       err = mime_maker_add_header (mime, "Content-type",
1385                                    "application/pgp-keys");
1386       if (err)
1387         goto leave;
1388
1389       if (es_fclose_snatch (key, &data, &datalen))
1390         {
1391           err = gpg_error_from_syserror ();
1392           goto leave;
1393         }
1394       key = NULL;
1395       err = mime_maker_add_body_data (mime, data, datalen);
1396       xfree (data);
1397       if (err)
1398         goto leave;
1399     }
1400   else
1401     {
1402       err = mime_maker_add_header (mime, "Content-Type",
1403                                    "multipart/encrypted; "
1404                                    "protocol=\"application/pgp-encrypted\"");
1405       if (err)
1406         goto leave;
1407       err = mime_maker_add_container (mime);
1408       if (err)
1409         goto leave;
1410
1411       err = mime_maker_add_header (mime, "Content-Type",
1412                                    "application/pgp-encrypted");
1413       if (err)
1414         goto leave;
1415       err = mime_maker_add_body (mime, "Version: 1\n");
1416       if (err)
1417         goto leave;
1418       err = mime_maker_add_header (mime, "Content-Type",
1419                                    "application/octet-stream");
1420       if (err)
1421         goto leave;
1422
1423       err = mime_maker_add_stream (mime, &keyenc);
1424       if (err)
1425         goto leave;
1426     }
1427
1428   err = wks_send_mime (mime);
1429
1430  leave:
1431   mime_maker_release (mime);
1432   xfree (submission_to);
1433   free_uidinfo_list (uidlist);
1434   es_fclose (keyenc);
1435   es_fclose (key);
1436   wks_free_policy (policy);
1437   xfree (policy);
1438   xfree (addrspec);
1439   return err;
1440 }
1441
1442
1443 \f
1444 static void
1445 encrypt_response_status_cb (void *opaque, const char *keyword, char *args)
1446 {
1447   gpg_error_t *failure = opaque;
1448   const char *fields[2];
1449
1450   if (DBG_CRYPTO)
1451     log_debug ("gpg status: %s %s\n", keyword, args);
1452
1453   if (!strcmp (keyword, "FAILURE"))
1454     {
1455       if (split_fields (args, fields, DIM (fields)) >= 2
1456           && !strcmp (fields[0], "encrypt"))
1457         *failure = strtoul (fields[1], NULL, 10);
1458     }
1459
1460 }
1461
1462
1463 /* Encrypt the INPUT stream to a new stream which is stored at success
1464  * at R_OUTPUT.  Encryption is done for ADDRSPEC and for FINGERPRINT
1465  * (so that the sent message may later be inspected by the user).  We
1466  * currently retrieve that key from the WKD, DANE, or from "local".
1467  * "local" is last to prefer the latest key version but use a local
1468  * copy in case we are working offline.  It might be useful for the
1469  * server to send the fingerprint of its encryption key - or even the
1470  * entire key back.  */
1471 static gpg_error_t
1472 encrypt_response (estream_t *r_output, estream_t input, const char *addrspec,
1473                   const char *fingerprint)
1474 {
1475   gpg_error_t err;
1476   ccparray_t ccp;
1477   const char **argv;
1478   estream_t output;
1479   gpg_error_t gpg_err = 0;
1480
1481   *r_output = NULL;
1482
1483   output = es_fopenmem (0, "w+b");
1484   if (!output)
1485     {
1486       err = gpg_error_from_syserror ();
1487       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1488       return err;
1489     }
1490
1491   ccparray_init (&ccp, 0);
1492
1493   ccparray_put (&ccp, "--no-options");
1494   if (opt.verbose < 2)
1495     ccparray_put (&ccp, "--quiet");
1496   else
1497     ccparray_put (&ccp, "--verbose");
1498   ccparray_put (&ccp, "--batch");
1499   ccparray_put (&ccp, "--status-fd=2");
1500   ccparray_put (&ccp, "--always-trust");
1501   ccparray_put (&ccp, "--armor");
1502   ccparray_put (&ccp, "-z0");  /* No compression for improved robustness.  */
1503   if (fake_submission_addr)
1504     ccparray_put (&ccp, "--auto-key-locate=clear,local");
1505   else
1506     ccparray_put (&ccp, "--auto-key-locate=clear,wkd,dane,local");
1507   ccparray_put (&ccp, "--recipient");
1508   ccparray_put (&ccp, addrspec);
1509   ccparray_put (&ccp, "--recipient");
1510   ccparray_put (&ccp, fingerprint);
1511   ccparray_put (&ccp, "--encrypt");
1512   ccparray_put (&ccp, "--");
1513
1514   ccparray_put (&ccp, NULL);
1515   argv = ccparray_get (&ccp, NULL);
1516   if (!argv)
1517     {
1518       err = gpg_error_from_syserror ();
1519       goto leave;
1520     }
1521   err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
1522                                 NULL, output,
1523                                 encrypt_response_status_cb, &gpg_err);
1524   if (err)
1525     {
1526       if (gpg_err)
1527         err = gpg_err;
1528       log_error ("encryption failed: %s\n", gpg_strerror (err));
1529       goto leave;
1530     }
1531
1532   es_rewind (output);
1533   *r_output = output;
1534   output = NULL;
1535
1536  leave:
1537   es_fclose (output);
1538   xfree (argv);
1539   return err;
1540 }
1541
1542
1543 static gpg_error_t
1544 send_confirmation_response (const char *sender, const char *address,
1545                             const char *nonce, int encrypt,
1546                             const char *fingerprint)
1547 {
1548   gpg_error_t err;
1549   estream_t body = NULL;
1550   estream_t bodyenc = NULL;
1551   mime_maker_t mime = NULL;
1552
1553   body = es_fopenmem (0, "w+b");
1554   if (!body)
1555     {
1556       err = gpg_error_from_syserror ();
1557       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1558       return err;
1559     }
1560
1561   /* It is fine to use 8 bit encoding because that is encrypted and
1562    * only our client will see it.  */
1563   if (encrypt)
1564     {
1565       es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
1566                 "Content-Transfer-Encoding: 8bit\n"
1567                 "\n",
1568                 body);
1569     }
1570
1571   es_fprintf (body, ("type: confirmation-response\n"
1572                      "sender: %s\n"
1573                      "address: %s\n"
1574                      "nonce: %s\n"),
1575               sender,
1576               address,
1577               nonce);
1578
1579   es_rewind (body);
1580   if (encrypt)
1581     {
1582       err = encrypt_response (&bodyenc, body, sender, fingerprint);
1583       if (err)
1584         goto leave;
1585       es_fclose (body);
1586       body = NULL;
1587     }
1588
1589   err = mime_maker_new (&mime, NULL);
1590   if (err)
1591     goto leave;
1592   err = mime_maker_add_header (mime, "From", address);
1593   if (err)
1594     goto leave;
1595   err = mime_maker_add_header (mime, "To", sender);
1596   if (err)
1597     goto leave;
1598   err = mime_maker_add_header (mime, "Subject", "Key publication confirmation");
1599   if (err)
1600     goto leave;
1601   err = mime_maker_add_header (mime, "Wks-Draft-Version",
1602                                STR2(WKS_DRAFT_VERSION));
1603   if (err)
1604     goto leave;
1605
1606   if (encrypt)
1607     {
1608       err = mime_maker_add_header (mime, "Content-Type",
1609                                    "multipart/encrypted; "
1610                                    "protocol=\"application/pgp-encrypted\"");
1611       if (err)
1612         goto leave;
1613       err = mime_maker_add_container (mime);
1614       if (err)
1615         goto leave;
1616
1617       err = mime_maker_add_header (mime, "Content-Type",
1618                                    "application/pgp-encrypted");
1619       if (err)
1620         goto leave;
1621       err = mime_maker_add_body (mime, "Version: 1\n");
1622       if (err)
1623         goto leave;
1624       err = mime_maker_add_header (mime, "Content-Type",
1625                                    "application/octet-stream");
1626       if (err)
1627         goto leave;
1628
1629       err = mime_maker_add_stream (mime, &bodyenc);
1630       if (err)
1631         goto leave;
1632     }
1633   else
1634     {
1635       err = mime_maker_add_header (mime, "Content-Type",
1636                                    "application/vnd.gnupg.wks");
1637       if (err)
1638         goto leave;
1639       err = mime_maker_add_stream (mime, &body);
1640       if (err)
1641         goto leave;
1642     }
1643
1644   err = wks_send_mime (mime);
1645
1646  leave:
1647   mime_maker_release (mime);
1648   es_fclose (bodyenc);
1649   es_fclose (body);
1650   return err;
1651 }
1652
1653
1654 /* Reply to a confirmation request.  The MSG has already been
1655  * decrypted and we only need to send the nonce back.  MAINFPR is
1656  * either NULL or the primary key fingerprint of the key used to
1657  * decrypt the request.  */
1658 static gpg_error_t
1659 process_confirmation_request (estream_t msg, const char *mainfpr)
1660 {
1661   gpg_error_t err;
1662   nvc_t nvc;
1663   nve_t item;
1664   const char *value, *sender, *address, *fingerprint, *nonce;
1665
1666   err = nvc_parse (&nvc, NULL, msg);
1667   if (err)
1668     {
1669       log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1670       goto leave;
1671     }
1672
1673   if (DBG_MIME)
1674     {
1675       log_debug ("request follows:\n");
1676       nvc_write (nvc, log_get_stream ());
1677     }
1678
1679   /* Check that this is a confirmation request.  */
1680   if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1681         && !strcmp (value, "confirmation-request")))
1682     {
1683       if (item && value)
1684         log_error ("received unexpected wks message '%s'\n", value);
1685       else
1686         log_error ("received invalid wks message: %s\n", "'type' missing");
1687       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1688       goto leave;
1689     }
1690
1691   /* Get the fingerprint.  */
1692   if (!((item = nvc_lookup (nvc, "fingerprint:"))
1693         && (value = nve_value (item))
1694         && strlen (value) >= 40))
1695     {
1696       log_error ("received invalid wks message: %s\n",
1697                  "'fingerprint' missing or invalid");
1698       err = gpg_error (GPG_ERR_INV_DATA);
1699       goto leave;
1700     }
1701   fingerprint = value;
1702
1703   /* Check that the fingerprint matches the key used to decrypt the
1704    * message.  In --read mode or with the old format we don't have the
1705    * decryption key; thus we can't bail out.  */
1706   if (!mainfpr || ascii_strcasecmp (mainfpr, fingerprint))
1707     {
1708       log_info ("target fingerprint: %s\n", fingerprint);
1709       log_info ("but decrypted with: %s\n", mainfpr);
1710       log_error ("confirmation request not decrypted with target key\n");
1711       if (mainfpr)
1712         {
1713           err = gpg_error (GPG_ERR_INV_DATA);
1714           goto leave;
1715         }
1716     }
1717
1718   /* Get the address.  */
1719   if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1720         && is_valid_mailbox (value)))
1721     {
1722       log_error ("received invalid wks message: %s\n",
1723                  "'address' missing or invalid");
1724       err = gpg_error (GPG_ERR_INV_DATA);
1725       goto leave;
1726     }
1727   address = value;
1728   /* FIXME: Check that the "address" matches the User ID we want to
1729    * publish.  */
1730
1731   /* Get the sender.  */
1732   if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1733         && is_valid_mailbox (value)))
1734     {
1735       log_error ("received invalid wks message: %s\n",
1736                  "'sender' missing or invalid");
1737       err = gpg_error (GPG_ERR_INV_DATA);
1738       goto leave;
1739     }
1740   sender = value;
1741   /* FIXME: Check that the "sender" matches the From: address.  */
1742
1743   /* Get the nonce.  */
1744   if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1745         && strlen (value) > 16))
1746     {
1747       log_error ("received invalid wks message: %s\n",
1748                  "'nonce' missing or too short");
1749       err = gpg_error (GPG_ERR_INV_DATA);
1750       goto leave;
1751     }
1752   nonce = value;
1753
1754   /* Send the confirmation.  If no key was found, try again without
1755    * encryption.  */
1756   err = send_confirmation_response (sender, address, nonce, 1, fingerprint);
1757   if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
1758     {
1759       log_info ("no encryption key found - sending response in the clear\n");
1760       err = send_confirmation_response (sender, address, nonce, 0, NULL);
1761     }
1762
1763  leave:
1764   nvc_release (nvc);
1765   return err;
1766 }
1767
1768
1769 /* Read a confirmation request and decrypt it if needed.  This
1770  * function may not be used with a mail or MIME message but only with
1771  * the actual encrypted or plaintext WKS data.  */
1772 static gpg_error_t
1773 read_confirmation_request (estream_t msg)
1774 {
1775   gpg_error_t err;
1776   int c;
1777   estream_t plaintext = NULL;
1778
1779   /* We take a really simple approach to check whether MSG is
1780    * encrypted: We know that an encrypted message is always armored
1781    * and thus starts with a few dashes.  It is even sufficient to
1782    * check for a single dash, because that can never be a proper first
1783    * WKS data octet.  We need to skip leading spaces, though. */
1784   while ((c = es_fgetc (msg)) == ' ' || c == '\t' || c == '\r' || c == '\n')
1785     ;
1786   if (c == EOF)
1787     {
1788       log_error ("can't process an empty message\n");
1789       return gpg_error (GPG_ERR_INV_DATA);
1790     }
1791   if (es_ungetc (c, msg) != c)
1792     {
1793       log_error ("error ungetting octet from message\n");
1794       return gpg_error (GPG_ERR_INTERNAL);
1795     }
1796
1797   if (c != '-')
1798     err = process_confirmation_request (msg, NULL);
1799   else
1800     {
1801       struct decrypt_stream_parm_s decinfo;
1802
1803       err = decrypt_stream (&plaintext, &decinfo, msg);
1804       if (err)
1805         log_error ("decryption failed: %s\n", gpg_strerror (err));
1806       else if (decinfo.otrust != 'u')
1807         {
1808           err = gpg_error (GPG_ERR_WRONG_SECKEY);
1809           log_error ("key used to decrypt the confirmation request"
1810                      " was not generated by us (otrust=%c)\n", decinfo.otrust);
1811         }
1812       else
1813         err = process_confirmation_request (plaintext, decinfo.mainfpr);
1814       xfree (decinfo.fpr);
1815       xfree (decinfo.mainfpr);
1816     }
1817
1818   es_fclose (plaintext);
1819   return err;
1820 }
1821
1822
1823 /* Called from the MIME receiver to process the plain text data in MSG.  */
1824 static gpg_error_t
1825 command_receive_cb (void *opaque, const char *mediatype,
1826                     estream_t msg, unsigned int flags)
1827 {
1828   gpg_error_t err;
1829
1830   (void)opaque;
1831   (void)flags;
1832
1833   if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1834     err = read_confirmation_request (msg);
1835   else
1836     {
1837       log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1838       err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1839     }
1840
1841   return err;
1842 }
1843
1844
1845 \f
1846 /* An object used to communicate with the mirror_one_key callback.  */
1847 struct
1848 {
1849   const char *domain;
1850   int anyerror;
1851   unsigned int nkeys;   /* Number of keys processed.  */
1852   unsigned int nuids;   /* Number of published user ids.  */
1853 } mirror_one_key_parm;
1854
1855
1856 /* Return true if the Given a mail DOMAIN and the full addrspec MBOX
1857  * match.  */
1858 static int
1859 domain_matches_mbox (const char *domain, const char *mbox)
1860 {
1861   const char *s;
1862
1863   if (!domain || !mbox)
1864     return 0;
1865   s = strchr (domain, '@');
1866   if (s)
1867     domain = s+1;
1868   if (!*domain)
1869     return 0; /* Not a valid domain.  */
1870
1871   s = strchr (mbox, '@');
1872   if (!s || !s[1])
1873     return 0; /* Not a valid mbox.  */
1874   mbox = s+1;
1875
1876   return !ascii_strcasecmp (domain, mbox);
1877 }
1878
1879
1880 /* Core of mirror_one_key with the goal of mirroring just one uid.
1881  * UIDLIST is used to figure out whether the given MBOX occurs several
1882  * times in UIDLIST and then to single out the newest one.  This is
1883  * so that for a key with
1884  *    uid: Joe Someone <joe@example.org>
1885  *    uid: Joe <joe@example.org>
1886  * only the news user id (and thus its self-signature) is used.
1887  * UIDLIST is nodified to set all MBOX fields to NULL for a processed
1888  * user id.  FPR is the fingerprint of the key.
1889  */
1890 static gpg_error_t
1891 mirror_one_keys_userid (estream_t key, const char *mbox, uidinfo_list_t uidlist,
1892                         const char *fpr)
1893 {
1894   gpg_error_t err;
1895   uidinfo_list_t uid, thisuid, firstuid;
1896   time_t thistime;
1897   estream_t newkey = NULL;
1898
1899   /* Find the UID we want to use.  */
1900   thistime = 0;
1901   thisuid = firstuid = NULL;
1902   for (uid = uidlist; uid; uid = uid->next)
1903     {
1904       if ((uid->flags & 1) || !uid->mbox || strcmp (uid->mbox, mbox))
1905         continue; /* Already processed or no matching mbox.  */
1906       uid->flags |= 1;  /* Set "processed" flag.  */
1907       if (!firstuid)
1908         firstuid = uid;
1909       if (uid->created > thistime)
1910         {
1911           thistime = uid->created;
1912           thisuid = uid;
1913         }
1914     }
1915   if (!thisuid)
1916     thisuid = firstuid;  /* This is the case for a missing timestamp.  */
1917   if (!thisuid)
1918     {
1919       log_error ("error finding the user id for %s (%s)\n", fpr, mbox);
1920       err = gpg_error (GPG_ERR_NO_USER_ID);
1921       goto leave;
1922     }
1923
1924   /* Always filter the key so that the result will be non-armored.  */
1925   es_rewind (key);
1926   err = wks_filter_uid (&newkey, key, thisuid->uid, 1);
1927   if (err)
1928     {
1929       log_error ("error filtering key %s: %s\n", fpr, gpg_strerror (err));
1930       err = gpg_error (GPG_ERR_NO_PUBKEY);
1931       goto leave;
1932     }
1933
1934   if (opt.add_revocs)
1935     {
1936       if (es_fseek (newkey, 0, SEEK_END))
1937         {
1938           err = gpg_error_from_syserror ();
1939           log_error ("error seeking stream: %s\n", gpg_strerror (err));
1940           goto leave;
1941         }
1942       err = wks_find_add_revocs (newkey, mbox);
1943       if (err)
1944         {
1945           log_error ("error finding revocations for '%s': %s\n",
1946                      mbox, gpg_strerror (err));
1947           goto leave;
1948         }
1949       es_rewind (newkey);
1950     }
1951
1952   err = wks_install_key_core (newkey, mbox);
1953   if (opt.verbose)
1954     log_info ("key %s published for '%s'\n", fpr, mbox);
1955   mirror_one_key_parm.nuids++;
1956   if (!opt.quiet && !(mirror_one_key_parm.nuids % 25))
1957     log_info ("%u user ids from %d keys so far\n",
1958               mirror_one_key_parm.nuids, mirror_one_key_parm.nkeys);
1959
1960  leave:
1961   es_fclose (newkey);
1962   return err;
1963 }
1964
1965
1966 /* The callback used by command_mirror.  It received an estream with
1967  * one key and should return success to process the next key.  */
1968 static gpg_error_t
1969 mirror_one_key (estream_t key)
1970 {
1971   gpg_error_t err = 0;
1972   char *fpr;
1973   uidinfo_list_t uidlist = NULL;
1974   uidinfo_list_t uid;
1975   const char *domain = mirror_one_key_parm.domain;
1976
1977   /* List the key to get all user ids.  */
1978   err = wks_list_key (key, &fpr, &uidlist);
1979   if (err)
1980     {
1981       log_error ("error parsing a key: %s - skipped\n",
1982                  gpg_strerror (err));
1983       mirror_one_key_parm.anyerror = 1;
1984       err = 0;
1985       goto leave;
1986     }
1987   for (uid = uidlist; uid; uid = uid->next)
1988     {
1989       if (!uid->mbox || (uid->flags & 1))
1990         continue; /* No mail box or already processed.  */
1991       if (uid->expired)
1992         continue;
1993       if (!domain_matches_mbox (domain, uid->mbox))
1994         continue; /* We don't want this one.  */
1995       if (is_in_blacklist (uid->mbox))
1996         continue;
1997
1998       err = mirror_one_keys_userid (key, uid->mbox, uidlist, fpr);
1999       if (err)
2000         {
2001           log_error ("error processing key %s: %s - skipped\n",
2002                      fpr, gpg_strerror (err));
2003           mirror_one_key_parm.anyerror = 1;
2004           err = 0;
2005           goto leave;
2006         }
2007     }
2008   mirror_one_key_parm.nkeys++;
2009
2010
2011  leave:
2012   free_uidinfo_list (uidlist);
2013   xfree (fpr);
2014   return err;
2015 }
2016
2017
2018 /* Copy the keys from the configured LDAP server into a local WKD.
2019  * DOMAINLIST is an array of domain names to restrict the copy to only
2020  * the given domains; if it is NULL all keys are mirrored.  */
2021 static gpg_error_t
2022 command_mirror (char *domainlist[])
2023 {
2024   gpg_error_t err;
2025   const char *domain;
2026   char *domainbuf = NULL;
2027
2028   mirror_one_key_parm.anyerror = 0;
2029   mirror_one_key_parm.nkeys = 0;
2030   mirror_one_key_parm.nuids = 0;
2031
2032   if (!domainlist)
2033     {
2034       mirror_one_key_parm.domain = "";
2035       err = wkd_dirmngr_ks_get (NULL, mirror_one_key);
2036     }
2037   else
2038     {
2039       while ((domain = *domainlist++))
2040         {
2041           if (*domain != '.' && domain[1] != '@')
2042             {
2043               /* This does not already specify a mail search by
2044                * domain.  Change it.  */
2045               xfree (domainbuf);
2046               domainbuf = xstrconcat (".@", domain, NULL);
2047               domain = domainbuf;
2048             }
2049           mirror_one_key_parm.domain = domain;
2050           if (opt.verbose)
2051             log_info ("mirroring keys for domain '%s'\n", domain+2);
2052           err = wkd_dirmngr_ks_get (domain, mirror_one_key);
2053           if (err)
2054             break;
2055         }
2056     }
2057
2058   if (!opt.quiet)
2059     log_info ("a total of %u user ids from %d keys published\n",
2060               mirror_one_key_parm.nuids, mirror_one_key_parm.nkeys);
2061   if (err)
2062     log_error ("error mirroring LDAP directory: %s <%s>\n",
2063                gpg_strerror (err), gpg_strsource (err));
2064   else if (mirror_one_key_parm.anyerror)
2065     log_info ("warning: errors encountered - not all keys are mirrored\n");
2066
2067   xfree (domainbuf);
2068   return err;
2069 }