1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-11-10 21:38:50 +01:00

gpg-mail-tube: New feature --as-attach.

* tools/gpg-mail-tube.c (oAsAttach): NEw.
(opts): Add --as-attach.
(opt): Add .as_attach.
(parse_arguments): Set it.
(mail_tube_encrypt): Detect plain text and hhandle new option.
This commit is contained in:
Werner Koch 2024-08-29 17:46:39 +02:00
parent ac30449867
commit 4511997e9e
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 89 additions and 20 deletions

View File

@ -2171,10 +2171,10 @@ gpgtar --list-archive test1
@c @c
@manpage gpg-mail-tube.1 @manpage gpg-mail-tube.1
@node gpg-mail-tube @node gpg-mail-tube
@section Encrypt rfc822 formated mail in a pipeline @section Encrypt rfc822 formatted mail in a pipeline
@ifset manverb @ifset manverb
.B gpg-mail-tube .B gpg-mail-tube
\- Encrypt rfc822 formated mail in a pipeline \- Encrypt rfc822 formatted mail in a pipeline
@end ifset @end ifset
@mansect synopsis @mansect synopsis
@ -2229,6 +2229,15 @@ Put the given environment string into the environment of this process
and of the called gpg. This option is required if there is no other and of the called gpg. This option is required if there is no other
way to set the environemt. way to set the environemt.
@item --as-attach
@itemx -a
@opindex as-attach
Do not write a PGP/MIME mail but emit a simple body along with an
attachment containing the encrypted body of the input mail. If the
input was a plain text message a simple encrypted file will be
attached. If the input was a multipart MIME message the encrypted
file is of type message/rfc822.
@item --gpg @var{gpgcmd} @item --gpg @var{gpgcmd}
@opindex gpg @opindex gpg
Use the specified command @var{gpgcmd} instead of @command{gpg}. Use the specified command @var{gpgcmd} instead of @command{gpg}.

View File

