core: Support usage of gpgtar for encryption

* src/gpgme.h.in (GPGME_ENCRYPT_ARCHIVE): New encryption flag.
* src/engine-gpg.c (arg_and_data_s): New field gpg_arg.
(engine_gpg): New flag use_gpgtar.
(_add_arg): Add argument gpg_arg and set it.
(add_arg_ext, add_arg_with_locp, add_arg, add_arg_pfx, add_arg_len):
Adjust call of _add_arg.
(add_arg_with_locp): Add argument front.
(add_gpg_arg, add_gpg_arg_with_value): New.
(gpg_new): Use add_gpg_arg_with_value for gpg-only options with a value
and add_gpg_arg for gpg-only options without.
(build_argv): Consider usage of gpgtar when counting arguments to pass
to gpg/gpgtar. Prepend "--gpg-args" to all gpg-only arguments if gpgtar
is used.
(start): Set program to use. Read diagnostics output from stderr when
using gpgtar. Do not pass --status-fd to gpgtar for gpg < 2.4.1. Use
add_gpg_arg_with_value for --lc-ctype and --lc-messages.
(gpg_encrypt): Set use_gpgtar engine flag if GPGME_ENCRYPT_ARCHIVE flag
is set. Check for new enough gpg and incompatible flags. Use
add_gpg_arg_with_value for gpg-only options with a value and
add_gpg_arg for gpg-only options without a value. Set extra options
for gpgtar and pass input data to stdin when using gpgtar.
* src/engine-gpgsm.c (gpgsm_encrypt): Return error if new flag is set.
* src/engine-uiserver.c (uiserver_encrypt): Ditto.

* tests/run-encrypt.c (show_usage): New options --archive and
--diagnostics.
(main): Parse new options. Encrypt with gpgtar if --archive is given.
Print stderr of gpg/gpgtar if --diagnostics is given.
--

With this change the gpgme_op_encrypt* functions get support for
encrypting a list of files and/or directories passed as NUL-separated
list in "plain" data with gpgtar.

GnuPG-bug-id: 6342
This commit is contained in:
Ingo Klöcker 2023-01-18 11:48:02 +01:00
parent d56b3bc1cf
commit 5d8316da1d
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
5 changed files with 303 additions and 117 deletions

View File

