From d02de6c0a4a55a2720cfa5caddcbfc4ce988a2ec Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 19 Apr 2016 17:47:24 +0200 Subject: [PATCH] gpg: Improve UID selction of --quick-sign-key. * g10/keyedit.c (keyedit_quick_sign): Improve UID selection and print error for non-found userids. -- GnuPG-bug-id: 2315 --- doc/gpg.texi | 9 +++++--- g10/keyedit.c | 64 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/doc/gpg.texi b/doc/gpg.texi index 5994d9f4a..781a18828 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -973,9 +973,12 @@ Directly sign a key from the passphrase without any further user interaction. The @code{fpr} must be the verified primary fingerprint of a key in the local keyring. If no @code{names} are given, all useful user ids are signed; with given [@code{names}] only useful user -ids matching one of theses names are signed. The command -@option{--quick-lsign-key} marks the signatures as non-exportable. If -such a non-exportable signature already exists the +ids matching one of theses names are signed. By default, or if a name +is prefixed with a '*', a case insensitive substring match is used. +If a name is prefixed with a '=' a case sensitive exact match is done. + +The command @option{--quick-lsign-key} marks the signatures as +non-exportable. If such a non-exportable signature already exists the @option{--quick-sign-key} turns it into a exportable signature. This command uses reasonable defaults and thus does not provide the diff --git a/g10/keyedit.c b/g10/keyedit.c index cd8932519..84f04318e 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -2927,12 +2927,11 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid) /* 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 - UIDS is an empty list all usable UIDs are signed, if it is not - empty, only those user ids matching one of the entries of the loist - are signed. With LOCAL being true kthe signatures are marked as - non-exportable. */ + available and FPR is the primary fingerprint all user ids of the + key are signed using the default signing key. If UIDS is an empty + list all usable UIDs are signed, if it is not empty, only those + user ids matching one of the entries of the list are signed. With + LOCAL being true the signatures are marked as non-exportable. */ void keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids, strlist_t locusr, int local) @@ -3025,27 +3024,72 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids, menu_select_uid (keyblock, 0); /* Better clear the flags first. */ for (sl=uids; sl; sl = sl->next) { + const char *name = sl->d; + int count = 0; + + sl->flags &= ~(1|2); /* Clear flags used for error reporting. */ + for (node = keyblock; node; node = node->next) { if (node->pkt->pkttype == PKT_USER_ID) { PKT_user_id *uid = node->pkt->pkt.user_id; - if (!uid->attrib_data - && ascii_memistr (uid->name, uid->len, sl->d)) + if (uid->attrib_data) + ; + else if (*name == '=' + && strlen (name+1) == uid->len + && !memcmp (uid->name, name + 1, uid->len)) + { /* Exact match - we don't do a check for ambiguity + * in this case. */ + node->flag |= NODFLG_SELUID; + if (any != -1) + { + sl->flags |= 1; /* Report as found. */ + any = 1; + } + } + else if (ascii_memistr (uid->name, uid->len, + *name == '*'? name+1:name)) { node->flag |= NODFLG_SELUID; - any = 1; + if (any != -1) + { + sl->flags |= 1; /* Report as found. */ + any = 1; + } + count++; } } } + + if (count > 1) + { + any = -1; /* Force failure at end. */ + sl->flags |= 2; /* Report as ambiguous. */ + } } - if (uids && !any) + /* Check whether all given user ids were found. */ + for (sl=uids; sl; sl = sl->next) + if (!(sl->flags & 1)) + any = -1; /* That user id was not found. */ + + /* Print an error if there was a problem with the user ids. */ + if (uids && any < 1) { if (!opt.verbose) show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1); es_fflush (es_stdout); + for (sl=uids; sl; sl = sl->next) + { + if ((sl->flags & 2)) + log_info (_("Invalid user ID '%s': %s\n"), + sl->d, gpg_strerror (GPG_ERR_AMBIGUOUS_NAME)); + else if (!(sl->flags & 1)) + log_info (_("Invalid user ID '%s': %s\n"), + sl->d, gpg_strerror (GPG_ERR_NOT_FOUND)); + } log_error ("%s %s", _("No matching user IDs."), _("Nothing to sign.\n")); goto leave; }