core: New function gpgme_op_setexpire.
* src/gpgme.h.in (gpgme_op_setexpire_start, gpgme_op_setexpire): New. * src/libgpgme.vers, src/gpgme.def: Add new functions. * src/genkey.c (setexpire): New. (gpgme_op_setexpire_start, gpgme_op_setexpire): New. * src/engine.h, src/engine.c: (_gpgme_engine_op_setexpire): New. * src/engine-backend.h (engine_ops): Add 'setexpire' and adjust all engine initializers. * src/engine-gpg.c (gpg_setexpire): New. (_gpgme_engine_ops_gpg): Set setexpire to gpg_setexpire. * doc/gpgme.texi: Document new functions. * tests/run-genkey.c: Add option --setexpire. -- This extends GPGME to support the --quick-set-expire command added by GnuPG 2.1.22. This allows changing subkeys expiry date without going through the editinteractor interface. Co-authored-by: Andre Heinecke <aheinecke@gnupg.org> GnuPG-bug-id: 4999
This commit is contained in:
parent
81db412245
commit
db82e99a8a
9
NEWS
9
NEWS
@ -1,6 +1,15 @@
|
||||
Noteworthy changes in version 1.14.1 (unreleased)
|
||||
-------------------------------------------------
|
||||
|
||||
* New function gpgme_op_setexpire to make changing the expiration
|
||||
easier (requires GnuPG 2.1.22). [#4999]
|
||||
|
||||
* Interface changes relative to the 1.14.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_op_setexpire_start NEW.
|
||||
gpgme_op_setexpire NEW.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.14.0 (2020-07-16)
|
||||
-------------------------------------------------
|
||||
|
||||
|
@ -4016,6 +4016,81 @@ The function @code{gpgme_key_unref} releases a reference for the key
|
||||
and all resources associated to it will be released.
|
||||
@end deftypefun
|
||||
|
||||
@c
|
||||
@c gpgme_op_setexpire
|
||||
@c
|
||||
@deftypefun gpgme_error_t gpgme_op_setexpire @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{key}}, @
|
||||
@w{unsigned long @var{expires}}, @
|
||||
@w{const char *@var{subfprs}}, @
|
||||
@w{unsigned int @var{reserved}});
|
||||
|
||||
@since{1.14.1}
|
||||
|
||||
The function @code{gpgme_op_setexpire} sets the expiration time of
|
||||
the key @var{key} or of the specified subkeys.
|
||||
This function requires at least version 2.1.22 of GnuPG.
|
||||
|
||||
@var{key} specifies the key to operate on.
|
||||
|
||||
@var{expires} specifies the expiration time in seconds from now.
|
||||
To be similar to other usages where expiration times are provided
|
||||
in unsigned long this is similar to the key creation date
|
||||
and so it is in seconds from NOW.
|
||||
|
||||
The common case is to use 0 to not set an expiration time.
|
||||
Note that this parameter takes an unsigned long value and not
|
||||
a @code{time_t} to avoid problems on systems which use a signed
|
||||
32 bit @code{time_t}. Note further that the OpenPGP protocol
|
||||
uses 32 bit values for timestamps and thus can
|
||||
only encode dates up to the year 2106.
|
||||
|
||||
@var{subfprs} selects the subkey(s) for which the expiration time
|
||||
should be set. If @var{subfprs} is set to @code{NULL}, then the
|
||||
expiration time of the primary key is set. If @var{subfprs} is
|
||||
an asterisk (@code{*}), then the expiration times of all non-revoked
|
||||
and not yet expired subkeys are set. To select more than one subkey
|
||||
put all subkey fingerprints into one string separated by linefeeds
|
||||
characters (@code{\n}).
|
||||
|
||||
@var{reserved} is reserved for later use and must be @code{0}.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_setexpire_start @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{key}}, @
|
||||
@w{unsigned long @var{expires}}, @
|
||||
@w{const char *@var{subfprs}}, @
|
||||
@w{unsigned int @var{flags}});
|
||||
|
||||
@since{1.14.1}
|
||||
|
||||
The function @code{gpgme_op_setexpire_start} initiates a
|
||||
@code{gpgme_op_setexpire} operation; see there for details. It must
|
||||
be completed by calling @code{gpgme_wait} on the context.
|
||||
@xref{Waiting For Completion}.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@deftypefun gpgme_error_t gpgme_op_revuid_start @
|
||||
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||
@w{gpgme_key_t @var{key}}, @
|
||||
@w{const char *@var{userid}}, @
|
||||
@w{unsigned int @var{flags}});
|
||||
|
||||
@since{1.14.1}
|
||||
|
||||
The function @code{gpgme_op_setexpire_start} initiates a
|
||||
@code{gpgme_op_setexpire} operation; see there for details. It must
|
||||
be completed by calling @code{gpgme_wait} on the context.
|
||||
@xref{Waiting For Completion}.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Generating Keys
|
||||
@subsection Generating Keys
|
||||
|
@ -828,6 +828,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
|
||||
NULL, /* sign */
|
||||
NULL, /* verify */
|
||||
NULL, /* getauditlog */
|
||||
NULL, /* setexpire */
|
||||
llass_transact, /* opassuan_transact */
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
@ -120,6 +120,9 @@ struct engine_ops
|
||||
gpgme_ctx_t ctx);
|
||||
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
|
||||
unsigned int flags);
|
||||
gpgme_error_t (*setexpire) (void *engine, gpgme_key_t key,
|
||||
unsigned long expires, const char *subfprs,
|
||||
unsigned int reserved);
|
||||
gpgme_error_t (*opassuan_transact) (void *engine,
|
||||
const char *command,
|
||||
gpgme_assuan_data_cb_t data_cb,
|
||||
|
@ -808,6 +808,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
|
||||
NULL, /* sign */
|
||||
NULL, /* verify */
|
||||
NULL, /* getauditlog */
|
||||
NULL, /* setexpire */
|
||||
g13_transact,
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
@ -3426,6 +3426,59 @@ gpg_getauditlog (void *engine, gpgme_data_t output, unsigned int flags)
|
||||
#undef MYBUFLEN
|
||||
}
|
||||
|
||||
static gpgme_error_t
|
||||
gpg_setexpire (void *engine, gpgme_key_t key, unsigned long expires,
|
||||
const char *subfprs, unsigned int reserved)
|
||||
{
|
||||
engine_gpg_t gpg = engine;
|
||||
gpgme_error_t err;
|
||||
const char *s;
|
||||
|
||||
if (reserved)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (!key || !key->fpr)
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
if (!have_gpg_version (gpg, "2.1.22"))
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
|
||||
err = add_arg (gpg, "--quick-set-expire");
|
||||
|
||||
if (!err)
|
||||
err = add_arg (gpg, "--");
|
||||
|
||||
if (!err)
|
||||
err = add_arg (gpg, key->fpr);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
char tmpbuf[8+20];
|
||||
snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
|
||||
err = add_arg (gpg, tmpbuf);
|
||||
}
|
||||
|
||||
if (!err && subfprs)
|
||||
{
|
||||
for (; !err && (s = strchr (subfprs, '\n')); subfprs = s + 1)
|
||||
{
|
||||
if ((s - subfprs))
|
||||
{
|
||||
err = add_arg_len (gpg, NULL, subfprs, s - subfprs);
|
||||
}
|
||||
}
|
||||
if (!err && *subfprs)
|
||||
{
|
||||
err = add_arg (gpg, subfprs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
err = start (gpg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct engine_ops _gpgme_engine_ops_gpg =
|
||||
@ -3464,6 +3517,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
||||
gpg_sign,
|
||||
gpg_verify,
|
||||
gpg_getauditlog,
|
||||
gpg_setexpire,
|
||||
NULL, /* opassuan_transact */
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
@ -1306,6 +1306,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
||||
NULL, /* sign */
|
||||
NULL, /* verify */
|
||||
NULL, /* getauditlog */
|
||||
NULL, /* setexpire */
|
||||
NULL, /* opassuan_transact */
|
||||
gpgconf_conf_load,
|
||||
gpgconf_conf_save,
|
||||
|
@ -2326,6 +2326,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
||||
gpgsm_sign,
|
||||
gpgsm_verify,
|
||||
gpgsm_getauditlog,
|
||||
NULL, /* setexpire */
|
||||
NULL, /* opassuan_transact */
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
@ -468,6 +468,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
|
||||
NULL, /* sign */
|
||||
NULL, /* verify */
|
||||
NULL, /* getauditlog */
|
||||
NULL, /* setexpire */
|
||||
NULL, /* opassuan_transact */
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
@ -1439,6 +1439,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
|
||||
uiserver_sign,
|
||||
uiserver_verify,
|
||||
NULL, /* getauditlog */
|
||||
NULL, /* setexpire */
|
||||
NULL, /* opassuan_transact */
|
||||
NULL, /* conf_load */
|
||||
NULL, /* conf_save */
|
||||
|
14
src/engine.c
14
src/engine.c
@ -1128,3 +1128,17 @@ _gpgme_engine_op_spawn (engine_t engine,
|
||||
return (*engine->ops->opspawn) (engine->engine, file, argv,
|
||||
datain, dataout, dataerr, flags);
|
||||
}
|
||||
|
||||
gpgme_error_t
|
||||
_gpgme_engine_op_setexpire (engine_t engine, gpgme_key_t key,
|
||||
unsigned long expires, const char *subfprs,
|
||||
unsigned int reserved)
|
||||
{
|
||||
if (!engine)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (!engine->ops->setexpire)
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
return (*engine->ops->setexpire) (engine->engine, key, expires, subfprs, reserved);
|
||||
}
|
||||
|
@ -210,6 +210,11 @@ gpgme_error_t _gpgme_engine_op_spawn (engine_t engine,
|
||||
gpgme_data_t dataout,
|
||||
gpgme_data_t dataerr,
|
||||
unsigned int flags);
|
||||
gpgme_error_t _gpgme_engine_op_setexpire (engine_t engine,
|
||||
gpgme_key_t key,
|
||||
unsigned long expires,
|
||||
const char *subfprs,
|
||||
unsigned int reserved);
|
||||
|
||||
/* The available engine option flags. */
|
||||
#define GPGME_ENGINE_FLAG_OFFLINE 1
|
||||
|
52
src/genkey.c
52
src/genkey.c
@ -663,3 +663,55 @@ gpgme_op_set_uid_flag (gpgme_ctx_t ctx,
|
||||
{
|
||||
return set_uid_flag (ctx, 1, key, userid, name, value);
|
||||
}
|
||||
|
||||
/* Set the expiration time of a key or its subkeys. See
|
||||
--quick-set-expire in the gnupg documentation. */
|
||||
static gpg_error_t
|
||||
setexpire (gpgme_ctx_t ctx, int synchronous,
|
||||
gpgme_key_t key,
|
||||
unsigned long expires,
|
||||
const char *subfprs,
|
||||
unsigned int reserved)
|
||||
{
|
||||
gpgme_error_t err = 0;
|
||||
|
||||
TRACE_BEG (DEBUG_CTX, "gpgme_op_setexpire", ctx,
|
||||
"%d key=%p expiry: %lu subkeys: '%s' reserved=0x%x",
|
||||
synchronous, key, expires, subfprs, reserved);
|
||||
|
||||
if (!ctx || !key)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
|
||||
|
||||
err = _gpgme_op_reset (ctx, synchronous);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = _gpgme_engine_op_setexpire (ctx->engine, key, expires, subfprs, reserved);
|
||||
|
||||
if (synchronous && !err)
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
||||
/* See setexpire. */
|
||||
gpgme_error_t
|
||||
gpgme_op_setexpire_start (gpgme_ctx_t ctx,
|
||||
gpgme_key_t key,
|
||||
unsigned long expires,
|
||||
const char *subfprs,
|
||||
unsigned int reserved)
|
||||
{
|
||||
return setexpire (ctx, 0, key, expires, subfprs, reserved);
|
||||
}
|
||||
|
||||
|
||||
/* See setexpire. This is the synchronous variant. */
|
||||
gpgme_error_t
|
||||
gpgme_op_setexpire (gpgme_ctx_t ctx,
|
||||
gpgme_key_t key,
|
||||
unsigned long expires,
|
||||
const char *subfprs,
|
||||
unsigned int reserved)
|
||||
{
|
||||
return setexpire (ctx, 1, key, expires, subfprs, reserved);
|
||||
}
|
||||
|
@ -274,5 +274,8 @@ EXPORTS
|
||||
|
||||
gpgme_data_new_from_estream @204
|
||||
|
||||
gpgme_op_setexpire @205
|
||||
gpgme_op_setexpire_start @206
|
||||
|
||||
; END
|
||||
|
||||
|
@ -1868,6 +1868,13 @@ gpgme_error_t gpgme_op_set_uid_flag (gpgme_ctx_t ctx,
|
||||
gpgme_key_t key, const char *userid,
|
||||
const char *name, const char *value);
|
||||
|
||||
/* Change the expiry of a key. */
|
||||
gpgme_error_t gpgme_op_setexpire_start (gpgme_ctx_t ctx,
|
||||
gpgme_key_t key, unsigned long expires,
|
||||
const char *subfprs, unsigned int reserved);
|
||||
gpgme_error_t gpgme_op_setexpire (gpgme_ctx_t ctx,
|
||||
gpgme_key_t key, unsigned long expires,
|
||||
const char *subfprs, unsigned int reserved);
|
||||
|
||||
/* Retrieve a pointer to the result of a genkey, createkey, or
|
||||
* createsubkey operation. */
|
||||
|
@ -273,6 +273,9 @@ GPGME_1.0 {
|
||||
gpgme_err_code_from_syserror;
|
||||
gpgme_err_set_errno;
|
||||
|
||||
gpgme_op_setexpire;
|
||||
gpgme_op_setexpire_start;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
||||
|
@ -205,12 +205,15 @@ show_usage (int ex)
|
||||
" for addkey: FPR [ALGO [USAGE [EXPIRESECONDS]]]\n"
|
||||
" for adduid: FPR USERID\n"
|
||||
" for revuid: FPR USERID\n"
|
||||
" for setexpire: FPR EXPIRE [SUBFPRS]\n"
|
||||
" for set-primary: FPR USERID\n"
|
||||
"Options:\n"
|
||||
" --addkey add a subkey to the key with FPR\n"
|
||||
" --adduid add a user id to the key with FPR\n"
|
||||
" --revuid revoke a user id from the key with FPR\n"
|
||||
" --set-primary set the primary key flag on USERID\n"
|
||||
" --setexpire set the expiration time of the key FPR\n"
|
||||
" or of its subkeys SUBFPRS\n"
|
||||
" --verbose run in verbose mode\n"
|
||||
" --status print status lines from the backend\n"
|
||||
" --progress print progress info\n"
|
||||
@ -238,12 +241,17 @@ main (int argc, char **argv)
|
||||
int adduid = 0;
|
||||
int revuid = 0;
|
||||
int setpri = 0;
|
||||
int setexpire = 0;
|
||||
const char *userid;
|
||||
const char *algo = NULL;
|
||||
const char *newuserid = NULL;
|
||||
const char *subfprs = NULL;
|
||||
unsigned int flags = 0;
|
||||
unsigned long expire = 0;
|
||||
gpgme_genkey_result_t result;
|
||||
int i;
|
||||
size_t n;
|
||||
char *subfprs_buffer = NULL;
|
||||
|
||||
if (argc)
|
||||
{ argc--; argv++; }
|
||||
@ -264,6 +272,7 @@ main (int argc, char **argv)
|
||||
adduid = 0;
|
||||
revuid = 0;
|
||||
setpri = 0;
|
||||
setexpire = 0;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--adduid"))
|
||||
@ -272,6 +281,7 @@ main (int argc, char **argv)
|
||||
adduid = 1;
|
||||
revuid = 0;
|
||||
setpri = 0;
|
||||
setexpire = 0;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--revuid"))
|
||||
@ -280,6 +290,7 @@ main (int argc, char **argv)
|
||||
adduid = 0;
|
||||
revuid = 1;
|
||||
setpri = 0;
|
||||
setexpire = 0;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--set-primary"))
|
||||
@ -288,6 +299,16 @@ main (int argc, char **argv)
|
||||
adduid = 0;
|
||||
revuid = 0;
|
||||
setpri = 1;
|
||||
setexpire = 0;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--setexpire"))
|
||||
{
|
||||
addkey = 0;
|
||||
adduid = 0;
|
||||
revuid = 0;
|
||||
setpri = 0;
|
||||
setexpire = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--verbose"))
|
||||
@ -341,6 +362,48 @@ main (int argc, char **argv)
|
||||
userid = argv[0];
|
||||
newuserid = argv[1];
|
||||
}
|
||||
else if (setexpire)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
show_usage (1);
|
||||
}
|
||||
userid = argv[0];
|
||||
argc--; argv++;
|
||||
expire = parse_expire_string (argv[0]);
|
||||
argc--; argv++;
|
||||
if (argc > 1)
|
||||
{
|
||||
/* Several subkey fprs given */
|
||||
for (i=0, n = 0; i < argc; i++)
|
||||
n += strlen (argv[1]) + 1;
|
||||
n++;
|
||||
subfprs_buffer = malloc (n);
|
||||
if (!subfprs_buffer)
|
||||
{
|
||||
fprintf (stderr, PGM ": malloc failed: %s\n",
|
||||
gpg_strerror (gpg_error_from_syserror ()));
|
||||
exit (1);
|
||||
}
|
||||
*subfprs_buffer = 0;
|
||||
for (i=0; i < argc; i++)
|
||||
{
|
||||
strcat (subfprs_buffer, argv[i]);
|
||||
strcat (subfprs_buffer, "\n");
|
||||
}
|
||||
subfprs = subfprs_buffer;
|
||||
}
|
||||
else if (argc)
|
||||
{
|
||||
/* One subkey fpr (or '*') given */
|
||||
subfprs = *argv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No subkey fpr given. */
|
||||
subfprs = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!argc || argc > 4)
|
||||
@ -373,7 +436,8 @@ main (int argc, char **argv)
|
||||
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
|
||||
}
|
||||
|
||||
if (addkey || adduid || revuid || setpri)
|
||||
|
||||
if (addkey || adduid || revuid || setpri || setexpire)
|
||||
{
|
||||
gpgme_key_t akey;
|
||||
|
||||
@ -425,6 +489,17 @@ main (int argc, char **argv)
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
else if (setexpire)
|
||||
{
|
||||
err = gpgme_op_setexpire (ctx, akey, expire, subfprs, 0);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": gpgme_op_setexpire failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
gpgme_key_unref (akey);
|
||||
}
|
||||
else
|
||||
@ -438,7 +513,7 @@ main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (!setpri)
|
||||
if (!setpri && !setexpire)
|
||||
{
|
||||
result = gpgme_op_genkey_result (ctx);
|
||||
if (!result)
|
||||
|
Loading…
Reference in New Issue
Block a user