core: Support direct signing of file with gpg
* src/gpgme.h.in (GPGME_SIG_MODE_FILE): New signature mode flag. * src/engine-gpg.c (gpg_sign): Separate signature mode from additional flags. Check for incompatible flags. Explicitly set output to stdout if no output file is used. Pass filename instead of fd to gpg when new flag is set. * src/engine-gpgsm.c (gpgsm_sign): Return error if new flag is set. * src/engine-uiserver.c (uiserver_sign): Ditto. * src/sign.c (sign_start): Consider new flag on check for invalid flags. * tests/run-sign.c (show_usage): New options --detach and --direct-file-io. (main): Parse new options. Create a detached signature if --detach is given. Make gpg read the input file itself if --direct-file-io is given. -- With this change the gpgme_op_sign* functions gain the possibility to make gpg read the data to sign directly from a file instead of from an input FD to which it is written by gpgme. GnuPG-bug-id: 6550
This commit is contained in:
parent
0221d7f28a
commit
963ace1f9f
5
NEWS
5
NEWS
@ -1,12 +1,13 @@
|
||||
Noteworthy changes in version 1.23.3 (unrelease)
|
||||
-------------------------------------------------
|
||||
|
||||
* Extended gpgme_op_encrypt* and gpgme_op_encrypt_sign* to allow reading
|
||||
the input data directly from a file. [T6550]
|
||||
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
|
||||
to allow reading the input data directly from a file. [T6550]
|
||||
|
||||
* Interface changes relative to the 1.23.2 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GPGME_ENCRYPT_FILE NEW.
|
||||
GPGME_SIG_MODE_FILE NEW.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.23.2 (2023-11-28)
|
||||
|
@ -6366,6 +6366,16 @@ A signed archive is created from the given files and directories. This
|
||||
feature is currently only supported for the OpenPGP crypto engine and requires
|
||||
GnuPG 2.4.1.
|
||||
|
||||
@item GPGME_SIG_MODE_FILE
|
||||
@since{1.24.0}
|
||||
|
||||
The filename set with @code{gpgme_data_set_file_name} for the data object
|
||||
@var{plain} is passed to gpg, so that gpg reads the plaintext directly from
|
||||
this file instead of from the data object @var{plain}. This flag can be
|
||||
combined with @code{GPGME_SIG_MODE_NORMAL}, @code{GPGME_SIG_MODE_DETACH},
|
||||
and @code{GPGME_SIG_MODE_CLEAR}, but not with @code{GPGME_SIG_MODE_ARCHIVE}.
|
||||
This feature is currently only supported for the OpenPGP crypto engine.
|
||||
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@ -6379,7 +6389,12 @@ if that is not set, by the encoding specified for @var{sig}), the text
|
||||
mode attributes set for the context @var{ctx} and the requested signature
|
||||
mode @var{mode}.
|
||||
|
||||
If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested, then a
|
||||
If the signature mode flag @code{GPGME_SIG_MODE_FILE} is set and a filename
|
||||
has been set with @code{gpgme_data_set_file_name} for the data object
|
||||
@var{plain}, then this filename is passed to gpg, so that gpg reads the
|
||||
plaintext directly from this file instead of from the data object @var{plain}.
|
||||
|
||||
If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested then a
|
||||
signed archive is created from the files and directories given as
|
||||
NUL-separated list in the data object @var{plain}. The paths of the files
|
||||
and directories have to be given as paths relative to the current working
|
||||
|
@ -3615,25 +3615,32 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
{
|
||||
engine_gpg_t gpg = engine;
|
||||
gpgme_error_t err;
|
||||
const char *output = NULL;
|
||||
const char *file_name = NULL;
|
||||
unsigned int mode = flags & (GPGME_SIG_MODE_NORMAL
|
||||
|GPGME_SIG_MODE_DETACH
|
||||
|GPGME_SIG_MODE_CLEAR
|
||||
|GPGME_SIG_MODE_ARCHIVE);
|
||||
|
||||
(void)include_certs;
|
||||
|
||||
if ((flags != GPGME_SIG_MODE_NORMAL) && (flags != GPGME_SIG_MODE_DETACH)
|
||||
&& (flags != GPGME_SIG_MODE_CLEAR) && (flags != GPGME_SIG_MODE_ARCHIVE))
|
||||
if ((mode != GPGME_SIG_MODE_NORMAL) && (mode != GPGME_SIG_MODE_DETACH)
|
||||
&& (mode != GPGME_SIG_MODE_CLEAR) && (mode != GPGME_SIG_MODE_ARCHIVE))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
gpg->flags.use_gpgtar = !!(flags & GPGME_SIG_MODE_ARCHIVE);
|
||||
gpg->flags.use_gpgtar = !!(mode == GPGME_SIG_MODE_ARCHIVE);
|
||||
|
||||
if (gpg->flags.use_gpgtar && !have_usable_gpgtar (gpg))
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
|
||||
if (flags & GPGME_SIG_MODE_CLEAR)
|
||||
if (gpg->flags.use_gpgtar && (flags & GPGME_SIG_MODE_FILE))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (mode == GPGME_SIG_MODE_CLEAR)
|
||||
err = add_arg (gpg, "--clearsign");
|
||||
else
|
||||
{
|
||||
err = add_arg (gpg, "--sign");
|
||||
if (!err && (flags & GPGME_SIG_MODE_DETACH))
|
||||
if (!err && (mode == GPGME_SIG_MODE_DETACH))
|
||||
err = add_arg (gpg, "--detach");
|
||||
if (!err && use_armor)
|
||||
err = add_gpg_arg (gpg, "--armor");
|
||||
@ -3657,20 +3664,24 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_SIG);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
output = gpgme_data_get_file_name (out);
|
||||
if (output)
|
||||
{
|
||||
err = add_arg (gpg, "--output");
|
||||
if (!err)
|
||||
{
|
||||
const char *output = gpgme_data_get_file_name (out);
|
||||
if (output)
|
||||
err = add_arg (gpg, output);
|
||||
else
|
||||
{
|
||||
err = add_arg (gpg, "-");
|
||||
if (!err)
|
||||
err = add_data (gpg, out, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
file_name = gpgme_data_get_file_name (in);
|
||||
/* Tell the gpg object about the data. */
|
||||
if (gpg->flags.use_gpgtar)
|
||||
{
|
||||
const char *file_name = gpgme_data_get_file_name (in);
|
||||
if (!err && file_name)
|
||||
{
|
||||
err = add_arg (gpg, "--directory");
|
||||
@ -3689,9 +3700,17 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
if (!err)
|
||||
err = add_data (gpg, in, 0, 0);
|
||||
}
|
||||
else if (flags & GPGME_SIG_MODE_FILE)
|
||||
{
|
||||
if (!err)
|
||||
err = add_arg (gpg, "--");
|
||||
if (!err && (!file_name || !*file_name))
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
if (!err)
|
||||
err = add_arg (gpg, file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *file_name = gpgme_data_get_file_name (in);
|
||||
if (!err && file_name)
|
||||
err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0);
|
||||
if (!err)
|
||||
@ -3702,9 +3721,6 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
err = add_data (gpg, in, -1, 0);
|
||||
}
|
||||
|
||||
if (!err && !output)
|
||||
err = add_data (gpg, out, 1, 1);
|
||||
|
||||
if (!err)
|
||||
err = start (gpg);
|
||||
|
||||
|
@ -2128,7 +2128,9 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
if (!gpgsm)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
|
||||
if (flags & (GPGME_SIG_MODE_CLEAR
|
||||
| GPGME_SIG_MODE_ARCHIVE
|
||||
| GPGME_SIG_MODE_FILE))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
/* FIXME: This does not work as RESET does not reset it so we can't
|
||||
|
@ -1237,7 +1237,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
else
|
||||
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
|
||||
|
||||
if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
|
||||
if (flags & (GPGME_SIG_MODE_CLEAR
|
||||
| GPGME_SIG_MODE_ARCHIVE
|
||||
| GPGME_SIG_MODE_FILE))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (gpgrt_asprintf (&cmd, "SIGN%s%s", protocol,
|
||||
|
@ -309,7 +309,8 @@ typedef enum
|
||||
GPGME_SIG_MODE_NORMAL = 0,
|
||||
GPGME_SIG_MODE_DETACH = 1,
|
||||
GPGME_SIG_MODE_CLEAR = 2,
|
||||
GPGME_SIG_MODE_ARCHIVE = 4
|
||||
GPGME_SIG_MODE_ARCHIVE = 4,
|
||||
GPGME_SIG_MODE_FILE = 8
|
||||
}
|
||||
gpgme_sig_mode_t;
|
||||
|
||||
|
@ -450,7 +450,8 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
|
||||
|
||||
if (flags & ~(GPGME_SIG_MODE_DETACH
|
||||
|GPGME_SIG_MODE_CLEAR
|
||||
|GPGME_SIG_MODE_ARCHIVE))
|
||||
|GPGME_SIG_MODE_ARCHIVE
|
||||
|GPGME_SIG_MODE_FILE))
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (!plain)
|
||||
|
@ -87,6 +87,8 @@ show_usage (int ex)
|
||||
" --sender MBOX use MBOX as sender address\n"
|
||||
" --include-key-block use this option with gpg\n"
|
||||
" --clear create a clear text signature\n"
|
||||
" --detach create a detached signature\n"
|
||||
" --direct-file-io pass FILE instead of stream with content of FILE to backend\n"
|
||||
" --archive create a signed archive with the given file or directory\n"
|
||||
" --directory DIR switch to directory DIR before creating the archive\n"
|
||||
" --output FILE write output to FILE instead of stdout\n"
|
||||
@ -113,6 +115,7 @@ main (int argc, char **argv)
|
||||
int use_loopback = 0;
|
||||
int include_key_block = 0;
|
||||
int diagnostics = 0;
|
||||
int direct_file_io = 0;
|
||||
const char *sender = NULL;
|
||||
const char *s;
|
||||
|
||||
@ -185,6 +188,16 @@ main (int argc, char **argv)
|
||||
sigmode = GPGME_SIG_MODE_CLEAR;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--detach"))
|
||||
{
|
||||
sigmode = GPGME_SIG_MODE_DETACH;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--direct-file-io"))
|
||||
{
|
||||
direct_file_io = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--archive"))
|
||||
{
|
||||
sigmode = GPGME_SIG_MODE_ARCHIVE;
|
||||
@ -269,7 +282,15 @@ main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (sigmode == GPGME_SIG_MODE_ARCHIVE)
|
||||
if (direct_file_io)
|
||||
{
|
||||
sigmode |= GPGME_SIG_MODE_FILE;
|
||||
err = gpgme_data_new (&in);
|
||||
fail_if_err (err);
|
||||
err = gpgme_data_set_file_name (in, *argv);
|
||||
fail_if_err (err);
|
||||
}
|
||||
else if (sigmode == GPGME_SIG_MODE_ARCHIVE)
|
||||
{
|
||||
const char *path = *argv;
|
||||
err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
|
||||
|
Loading…
Reference in New Issue
Block a user