core: New function gpgme_op_adduid.

* src/genkey.c: Replace most error codes GPG_ERR_INV_VALUE by
GPG_ERR_INV_ARG.
(struct op_data_t): Add field UIDMODE.
(genkey_status_handler): Use UIDMODE.
(adduid_start): New.
(gpgme_op_adduid_start, gpgme_op_adduid): New.
* src/gpgme.def, src/libgpgme.vers: Add them.
* tests/run-genkey.c: Add option --adduid.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-09-14 11:40:34 +02:00
parent cc353701b0
commit 3210f3e472
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 192 additions and 33 deletions

2
NEWS
View File

@ -19,6 +19,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
gpgme_op_createkey_start NEW. gpgme_op_createkey_start NEW.
gpgme_op_createsubkey NEW. gpgme_op_createsubkey NEW.
gpgme_op_createsubkey_start NEW. gpgme_op_createsubkey_start NEW.
gpgme_op_adduid_start NEW.
gpgme_op_adduid 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.

View File

@ -2114,11 +2114,25 @@ gpg_addkey (engine_gpg_t gpg,
static gpgme_error_t static gpgme_error_t
gpg_adduid (engine_gpg_t gpg, gpg_adduid (engine_gpg_t gpg,
const char *userid, gpgme_key_t key,
unsigned int flags, const char *userid)
int use_armor)
{ {
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); gpgme_error_t err;
if (!key || !key->fpr || !userid)
return gpg_error (GPG_ERR_INV_ARG);
err = add_arg (gpg, "--quick-adduid");
if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_arg (gpg, key->fpr);
if (!err)
err = add_arg (gpg, userid);
if (!err)
err = start (gpg);
return err;
} }
@ -2170,7 +2184,7 @@ gpg_genkey (void *engine,
else if (!userid && key) else if (!userid && key)
err = gpg_addkey (gpg, algo, expires, key, flags, use_armor); err = gpg_addkey (gpg, algo, expires, key, flags, use_armor);
else if (userid && key && !algo) else if (userid && key && !algo)
err = gpg_adduid (gpg, userid, flags, use_armor); err = gpg_adduid (gpg, key, userid);
else else
err = gpg_error (GPG_ERR_INV_VALUE); err = gpg_error (GPG_ERR_INV_VALUE);

View File

@ -42,6 +42,9 @@ typedef struct
/* The error code from certain ERROR status lines or 0. */ /* The error code from certain ERROR status lines or 0. */
gpg_error_t error_code; gpg_error_t error_code;
/* Flag to indicate that a UID is to be added. */
gpg_error_t uidmode;
/* The key parameters passed to the crypto engine. */ /* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter; gpgme_data_t key_parameter;
} *op_data_t; } *op_data_t;
@ -142,7 +145,10 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
if (args && *args) if (args && *args)
{ {
if (*args == 'B' || *args == 'P') if (*args == 'B' || *args == 'P')
opd->result.primary = 1; {
opd->result.primary = 1;
opd->result.uid = 1;
}
if (*args == 'B' || *args == 'S') if (*args == 'B' || *args == 'S')
opd->result.sub = 1; opd->result.sub = 1;
if (args[1] == ' ') if (args[1] == ' ')
@ -171,10 +177,12 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
case GPGME_STATUS_EOF: case GPGME_STATUS_EOF:
if (opd->error_code) if (opd->error_code)
return opd->error_code; return opd->error_code;
else if (!opd->result.primary && !opd->result.sub) else if (!opd->uidmode && !opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
else if (opd->failure_code) else if (opd->failure_code)
return opd->failure_code; return opd->failure_code;
else if (opd->uidmode)
opd->result.uid = 1; /* We have no status line, thus this hack. */
break; break;
case GPGME_STATUS_INQUIRE_MAXLEN: case GPGME_STATUS_INQUIRE_MAXLEN:
@ -277,7 +285,7 @@ gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
TRACE_LOGBUF (parms, strlen (parms)); TRACE_LOGBUF (parms, strlen (parms));
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 0, parms, pubkey, seckey); err = genkey_start (ctx, 0, parms, pubkey, seckey);
return TRACE_ERR (err); return TRACE_ERR (err);
@ -298,7 +306,7 @@ gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey,
TRACE_LOGBUF (parms, strlen (parms)); TRACE_LOGBUF (parms, strlen (parms));
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 1, parms, pubkey, seckey); err = genkey_start (ctx, 1, parms, pubkey, seckey);
if (!err) if (!err)
@ -323,7 +331,7 @@ createkey_start (gpgme_ctx_t ctx, int synchronous,
return err; return err;
if (reserved || anchorkey || !userid) if (reserved || anchorkey || !userid)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data); sizeof (*opd), release_op_data);
@ -360,7 +368,7 @@ gpgme_op_createkey_start (gpgme_ctx_t ctx, const char *userid, const char *algo,
"userid='%s', algo='%s' flags=0x%x", userid, algo, flags); "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createkey_start (ctx, 0, err = createkey_start (ctx, 0,
userid, algo, reserved, expires, anchorkey, flags); userid, algo, reserved, expires, anchorkey, flags);
@ -379,7 +387,7 @@ gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,
"userid='%s', algo='%s' flags=0x%x", userid, algo, flags); "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createkey_start (ctx, 1, err = createkey_start (ctx, 1,
userid, algo, reserved, expires, anchorkey, flags); userid, algo, reserved, expires, anchorkey, flags);
@ -409,7 +417,7 @@ createsubkey_start (gpgme_ctx_t ctx, int synchronous,
return err; return err;
if (reserved || !key) if (reserved || !key)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data); sizeof (*opd), release_op_data);
@ -447,7 +455,7 @@ gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
"key=%p, algo='%s' flags=0x%x", key, algo, flags); "key=%p, algo='%s' flags=0x%x", key, algo, flags);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags); err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags);
return TRACE_ERR (err); return TRACE_ERR (err);
@ -465,10 +473,92 @@ gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
"key=%p, algo='%s' flags=0x%x", key, algo, flags); "key=%p, algo='%s' flags=0x%x", key, algo, flags);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags); err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags);
if (!err) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
return TRACE_ERR (err); return TRACE_ERR (err);
} }
static gpgme_error_t
adduid_start (gpgme_ctx_t ctx, int synchronous,
gpgme_key_t key, const char *userid, 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);
if (!key || !userid)
return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
opd->uidmode = 1;
_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,
userid, NULL, 0, 0,
key, flags,
NULL, ctx->use_armor, NULL, NULL);
}
/* Add USERID to an existing KEY. */
gpgme_error_t
gpgme_op_adduid_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid_start", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = adduid_start (ctx, 0, key, userid, flags);
return TRACE_ERR (err);
}
gpgme_error_t
gpgme_op_adduid (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = adduid_start (ctx, 1, key, userid, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}

View File

@ -233,6 +233,8 @@ EXPORTS
gpgme_op_createkey @173 gpgme_op_createkey @173
gpgme_op_createsubkey_start @174 gpgme_op_createsubkey_start @174
gpgme_op_createsubkey @175 gpgme_op_createsubkey @175
gpgme_op_adduid_start @176
gpgme_op_adduid @177
; END ; END

View File

@ -1835,8 +1835,11 @@ struct _gpgme_op_genkey_result
/* A sub key was generated. */ /* A sub key was generated. */
unsigned int sub : 1; unsigned int sub : 1;
/* A user id was generated. */
unsigned int uid : 1;
/* Internal to GPGME, do not use. */ /* Internal to GPGME, do not use. */
unsigned int _unused : 30; unsigned int _unused : 29;
/* The fingerprint of the generated key. */ /* The fingerprint of the generated key. */
char *fpr; char *fpr;
@ -1888,6 +1891,14 @@ gpgme_error_t gpgme_op_createsubkey (gpgme_ctx_t ctx,
unsigned long expires, unsigned long expires,
unsigned int flags); unsigned int flags);
/* Add USERID to an existing KEY. */
gpgme_error_t gpgme_op_adduid_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
unsigned int flags);
gpgme_error_t gpgme_op_adduid (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
unsigned int flags);
/* Retrieve a pointer to the result of a genkey, createkey, or /* Retrieve a pointer to the result of a genkey, createkey, or

View File

@ -107,6 +107,8 @@ GPGME_1.1 {
gpgme_op_createkey; gpgme_op_createkey;
gpgme_op_createsubkey_start; gpgme_op_createsubkey_start;
gpgme_op_createsubkey; gpgme_op_createsubkey;
gpgme_op_adduid_start;
gpgme_op_adduid;
}; };

View File

@ -199,9 +199,13 @@ parse_usage_string (const char *string)
static int static int
show_usage (int ex) show_usage (int ex)
{ {
fputs ("usage: " PGM " [options] USERID [ALGO [USAGE [EXPIRESECONDS]]]\n\n" fputs ("usage: " PGM " [options] ARGS\n"
" args: USERID [ALGO [USAGE [EXPIRESECONDS]]]\n"
" for addkey: FPR [ALGO [USAGE [EXPIRESECONDS]]]\n"
" for adduid: FPR USERID\n"
"Options:\n" "Options:\n"
" --addkey add a subkey to the key with USERID\n" " --addkey add a subkey to the key with FPR\n"
" --adduid add a user id to the key with FPR\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"
@ -226,8 +230,10 @@ main (int argc, char **argv)
int print_progress = 0; int print_progress = 0;
int use_loopback = 0; int use_loopback = 0;
int addkey = 0; int addkey = 0;
int adduid = 0;
const char *userid; const char *userid;
const char *algo = NULL; const char *algo = NULL;
const char *newuserid = NULL;
unsigned int flags = 0; unsigned int flags = 0;
unsigned long expire = 0; unsigned long expire = 0;
gpgme_genkey_result_t result; gpgme_genkey_result_t result;
@ -248,6 +254,13 @@ main (int argc, char **argv)
else if (!strcmp (*argv, "--addkey")) else if (!strcmp (*argv, "--addkey"))
{ {
addkey = 1; addkey = 1;
adduid = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--adduid"))
{
addkey = 0;
adduid = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--verbose")) else if (!strcmp (*argv, "--verbose"))
@ -294,15 +307,25 @@ main (int argc, char **argv)
show_usage (1); show_usage (1);
} }
if (!argc || argc > 4) if (adduid)
show_usage (1); {
userid = argv[0]; if (argc != 2)
if (argc > 1) show_usage (1);
algo = argv[1]; userid = argv[0];
if (argc > 2) newuserid = argv[1];
flags |= parse_usage_string (argv[2]); }
if (argc > 3) else
expire = parse_expire_string (argv[3]); {
if (!argc || argc > 4)
show_usage (1);
userid = argv[0];
if (argc > 1)
algo = argv[1];
if (argc > 2)
flags |= parse_usage_string (argv[2]);
if (argc > 3)
expire = parse_expire_string (argv[3]);
}
init_gpgme (protocol); init_gpgme (protocol);
@ -323,7 +346,7 @@ main (int argc, char **argv)
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
} }
if (addkey) if (addkey || adduid)
{ {
gpgme_key_t akey; gpgme_key_t akey;
@ -335,12 +358,25 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags); if (addkey)
if (err)
{ {
fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n", err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
gpg_strerror (err)); if (err)
exit (1); {
fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
else if (adduid)
{
err = gpgme_op_adduid (ctx, akey, newuserid, flags);
if (err)
{
fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
gpg_strerror (err));
exit (1);
}
} }
gpgme_key_unref (akey); gpgme_key_unref (akey);
} }
@ -373,6 +409,8 @@ main (int argc, char **argv)
fprintf (stderr, PGM": primary key was not generated\n"); fprintf (stderr, PGM": primary key was not generated\n");
if (!result->sub) if (!result->sub)
fprintf (stderr, PGM": sub key was not generated\n"); fprintf (stderr, PGM": sub key was not generated\n");
if (!result->uid)
fprintf (stderr, PGM": uid was not generated\n");
gpgme_release (ctx); gpgme_release (ctx);
return 0; return 0;