core: New API gpgme_op_set_uid_flag.

* src/gpgme.h.in (gpgme_op_set_uid_flag_start): New.
(gpgme_op_set_uid_flag_start): New.
* src/gpgme.def, src/libgpgme.vers: Add them.
* src/genkey.c (addrevuid_start): Change arg revoke to a flag.
(gpgme_op_revuid_start): Pass GENKEY_EXTRAFLAG_REVOKE for the fomer
revoke parameter.
(gpgme_op_revuid): Ditto.
(set_uid_flag): New.
(gpgme_op_set_uid_flag_start): New.
(gpgme_op_set_uid_flag): New.
* src/engine.h (GENKEY_EXTRAFLAG_SETPRIMARY): new.
* src/engine-gpg.c (gpg_adduid): Implement that flag.

* tests/run-genkey.c (main): New command --set-primary.
--

GnuPG-bug-id: 2931
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-03-21 19:02:20 +01:00
parent f3e8d8a451
commit 421ddd1e67
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
9 changed files with 189 additions and 32 deletions

6
NEWS
View File

@ -10,10 +10,12 @@ Noteworthy changes in version 1.8.1 (unreleased)
gpgme_op_createkey CHANGED: Meaning of 'expire' parameter.
gpgme_op_createsubkey CHANGED: Meaning of 'expire' parameter.
GPGME_CREATE_NOEXPIRE NEW.
gpgme_subkey_t EXTENDED: New field is_de_vs.
gpgme_subkey_t EXTENDED: New field 'is_de_vs'.
gpgme_op_keylist_from_data_start NEW.
gpgme_op_set_uid_flag_start NEW.
gpgme_op_set_uid_flag NEW.
GPGME_ENCRYPT_THROW_KEYIDS NEW.
gpgme_data_rewind UN-DEPRECATE
gpgme_data_rewind UN-DEPRECATE.
cpp: Context::revUid(const Key&, const char*) NEW.
cpp: Context::startRevUid(const Key&, const char*) NEW.
cpp: Context::addUid(const Key&, const char*) NEW.

View File

@ -3896,6 +3896,61 @@ be completed by calling @code{gpgme_wait} on the context.
@end deftypefun
@c
@c gpgme_op_set_uid_flag
@c
@deftypefun gpgme_error_t gpgme_op_set_ui_flag @
(@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_key_t @var{key}}, @
@w{const char *@var{userid}}, @
@w{cons char * @var{name}}, @
@w{cons char * @var{value}});
The function @code{gpgme_op_set_uid_flag} is used to set flags on a
user ID from the OpenPGP key given by @var{KEY}. Setting flags on
user IDs after key creation is a feature of the OpenPGP protocol and
thus the protocol for the context @var{ctx} must be set to OpenPGP.
@var{key} specifies the key to operate on. This parameters is required.
@var{userid} is the user ID of the key to be manipulated. This user ID
must be given verbatim because the engine does an exact and case
sensitive match. Thus the @code{uid} field from the user ID object
(@code{gpgme_user_id_t}) is to be used. This is a required parameter.
@var{name} names the flag which is to be changed. The only currently
supported flag is:
@table @code
@item primary
This sets the primary key flag on the given user ID. All other
primary key flag on other user IDs are removed. @var{value} must be
given as NULL. For technical reasons this functions bumps the
creation timestamp of all affected self-signatures up by one second.
At least GnuPG version 2.1.20 is required.
@end table
The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
the engine does not support the command, or a bunch of other error
codes.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_set_uid_flag_start @
(@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_key_t @var{key}}, @
@w{const char *@var{userid}}, @
@w{cons char * @var{name}}, @
@w{cons char * @var{value}});
The function @code{gpgme_op_set_uid_flag_start} initiates a
@code{gpgme_op_set_uid_flag} operation; see there for details. It must
be completed by calling @code{gpgme_wait} on the context.
@xref{Waiting For Completion}.
@end deftypefun
@c
@c gpgme_op_genkey
@c

View File

