mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
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:
parent
3c439c0447
commit
64e809b791
12
doc/gpg.texi
12
doc/gpg.texi
@ -568,7 +568,7 @@ This section explains the main commands for key management
|
|||||||
@ifset gpgtwoone
|
@ifset gpgtwoone
|
||||||
@item --quick-gen-key @code{user-id}
|
@item --quick-gen-key @code{user-id}
|
||||||
@opindex quick-gen-key
|
@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
|
In contrast to @option{--gen-key} the key is generated directly
|
||||||
without the need to answer a bunch of prompts. Unless the option
|
without the need to answer a bunch of prompts. Unless the option
|
||||||
@option{--yes} is given, the key creation will be canceled if the
|
@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.
|
of verified fingerprints.
|
||||||
@end ifset
|
@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}
|
@item --passwd @var{user_id}
|
||||||
@opindex passwd
|
@opindex passwd
|
||||||
Change the passphrase of the secret key belonging to the certificate
|
Change the passphrase of the secret key belonging to the certificate
|
||||||
|
17
g10/gpg.c
17
g10/gpg.c
@ -116,6 +116,7 @@ enum cmd_and_opt_values
|
|||||||
aLSignKey,
|
aLSignKey,
|
||||||
aQuickSignKey,
|
aQuickSignKey,
|
||||||
aQuickLSignKey,
|
aQuickLSignKey,
|
||||||
|
aQuickAddUid,
|
||||||
aListConfig,
|
aListConfig,
|
||||||
aListGcryptConfig,
|
aListGcryptConfig,
|
||||||
aGPGConfList,
|
aGPGConfList,
|
||||||
@ -414,6 +415,8 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
N_("generate a new key pair")),
|
N_("generate a new key pair")),
|
||||||
ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
|
ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
|
||||||
N_("quickly generate a new key pair")),
|
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" ,
|
ARGPARSE_c (aFullKeygen, "full-gen-key" ,
|
||||||
N_("full featured key pair generation")),
|
N_("full featured key pair generation")),
|
||||||
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
|
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
|
||||||
@ -2327,6 +2330,7 @@ main (int argc, char **argv)
|
|||||||
case aLSignKey:
|
case aLSignKey:
|
||||||
case aStore:
|
case aStore:
|
||||||
case aQuickKeygen:
|
case aQuickKeygen:
|
||||||
|
case aQuickAddUid:
|
||||||
case aExportOwnerTrust:
|
case aExportOwnerTrust:
|
||||||
case aImportOwnerTrust:
|
case aImportOwnerTrust:
|
||||||
case aRebuildKeydbCaches:
|
case aRebuildKeydbCaches:
|
||||||
@ -3604,6 +3608,7 @@ main (int argc, char **argv)
|
|||||||
case aDeleteSecretKeys:
|
case aDeleteSecretKeys:
|
||||||
case aDeleteSecretAndPublicKeys:
|
case aDeleteSecretAndPublicKeys:
|
||||||
case aQuickKeygen:
|
case aQuickKeygen:
|
||||||
|
case aQuickAddUid:
|
||||||
case aFullKeygen:
|
case aFullKeygen:
|
||||||
case aKeygen:
|
case aKeygen:
|
||||||
case aImport:
|
case aImport:
|
||||||
@ -3924,6 +3929,18 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case aFastImport:
|
||||||
opt.import_options |= IMPORT_FAST;
|
opt.import_options |= IMPORT_FAST;
|
||||||
case aImport:
|
case aImport:
|
||||||
|
118
g10/keyedit.c
118
g10/keyedit.c
@ -1,7 +1,6 @@
|
|||||||
/* keyedit.c - keyedit stuff
|
/* keyedit.c - Edit properties of a key
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
|
||||||
* 2008, 2009, 2010 Free Software Foundation, Inc.
|
* Copyright (C) 1998-2015 Werner Koch
|
||||||
* Copyright (C) 2013, 2014 Werner Koch
|
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -59,7 +58,8 @@ static void show_key_with_all_names (estream_t fp,
|
|||||||
int nowarn);
|
int nowarn);
|
||||||
static void show_key_and_fingerprint (KBNODE keyblock);
|
static void show_key_and_fingerprint (KBNODE keyblock);
|
||||||
static void subkey_expire_warning (kbnode_t 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 void menu_deluid (KBNODE pub_keyblock);
|
||||||
static int menu_delsig (KBNODE pub_keyblock);
|
static int menu_delsig (KBNODE pub_keyblock);
|
||||||
static int menu_clean (KBNODE keyblock, int self_only);
|
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;
|
photo = 1;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case cmdADDUID:
|
case cmdADDUID:
|
||||||
if (menu_adduid (keyblock, photo, arg_string))
|
if (menu_adduid (keyblock, photo, arg_string, NULL))
|
||||||
{
|
{
|
||||||
update_trust = 1;
|
update_trust = 1;
|
||||||
redisplay = 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
|
/* Unattended key signing function. If the key specifified by FPR is
|
||||||
availabale and FPR is the primary fingerprint all user ids of the
|
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
|
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.
|
* Ask for a new user id, add the self-signature, and update the
|
||||||
* Return true if there is a new user id
|
* 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
|
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_user_id *uid;
|
||||||
PKT_public_key *pk = NULL;
|
PKT_public_key *pk = NULL;
|
||||||
@ -3239,6 +3330,9 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
|
|||||||
KBNODE pub_where = NULL;
|
KBNODE pub_where = NULL;
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
|
||||||
|
if (photo && uidstring)
|
||||||
|
return 0; /* Not allowed. */
|
||||||
|
|
||||||
for (node = pub_keyblock; node; pub_where = node, node = node->next)
|
for (node = pub_keyblock; node; pub_where = node, node = node->next)
|
||||||
{
|
{
|
||||||
if (node->pkt->pkttype == PKT_PUBLIC_KEY)
|
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);
|
uid = generate_photo_id (pk, photo_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
uid = generate_user_id (pub_keyblock);
|
uid = generate_user_id (pub_keyblock, uidstring);
|
||||||
if (!uid)
|
if (!uid)
|
||||||
|
{
|
||||||
|
if (uidstring)
|
||||||
|
log_error ("%s", _("Such a user ID already exists on this key!\n"));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
|
err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
|
||||||
keygen_add_std_prefs, pk, NULL);
|
keygen_add_std_prefs, pk, NULL);
|
||||||
|
54
g10/keygen.c
54
g10/keygen.c
@ -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
|
/* 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
|
printed for use during a new key creation. If KEYBLOCK is not NULL
|
||||||
the function prevents the creation of an already existing user
|
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)
|
if (!fail && keyblock)
|
||||||
{
|
{
|
||||||
PKT_user_id *uidpkt = uid_from_string (uid);
|
if (uid_already_in_keyblock (keyblock, 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"));
|
tty_printf (_("Such a user ID already exists on this key!\n"));
|
||||||
free_user_id (uidpkt);
|
fail = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;) {
|
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
|
/* Generate a new user id packet or return NULL if canceled. If
|
||||||
KEYBLOCK is not NULL the function prevents the creation of an
|
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 *
|
PKT_user_id *
|
||||||
generate_user_id (KBNODE keyblock)
|
generate_user_id (KBNODE keyblock, const char *uidstr)
|
||||||
{
|
{
|
||||||
|
PKT_user_id *uid;
|
||||||
char *p;
|
char *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);
|
p = ask_user_id (1, 1, keyblock);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL; /* Canceled. */
|
return NULL; /* Canceled. */
|
||||||
return uid_from_string (p);
|
uid = uid_from_string (p);
|
||||||
|
xfree (p);
|
||||||
|
}
|
||||||
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||||
strlist_t commands, int quiet, int seckey_check );
|
strlist_t commands, int quiet, int seckey_check );
|
||||||
void keyedit_passwd (ctrl_t ctrl, const char *username);
|
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,
|
void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
|
||||||
strlist_t uids, strlist_t locusr, int local);
|
strlist_t uids, strlist_t locusr, int local);
|
||||||
void show_basic_key_info (KBNODE keyblock);
|
void show_basic_key_info (KBNODE keyblock);
|
||||||
|
@ -544,6 +544,6 @@ int update_keysig_packet( PKT_signature **ret_sig,
|
|||||||
void *opaque );
|
void *opaque );
|
||||||
|
|
||||||
/*-- keygen.c --*/
|
/*-- 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*/
|
#endif /*G10_PACKET_H*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user