tools: Call sendmail directly from the wks tools.

* tools/send-mail.c, tools/send-mail.h: New.
* tools/wks-util.c: New.
* tools/Makefile.am (gpg_wks_server_SOURCES): Add them.
(gpg_wks_client_SOURCES): Ditto.
* tools/gpg-wks.h (opt): Add fields use_sendmail and output.
* tools/gpg-wks-client.c: Add options --send and --output.  Rename
command --send to --create.
(command_send, send_confirmation_response): Output via wks_send_mime.
* tools/gpg-wks-server.c:  Add options --send and --output.
(send_confirmation_request): Output via wks_send_mime.
(check_and_publish): Add hack for name-value bug.
--

With this code, a dedicated user on the server along with a procmail
script, it was possible to run a basic test.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-07-03 00:41:30 +02:00
parent c619035d9c
commit 7705f310f1
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 279 additions and 17 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

129
tools/send-mail.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

27
tools/send-mail.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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*/

65
tools/wks-util.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}