@ -57,6 +57,7 @@ struct arg_and_data_s
int inbound; /* True if this is used for reading from gpg. */ int inbound; /* True if this is used for reading from gpg. */
int dup_to; int dup_to;
int print_fd; /* Print the fd number and not the special form of it. */ int print_fd; /* Print the fd number and not the special form of it. */
int gpg_arg; /* True if this argument is not known by gpgtar. */
int *arg_locp; /* Write back the argv idx of this argument when int *arg_locp; /* Write back the argv idx of this argument when
building command line to this location. */ building command line to this location. */
char arg[FLEXIBLE_ARRAY_MEMBER]; /* Used if data above is not used. */ char arg[FLEXIBLE_ARRAY_MEMBER]; /* Used if data above is not used. */
@ -145,6 +146,7 @@ struct engine_gpg
char *trust_model; char *trust_model;
struct { struct {
unsigned int use_gpgtar : 1;
unsigned int no_symkey_cache : 1; unsigned int no_symkey_cache : 1;
unsigned int offline : 1; unsigned int offline : 1;
unsigned int ignore_mdc_error : 1; unsigned int ignore_mdc_error : 1;
@ -247,7 +249,7 @@ _prepend_to_arglist (engine_gpg_t gpg, struct arg_and_data_s *a)
options added late in the process. */ options added late in the process. */
static gpgme_error_t static gpgme_error_t
_add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen, _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
int front, int *arg_locp) int front, int *arg_locp, int gpg_arg)
{ {
struct arg_and_data_s *a; struct arg_and_data_s *a;
size_t prefixlen = prefix? strlen (prefix) : 0; size_t prefixlen = prefix? strlen (prefix) : 0;
@ -262,6 +264,7 @@ _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
a->data = NULL; a->data = NULL;
a->dup_to = -1; a->dup_to = -1;
a->arg_locp = arg_locp; a->arg_locp = arg_locp;
a->gpg_arg = gpg_arg;
if (prefixlen) if (prefixlen)
memcpy (a->arg, prefix, prefixlen); memcpy (a->arg, prefix, prefixlen);
@ -279,32 +282,44 @@ _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
static gpgme_error_t static gpgme_error_t
add_arg_ext (engine_gpg_t gpg, const char *arg, int front) add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
{ {
return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL); return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL, 0);
} }
static gpgme_error_t static gpgme_error_t
add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp) add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp, int front)
{ {
return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp); return _add_arg (gpg, NULL, arg, strlen (arg), front, locp, 0);
} }
static gpgme_error_t static gpgme_error_t
add_arg (engine_gpg_t gpg, const char *arg) add_arg (engine_gpg_t gpg, const char *arg)
{ {
return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL); return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL, 0);
} }
static gpgme_error_t static gpgme_error_t
add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg) add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg)
{ {
return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL); return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL, 0);
}
static gpgme_error_t
add_gpg_arg (engine_gpg_t gpg, const char *arg)
{
return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL, 1);
}
static gpgme_error_t
add_gpg_arg_with_value (engine_gpg_t gpg, const char *arg, const char *value, int front)
{
return _add_arg (gpg, arg, value, strlen (value), front, NULL, 1);
} }
static gpgme_error_t static gpgme_error_t
add_arg_len (engine_gpg_t gpg, const char *prefix, add_arg_len (engine_gpg_t gpg, const char *prefix,
const char *arg, size_t arglen) const char *arg, size_t arglen)
{ {
return _add_arg (gpg, prefix, arg, arglen, 0, NULL); return _add_arg (gpg, prefix, arg, arglen, 0, NULL, 0);
} }
@ -557,22 +572,18 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
if (home_dir) if (home_dir)
{ {
rc = add_arg (gpg, "--homedir"); rc = add_gpg_arg_with_value (gpg, "--homedir=", home_dir, 0);
if (!rc)
rc = add_arg (gpg, home_dir);
if (rc) if (rc)
goto leave; goto leave;
} }
rc = add_arg (gpg, "--no-tty"); rc = add_gpg_arg (gpg, "--no-tty");
if (!rc) if (!rc)
rc = add_arg (gpg, "--charset"); rc = add_gpg_arg (gpg, "--charset=utf8");
if (!rc) if (!rc)
rc = add_arg (gpg, "utf8"); rc = add_gpg_arg (gpg, "--enable-progress-filter");
if (!rc)
rc = add_arg (gpg, "--enable-progress-filter");
if (!rc && have_gpg_version (gpg, "2.1.11")) if (!rc && have_gpg_version (gpg, "2.1.11"))
rc = add_arg (gpg, "--exit-on-status-write-error"); rc = add_gpg_arg (gpg, "--exit-on-status-write-error");
if (rc) if (rc)
goto leave; goto leave;
@ -581,9 +592,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
goto leave; goto leave;
if (dft_display) if (dft_display)
{ {
rc = add_arg (gpg, "--display"); rc = add_gpg_arg_with_value (gpg, "--display=", dft_display, 0);
if (!rc)
rc = add_arg (gpg, dft_display);
free (dft_display); free (dft_display);
if (rc) if (rc)
@ -610,11 +619,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
if (!err) if (!err)
{ {
if (*dft_ttyname) if (*dft_ttyname)
{ rc = add_gpg_arg_with_value (gpg, "--ttyname=", dft_ttyname, 0);
rc = add_arg (gpg, "--ttyname");
if (!rc)
rc = add_arg (gpg, dft_ttyname);
}
else else
rc = 0; rc = 0;
if (!rc) if (!rc)
@ -624,11 +629,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir,
goto leave; goto leave;
if (dft_ttytype) if (dft_ttytype)
{ rc = add_gpg_arg_with_value (gpg, "--ttytype=", dft_ttytype, 0);
rc = add_arg (gpg, "--ttytype");
if (!rc)
rc = add_arg (gpg, dft_ttytype);
}
free (dft_ttytype); free (dft_ttytype);
} }
@ -902,7 +903,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
argc++; /* For argv[0]. */ argc++; /* For argv[0]. */
for (a = gpg->arglist; a; a = a->next) for (a = gpg->arglist; a; a = a->next)
{ {
argc++; argc += 1 + (gpg->flags.use_gpgtar && a->gpg_arg);
if (a->data) if (a->data)
{ {
/*fprintf (stderr, "build_argv: data\n" );*/ /*fprintf (stderr, "build_argv: data\n" );*/
@ -921,21 +922,21 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (use_agent) if (use_agent)
argc++; argc++;
if (*gpg->request_origin) if (*gpg->request_origin)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->auto_key_locate) if (gpg->auto_key_locate)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->trust_model) if (gpg->trust_model)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->flags.no_symkey_cache) if (gpg->flags.no_symkey_cache)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->flags.ignore_mdc_error) if (gpg->flags.ignore_mdc_error)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->flags.offline) if (gpg->flags.offline)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->flags.no_auto_check_trustdb) if (gpg->flags.no_auto_check_trustdb)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (gpg->pinentry_mode) if (gpg->pinentry_mode)
argc++; argc += 1 + !!gpg->flags.use_gpgtar;
if (!gpg->cmd.used) if (!gpg->cmd.used)
argc++; /* --batch */ argc++; /* --batch */
@ -988,6 +989,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (*gpg->request_origin) if (*gpg->request_origin)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = _gpgme_strconcat ("--request-origin=", argv[argc] = _gpgme_strconcat ("--request-origin=",
gpg->request_origin, NULL); gpg->request_origin, NULL);
if (!argv[argc]) if (!argv[argc])
@ -1001,6 +1013,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->auto_key_locate) if (gpg->auto_key_locate)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup (gpg->auto_key_locate); argv[argc] = strdup (gpg->auto_key_locate);
if (!argv[argc]) if (!argv[argc])
{ {
@ -1013,6 +1036,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->trust_model) if (gpg->trust_model)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup (gpg->trust_model); argv[argc] = strdup (gpg->trust_model);
if (!argv[argc]) if (!argv[argc])
{ {
@ -1025,6 +1059,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->flags.no_symkey_cache) if (gpg->flags.no_symkey_cache)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup ("--no-symkey-cache"); argv[argc] = strdup ("--no-symkey-cache");
if (!argv[argc]) if (!argv[argc])
{ {
@ -1037,6 +1082,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->flags.ignore_mdc_error) if (gpg->flags.ignore_mdc_error)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup ("--ignore-mdc-error"); argv[argc] = strdup ("--ignore-mdc-error");
if (!argv[argc]) if (!argv[argc])
{ {
@ -1049,6 +1105,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->flags.offline) if (gpg->flags.offline)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup ("--disable-dirmngr"); argv[argc] = strdup ("--disable-dirmngr");
if (!argv[argc]) if (!argv[argc])
{ {
@ -1061,6 +1128,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
if (gpg->flags.no_auto_check_trustdb) if (gpg->flags.no_auto_check_trustdb)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup ("--no-auto-check-trustdb"); argv[argc] = strdup ("--no-auto-check-trustdb");
if (!argv[argc]) if (!argv[argc])
{ {
@ -1084,6 +1162,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
} }
if (s) if (s)
{ {
if (gpg->flags.use_gpgtar)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup (s); argv[argc] = strdup (s);
if (!argv[argc]) if (!argv[argc])
{ {
@ -1194,6 +1283,17 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
} }
else else
{ {
if (gpg->flags.use_gpgtar && a->gpg_arg)
{
argv[argc] = strdup ("--gpg-args");
if (!argv[argc])
{
err = gpg_error_from_syserror ();
if (err)
goto leave;
}
argc++;
}
argv[argc] = strdup (a->arg); argv[argc] = strdup (a->arg);
if (!argv[argc]) if (!argv[argc])
{ {
@ -1539,52 +1639,65 @@ start (engine_gpg_t gpg)
if (!gpg) if (!gpg)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (!gpg->file_name && !_gpgme_get_default_gpg_name ()) if (!gpg->flags.use_gpgtar)
pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
else
pgmname = _gpgme_get_default_gpgtar_name ();
if (!pgmname)
return trace_gpg_error (GPG_ERR_INV_ENGINE); return trace_gpg_error (GPG_ERR_INV_ENGINE);
rc = gpgme_data_new (&gpg->diagnostics); rc = gpgme_data_new (&gpg->diagnostics);
if (rc) if (rc)
return rc; return rc;
rc = add_data_ext (gpg, gpg->diagnostics, -2, 1, 1); if (gpg->flags.use_gpgtar)
if (rc) {
return rc; /* Read the diagnostics output from gpgtar's stderr. */
rc = add_data (gpg, gpg->diagnostics, 2, 1);
if (rc)
return rc;
}
else
{
rc = add_data_ext (gpg, gpg->diagnostics, -2, 1, 1);
if (rc)
return rc;
rc = add_arg_ext (gpg, "--logger-fd", 1); rc = add_arg_ext (gpg, "--logger-fd", 1);
if (rc) if (rc)
return rc; return rc;
}
{ if (!gpg->flags.use_gpgtar || have_gpg_version (gpg, "2.4.1"))
char buf[25]; {
_gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]); /* Do not pass --status-fd to gpgtar for gpg < 2.4.1. */
rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc, 1); {
if (rc) char buf[25];
return rc; _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
} rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc, 1);
if (rc)
return rc;
}
rc = add_arg_ext (gpg, "--status-fd", 1); rc = add_arg_ext (gpg, "--status-fd", 1);
if (rc) if (rc)
return rc; return rc;
}
if (gpg->lc_ctype) if (gpg->lc_ctype)
{ {
rc = add_arg_ext (gpg, gpg->lc_ctype, 1); rc = add_gpg_arg_with_value (gpg, "--lc-ctype=", gpg->lc_ctype, 1);
if (!rc)
rc = add_arg_ext (gpg, "--lc-ctype", 1);
if (rc) if (rc)
return rc; return rc;
} }
if (gpg->lc_messages) if (gpg->lc_messages)
{ {
rc = add_arg_ext (gpg, gpg->lc_messages, 1); rc = add_gpg_arg_with_value (gpg, "--lc-messages=", gpg->lc_messages, 1);
if (!rc)
rc = add_arg_ext (gpg, "--lc-messages", 1);
if (rc) if (rc)
return rc; return rc;
} }
pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
rc = build_argv (gpg, pgmname); rc = build_argv (gpg, pgmname);
if (rc) if (rc)
return rc; return rc;
@ -2201,6 +2314,14 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
engine_gpg_t gpg = engine; engine_gpg_t gpg = engine;
gpgme_error_t err = 0; gpgme_error_t err = 0;
gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE);
if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.3.5"))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
if (gpg->flags.use_gpgtar && (flags & GPGME_ENCRYPT_WRAP))
return gpg_error (GPG_ERR_INV_VALUE);
if (recp || recpstring) if (recp || recpstring)
err = add_arg (gpg, "--encrypt"); err = add_arg (gpg, "--encrypt");
@ -2208,7 +2329,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
err = add_arg (gpg, "--symmetric"); err = add_arg (gpg, "--symmetric");
if (!err && use_armor) if (!err && use_armor)
err = add_arg (gpg, "--armor"); err = add_gpg_arg (gpg, "--armor");
if (!err && (flags & GPGME_ENCRYPT_WRAP)) if (!err && (flags & GPGME_ENCRYPT_WRAP))
{ {
@ -2218,31 +2339,31 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
* the encryption would add an additional compression layer. * the encryption would add an additional compression layer.
* We better suppress that. */ * We better suppress that. */
flags |= GPGME_ENCRYPT_NO_COMPRESS; flags |= GPGME_ENCRYPT_NO_COMPRESS;
err = add_arg (gpg, "--no-literal"); err = add_gpg_arg (gpg, "--no-literal");
} }
if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
err = add_arg (gpg, "--compress-algo=none"); err = add_gpg_arg (gpg, "--compress-algo=none");
if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS))
err = add_arg (gpg, "--throw-keyids"); err = add_gpg_arg (gpg, "--throw-keyids");
if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
&& have_gpg_version (gpg, "2.1.14")) && have_gpg_version (gpg, "2.1.14"))
err = add_arg (gpg, "--mimemode"); err = add_gpg_arg (gpg, "--mimemode");
if (!err && gpg->flags.include_key_block) if (!err && gpg->flags.include_key_block)
err = add_arg (gpg, "--include-key-block"); err = add_gpg_arg (gpg, "--include-key-block");
if (recp || recpstring) if (recp || recpstring)
{ {
/* If we know that all recipients are valid (full or ultimate trust) /* If we know that all recipients are valid (full or ultimate trust)
we can suppress further checks. */ we can suppress further checks. */
if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
err = add_arg (gpg, "--always-trust"); err = add_gpg_arg (gpg, "--always-trust");
if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
err = add_arg (gpg, "--no-encrypt-to"); err = add_gpg_arg (gpg, "--no-encrypt-to");
if (!err && !recp && recpstring) if (!err && !recp && recpstring)
err = append_args_from_recipients_string (gpg, flags, recpstring); err = append_args_from_recipients_string (gpg, flags, recpstring);
@ -2260,16 +2381,31 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
if (gpgme_data_get_file_name (plain)) if (gpgme_data_get_file_name (plain))
{ {
if (!err) if (!err)
err = add_arg (gpg, "--set-filename"); err = add_gpg_arg_with_value (gpg, "--set-filename", gpgme_data_get_file_name (plain), 0);
if (!err) }
err = add_arg (gpg, gpgme_data_get_file_name (plain)); if (gpg->flags.use_gpgtar)
{
if (!err)
err = add_arg (gpg, "--files-from");
if (!err)
err = add_arg (gpg, "-");
if (!err)
err = add_arg (gpg, "--null");
if (!err)
err = add_arg (gpg, "--utf8-strings");
/* Pass the filenames to gpgtar's stdin. */
if (!err)
err = add_data (gpg, plain, 0, 0);
}
else
{
if (!err)
err = add_input_size_hint (gpg, plain);
if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, plain, -1, 0);
} }
if (!err)
err = add_input_size_hint (gpg, plain);
if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, plain, -1, 0);
if (!err) if (!err)
err = start (gpg); err = start (gpg);

View File

@ -1469,6 +1469,9 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
if (!recp && !recpstring) /* Symmetric only */ if (!recp && !recpstring) /* Symmetric only */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (flags & GPGME_ENCRYPT_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
{ {
err = gpgsm_assuan_simple_command (gpgsm, err = gpgsm_assuan_simple_command (gpgsm,

View File

@ -1145,6 +1145,9 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
else else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
if (flags & GPGME_ENCRYPT_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (flags & GPGME_ENCRYPT_PREPARE) if (flags & GPGME_ENCRYPT_PREPARE)
{ {
if (!recp || plain || ciph) if (!recp || plain || ciph)

View File

@ -1299,7 +1299,8 @@ typedef enum
GPGME_ENCRYPT_SYMMETRIC = 32, GPGME_ENCRYPT_SYMMETRIC = 32,
GPGME_ENCRYPT_THROW_KEYIDS = 64, GPGME_ENCRYPT_THROW_KEYIDS = 64,
GPGME_ENCRYPT_WRAP = 128, GPGME_ENCRYPT_WRAP = 128,
GPGME_ENCRYPT_WANT_ADDRESS = 256 GPGME_ENCRYPT_WANT_ADDRESS = 256,
GPGME_ENCRYPT_ARCHIVE = 512
} }
gpgme_encrypt_flags_t; gpgme_encrypt_flags_t;

View File

@ -107,6 +107,8 @@ show_usage (int ex)
" --no-symkey-cache disable the use of that cache\n" " --no-symkey-cache disable the use of that cache\n"
" --wrap assume input is valid OpenPGP message\n" " --wrap assume input is valid OpenPGP message\n"
" --symmetric encrypt symmetric (OpenPGP only)\n" " --symmetric encrypt symmetric (OpenPGP only)\n"
" --archive encrypt given file or directory into an archive\n"
" --diagnostics print diagnostics\n"
, stderr); , stderr);
exit (ex); exit (ex);
} }
@ -132,6 +134,7 @@ main (int argc, char **argv)
gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST; gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
gpgme_off_t offset; gpgme_off_t offset;
int no_symkey_cache = 0; int no_symkey_cache = 0;
int diagnostics = 0;
if (argc) if (argc)
{ argc--; argv++; } { argc--; argv++; }
@ -225,6 +228,16 @@ main (int argc, char **argv)
no_symkey_cache = 1; no_symkey_cache = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--archive"))
{
flags |= GPGME_ENCRYPT_ARCHIVE;
argc--; argv++;
}
else if (!strcmp (*argv, "--diagnostics"))
{
diagnostics = 1;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
@ -269,48 +282,56 @@ main (int argc, char **argv)
} }
keys[i] = NULL; keys[i] = NULL;
err = gpgme_data_new_from_file (&in, *argv, 1); if (flags & GPGME_ENCRYPT_ARCHIVE)
if (err)
{ {
fprintf (stderr, PGM ": error reading `%s': %s\n", const char *path = *argv;
*argv, gpg_strerror (err)); err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
exit (1);
} }
offset = gpgme_data_seek (in, 0, SEEK_END); else
if (offset == (gpgme_off_t)(-1))
{ {
err = gpg_error_from_syserror (); err = gpgme_data_new_from_file (&in, *argv, 1);
fprintf (stderr, PGM ": error seeking `%s': %s\n", if (err)
*argv, gpg_strerror (err)); {
exit (1); fprintf (stderr, PGM ": error reading `%s': %s\n",
} *argv, gpg_strerror (err));
if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1)) exit (1);
{ }
err = gpg_error_from_syserror (); offset = gpgme_data_seek (in, 0, SEEK_END);
fprintf (stderr, PGM ": error seeking `%s': %s\n", if (offset == (gpgme_off_t)(-1))
*argv, gpg_strerror (err)); {
exit (1); err = gpg_error_from_syserror ();
} fprintf (stderr, PGM ": error seeking `%s': %s\n",
{ *argv, gpg_strerror (err));
char numbuf[50]; exit (1);
char *p; }
if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
{
err = gpg_error_from_syserror ();
fprintf (stderr, PGM ": error seeking `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
{
char numbuf[50];
char *p;
p = numbuf + sizeof numbuf; p = numbuf + sizeof numbuf;
*--p = 0; *--p = 0;
do do
{ {
*--p = '0' + (offset % 10); *--p = '0' + (offset % 10);
offset /= 10; offset /= 10;
}
while (offset);
err = gpgme_data_set_flag (in, "size-hint", p);
if (err)
{
fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
} }
while (offset); }
err = gpgme_data_set_flag (in, "size-hint", p);
if (err)
{
fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
}
err = gpgme_data_new (&out); err = gpgme_data_new (&out);
fail_if_err (err); fail_if_err (err);
@ -318,6 +339,28 @@ main (int argc, char **argv)
err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring, err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring,
flags, in, out); flags, in, out);
result = gpgme_op_encrypt_result (ctx); result = gpgme_op_encrypt_result (ctx);
if (diagnostics)
{
gpgme_data_t diag;
gpgme_error_t diag_err;
gpgme_data_new (&diag);
diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG);
if (diag_err)
{
fprintf (stderr, PGM ": getting diagnostics failed: %s\n",
gpgme_strerror (diag_err));
}
else
{
fputs ("Begin Diagnostics:\n", stdout);
print_data (diag);
fputs ("End Diagnostics.\n", stdout);
}
gpgme_data_release (diag);
}
if (result) if (result)
print_result (result); print_result (result);
if (err) if (err)