core: New function gpgme_op_createsubkey.
* src/genkey.c (createsubkey_start): New. (gpgme_op_createsubkey_start, gpgme_op_createsubkey): New. * src/gpgme.def, src/libgpgme.vers: Add them. * src/engine-gpg.c (gpg_createkey): Factor some code out to ... (gpg_add_algo_usage_expire): new. (gpg_addkey): Implement. * tests/run-genkey.c: Add option --addkey. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
51f9acbca9
commit
cc353701b0
2
NEWS
2
NEWS
@ -17,6 +17,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
|
||||
gpgme_data_set_flag NEW.
|
||||
gpgme_op_createkey NEW.
|
||||
gpgme_op_createkey_start NEW.
|
||||
gpgme_op_createsubkey NEW.
|
||||
gpgme_op_createsubkey_start NEW.
|
||||
gpgme_genkey_result_t EXTENDED: New fields pubkey and seckey.
|
||||
gpgme_signature_t EXTENDED: New field key.
|
||||
gpgme_key_t EXTENDED: New field fpr.
|
||||
|
@ -3792,7 +3792,7 @@ The function @code{gpgme_op_genkey} generates a new key pair in the
|
||||
context @var{ctx}. The meaning of @var{public} and @var{secret}
|
||||
depends on the crypto backend.
|
||||
|
||||
GnuPG does not support @var{public} and @var{secret}, they should be
|
||||
GPG does not support @var{public} and @var{secret}, they should be
|
||||
@code{NULL}. GnuPG will generate a key pair and add it to the
|
||||
standard key ring. The fingerprint of the generated key is available
|
||||
with @code{gpgme_op_genkey_result}.
|
||||
|
@ -1969,6 +1969,47 @@ gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Helper to add algo, usage, and expire to the list of args. */
|
||||
static gpgme_error_t
|
||||
gpg_add_algo_usage_expire (engine_gpg_t gpg,
|
||||
const char *algo,
|
||||
unsigned long expires,
|
||||
unsigned int flags)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
/* This condition is only required to allow the use of gpg < 2.1.16 */
|
||||
if (algo
|
||||
|| (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
|
||||
| GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
|
||||
|| expires)
|
||||
{
|
||||
err = add_arg (gpg, algo? algo : "default");
|
||||
if (!err)
|
||||
{
|
||||
char tmpbuf[5*4+1];
|
||||
snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
|
||||
(flags & GPGME_CREATE_SIGN)? " sign":"",
|
||||
(flags & GPGME_CREATE_ENCR)? " encr":"",
|
||||
(flags & GPGME_CREATE_CERT)? " cert":"",
|
||||
(flags & GPGME_CREATE_AUTH)? " auth":"");
|
||||
err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
|
||||
}
|
||||
if (!err && expires)
|
||||
{
|
||||
char tmpbuf[8+20];
|
||||
snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
|
||||
err = add_arg (gpg, tmpbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
gpg_createkey_from_param (engine_gpg_t gpg,
|
||||
gpgme_data_t help_data, int use_armor)
|
||||
@ -2026,32 +2067,8 @@ gpg_createkey (engine_gpg_t gpg,
|
||||
if (!err)
|
||||
err = add_arg (gpg, userid);
|
||||
|
||||
/* This condition is only required to allow the use of gpg < 2.1.16 */
|
||||
if (algo
|
||||
|| (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
|
||||
| GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
|
||||
|| expires)
|
||||
{
|
||||
|
||||
if (!err)
|
||||
err = add_arg (gpg, algo? algo : "default");
|
||||
if (!err)
|
||||
{
|
||||
char tmpbuf[5*4+1];
|
||||
snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
|
||||
(flags & GPGME_CREATE_SIGN)? " sign":"",
|
||||
(flags & GPGME_CREATE_ENCR)? " encr":"",
|
||||
(flags & GPGME_CREATE_CERT)? " cert":"",
|
||||
(flags & GPGME_CREATE_AUTH)? " auth":"");
|
||||
err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
|
||||
}
|
||||
if (!err && expires)
|
||||
{
|
||||
char tmpbuf[8+20];
|
||||
snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
|
||||
err = add_arg (gpg, tmpbuf);
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
|
||||
|
||||
if (!err)
|
||||
err = start (gpg);
|
||||
@ -2067,7 +2084,31 @@ gpg_addkey (engine_gpg_t gpg,
|
||||
unsigned int flags,
|
||||
int use_armor)
|
||||
{
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
gpgme_error_t err;
|
||||
|
||||
if (!key || !key->fpr)
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
err = add_arg (gpg, "--quick-addkey");
|
||||
if (!err && use_armor)
|
||||
err = add_arg (gpg, "--armor");
|
||||
if (!err && (flags & GPGME_CREATE_NOPASSWD))
|
||||
{
|
||||
err = add_arg (gpg, "--passphrase");
|
||||
if (!err)
|
||||
err = add_arg (gpg, "");
|
||||
}
|
||||
if (!err)
|
||||
err = add_arg (gpg, "--");
|
||||
if (!err)
|
||||
err = add_arg (gpg, key->fpr);
|
||||
|
||||
if (!err)
|
||||
err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
|
||||
|
||||
if (!err)
|
||||
err = start (gpg);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
85
src/genkey.c
85
src/genkey.c
@ -387,3 +387,88 @@ gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
createsubkey_start (gpgme_ctx_t ctx, int synchronous,
|
||||
gpgme_key_t key,
|
||||
const char *algo,
|
||||
unsigned long reserved, unsigned long expires,
|
||||
unsigned int flags)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
void *hook;
|
||||
op_data_t opd;
|
||||
|
||||
if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
|
||||
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
|
||||
|
||||
err = _gpgme_op_reset (ctx, synchronous);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (reserved || !key)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
|
||||
sizeof (*opd), release_op_data);
|
||||
opd = hook;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
|
||||
|
||||
if (ctx->passphrase_cb)
|
||||
{
|
||||
err = _gpgme_engine_set_command_handler
|
||||
(ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return _gpgme_engine_op_genkey (ctx->engine,
|
||||
NULL, algo, reserved, expires,
|
||||
key, flags,
|
||||
NULL, ctx->use_armor, NULL, NULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Add a subkey to an existing KEY. */
|
||||
gpgme_error_t
|
||||
gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
|
||||
unsigned long reserved, unsigned long expires,
|
||||
unsigned int flags)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey_start", ctx,
|
||||
"key=%p, algo='%s' flags=0x%x", key, algo, flags);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
||||
|
||||
gpgme_error_t
|
||||
gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
|
||||
unsigned long reserved, unsigned long expires,
|
||||
unsigned int flags)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
|
||||
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey", ctx,
|
||||
"key=%p, algo='%s' flags=0x%x", key, algo, flags);
|
||||
|
||||
if (!ctx)
|
||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||
|
||||
err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags);
|
||||
if (!err)
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return TRACE_ERR (err);
|
||||
}
|
||||
|
@ -231,6 +231,8 @@ EXPORTS
|
||||
|
||||
gpgme_op_createkey_start @172
|
||||
gpgme_op_createkey @173
|
||||
gpgme_op_createsubkey_start @174
|
||||
gpgme_op_createsubkey @175
|
||||
|
||||
; END
|
||||
|
||||
|
@ -105,6 +105,8 @@ GPGME_1.1 {
|
||||
|
||||
gpgme_op_createkey_start;
|
||||
gpgme_op_createkey;
|
||||
gpgme_op_createsubkey_start;
|
||||
gpgme_op_createsubkey;
|
||||
};
|
||||
|
||||
|
||||
|
@ -201,6 +201,7 @@ show_usage (int ex)
|
||||
{
|
||||
fputs ("usage: " PGM " [options] USERID [ALGO [USAGE [EXPIRESECONDS]]]\n\n"
|
||||
"Options:\n"
|
||||
" --addkey add a subkey to the key with USERID\n"
|
||||
" --verbose run in verbose mode\n"
|
||||
" --status print status lines from the backend\n"
|
||||
" --progress print progress info\n"
|
||||
@ -224,6 +225,7 @@ main (int argc, char **argv)
|
||||
int print_status = 0;
|
||||
int print_progress = 0;
|
||||
int use_loopback = 0;
|
||||
int addkey = 0;
|
||||
const char *userid;
|
||||
const char *algo = NULL;
|
||||
unsigned int flags = 0;
|
||||
@ -243,6 +245,11 @@ main (int argc, char **argv)
|
||||
}
|
||||
else if (!strcmp (*argv, "--help"))
|
||||
show_usage (0);
|
||||
else if (!strcmp (*argv, "--addkey"))
|
||||
{
|
||||
addkey = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (!strcmp (*argv, "--verbose"))
|
||||
{
|
||||
verbose = 1;
|
||||
@ -316,12 +323,36 @@ main (int argc, char **argv)
|
||||
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
|
||||
}
|
||||
|
||||
err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags);
|
||||
if (err)
|
||||
if (addkey)
|
||||
{
|
||||
fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
exit (1);
|
||||
gpgme_key_t akey;
|
||||
|
||||
err = gpgme_get_key (ctx, userid, &akey, 1);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": error getting secret key for '%s': %s\n",
|
||||
userid, gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
gpgme_key_unref (akey);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
result = gpgme_op_genkey_result (ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user