gpg: New command --quick-adduid.

* g10/keygen.c (ask_user_id): Factor some code out to ...
(uid_already_in_keyblock): new.
(generate_user_id): Add arg UIDSTR.  Fix leaked P.
* g10/keyedit.c (menu_adduid): Add new arg uidstring.  Adjust caller.
(keyedit_quick_adduid): New.
* g10/gpg.c (aQuickAddUid): New.
(opts):  Add command --quick-adduid.
(main): Implement that.
--

GnuPG-bug-id: 1956
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-05-08 16:08:57 +02:00
parent 3c439c0447
commit 64e809b791
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 185 additions and 30 deletions

View File

@ -568,7 +568,7 @@ This section explains the main commands for key management
@ifset gpgtwoone
@item --quick-gen-key @code{user-id}
@opindex quick-gen-key
This is simple command to generate a standard key with one user id.
This is a simple command to generate a standard key with one user id.
In contrast to @option{--gen-key} the key is generated directly
without the need to answer a bunch of prompts. Unless the option
@option{--yes} is given, the key creation will be canceled if the
@ -945,6 +945,16 @@ Its intended use is to help unattended key signing by utilizing a list
of verified fingerprints.
@end ifset
@ifset gpgtwoone
@item --quick-adduid @var{user-id} @var{new-user-id}
@opindex quick-adduid
This command adds a new user id to an existing key. In contrast to
the interactive sub-command @code{adduid} of @option{--edit-key} the
@var{new-user-id} is added verbatim with only leading and trailing
white space removed, it is expected to be UTF-8 encoded, and no checks
on its form are applied.
@end ifset
@item --passwd @var{user_id}
@opindex passwd
Change the passphrase of the secret key belonging to the certificate

View File

@ -116,6 +116,7 @@ enum cmd_and_opt_values
aLSignKey,
aQuickSignKey,
aQuickLSignKey,
aQuickAddUid,
aListConfig,
aListGcryptConfig,
aGPGConfList,
@ -414,6 +415,8 @@ static ARGPARSE_OPTS opts[] = {
N_("generate a new key pair")),
ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
N_("quickly generate a new key pair")),
ARGPARSE_c (aQuickAddUid, "quick-adduid",
N_("quickly add a new user-id")),
ARGPARSE_c (aFullKeygen, "full-gen-key" ,
N_("full featured key pair generation")),
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
@ -2327,6 +2330,7 @@ main (int argc, char **argv)
case aLSignKey:
case aStore:
case aQuickKeygen:
case aQuickAddUid:
case aExportOwnerTrust:
case aImportOwnerTrust:
case aRebuildKeydbCaches:
@ -3604,6 +3608,7 @@ main (int argc, char **argv)
case aDeleteSecretKeys:
case aDeleteSecretAndPublicKeys:
case aQuickKeygen:
case aQuickAddUid:
case aFullKeygen:
case aKeygen:
case aImport:
@ -3924,6 +3929,18 @@ main (int argc, char **argv)
}
break;
case aQuickAddUid:
{
const char *uid, *newuid;
if (argc != 2)
wrong_args ("--quick-adduid USER-ID NEW-USER-ID");
uid = *argv++; argc--;
newuid = *argv++; argc--;
keyedit_quick_adduid (ctrl, uid, newuid);
}
break;
case aFastImport:
opt.import_options |= IMPORT_FAST;
case aImport:

View File

