core: Fix expiration time handling when creating keys.

* NEWS: Update.
* doc/gpgme.texi (gpgme_op_createkey): Clarify the meaning of the
'expire' parameter.
(GPGME_CREATE_NOEXPIRE): Document new flag.
(gpgme_op_createsubkey): Clarify the meaning of the 'expire'
parameter.
* src/engine-gpg.c (gpg_add_algo_usage_expire): Fix handling of the
expiration time.
* src/gpgme.h.in (GPGME_CREATE_NOEXPIRE): New macro.
--

Previously, the documentation stated that the expiration time was an
absolute timestamp.  However, this value was passed using the
'seconds=N' syntax to GnuPG which specifies the expiration time in
seconds relative to the creation time.  Fix the documentation.

Furthermore, the documentation stated that using 0 results in keys
that do not expire.  This was communicated to GnuPG by using the
implicit default.  However, as of GnuPG 2.1.17, the default was
changed to create keys that expire within a reasonable timespan.

Fix this discrepancy by aligning the behavior with recent GnuPG
versions: 0 means use a reasonable default, and introduce a flag that
can be used to create keys that do not expire.  Communicate this
explicitly to GnuPG.

Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2017-02-15 16:17:13 +01:00
parent 27544d0a74
commit de708e5934
No known key found for this signature in database
GPG Key ID: DD1A52F9DA8C9020
4 changed files with 36 additions and 19 deletions

3
NEWS
View File

@ -7,6 +7,9 @@ Noteworthy changes in version 1.8.1 (unreleased)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_strerror_r CHANGED: Use gpgme_error_t (compatible type). gpgme_strerror_r CHANGED: Use gpgme_error_t (compatible type).
gpgme_data_set_flag CHANGED: Return gpgme_error_t (compatible type). gpgme_data_set_flag CHANGED: Return gpgme_error_t (compatible type).
gpgme_op_createkey CHANGED: Meaning of 'expire' parameter.
gpgme_op_createsubkey CHANGED: Meaning of 'expire' parameter.
GPGME_CREATE_NOEXPIRE NEW.
cpp: Context::revUid(const Key&, const char*) NEW. cpp: Context::revUid(const Key&, const char*) NEW.
cpp: Context::startRevUid(const Key&, const char*) NEW. cpp: Context::startRevUid(const Key&, const char*) NEW.
cpp: Context::addUid(const Key&, const char*) NEW. cpp: Context::addUid(const Key&, const char*) NEW.

View File

@ -3612,13 +3612,14 @@ primary key plus a secondary key (subkey).
@var{reserved} must be set to zero. @var{reserved} must be set to zero.
@var{expires} can be set to the number of seconds since Epoch of the @var{expires} specifies the expiration time in seconds. If you supply
desired expiration date in UTC for the new key. Using 0 does not 0, a reasonable expiration time is chosen. Use the flag
set an expiration date. Note that this parameter takes an unsigned long @code{GPGME_CREATE_NOEXPIRE} to create keys that do not expire. Note
value and not a @code{time_t} to avoid problems on systems which use a that this parameter takes an unsigned long value and not a
signed 32 bit @code{time_t}. Note further that the OpenPGP protocol @code{time_t} to avoid problems on systems which use a signed 32 bit
uses 32 bit values for timestamps and thus can only encode dates up to @code{time_t}. Note further that the OpenPGP protocol uses 32 bit
the year 2106. values for timestamps and thus can only encode dates up to the year
2106.
@var{extrakey} is currently not used and must be set to @code{NULL}. @var{extrakey} is currently not used and must be set to @code{NULL}.
A future version of GPGME may use this parameter to create X.509 keys. A future version of GPGME may use this parameter to create X.509 keys.
@ -3660,6 +3661,9 @@ The engine does not allow the creation of a key with a user ID
already existing in the local key database. This flag can be used to already existing in the local key database. This flag can be used to
override this check. override this check.
@item GPGME_CREATE_NOEXPIRE
Request generation of keys that do not expire.
@end table @end table
After the operation completed successfully, information about the After the operation completed successfully, information about the
@ -3719,13 +3723,14 @@ able to already handle such future algorithms.
@var{reserved} must be set to zero. @var{reserved} must be set to zero.
@var{expires} can be set to the number of seconds since Epoch of the @var{expires} specifies the expiration time in seconds. If you supply
desired expiration date in UTC for the new subkey. Using 0 does not 0, a reasonable expiration time is chosen. Use the flag
set an expiration date. Note that this parameter takes an unsigned long @code{GPGME_CREATE_NOEXPIRE} to create keys that do not expire. Note
value and not a @code{time_t} to avoid problems on systems which use a that this parameter takes an unsigned long value and not a
signed 32 bit @code{time_t}. Note further that the OpenPGP protocol @code{time_t} to avoid problems on systems which use a signed 32 bit
uses 32 bit values for timestamps and thus can only encode dates up to @code{time_t}. Note further that the OpenPGP protocol uses 32 bit
the year 2106. values for timestamps and thus can only encode dates up to the year
2106.
@var{flags} takes the same values as described above for @var{flags} takes the same values as described above for
@code{gpgme_op_createkey}. @code{gpgme_op_createkey}.

View File

@ -2076,7 +2076,8 @@ gpg_add_algo_usage_expire (engine_gpg_t gpg,
/* This condition is only required to allow the use of gpg < 2.1.16 */ /* This condition is only required to allow the use of gpg < 2.1.16 */
if (algo if (algo
|| (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
| GPGME_CREATE_CERT | GPGME_CREATE_AUTH)) | GPGME_CREATE_CERT | GPGME_CREATE_AUTH
| GPGME_CREATE_NOEXPIRE))
|| expires) || expires)
{ {
err = add_arg (gpg, algo? algo : "default"); err = add_arg (gpg, algo? algo : "default");
@ -2090,11 +2091,18 @@ gpg_add_algo_usage_expire (engine_gpg_t gpg,
(flags & GPGME_CREATE_AUTH)? " auth":""); (flags & GPGME_CREATE_AUTH)? " auth":"");
err = add_arg (gpg, *tmpbuf? tmpbuf : "default"); err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
} }
if (!err && expires) if (!err)
{ {
char tmpbuf[8+20]; if (flags & GPGME_CREATE_NOEXPIRE)
snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires); err = add_arg (gpg, "never");
err = add_arg (gpg, tmpbuf); else if (expires == 0)
err = add_arg (gpg, "-");
else
{
char tmpbuf[8+20];
snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
err = add_arg (gpg, tmpbuf);
}
} }
} }
else else

View File

@ -1637,6 +1637,7 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx,
#define GPGME_CREATE_WANTPUB (1 << 10) /* Return the public key. */ #define GPGME_CREATE_WANTPUB (1 << 10) /* Return the public key. */
#define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */ #define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */
#define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */ #define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */
#define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */
/* An object to return result from a key generation. /* An object to return result from a key generation.
* This structure shall be considered read-only and an application * This structure shall be considered read-only and an application