@ -49,6 +49,7 @@ enum cmd_and_opt_values
oQuiet = 'q', oQuiet = 'q',
oVerbose = 'v', oVerbose = 'v',
oAsAttach = 'a',
oDebug = 500, oDebug = 500,
@ -77,6 +78,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oVSD, "vsd", "run the vsd installation of gpg"), ARGPARSE_s_n (oVSD, "vsd", "run the vsd installation of gpg"),
ARGPARSE_s_s (oLogFile, "log-file", "|FILE|write diagnostics to FILE"), ARGPARSE_s_s (oLogFile, "log-file", "|FILE|write diagnostics to FILE"),
ARGPARSE_s_n (oNoStderr, "no-stderr", "suppress all output to stderr"), ARGPARSE_s_n (oNoStderr, "no-stderr", "suppress all output to stderr"),
ARGPARSE_s_n (oAsAttach, "as-attachment","attach the encrypted mail"),
ARGPARSE_end () ARGPARSE_end ()
}; };
@ -94,6 +96,7 @@ static struct
unsigned int vsd:1; unsigned int vsd:1;
unsigned int no_stderr:1;/* Avoid any writes to stderr. */ unsigned int no_stderr:1;/* Avoid any writes to stderr. */
unsigned int as_attach:1;/* Create an encrypted attachment. */
} opt; } opt;
@ -217,6 +220,7 @@ parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts)
break; break;
case oLogFile: opt.logfile = pargs->r.ret_str; break; case oLogFile: opt.logfile = pargs->r.ret_str; break;
case oNoStderr: opt.no_stderr = 1; break; case oNoStderr: opt.no_stderr = 1; break;
case oAsAttach: opt.as_attach = 1; break;
case oGpgProgram: case oGpgProgram:
opt.gpg_program = pargs->r.ret_str; opt.gpg_program = pargs->r.ret_str;
@ -381,7 +385,7 @@ mail_tube_message_cb (void *opaque,
* collected by the parser and thus with canonicalized names. * collected by the parser and thus with canonicalized names.
* The original idea was to keep the lines as received so not to * The original idea was to keep the lines as received so not to
* break DKIM. But DKIM would break anyway because DKIM should * break DKIM. But DKIM would break anyway because DKIM should
* aleays cover the CT field which we have to replace. */ * always cover the CT field which we have to replace. */
if (!(s = rfc822parse_last_header_line (msg))) if (!(s = rfc822parse_last_header_line (msg)))
; ;
else if (!rfc822_cmp_header_name (s, "Content-Type")) else if (!rfc822_cmp_header_name (s, "Content-Type"))
@ -425,6 +429,7 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
gpgrt_process_t proc = NULL; gpgrt_process_t proc = NULL;
int exitcode; int exitcode;
int i, found; int i, found;
int ct_text = 0;
ctx->msg = rfc822parse_open (mail_tube_message_cb, ctx); ctx->msg = rfc822parse_open (mail_tube_message_cb, ctx);
if (!ctx->msg) if (!ctx->msg)
@ -491,6 +496,18 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
} }
rfc822parse_enum_header_lines (NULL, &iterp); /* Close enumerator. */ rfc822parse_enum_header_lines (NULL, &iterp); /* Close enumerator. */
if (opt.as_attach)
{
rfc822parse_field_t field;
const char *media;
field = rfc822parse_parse_field (ctx->msg, "Content-Type", -1);
if (field && (media = rfc822parse_query_media_type (field, NULL))
&& !strcmp (media, "text"))
ct_text = 1;
rfc822parse_release_field (field);
}
/* Create a boundary. We use a pretty simple random string to avoid /* Create a boundary. We use a pretty simple random string to avoid
* the Libgcrypt overhead. It could actually be a constant string * the Libgcrypt overhead. It could actually be a constant string
* because this is the outer container. */ * because this is the outer container. */
@ -507,10 +524,16 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
if (!ctx->mime_version_seen) if (!ctx->mime_version_seen)
es_fprintf (es_stdout, "MIME-Version: 1.0\r\n"); es_fprintf (es_stdout, "MIME-Version: 1.0\r\n");
es_fprintf (es_stdout,
"Content-Type: multipart/encrypted;" if (opt.as_attach)
" protocol=\"application/pgp-encrypted\";\r\n" es_fprintf (es_stdout,
"\tboundary=\"=-=mt-%s=-=\r\n", boundary); "Content-Type: multipart/mixed;"
" boundary=\"=-=mt-%s=-=\r\n", boundary);
else
es_fprintf (es_stdout,
"Content-Type: multipart/encrypted;"
" protocol=\"application/pgp-encrypted\";\r\n"
"\tboundary=\"=-=mt-%s=-=\r\n", boundary);
/* Add the extra headers. */ /* Add the extra headers. */
for (sl = opt.extra_headers; sl; sl = sl->next) for (sl = opt.extra_headers; sl; sl = sl->next)
@ -520,13 +543,42 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
es_fprintf (es_stdout, "%.*s: %s\r\n", (int)(s - sl->d), sl->d, s + 1); es_fprintf (es_stdout, "%.*s: %s\r\n", (int)(s - sl->d), sl->d, s + 1);
} }
/* Output the PGP/MIME boilerplate. */ /* Output the plain or PGP/MIME boilerplate. */
es_fprintf (es_stdout, if (opt.as_attach)
{
es_fprintf (es_stdout,
"\r\n"
"\r\n"
"--=-=mt-%s=-=\r\n"
"Content-Type: text/plain; charset=us-ascii\r\n"
"Content-Disposition: inline\r\n"
"\r\n"
"Please find attached an encrypted %s.\r\n"
"\r\n"
"--=-=mt-%s=-=\r\n",
boundary,
ct_text? "file":"message",
boundary);
if (ct_text)
es_fprintf (es_stdout,
"Content-Type: text/plain; charset=us-ascii\r\n"
"Content-Description: PGP encrypted file\r\n"
"Content-Disposition: attachment; filename=\"%s\"\r\n"
"\r\n", "pgp-encrypted-file.asc");
else
es_fprintf (es_stdout,
"Content-Type: message/rfc822\r\n"
"Content-Description: PGP encrypted message\r\n"
"Content-Disposition: attachment; filename=\"%s\"\r\n"
"\r\n", "pgp-encrypted-msg.eml.asc");
}
else
es_fprintf (es_stdout,
"\r\n" "\r\n"
"This is a PGP/MIME encrypted message.\r\n"
"\r\n" "\r\n"
"--=-=mt-%s=-=\r\n" "--=-=mt-%s=-=\r\n"
"Content-Type: application/pgp-encrypted\r\n" "Content-Type: application/pgp-encrypted\r\n"
"Content-Description: PGP/MIME version id\r\n"
"\r\n" "\r\n"
"Version: 1\r\n" "Version: 1\r\n"
"\r\n" "\r\n"
@ -544,18 +596,26 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
goto leave; goto leave;
} }
/* Write new mime headers using the old content-* values. */ if (opt.as_attach && ct_text)
for (i=0; i < DIM (ct_names); i++)
{ {
line = rfc822parse_get_field (ctx->msg, ct_names[i], -1, NULL); /* No headers at all; write as plain file and ignore the encoding. */
if (line) /* FIXME: Should we do a base64 or QP decoding? */
{ }
es_fprintf (gpginfp, "%s\r\n", line); else
rfc822_free (line); {
} /* Write new mime headers using the old content-* values. */
for (i=0; i < DIM (ct_names); i++)
{
line = rfc822parse_get_field (ctx->msg, ct_names[i], -1, NULL);
log_debug ("OLD CT is '%s'\n", line);
if (line)
{
es_fprintf (gpginfp, "%s\r\n", line);
rfc822_free (line);
}
}
es_fprintf (gpginfp, "\r\n"); /* End of MIME header. */
} }
es_fprintf (gpginfp, "\r\n"); /* End of MIME header. */
/* Read the remaining input and feed it to gpg. */ /* Read the remaining input and feed it to gpg. */
while (es_fgets (ctx->line, sizeof (ctx->line), fpin)) while (es_fgets (ctx->line, sizeof (ctx->line), fpin))