@ -1,7 +1,6 @@
/* keyedit.c - keyedit stuff
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
* 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright (C) 2013, 2014 Werner Koch
/* keyedit.c - Edit properties of a key
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
* Copyright (C) 1998-2015 Werner Koch
*
* This file is part of GnuPG.
*
@ -59,7 +58,8 @@ static void show_key_with_all_names (estream_t fp,
int nowarn);
static void show_key_and_fingerprint (KBNODE keyblock);
static void subkey_expire_warning (kbnode_t keyblock);
static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name);
static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name,
const char *uidstr);
static void menu_deluid (KBNODE pub_keyblock);
static int menu_delsig (KBNODE pub_keyblock);
static int menu_clean (KBNODE keyblock, int self_only);
@ -1757,7 +1757,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
photo = 1;
/* fall through */
case cmdADDUID:
if (menu_adduid (keyblock, photo, arg_string))
if (menu_adduid (keyblock, photo, arg_string, NULL))
{
update_trust = 1;
redisplay = 1;
@ -2288,6 +2288,93 @@ leave:
}
/* Unattended adding of a new keyid. USERNAME specifies the
key. NEWUID is the new user id to add to the key. */
void
keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
{
gpg_error_t err;
KEYDB_HANDLE kdbhd = NULL;
KEYDB_SEARCH_DESC desc;
kbnode_t keyblock = NULL;
kbnode_t node;
char *uidstring = NULL;
uidstring = xstrdup (newuid);
trim_spaces (uidstring);
if (!*uidstring)
{
log_error ("%s\n", gpg_strerror (GPG_ERR_INV_USER_ID));
goto leave;
}
#ifdef HAVE_W32_SYSTEM
/* See keyedit_menu for why we need this. */
check_trustdb_stale ();
#endif
/* Search the key; we don't want the whole getkey stuff here. */
kdbhd = keydb_new ();
err = classify_user_id (username, &desc, 1);
if (!err)
err = keydb_search (kdbhd, &desc, 1, NULL);
if (!err)
{
err = keydb_get_keyblock (kdbhd, &keyblock);
if (err)
{
log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
goto leave;
}
/* Now with the keyblock retrieved, search again to detect an
ambiguous specification. We need to save the found state so
that we can do an update later. */
keydb_push_found_state (kdbhd);
err = keydb_search (kdbhd, &desc, 1, NULL);
if (!err)
err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
err = 0;
keydb_pop_found_state (kdbhd);
if (!err)
{
/* We require the secret primary key to add a UID. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
if (!node)
BUG ();
err = agent_probe_secret_key (ctrl, node->pkt->pkt.public_key);
}
}
if (err)
{
log_error (_("secret key \"%s\" not found: %s\n"),
username, gpg_strerror (err));
goto leave;
}
fix_keyblock (&keyblock);
if (menu_adduid (keyblock, 0, NULL, uidstring))
{
err = keydb_update_keyblock (kdbhd, keyblock);
if (err)
{
log_error (_("update failed: %s\n"), gpg_strerror (err));
goto leave;
}
if (update_trust)
revalidation_mark ();
}
leave:
xfree (uidstring);
release_kbnode (keyblock);
keydb_release (kdbhd);
}
/* Unattended key signing function. If the key specifified by FPR is
availabale and FPR is the primary fingerprint all user ids of the
user ids of the key are signed using the default signing key. If
@ -3225,11 +3312,15 @@ subkey_expire_warning (kbnode_t keyblock)
/*
* Ask for a new user id, add the self-signature and update the keyblock.
* Return true if there is a new user id
* Ask for a new user id, add the self-signature, and update the
* keyblock. If UIDSTRING is not NULL the user ID is generated
* unattended using that string. UIDSTRING is expected to be utf-8
* encoded and white space trimmed. Returns true if there is a new
* user id.
*/
static int
menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
const char *uidstring)
{
PKT_user_id *uid;
PKT_public_key *pk = NULL;
@ -3239,6 +3330,9 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
KBNODE pub_where = NULL;
gpg_error_t err;
if (photo && uidstring)
return 0; /* Not allowed. */
for (node = pub_keyblock; node; pub_where = node, node = node->next)
{
if (node->pkt->pkttype == PKT_PUBLIC_KEY)
@ -3291,9 +3385,13 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
uid = generate_photo_id (pk, photo_name);
}
else
uid = generate_user_id (pub_keyblock);
uid = generate_user_id (pub_keyblock, uidstring);
if (!uid)
return 0;
{
if (uidstring)
log_error ("%s", _("Such a user ID already exists on this key!\n"));
return 0;
}
err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
keygen_add_std_prefs, pk, NULL);

View File

@ -2446,6 +2446,24 @@ uid_from_string (const char *string)
}
/* Return true if the user id UID already exists in the keyblock. */
static int
uid_already_in_keyblock (kbnode_t keyblock, const char *uid)
{
PKT_user_id *uidpkt = uid_from_string (uid);
kbnode_t node;
int result = 0;
for (node=keyblock; node && !result; node=node->next)
if (!is_deleted_kbnode (node)
&& node->pkt->pkttype == PKT_USER_ID
&& !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
result = 1;
free_user_id (uidpkt);
return result;
}
/* Ask for a user ID. With a MODE of 1 an extra help prompt is
printed for use during a new key creation. If KEYBLOCK is not NULL
the function prevents the creation of an already existing user
@ -2583,17 +2601,11 @@ ask_user_id (int mode, int full, KBNODE keyblock)
if (!fail && keyblock)
{
PKT_user_id *uidpkt = uid_from_string (uid);
KBNODE node;
for (node=keyblock; node && !fail; node=node->next)
if (!is_deleted_kbnode (node)
&& node->pkt->pkttype == PKT_USER_ID
&& !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
fail = 1;
if (fail)
tty_printf (_("Such a user ID already exists on this key!\n"));
free_user_id (uidpkt);
if (uid_already_in_keyblock (keyblock, uid))
{
tty_printf (_("Such a user ID already exists on this key!\n"));
fail = 1;
}
}
for(;;) {
@ -2767,16 +2779,32 @@ do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
/* Generate a new user id packet or return NULL if canceled. If
KEYBLOCK is not NULL the function prevents the creation of an
already existing user ID. */
already existing user ID. If UIDSTR is not NULL the user is not
asked but UIDSTR is used to create the user id packet; if the user
id already exists NULL is returned. UIDSTR is expected to be utf-8
encoded and should have already been checked for a valid length
etc. */
PKT_user_id *
generate_user_id (KBNODE keyblock)
generate_user_id (KBNODE keyblock, const char *uidstr)
{
PKT_user_id *uid;
char *p;
p = ask_user_id (1, 1, keyblock);
if (!p)
return NULL; /* Canceled. */
return uid_from_string (p);
if (uidstr)
{
if (uid_already_in_keyblock (keyblock, uidstr))
return NULL; /* Already exists. */
uid = uid_from_string (uidstr);
}
else
{
p = ask_user_id (1, 1, keyblock);
if (!p)
return NULL; /* Canceled. */
uid = uid_from_string (p);
xfree (p);
}
return uid;
}

View File

@ -247,6 +247,8 @@ gpg_error_t delete_keys (strlist_t names, int secret, int allow_both);
void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
strlist_t commands, int quiet, int seckey_check );
void keyedit_passwd (ctrl_t ctrl, const char *username);
void keyedit_quick_adduid (ctrl_t ctrl, const char *username,
const char *newuid);
void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
strlist_t uids, strlist_t locusr, int local);
void show_basic_key_info (KBNODE keyblock);

View File

@ -544,6 +544,6 @@ int update_keysig_packet( PKT_signature **ret_sig,
void *opaque );
/*-- keygen.c --*/
PKT_user_id *generate_user_id (KBNODE keyblock);
PKT_user_id *generate_user_id (kbnode_t keyblock, const char *uidstr);
#endif /*G10_PACKET_H*/