diff --git a/tools/Makefile.am b/tools/Makefile.am index 362ee1faf..7bc14568a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -147,21 +147,25 @@ gpgtar_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ gpg_wks_server_SOURCES = \ gpg-wks-server.c \ gpg-wks.h \ + wks-util.c \ wks-receive.c \ rfc822parse.c rfc822parse.h \ mime-parser.c mime-parser.h \ - mime-maker.h mime-maker.c + mime-maker.c mime-maker.h \ + send-mail.c send-mail.h gpg_wks_server_CFLAGS = $(GPG_ERROR_CFLAGS) gpg_wks_server_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) gpg_wks_client_SOURCES = \ gpg-wks-client.c \ - gpg-wks.h \ + gpg-wks.h \ + wks-util.c \ wks-receive.c \ rfc822parse.c rfc822parse.h \ mime-parser.c mime-parser.h \ - mime-maker.h mime-maker.c \ + mime-maker.h mime-maker.c \ + send-mail.c send-mail.h \ call-dirmngr.c call-dirmngr.h gpg_wks_client_CFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index c7cb8fb69..25ee43f2e 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -34,6 +34,7 @@ #include "name-value.h" #include "call-dirmngr.h" #include "mime-maker.h" +#include "send-mail.h" #include "gpg-wks.h" @@ -44,13 +45,15 @@ enum cmd_and_opt_values oQuiet = 'q', oVerbose = 'v', + oOutput = 'o', oDebug = 500, - aSend, + aCreate, aReceive, oGpgProgram, + oSend, oDummy }; @@ -60,8 +63,8 @@ enum cmd_and_opt_values static ARGPARSE_OPTS opts[] = { ARGPARSE_group (300, ("@Commands:\n ")), - ARGPARSE_c (aSend, "send", - ("send a publication request")), + ARGPARSE_c (aCreate, "create", + ("create a publication request")), ARGPARSE_c (aReceive, "receive", ("receive a confirmation request")), @@ -71,6 +74,8 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oQuiet, "quiet", ("be somewhat more quiet")), ARGPARSE_s_s (oDebug, "debug", "@"), ARGPARSE_s_s (oGpgProgram, "gpg", "@"), + ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"), + ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"), ARGPARSE_end () @@ -112,10 +117,10 @@ my_strusage( int level ) case 1: case 40: - p = ("Usage: gpg-wks-client --send|--receive [args] (-h for help)"); + p = ("Usage: gpg-wks-client [command] [options] [args] (-h for help)"); break; case 41: - p = ("Syntax: gpg-wks-client --send|--receive [args]\n" + p = ("Syntax: gpg-wks-client [command] [options] [args]\n" "Client for the Web Key Service\n"); break; @@ -158,8 +163,14 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oGpgProgram: opt.gpg_program = pargs->r.ret_str; break; + case oSend: + opt.use_sendmail = 1; + break; + case oOutput: + opt.output = pargs->r.ret_str; + break; - case aSend: + case aCreate: case aReceive: cmd = pargs->r_opt; break; @@ -221,12 +232,12 @@ main (int argc, char **argv) /* Run the selected command. */ switch (cmd) { - case aSend: + case aCreate: if (argc != 2) - wrong_args ("--send FINGERPRINT USER-ID"); + wrong_args ("--create FINGERPRINT USER-ID"); err = command_send (argv[0], argv[1]); if (err) - log_error ("sending key failed: %s\n", gpg_strerror (err)); + log_error ("creating request failed: %s\n", gpg_strerror (err)); break; case aReceive: @@ -234,7 +245,7 @@ main (int argc, char **argv) wrong_args ("--receive"); err = wks_receive (es_stdin, command_receive_cb, NULL); if (err) - log_error ("reading mail failed: %s\n", gpg_strerror (err)); + log_error ("processing mail failed: %s\n", gpg_strerror (err)); break; default: @@ -407,7 +418,7 @@ command_send (const char *fingerprint, char *userid) if (err) goto leave; - err = mime_maker_make (mime, es_stdout); + err = wks_send_mime (mime); leave: mime_maker_release (mime); @@ -502,7 +513,7 @@ send_confirmation_response (const char *sender, const char *address, if (err) goto leave; - err = mime_maker_make (mime, es_stdout); + err = wks_send_mime (mime); leave: mime_maker_release (mime); diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 1106934be..305b454a7 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -40,6 +40,7 @@ #include "mbox-util.h" #include "name-value.h" #include "mime-maker.h" +#include "send-mail.h" #include "gpg-wks.h" @@ -50,6 +51,7 @@ enum cmd_and_opt_values oQuiet = 'q', oVerbose = 'v', + oOutput = 'o', oDebug = 500, @@ -57,6 +59,7 @@ enum cmd_and_opt_values aCron, oGpgProgram, + oSend, oFrom, oHeader, @@ -79,7 +82,9 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oQuiet, "quiet", ("be somewhat more quiet")), ARGPARSE_s_s (oDebug, "debug", "@"), ARGPARSE_s_s (oGpgProgram, "gpg", "@"), - ARGPARSE_s_s (oFrom, "from" , "|ADDR|use ADDR as the default sender"), + ARGPARSE_s_n (oSend, "send", "send the mail using sendmail"), + ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"), + ARGPARSE_s_s (oFrom, "from", "|ADDR|use ADDR as the default sender"), ARGPARSE_s_s (oHeader, "header" , "|NAME=VALUE|add \"NAME: VALUE\" as header to all mails"), @@ -182,6 +187,12 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oHeader: append_to_strlist (&opt.extra_headers, pargs->r.ret_str); break; + case oSend: + opt.use_sendmail = 1; + break; + case oOutput: + opt.output = pargs->r.ret_str; + break; case aReceive: case aCron: @@ -831,7 +842,7 @@ send_confirmation_request (server_ctx_t ctx, if (err) goto leave; - err = mime_maker_make (mime, es_stdout); + err = wks_send_mime (mime); leave: mime_maker_release (mime); @@ -923,6 +934,14 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce) const char *s; strlist_t sl; + /* FIXME: There is a bug in name-value.c which adds white space for + * the last pair and thus we strip the nonce here until this has + * been fixed. */ + char *nonce2 = xstrdup (nonce); + trim_trailing_spaces (nonce2); + nonce = nonce2; + + domain = strchr (address, '@'); log_assert (domain && domain[1]); domain++; @@ -1027,6 +1046,7 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce) xfree (hash); xfree (fnewname); xfree (fname); + xfree (nonce2); return err; } diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index 873925c60..be85eecfb 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -22,6 +22,7 @@ #include "../common/util.h" #include "../common/strlist.h" +#include "mime-maker.h" /* We keep all global options in the structure OPT. */ struct @@ -29,6 +30,8 @@ struct int verbose; unsigned int debug; int quiet; + int use_sendmail; + const char *output; const char *gpg_program; const char *directory; const char *default_from; @@ -43,6 +46,9 @@ struct #define DBG_EXTPROG_VALUE 16384 /* debug external program calls */ +/*-- wks-util.c --*/ +gpg_error_t wks_send_mime (mime_maker_t mime); + /*-- wks-receive.c --*/ gpg_error_t wks_receive (estream_t fp, gpg_error_t (*result_cb)(void *opaque, diff --git a/tools/send-mail.c b/tools/send-mail.c new file mode 100644 index 000000000..2266521a4 --- /dev/null +++ b/tools/send-mail.c @@ -0,0 +1,129 @@ +/* send-mail.c - Invoke sendmail or other delivery tool. + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "util.h" +#include "exectool.h" +#include "sysutils.h" +#include "send-mail.h" + + +static gpg_error_t +run_sendmail (estream_t data) +{ + gpg_error_t err; + const char pgmname[] = "/usr/lib/sendmail"; + const char *argv[3]; + + argv[0] = "-oi"; + argv[1] = "-t"; + argv[2] = NULL; + + err = gnupg_exec_tool_stream (pgmname, argv, data, NULL, NULL, NULL, NULL); + if (err) + log_error ("running '%s' failed: %s\n", pgmname, gpg_strerror (err)); + return err; +} + + +/* Send the data in FP as mail. */ +gpg_error_t +send_mail (estream_t fp) +{ + return run_sendmail (fp); +} + + +/* Convenience function to write a mail to a named file. */ +gpg_error_t +send_mail_to_file (estream_t fp, const char *fname) +{ + gpg_error_t err; + estream_t outfp = NULL; + char *buffer = NULL; + size_t buffersize = 32 * 1024; + size_t nbytes, nwritten; + + if (!fname) + fname = "-"; + + buffer = xtrymalloc (buffersize); + if (!buffer) + return gpg_error_from_syserror (); + + outfp = !strcmp (fname,"-")? es_stdout : es_fopen (fname, "wb"); + if (!outfp) + { + err = gpg_error_from_syserror (); + log_error ("error creating '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + for (;;) + { + if (es_read (fp, buffer, sizeof buffer, &nbytes)) + { + err = gpg_error_from_syserror (); + log_error ("error reading '%s': %s\n", + es_fname_get (fp), gpg_strerror (err)); + goto leave; + } + + if (!nbytes) + { + err = 0; + break; /* Ready. */ + } + + if (es_write (outfp, buffer, nbytes, &nwritten)) + { + err = gpg_error_from_syserror (); + log_error ("error writing '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + else if (nwritten != nbytes) + { + err = gpg_error (GPG_ERR_EIO); + log_error ("error writing '%s': %s\n", fname, "short write"); + goto leave; + } + } + + + leave: + if (err) + { + if (outfp && outfp != es_stdout) + { + es_fclose (outfp); + gnupg_remove (fname); + } + } + else if (outfp && outfp != es_stdout && es_fclose (outfp)) + { + err = gpg_error_from_syserror (); + log_error ("error closing '%s': %s\n", fname, gpg_strerror (err)); + } + + xfree (buffer); + return err; +} diff --git a/tools/send-mail.h b/tools/send-mail.h new file mode 100644 index 000000000..5f57854af --- /dev/null +++ b/tools/send-mail.h @@ -0,0 +1,27 @@ +/* send-mail.h - Invoke sendmail or other delivery tool. + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef GNUPG_SEND_MAIL_H +#define GNUPG_SEND_MAIL_H + +gpg_error_t send_mail (estream_t fp); +gpg_error_t send_mail_to_file (estream_t fp, const char *fname); + + +#endif /*GNUPG_SEND_MAIL_H*/ diff --git a/tools/wks-util.c b/tools/wks-util.c new file mode 100644 index 000000000..8d9f92bd3 --- /dev/null +++ b/tools/wks-util.c @@ -0,0 +1,65 @@ +/* wks-utils.c - Common helper fucntions for wks tools + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "util.h" +#include "mime-maker.h" +#include "send-mail.h" +#include "gpg-wks.h" + + +/* Helper to write mail to the output(s). */ +gpg_error_t +wks_send_mime (mime_maker_t mime) +{ + gpg_error_t err; + estream_t mail; + + /* Without any option we take a short path. */ + if (!opt.use_sendmail && !opt.output) + return mime_maker_make (mime, es_stdout); + + mail = es_fopenmem (0, "w+b"); + if (!mail) + { + err = gpg_error_from_syserror (); + return err; + } + + err = mime_maker_make (mime, mail); + + if (!err && opt.output) + { + es_rewind (mail); + err = send_mail_to_file (mail, opt.output); + } + + if (!err && opt.use_sendmail) + { + es_rewind (mail); + err = send_mail (mail); + } + + es_fclose (mail); + return err; +}