1 /* gpg-wks-server.c - A server for the Web Key Service protocols.
2 * Copyright (C) 2016 Werner Koch
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20 /* The Web Key Service I-D defines an update protocol to store a
21 * public key in the Web Key Directory. The current specification is
22 * draft-koch-openpgp-webkey-service-01.txt.
30 #include <sys/types.h>
40 #include "mbox-util.h"
41 #include "name-value.h"
42 #include "mime-maker.h"
43 #include "send-mail.h"
47 /* The time we wait for a confirmation response. */
48 #define PENDING_TTL (86400 * 3) /* 3 days. */
51 /* Constants to identify the commands and options. */
52 enum cmd_and_opt_values
75 /* The list of commands and options. */
76 static ARGPARSE_OPTS opts[] = {
77 ARGPARSE_group (300, ("@Commands:\n ")),
79 ARGPARSE_c (aReceive, "receive",
80 ("receive a submission or confirmation")),
81 ARGPARSE_c (aCron, "cron",
82 ("run regular jobs")),
83 ARGPARSE_c (aListDomains, "list-domains",
84 ("list configured domains")),
86 ARGPARSE_group (301, ("@\nOptions:\n ")),
88 ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
89 ARGPARSE_s_n (oQuiet, "quiet", ("be somewhat more quiet")),
90 ARGPARSE_s_s (oDebug, "debug", "@"),
91 ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
92 ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"),
93 ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
94 ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"),
95 ARGPARSE_s_s (oHeader, "header" ,
96 "|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"),
102 /* The list of supported debug flags. */
103 static struct debug_flags_s debug_flags [] =
105 { DBG_MIME_VALUE , "mime" },
106 { DBG_PARSER_VALUE , "parser" },
107 { DBG_CRYPTO_VALUE , "crypto" },
108 { DBG_MEMORY_VALUE , "memory" },
109 { DBG_MEMSTAT_VALUE, "memstat" },
110 { DBG_IPC_VALUE , "ipc" },
111 { DBG_EXTPROG_VALUE, "extprog" },
116 /* State for processing a message. */
120 strlist_t mboxes; /* List of addr-specs taken from the UIDs. */
121 unsigned int draft_version_2:1; /* Client supports the draft 2. */
123 typedef struct server_ctx_s *server_ctx_t;
126 static gpg_error_t get_domain_list (strlist_t *r_list);
128 static gpg_error_t command_receive_cb (void *opaque,
129 const char *mediatype, estream_t fp,
131 static gpg_error_t command_list_domains (void);
132 static gpg_error_t command_cron (void);
136 /* Print usage information and and provide strings for help. */
138 my_strusage( int level )
144 case 11: p = "gpg-wks-server (@GNUPG@)";
146 case 13: p = VERSION; break;
147 case 17: p = PRINTABLE_OS_NAME; break;
148 case 19: p = ("Please report bugs to <@EMAIL@>.\n"); break;
152 p = ("Usage: gpg-wks-server command [options] (-h for help)");
155 p = ("Syntax: gpg-wks-server command [options]\n"
156 "Server for the Web Key Service protocol\n");
159 default: p = NULL; break;
166 wrong_args (const char *text)
168 es_fprintf (es_stderr, "usage: %s [options] %s\n", strusage (11), text);
174 /* Command line parsing. */
175 static enum cmd_and_opt_values
176 parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
178 enum cmd_and_opt_values cmd = 0;
179 int no_more_options = 0;
181 while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
183 switch (pargs->r_opt)
185 case oQuiet: opt.quiet = 1; break;
186 case oVerbose: opt.verbose++; break;
188 if (parse_debug_flag (pargs->r.ret_str, &opt.debug, debug_flags))
190 pargs->r_opt = ARGPARSE_INVALID_ARG;
191 pargs->err = ARGPARSE_PRINT_ERROR;
196 opt.gpg_program = pargs->r.ret_str;
199 opt.default_from = pargs->r.ret_str;
202 append_to_strlist (&opt.extra_headers, pargs->r.ret_str);
205 opt.use_sendmail = 1;
208 opt.output = pargs->r.ret_str;
217 default: pargs->err = 2; break;
226 /* gpg-wks-server main. */
228 main (int argc, char **argv)
232 enum cmd_and_opt_values cmd;
234 gnupg_reopen_std ("gpg-wks-server");
235 set_strusage (my_strusage);
236 log_set_prefix ("gpg-wks-server", GPGRT_LOG_WITH_PREFIX);
238 /* Make sure that our subsystems are ready. */
239 init_common_subsystems (&argc, &argv);
241 /* Parse the command line. */
244 pargs.flags = ARGPARSE_FLAG_KEEP;
245 cmd = parse_arguments (&pargs, opts);
247 if (log_get_errorcount (0))
250 /* Print a warning if an argument looks like an option. */
251 if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
255 for (i=0; i < argc; i++)
256 if (argv[i][0] == '-' && argv[i][1] == '-')
257 log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
260 /* Set defaults for non given options. */
261 if (!opt.gpg_program)
262 opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
265 opt.directory = "/var/lib/gnupg/wks";
267 /* Check for syntax errors in the --header option to avoid later
268 * error messages with a not easy to find cause */
269 if (opt.extra_headers)
273 for (sl = opt.extra_headers; sl; sl = sl->next)
275 err = mime_maker_add_header (NULL, sl->d, NULL);
277 log_error ("syntax error in \"--header %s\": %s\n",
278 sl->d, gpg_strerror (err));
282 if (log_get_errorcount (0))
286 /* Check that we have a working directory. */
287 #if defined(HAVE_STAT)
291 if (stat (opt.directory, &sb))
293 err = gpg_error_from_syserror ();
294 log_error ("error accessing directory '%s': %s\n",
295 opt.directory, gpg_strerror (err));
298 if (!S_ISDIR(sb.st_mode))
300 log_error ("error accessing directory '%s': %s\n",
301 opt.directory, "not a directory");
304 if (sb.st_uid != getuid())
306 log_error ("directory '%s' not owned by user\n", opt.directory);
309 if ((sb.st_mode & (S_IROTH|S_IWOTH)))
311 log_error ("directory '%s' has too relaxed permissions\n",
317 log_fatal ("program build w/o stat() call\n");
318 #endif /*!HAVE_STAT*/
320 /* Run the selected command. */
325 wrong_args ("--receive");
326 err = wks_receive (es_stdin, command_receive_cb, NULL);
331 wrong_args ("--cron");
332 err = command_cron ();
336 err = command_list_domains ();
341 err = gpg_error (GPG_ERR_BUG);
346 log_error ("command failed: %s\n", gpg_strerror (err));
347 return log_get_errorcount (0)? 1:0;
351 /* Take the key in KEYFILE and write it to OUTFILE in binary encoding.
352 * If ADDRSPEC is given only matching user IDs are included in the
355 copy_key_as_binary (const char *keyfile, const char *outfile,
356 const char *addrspec)
360 const char **argv = NULL;
361 char *filterexp = NULL;
365 filterexp = es_bsprintf ("keep-uid=mbox = %s", addrspec);
368 err = gpg_error_from_syserror ();
369 log_error ("error allocating memory buffer: %s\n",
375 ccparray_init (&ccp, 0);
377 ccparray_put (&ccp, "--no-options");
379 ccparray_put (&ccp, "--quiet");
380 else if (opt.verbose > 1)
381 ccparray_put (&ccp, "--verbose");
382 ccparray_put (&ccp, "--batch");
383 ccparray_put (&ccp, "--yes");
384 ccparray_put (&ccp, "--always-trust");
385 ccparray_put (&ccp, "--no-keyring");
386 ccparray_put (&ccp, "--output");
387 ccparray_put (&ccp, outfile);
388 ccparray_put (&ccp, "--import-options=import-export");
391 ccparray_put (&ccp, "--import-filter");
392 ccparray_put (&ccp, filterexp);
394 ccparray_put (&ccp, "--import");
395 ccparray_put (&ccp, "--");
396 ccparray_put (&ccp, keyfile);
398 ccparray_put (&ccp, NULL);
399 argv = ccparray_get (&ccp, NULL);
402 err = gpg_error_from_syserror ();
405 err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
406 NULL, NULL, NULL, NULL);
409 log_error ("%s failed: %s\n", __func__, gpg_strerror (err));
420 /* Take the key in KEYFILE and write it to DANEFILE using the DANE
423 copy_key_as_dane (const char *keyfile, const char *danefile)
429 ccparray_init (&ccp, 0);
431 ccparray_put (&ccp, "--no-options");
433 ccparray_put (&ccp, "--quiet");
434 else if (opt.verbose > 1)
435 ccparray_put (&ccp, "--verbose");
436 ccparray_put (&ccp, "--batch");
437 ccparray_put (&ccp, "--yes");
438 ccparray_put (&ccp, "--always-trust");
439 ccparray_put (&ccp, "--no-keyring");
440 ccparray_put (&ccp, "--output");
441 ccparray_put (&ccp, danefile);
442 ccparray_put (&ccp, "--export-options=export-dane");
443 ccparray_put (&ccp, "--import-options=import-export");
444 ccparray_put (&ccp, "--import");
445 ccparray_put (&ccp, "--");
446 ccparray_put (&ccp, keyfile);
448 ccparray_put (&ccp, NULL);
449 argv = ccparray_get (&ccp, NULL);
452 err = gpg_error_from_syserror ();
455 err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
456 NULL, NULL, NULL, NULL);
459 log_error ("%s failed: %s\n", __func__, gpg_strerror (err));
470 encrypt_stream_status_cb (void *opaque, const char *keyword, char *args)
475 log_debug ("gpg status: %s %s\n", keyword, args);
479 /* Encrypt the INPUT stream to a new stream which is stored at success
480 * at R_OUTPUT. Encryption is done for the key in file KEYFIL. */
482 encrypt_stream (estream_t *r_output, estream_t input, const char *keyfile)
491 output = es_fopenmem (0, "w+b");
494 err = gpg_error_from_syserror ();
495 log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
499 ccparray_init (&ccp, 0);
501 ccparray_put (&ccp, "--no-options");
503 ccparray_put (&ccp, "--quiet");
504 else if (opt.verbose > 1)
505 ccparray_put (&ccp, "--verbose");
506 ccparray_put (&ccp, "--batch");
507 ccparray_put (&ccp, "--status-fd=2");
508 ccparray_put (&ccp, "--always-trust");
509 ccparray_put (&ccp, "--no-keyring");
510 ccparray_put (&ccp, "--armor");
511 ccparray_put (&ccp, "--recipient-file");
512 ccparray_put (&ccp, keyfile);
513 ccparray_put (&ccp, "--encrypt");
514 ccparray_put (&ccp, "--");
516 ccparray_put (&ccp, NULL);
517 argv = ccparray_get (&ccp, NULL);
520 err = gpg_error_from_syserror ();
523 err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
525 encrypt_stream_status_cb, NULL);
528 log_error ("encryption failed: %s\n", gpg_strerror (err));
544 sign_stream_status_cb (void *opaque, const char *keyword, char *args)
549 log_debug ("gpg status: %s %s\n", keyword, args);
552 /* Sign the INPUT stream to a new stream which is stored at success at
553 * R_OUTPUT. A detached signature is created using the key specified
556 sign_stream (estream_t *r_output, estream_t input, const char *userid)
565 output = es_fopenmem (0, "w+b");
568 err = gpg_error_from_syserror ();
569 log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
573 ccparray_init (&ccp, 0);
575 ccparray_put (&ccp, "--no-options");
577 ccparray_put (&ccp, "--quiet");
578 else if (opt.verbose > 1)
579 ccparray_put (&ccp, "--verbose");
580 ccparray_put (&ccp, "--batch");
581 ccparray_put (&ccp, "--status-fd=2");
582 ccparray_put (&ccp, "--armor");
583 ccparray_put (&ccp, "--local-user");
584 ccparray_put (&ccp, userid);
585 ccparray_put (&ccp, "--detach-sign");
586 ccparray_put (&ccp, "--");
588 ccparray_put (&ccp, NULL);
589 argv = ccparray_get (&ccp, NULL);
592 err = gpg_error_from_syserror ();
595 err = gnupg_exec_tool_stream (opt.gpg_program, argv, input,
597 sign_stream_status_cb, NULL);
600 log_error ("signing failed: %s\n", gpg_strerror (err));
615 /* Get the submission address for address MBOX. Caller must free the
616 * value. If no address can be found NULL is returned. */
618 get_submission_address (const char *mbox)
622 char *fname, *line, *p;
626 domain = strchr (mbox, '@');
631 fname = make_filename_try (opt.directory, domain, "submission-address", NULL);
634 err = gpg_error_from_syserror ();
635 log_error ("make_filename failed in %s: %s\n",
636 __func__, gpg_strerror (err));
640 fp = es_fopen (fname, "r");
643 err = gpg_error_from_syserror ();
644 if (gpg_err_code (err) == GPG_ERR_ENOENT)
645 log_info ("Note: no specific submission address configured"
646 " for domain '%s'\n", domain);
648 log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
655 if (es_getline (&line, &n, fp) < 0)
657 err = gpg_error_from_syserror ();
658 log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
667 p = strchr (line, '\n');
671 if (!is_valid_mailbox (line))
673 log_error ("invalid submission address for domain '%s' detected\n",
683 /* Get the policy flags for address MBOX and store them in POLICY. */
685 get_policy_flags (policy_flags_t policy, const char *mbox)
692 memset (policy, 0, sizeof *policy);
694 domain = strchr (mbox, '@');
696 return gpg_error (GPG_ERR_INV_USER_ID);
699 fname = make_filename_try (opt.directory, domain, "policy", NULL);
702 err = gpg_error_from_syserror ();
703 log_error ("make_filename failed in %s: %s\n",
704 __func__, gpg_strerror (err));
708 fp = es_fopen (fname, "r");
711 err = gpg_error_from_syserror ();
712 if (gpg_err_code (err) == GPG_ERR_ENOENT)
715 log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
720 err = wks_parse_policy (policy, fp, 0);
727 /* We store the key under the name of the nonce we will then send to
728 * the user. On success the nonce is stored at R_NONCE and the file
729 * name at R_FNAME. */
731 store_key_as_pending (const char *dir, estream_t key,
732 char **r_nonce, char **r_fname)
738 estream_t outfp = NULL;
740 size_t nbytes, nwritten;
745 dname = make_filename_try (dir, "pending", NULL);
748 err = gpg_error_from_syserror ();
752 /* Create the nonce. We use 20 bytes so that we don't waste a
753 * character in our zBase-32 encoding. Using the gcrypt's nonce
754 * function is faster than using the strong random function; this is
755 * Good Enough for our purpose. */
756 log_assert (sizeof buffer > 20);
757 gcry_create_nonce (buffer, 20);
758 nonce = zb32_encode (buffer, 8 * 20);
759 memset (buffer, 0, 20); /* Not actually needed but it does not harm. */
762 err = gpg_error_from_syserror ();
766 fname = strconcat (dname, "/", nonce, NULL);
769 err = gpg_error_from_syserror ();
773 /* With 128 bits of random we can expect that no other file exists
774 * under this name. We use "x" to detect internal errors. */
775 outfp = es_fopen (fname, "wbx,mode=-rw");
778 err = gpg_error_from_syserror ();
779 log_error ("error creating '%s': %s\n", fname, gpg_strerror (err));
785 if (es_read (key, buffer, sizeof buffer, &nbytes))
787 err = gpg_error_from_syserror ();
788 log_error ("error reading '%s': %s\n",
789 es_fname_get (key), gpg_strerror (err));
796 goto leave; /* Ready. */
798 if (es_write (outfp, buffer, nbytes, &nwritten))
800 err = gpg_error_from_syserror ();
801 log_error ("error writing '%s': %s\n", fname, gpg_strerror (err));
804 else if (nwritten != nbytes)
806 err = gpg_error (GPG_ERR_EIO);
807 log_error ("error writing '%s': %s\n", fname, "short write");
816 gnupg_remove (fname);
818 else if (es_fclose (outfp))
820 err = gpg_error_from_syserror ();
821 log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
839 /* Send a confirmation request. DIR is the directory used for the
840 * address MBOX. NONCE is the nonce we want to see in the response to
841 * this mail. FNAME the name of the file with the key. */
843 send_confirmation_request (server_ctx_t ctx,
844 const char *mbox, const char *nonce,
848 estream_t body = NULL;
849 estream_t bodyenc = NULL;
850 estream_t signeddata = NULL;
851 estream_t signature = NULL;
852 mime_maker_t mime = NULL;
853 char *from_buffer = NULL;
857 from = from_buffer = get_submission_address (mbox);
860 from = opt.default_from;
863 log_error ("no sender address found for '%s'\n", mbox);
864 err = gpg_error (GPG_ERR_CONFIGURATION);
867 log_info ("Note: using default sender address '%s'\n", from);
870 body = es_fopenmem (0, "w+b");
873 err = gpg_error_from_syserror ();
874 log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
878 if (!ctx->draft_version_2)
880 /* It is fine to use 8 bit encoding because that is encrypted and
881 * only our client will see it. */
882 es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
883 "Content-Transfer-Encoding: 8bit\n"
888 es_fprintf (body, ("type: confirmation-request\n"
899 err = encrypt_stream (&bodyenc, body, keyfile);
906 err = mime_maker_new (&mime, NULL);
909 err = mime_maker_add_header (mime, "From", from);
912 err = mime_maker_add_header (mime, "To", mbox);
915 err = mime_maker_add_header (mime, "Subject", "Confirm your key publication");
918 for (sl = opt.extra_headers; sl; sl = sl->next)
920 err = mime_maker_add_header (mime, sl->d, NULL);
925 if (!ctx->draft_version_2)
927 err = mime_maker_add_header (mime, "Content-Type",
928 "multipart/encrypted; "
929 "protocol=\"application/pgp-encrypted\"");
932 err = mime_maker_add_container (mime);
936 err = mime_maker_add_header (mime, "Content-Type",
937 "application/pgp-encrypted");
940 err = mime_maker_add_body (mime, "Version: 1\n");
943 err = mime_maker_add_header (mime, "Content-Type",
944 "application/octet-stream");
948 err = mime_maker_add_stream (mime, &bodyenc);
957 /* FIXME: Add micalg. */
958 err = mime_maker_add_header (mime, "Content-Type",
960 "protocol=\"application/pgp-signature\"");
963 err = mime_maker_add_container (mime);
967 err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
971 err = mime_maker_add_container (mime);
974 partid = mime_maker_get_partid (mime);
976 err = mime_maker_add_header (mime, "Content-Type", "text/plain");
980 err = mime_maker_add_body
982 "This message has been send to confirm your request\n"
983 "to publish your key. If you did not request a key\n"
984 "publication, simply ignore this message.\n"
986 "Most mail software can handle this kind of message\n"
987 "automatically and thus you would not have seen this\n"
988 "message. It seems that your client does not fully\n"
989 "support this service. The web page\n"
991 " https://gnupg.org/faq/wkd.html\n"
993 "explains how you can process this message anyway in\n"
994 "a few manual steps.\n");
998 err = mime_maker_add_header (mime, "Content-Type",
999 "application/vnd.gnupg.wks");
1003 err = mime_maker_add_stream (mime, &bodyenc);
1007 err = mime_maker_end_container (mime);
1011 mime_maker_dump_tree (mime);
1012 err = mime_maker_get_part (mime, partid, &signeddata);
1016 err = sign_stream (&signature, signeddata, from);
1020 err = mime_maker_add_header (mime, "Content-Type",
1021 "application/pgp-signature");
1025 err = mime_maker_add_stream (mime, &signature);
1030 err = wks_send_mime (mime);
1033 mime_maker_release (mime);
1034 es_fclose (signature);
1035 es_fclose (signeddata);
1036 es_fclose (bodyenc);
1038 xfree (from_buffer);
1043 /* Store the key given by KEY into the pending directory and send a
1044 * confirmation requests. */
1046 process_new_key (server_ctx_t ctx, estream_t key)
1054 struct policy_flags_s policybuf;
1056 /* First figure out the user id from the key. */
1058 free_strlist (ctx->mboxes);
1059 err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
1064 log_error ("error parsing key (no fingerprint)\n");
1065 err = gpg_error (GPG_ERR_NO_PUBKEY);
1068 log_info ("fingerprint: %s\n", ctx->fpr);
1069 for (sl = ctx->mboxes; sl; sl = sl->next)
1071 log_info (" addr-spec: %s\n", sl->d);
1074 /* Walk over all user ids and send confirmation requests for those
1076 for (sl = ctx->mboxes; sl; sl = sl->next)
1078 s = strchr (sl->d, '@');
1079 log_assert (s && s[1]);
1081 dname = make_filename_try (opt.directory, s+1, NULL);
1084 err = gpg_error_from_syserror ();
1088 if (access (dname, W_OK))
1090 log_info ("skipping address '%s': Domain not configured\n", sl->d);
1093 if (get_policy_flags (&policybuf, sl->d))
1095 log_info ("skipping address '%s': Bad policy flags\n", sl->d);
1099 if (policybuf.auth_submit)
1101 /* Bypass the confirmation stuff and publish the the key as is. */
1102 log_info ("publishing address '%s'\n", sl->d);
1103 /* FIXME: We need to make sure that we do this only for the
1104 * address in the mail. */
1105 log_debug ("auth-submit not yet working!\n");
1109 log_info ("storing address '%s'\n", sl->d);
1113 err = store_key_as_pending (dname, key, &nonce, &fname);
1117 err = send_confirmation_request (ctx, sl->d, nonce, fname);
1125 wipememory (nonce, strlen (nonce));
1134 /* Send a message to tell the user at MBOX that their key has been
1135 * published. FNAME the name of the file with the key. */
1137 send_congratulation_message (const char *mbox, const char *keyfile)
1140 estream_t body = NULL;
1141 estream_t bodyenc = NULL;
1142 mime_maker_t mime = NULL;
1143 char *from_buffer = NULL;
1147 from = from_buffer = get_submission_address (mbox);
1150 from = opt.default_from;
1153 log_error ("no sender address found for '%s'\n", mbox);
1154 err = gpg_error (GPG_ERR_CONFIGURATION);
1157 log_info ("Note: using default sender address '%s'\n", from);
1160 body = es_fopenmem (0, "w+b");
1163 err = gpg_error_from_syserror ();
1164 log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
1167 /* It is fine to use 8 bit encoding because that is encrypted and
1168 * only our client will see it. */
1169 es_fputs ("Content-Type: text/plain; charset=utf-8\n"
1170 "Content-Transfer-Encoding: 8bit\n"
1176 "The key for your address '%s' has been published\n"
1177 "and can now be retrieved from the Web Key Directory.\n"
1179 "For more information on this system see:\n"
1181 " https://gnupg.org/faq/wkd.html\n"
1185 " Gnu Key Publisher\n\n\n"
1187 "The GnuPG Project welcomes donations: %s\n",
1188 mbox, "https://gnupg.org/donate");
1191 err = encrypt_stream (&bodyenc, body, keyfile);
1197 err = mime_maker_new (&mime, NULL);
1200 err = mime_maker_add_header (mime, "From", from);
1203 err = mime_maker_add_header (mime, "To", mbox);
1206 err = mime_maker_add_header (mime, "Subject", "Your key has been published");
1209 for (sl = opt.extra_headers; sl; sl = sl->next)
1211 err = mime_maker_add_header (mime, sl->d, NULL);
1216 err = mime_maker_add_header (mime, "Content-Type",
1217 "multipart/encrypted; "
1218 "protocol=\"application/pgp-encrypted\"");
1221 err = mime_maker_add_container (mime);
1225 err = mime_maker_add_header (mime, "Content-Type",
1226 "application/pgp-encrypted");
1229 err = mime_maker_add_body (mime, "Version: 1\n");
1232 err = mime_maker_add_header (mime, "Content-Type",
1233 "application/octet-stream");
1237 err = mime_maker_add_stream (mime, &bodyenc);
1241 err = wks_send_mime (mime);
1244 mime_maker_release (mime);
1245 es_fclose (bodyenc);
1247 xfree (from_buffer);
1252 /* Check that we have send a request with NONCE and publish the key. */
1254 check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
1258 char *fnewname = NULL;
1259 estream_t key = NULL;
1264 char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
1266 /* FIXME: There is a bug in name-value.c which adds white space for
1267 * the last pair and thus we strip the nonce here until this has
1269 char *nonce2 = xstrdup (nonce);
1270 trim_trailing_spaces (nonce2);
1274 domain = strchr (address, '@');
1275 log_assert (domain && domain[1]);
1277 fname = make_filename_try (opt.directory, domain, "pending", nonce, NULL);
1280 err = gpg_error_from_syserror ();
1284 /* Try to open the file with the key. */
1285 key = es_fopen (fname, "rb");
1288 err = gpg_error_from_syserror ();
1289 if (gpg_err_code (err) == GPG_ERR_ENOENT)
1291 log_info ("no pending request for '%s'\n", address);
1292 err = gpg_error (GPG_ERR_NOT_FOUND);
1295 log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
1299 /* We need to get the fingerprint from the key. */
1301 free_strlist (ctx->mboxes);
1302 err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
1307 log_error ("error parsing key (no fingerprint)\n");
1308 err = gpg_error (GPG_ERR_NO_PUBKEY);
1311 log_info ("fingerprint: %s\n", ctx->fpr);
1312 for (sl = ctx->mboxes; sl; sl = sl->next)
1313 log_info (" addr-spec: %s\n", sl->d);
1315 /* Check that the key has 'address' as a user id. We use
1316 * case-insensitive matching because the client is expected to
1317 * return the address verbatim. */
1318 for (sl = ctx->mboxes; sl; sl = sl->next)
1319 if (!strcmp (sl->d, address))
1323 log_error ("error publishing key: '%s' is not a user ID of %s\n",
1325 err = gpg_error (GPG_ERR_NO_PUBKEY);
1330 /* Hash user ID and create filename. */
1331 s = strchr (address, '@');
1333 gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
1334 hash = zb32_encode (shaxbuf, 8*20);
1337 err = gpg_error_from_syserror ();
1341 fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
1344 err = gpg_error_from_syserror ();
1349 err = copy_key_as_binary (fname, fnewname, address);
1352 err = gpg_error_from_syserror ();
1353 log_error ("copying '%s' to '%s' failed: %s\n",
1354 fname, fnewname, gpg_strerror (err));
1358 log_info ("key %s published for '%s'\n", ctx->fpr, address);
1359 send_congratulation_message (address, fnewname);
1361 /* Try to publish as DANE record if the DANE directory exists. */
1364 fnewname = make_filename_try (opt.directory, domain, "dane", NULL);
1367 err = gpg_error_from_syserror ();
1370 if (!access (fnewname, W_OK))
1372 /* Yes, we have a dane directory. */
1373 s = strchr (address, '@');
1375 gcry_md_hash_buffer (GCRY_MD_SHA256, shaxbuf, address, s - address);
1377 hash = bin2hex (shaxbuf, 28, NULL);
1380 err = gpg_error_from_syserror ();
1384 fnewname = make_filename_try (opt.directory, domain, "dane", hash, NULL);
1387 err = gpg_error_from_syserror ();
1390 err = copy_key_as_dane (fname, fnewname);
1393 log_info ("key %s published for '%s' (DANE record)\n", ctx->fpr, address);
1406 /* Process a confirmation response in MSG. */
1408 process_confirmation_response (server_ctx_t ctx, estream_t msg)
1413 const char *value, *sender, *address, *nonce;
1415 err = nvc_parse (&nvc, NULL, msg);
1418 log_error ("parsing the WKS message failed: %s\n", gpg_strerror (err));
1424 log_debug ("response follows:\n");
1425 nvc_write (nvc, log_get_stream ());
1428 /* Check that this is a confirmation response. */
1429 if (!((item = nvc_lookup (nvc, "type:")) && (value = nve_value (item))
1430 && !strcmp (value, "confirmation-response")))
1433 log_error ("received unexpected wks message '%s'\n", value);
1435 log_error ("received invalid wks message: %s\n", "'type' missing");
1436 err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1440 /* Get the sender. */
1441 if (!((item = nvc_lookup (nvc, "sender:")) && (value = nve_value (item))
1442 && is_valid_mailbox (value)))
1444 log_error ("received invalid wks message: %s\n",
1445 "'sender' missing or invalid");
1446 err = gpg_error (GPG_ERR_INV_DATA);
1451 /* FIXME: Do we really need the sender?. */
1453 /* Get the address. */
1454 if (!((item = nvc_lookup (nvc, "address:")) && (value = nve_value (item))
1455 && is_valid_mailbox (value)))
1457 log_error ("received invalid wks message: %s\n",
1458 "'address' missing or invalid");
1459 err = gpg_error (GPG_ERR_INV_DATA);
1464 /* Get the nonce. */
1465 if (!((item = nvc_lookup (nvc, "nonce:")) && (value = nve_value (item))
1466 && strlen (value) > 16))
1468 log_error ("received invalid wks message: %s\n",
1469 "'nonce' missing or too short");
1470 err = gpg_error (GPG_ERR_INV_DATA);
1475 err = check_and_publish (ctx, address, nonce);
1485 /* Called from the MIME receiver to process the plain text data in MSG . */
1487 command_receive_cb (void *opaque, const char *mediatype,
1488 estream_t msg, unsigned int flags)
1491 struct server_ctx_s ctx;
1495 memset (&ctx, 0, sizeof ctx);
1496 if ((flags & WKS_RECEIVE_DRAFT2))
1497 ctx.draft_version_2 = 1;
1499 if (!strcmp (mediatype, "application/pgp-keys"))
1500 err = process_new_key (&ctx, msg);
1501 else if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
1502 err = process_confirmation_response (&ctx, msg);
1505 log_info ("ignoring unexpected message of type '%s'\n", mediatype);
1506 err = gpg_error (GPG_ERR_UNEXPECTED_MSG);
1510 free_strlist (ctx.mboxes);
1517 /* Return a list of all configured domains. ECh list element is the
1518 * top directory for for the domain. To figure out the actual domain
1519 * name strrchr(name, '/') can be used. */
1521 get_domain_list (strlist_t *r_list)
1526 struct dirent *dentry;
1528 strlist_t list = NULL;
1532 dir = opendir (opt.directory);
1535 err = gpg_error_from_syserror ();
1539 while ((dentry = readdir (dir)))
1541 if (*dentry->d_name == '.')
1543 if (!strchr (dentry->d_name, '.'))
1544 continue; /* No dot - can't be a domain subdir. */
1547 fname = make_filename_try (opt.directory, dentry->d_name, NULL);
1550 err = gpg_error_from_syserror ();
1551 log_error ("make_filename failed in %s: %s\n",
1552 __func__, gpg_strerror (err));
1556 if (stat (fname, &sb))
1558 err = gpg_error_from_syserror ();
1559 log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1562 if (!S_ISDIR(sb.st_mode))
1565 if (!add_to_strlist_try (&list, fname))
1567 err = gpg_error_from_syserror ();
1568 log_error ("add_to_strlist failed in %s: %s\n",
1569 __func__, gpg_strerror (err));
1578 free_strlist (list);
1588 expire_one_domain (const char *top_dirname, const char *domain)
1594 struct dirent *dentry;
1596 time_t now = gnupg_get_time ();
1598 dirname = make_filename_try (top_dirname, "pending", NULL);
1601 err = gpg_error_from_syserror ();
1602 log_error ("make_filename failed in %s: %s\n",
1603 __func__, gpg_strerror (err));
1607 dir = opendir (dirname);
1610 err = gpg_error_from_syserror ();
1611 log_error (("can't access directory '%s': %s\n"),
1612 dirname, gpg_strerror (err));
1616 while ((dentry = readdir (dir)))
1618 if (*dentry->d_name == '.')
1621 fname = make_filename_try (dirname, dentry->d_name, NULL);
1624 err = gpg_error_from_syserror ();
1625 log_error ("make_filename failed in %s: %s\n",
1626 __func__, gpg_strerror (err));
1629 if (strlen (dentry->d_name) != 32)
1631 log_info ("garbage file '%s' ignored\n", fname);
1634 if (stat (fname, &sb))
1636 err = gpg_error_from_syserror ();
1637 log_error ("error accessing '%s': %s\n", fname, gpg_strerror (err));
1640 if (S_ISDIR(sb.st_mode))
1642 log_info ("garbage directory '%s' ignored\n", fname);
1645 if (sb.st_mtime + PENDING_TTL < now)
1648 log_info ("domain %s: removing pending key '%s'\n",
1649 domain, dentry->d_name);
1652 err = gpg_error_from_syserror ();
1653 /* In case the file has just been renamed or another
1654 * processes is cleaning up, we don't print a diagnostic
1656 if (gpg_err_code (err) != GPG_ERR_ENOENT)
1657 log_error ("error removing '%s': %s\n",
1658 fname, gpg_strerror (err));
1674 /* Scan spool directories and expire too old pending keys. */
1676 expire_pending_confirmations (strlist_t domaindirs)
1678 gpg_error_t err = 0;
1682 for (sl = domaindirs; sl; sl = sl->next)
1684 domain = strrchr (sl->d, '/');
1685 log_assert (domain);
1688 expire_one_domain (sl->d, domain);
1695 /* List all configured domains. */
1697 command_list_domains (void)
1702 } requireddirs[] = {
1703 { "pending", "-rwx" },
1704 { "hu", "-rwxr-xr-x" }
1708 strlist_t domaindirs;
1715 err = get_domain_list (&domaindirs);
1718 log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1722 for (sl = domaindirs; sl; sl = sl->next)
1724 domain = strrchr (sl->d, '/');
1725 log_assert (domain);
1727 es_printf ("%s\n", domain);
1729 /* Check that the required directories are there. */
1730 for (i=0; i < DIM (requireddirs); i++)
1733 fname = make_filename_try (sl->d, requireddirs[i].name, NULL);
1736 err = gpg_error_from_syserror ();
1739 if (access (fname, W_OK))
1741 err = gpg_error_from_syserror ();
1742 if (gpg_err_code (err) == GPG_ERR_ENOENT)
1744 if (gnupg_mkdir (fname, requireddirs[i].perm))
1746 err = gpg_error_from_syserror ();
1747 log_error ("domain %s: error creating subdir '%s': %s\n",
1748 domain, requireddirs[i].name,
1749 gpg_strerror (err));
1752 log_info ("domain %s: subdir '%s' created\n",
1753 domain, requireddirs[i].name);
1756 log_error ("domain %s: problem with subdir '%s': %s\n",
1757 domain, requireddirs[i].name, gpg_strerror (err));
1761 /* Print a warning if the submission address is not configured. */
1763 fname = make_filename_try (sl->d, "submission-address", NULL);
1766 err = gpg_error_from_syserror ();
1769 if (access (fname, F_OK))
1771 err = gpg_error_from_syserror ();
1772 if (gpg_err_code (err) == GPG_ERR_ENOENT)
1773 log_error ("domain %s: submission address not configured\n",
1776 log_error ("domain %s: problem with '%s': %s\n",
1777 domain, fname, gpg_strerror (err));
1780 /* Check the syntax of the optional policy file. */
1782 fname = make_filename_try (sl->d, "policy", NULL);
1785 err = gpg_error_from_syserror ();
1788 fp = es_fopen (fname, "r");
1791 err = gpg_error_from_syserror ();
1792 if (gpg_err_code (err) != GPG_ERR_ENOENT)
1793 log_error ("domain %s: error in policy file: %s\n",
1794 domain, gpg_strerror (err));
1798 struct policy_flags_s policy;
1799 err = wks_parse_policy (&policy, fp, 0);
1803 struct policy_flags_s empty_policy;
1804 memset (&empty_policy, 0, sizeof empty_policy);
1805 if (!memcmp (&empty_policy, &policy, sizeof policy))
1806 log_error ("domain %s: empty policy file\n", domain);
1816 free_strlist (domaindirs);
1821 /* Run regular maintenance jobs. */
1826 strlist_t domaindirs;
1828 err = get_domain_list (&domaindirs);
1831 log_error ("error reading list of domains: %s\n", gpg_strerror (err));
1835 err = expire_pending_confirmations (domaindirs);
1837 free_strlist (domaindirs);