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