@ -2222,7 +2222,14 @@ gpg_adduid (engine_gpg_t gpg,
if (!key || !key->fpr || !userid)
return gpg_error (GPG_ERR_INV_ARG);
if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
if ((extraflags & GENKEY_EXTRAFLAG_SETPRIMARY))
{
if (!have_gpg_version (gpg, "2.1.20"))
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else
err = add_arg (gpg, "--quick-set-primary-uid");
}
else if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
err = add_arg (gpg, "--quick-revuid");
else
err = add_arg (gpg, "--quick-adduid");
@ -2262,7 +2269,7 @@ gpg_genkey (void *engine,
* USERID && !KEY - Create a new keyblock.
* !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
* USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
*
* or set a flag on a user id.
*/
if (help_data)
{

View File

@ -25,8 +25,9 @@
#include "gpgme.h"
/* Flags used by the EXTRAFLAGS arg of _gpgme_engine_op_genkey. */
#define GENKEY_EXTRAFLAG_ARMOR 1
#define GENKEY_EXTRAFLAG_REVOKE 2
#define GENKEY_EXTRAFLAG_ARMOR 1
#define GENKEY_EXTRAFLAG_REVOKE 2
#define GENKEY_EXTRAFLAG_SETPRIMARY 4
struct engine;

View File

@ -489,7 +489,7 @@ gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
static gpgme_error_t
addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke,
addrevuid_start (gpgme_ctx_t ctx, int synchronous, int extraflags,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
@ -512,7 +512,7 @@ addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke,
if (err)
return err;
opd->uidmode = revoke? 2 : 1;
opd->uidmode = extraflags? 2 : 1;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
@ -528,7 +528,7 @@ addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke,
userid, NULL, 0, 0,
key, flags,
NULL,
revoke? GENKEY_EXTRAFLAG_REVOKE : 0,
extraflags,
NULL, NULL);
}
@ -584,7 +584,7 @@ gpgme_op_revuid_start (gpgme_ctx_t ctx,
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 0, 1, key, userid, flags);
err = addrevuid_start (ctx, 0, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags);
return TRACE_ERR (err);
}
@ -601,8 +601,60 @@ gpgme_op_revuid (gpgme_ctx_t ctx,
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 1, 1, key, userid, flags);
err = addrevuid_start (ctx, 1, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
/* Set a flag on the USERID of KEY. The only supported flag right now
* is "primary" to mark the primary key. */
static gpg_error_t
set_uid_flag (gpgme_ctx_t ctx, int synchronous,
gpgme_key_t key, const char *userid,
const char *name, const char *value)
{
gpgme_error_t err;
TRACE_BEG4 (DEBUG_CTX, "gpgme_op_set_uid_flag", ctx,
"%d uid='%s' '%s'='%s'", synchronous, userid, name, value);
if (!ctx || !name || !key || !userid)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
if (!strcmp (name, "primary"))
{
if (value)
err = gpg_error (GPG_ERR_INV_ARG);
else
err = addrevuid_start (ctx, synchronous,
GENKEY_EXTRAFLAG_SETPRIMARY, key, userid, 0);
}
else
return err = gpg_error (GPG_ERR_UNKNOWN_NAME);
if (synchronous && !err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
/* See set_uid_flag. */
gpgme_error_t
gpgme_op_set_uid_flag_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
const char *name, const char *value)
{
return set_uid_flag (ctx, 0, key, userid, name, value);
}
/* See set_uid_flag. Thsi is the synchronous variant. */
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)
{
return set_uid_flag (ctx, 1, key, userid, name, value);
}

View File

@ -256,5 +256,8 @@ EXPORTS
gpgme_op_keylist_from_data_start @192
gpgme_op_set_uid_flag_start @193
gpgme_op_set_uid_flag @194
; END

View File

@ -1726,6 +1726,13 @@ gpgme_error_t gpgme_op_revuid (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
unsigned int reserved);
/* Set a flag on the USERID of KEY. See the manual for supported flags. */
gpgme_error_t gpgme_op_set_uid_flag_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
const char *name, const char *value);
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);
/* Retrieve a pointer to the result of a genkey, createkey, or

View File

@ -126,6 +126,9 @@ GPGME_1.1 {
gpgme_op_query_swdb;
gpgme_op_query_swdb_result;
gpgme_op_set_uid_flag_start;
gpgme_op_set_uid_flag;
};

View File

@ -204,10 +204,12 @@ show_usage (int ex)
" for addkey: FPR [ALGO [USAGE [EXPIRESECONDS]]]\n"
" for adduid: FPR USERID\n"
" for revuid: FPR USERID\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"
" --revuid revoke a user id from the key with FPR\n"
" --set-primary set the primary key flag on USERID\n"
" --verbose run in verbose mode\n"
" --status print status lines from the backend\n"
" --progress print progress info\n"
@ -234,6 +236,7 @@ main (int argc, char **argv)
int addkey = 0;
int adduid = 0;
int revuid = 0;
int setpri = 0;
const char *userid;
const char *algo = NULL;
const char *newuserid = NULL;
@ -259,6 +262,7 @@ main (int argc, char **argv)
addkey = 1;
adduid = 0;
revuid = 0;
setpri = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--adduid"))
@ -266,6 +270,7 @@ main (int argc, char **argv)
addkey = 0;
adduid = 1;
revuid = 0;
setpri = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--revuid"))
@ -273,6 +278,15 @@ main (int argc, char **argv)
addkey = 0;
adduid = 0;
revuid = 1;
setpri = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--set-primary"))
{
addkey = 0;
adduid = 0;
revuid = 0;
setpri = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--verbose"))
@ -319,7 +333,7 @@ main (int argc, char **argv)
show_usage (1);
}
if (adduid || revuid)
if (adduid || revuid || setpri)
{
if (argc != 2)
show_usage (1);
@ -358,7 +372,7 @@ main (int argc, char **argv)
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
}
if (addkey || adduid || revuid)
if (addkey || adduid || revuid || setpri)
{
gpgme_key_t akey;
@ -400,6 +414,16 @@ main (int argc, char **argv)
exit (1);
}
}
else if (setpri)
{
err = gpgme_op_set_uid_flag (ctx, akey, newuserid, "primary", NULL);
if (err)
{
fprintf (stderr, PGM ": gpgme_op_set_uid_flag failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
gpgme_key_unref (akey);
}
else
@ -413,27 +437,30 @@ main (int argc, char **argv)
}
}
result = gpgme_op_genkey_result (ctx);
if (!result)
if (!setpri)
{
fprintf (stderr, PGM": gpgme_op_genkey_result returned NULL\n");
exit (1);
result = gpgme_op_genkey_result (ctx);
if (!result)
{
fprintf (stderr, PGM": gpgme_op_genkey_result returned NULL\n");
exit (1);
}
printf ("Generated key: %s (%s)\n",
result->fpr ? result->fpr : "none",
result->primary ? (result->sub ? "primary, sub" : "primary")
/**/ : (result->sub ? "sub" : "none"));
if (result->fpr && strlen (result->fpr) < 40)
fprintf (stderr, PGM": generated key has unexpected fingerprint\n");
if (!result->primary)
fprintf (stderr, PGM": primary key was not generated\n");
if (!result->sub)
fprintf (stderr, PGM": sub key was not generated\n");
if (!result->uid)
fprintf (stderr, PGM": uid was not generated\n");
}
printf ("Generated key: %s (%s)\n",
result->fpr ? result->fpr : "none",
result->primary ? (result->sub ? "primary, sub" : "primary")
/**/ : (result->sub ? "sub" : "none"));
if (result->fpr && strlen (result->fpr) < 40)
fprintf (stderr, PGM": generated key has unexpected fingerprint\n");
if (!result->primary)
fprintf (stderr, PGM": primary key was not generated\n");
if (!result->sub)
fprintf (stderr, PGM": sub key was not generated\n");
if (!result->uid)
fprintf (stderr, PGM": uid was not generated\n");
gpgme_release (ctx);
return 0;
}