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_data_set_flag NEW.
|
||||||
gpgme_op_createkey NEW.
|
gpgme_op_createkey NEW.
|
||||||
gpgme_op_createkey_start 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_genkey_result_t EXTENDED: New fields pubkey and seckey.
|
||||||
gpgme_signature_t EXTENDED: New field key.
|
gpgme_signature_t EXTENDED: New field key.
|
||||||
gpgme_key_t EXTENDED: New field fpr.
|
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}
|
context @var{ctx}. The meaning of @var{public} and @var{secret}
|
||||||
depends on the crypto backend.
|
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
|
@code{NULL}. GnuPG will generate a key pair and add it to the
|
||||||
standard key ring. The fingerprint of the generated key is available
|
standard key ring. The fingerprint of the generated key is available
|
||||||
with @code{gpgme_op_genkey_result}.
|
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
|
static gpgme_error_t
|
||||||
gpg_createkey_from_param (engine_gpg_t gpg,
|
gpg_createkey_from_param (engine_gpg_t gpg,
|
||||||
gpgme_data_t help_data, int use_armor)
|
gpgme_data_t help_data, int use_armor)
|
||||||
@ -2026,32 +2067,8 @@ gpg_createkey (engine_gpg_t gpg,
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = add_arg (gpg, userid);
|
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)
|
if (!err)
|
||||||
err = add_arg (gpg, algo? algo : "default");
|
err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
|
||||||
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)
|
if (!err)
|
||||||
err = start (gpg);
|
err = start (gpg);
|
||||||
@ -2067,7 +2084,31 @@ gpg_addkey (engine_gpg_t gpg,
|
|||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
int use_armor)
|
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);
|
err = _gpgme_wait_one (ctx);
|
||||||
return TRACE_ERR (err);
|
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_start @172
|
||||||
gpgme_op_createkey @173
|
gpgme_op_createkey @173
|
||||||
|
gpgme_op_createsubkey_start @174
|
||||||
|
gpgme_op_createsubkey @175
|
||||||
|
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@ GPGME_1.1 {
|
|||||||
|
|
||||||
gpgme_op_createkey_start;
|
gpgme_op_createkey_start;
|
||||||
gpgme_op_createkey;
|
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"
|
fputs ("usage: " PGM " [options] USERID [ALGO [USAGE [EXPIRESECONDS]]]\n\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
|
" --addkey add a subkey to the key with USERID\n"
|
||||||
" --verbose run in verbose mode\n"
|
" --verbose run in verbose mode\n"
|
||||||
" --status print status lines from the backend\n"
|
" --status print status lines from the backend\n"
|
||||||
" --progress print progress info\n"
|
" --progress print progress info\n"
|
||||||
@ -224,6 +225,7 @@ main (int argc, char **argv)
|
|||||||
int print_status = 0;
|
int print_status = 0;
|
||||||
int print_progress = 0;
|
int print_progress = 0;
|
||||||
int use_loopback = 0;
|
int use_loopback = 0;
|
||||||
|
int addkey = 0;
|
||||||
const char *userid;
|
const char *userid;
|
||||||
const char *algo = NULL;
|
const char *algo = NULL;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
@ -243,6 +245,11 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else if (!strcmp (*argv, "--help"))
|
else if (!strcmp (*argv, "--help"))
|
||||||
show_usage (0);
|
show_usage (0);
|
||||||
|
else if (!strcmp (*argv, "--addkey"))
|
||||||
|
{
|
||||||
|
addkey = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
else if (!strcmp (*argv, "--verbose"))
|
else if (!strcmp (*argv, "--verbose"))
|
||||||
{
|
{
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
@ -316,6 +323,29 @@ main (int argc, char **argv)
|
|||||||
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
|
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addkey)
|
||||||
|
{
|
||||||
|
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);
|
err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -323,6 +353,7 @@ main (int argc, char **argv)
|
|||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = gpgme_op_genkey_result (ctx);
|
result = gpgme_op_genkey_result (ctx);
|
||||||
if (!result)
|
if (!result)
|
||||||
|
Loading…
Reference in New Issue
Block a user