summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@g10code.com>2015-11-05 17:29:53 +0100
committerNeal H. Walfield <neal@g10code.com>2015-11-06 12:04:35 +0100
commite8c53fca954d33366e3494a6d4eecc3868282bcc (patch)
treef5408893983c8e1c4e6af9fb4410fb4d916d4247 /g10
parentcommon: Add new function strlist_rev. (diff)
downloadgnupg2-e8c53fca954d33366e3494a6d4eecc3868282bcc.tar.xz
gnupg2-e8c53fca954d33366e3494a6d4eecc3868282bcc.zip
gpg: Check for ambiguous or non-matching key specs.
* g10/gpg.c (check_user_ids): New function. (main): Check that any user id specifications passed to --local-user and --remote-user correspond to exactly 1 user. Check that any user id specifications passed to --default-key correspond to at most 1 user. Warn if any user id specifications passed to --local-user or --default-user are possible ambiguous (are not specified by long keyid or fingerprint). * g10/getkey.c (parse_def_secret_key): Don't warn about possible ambiguous key descriptions here. -- Signed-off-by: Neal H. Walfield <neal@g10code.com> GnuPG-bug-id: 1128 Debian-debug-id: 544490
Diffstat (limited to 'g10')
-rw-r--r--g10/getkey.c9
-rw-r--r--g10/gpg.c208
2 files changed, 189 insertions, 28 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index b4086a270..9e123ee7f 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1142,15 +1142,6 @@ parse_def_secret_key (ctrl_t ctrl)
continue;
}
- if (! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
- || desc.mode == KEYDB_SEARCH_MODE_FPR16
- || desc.mode == KEYDB_SEARCH_MODE_FPR20
- || desc.mode == KEYDB_SEARCH_MODE_FPR)
- && ! warned)
- log_info (_("Warning: value '%s' for --default-key"
- " should be a long keyid or a fingerprint.\n"),
- t->d);
-
if (! hd)
hd = keydb_new ();
else
diff --git a/g10/gpg.c b/g10/gpg.c
index ef283b487..b15be9131 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2081,6 +2081,159 @@ get_default_configname (void)
return configname;
}
+gpg_error_t
+check_user_ids (strlist_t *sp,
+ int warn_possibly_ambiguous,
+ int error_if_not_found)
+{
+ strlist_t s = *sp;
+ strlist_t s2 = NULL;
+ strlist_t t;
+
+ gpg_error_t rc = 0;
+ gpg_error_t err;
+
+ KEYDB_HANDLE hd = NULL;
+
+ if (! s)
+ return 0;
+
+ for (t = s; t; t = t->next)
+ {
+ const char *option;
+
+ KEYDB_SEARCH_DESC desc;
+ KBNODE kb;
+ PKT_public_key *pk;
+ char fingerprint_bin[MAX_FINGERPRINT_LEN];
+ size_t fingerprint_bin_len = sizeof (fingerprint_bin);
+ char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
+
+
+ switch (t->flags >> 2)
+ {
+ case oDefaultKey: option = "--default-key"; break;
+ case oEncryptTo: option = "--encrypt-to"; break;
+ case oHiddenEncryptTo: option = "--hidden-encrypt-to"; break;
+ case oEncryptToDefaultKey: option = "--encrypt-to-default-key"; break;
+ case oRecipient: option = "--recipient"; break;
+ case oHiddenRecipient: option = "--hidden-recipient"; break;
+ case oLocalUser: option = "--local-user"; break;
+ default: log_bug ("Unsupport option: %d\n", t->flags >> 2);
+ }
+
+ err = classify_user_id (t->d, &desc, 1);
+ if (err)
+ {
+ if (! rc)
+ rc = err;
+
+ log_error (_("Invalid value ('%s')."), t->d);
+ if (!opt.quiet)
+ log_info (_("(check argument of option '%s')\n"), option);
+ continue;
+ }
+
+ if (warn_possibly_ambiguous
+ && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+ || desc.mode == KEYDB_SEARCH_MODE_FPR16
+ || desc.mode == KEYDB_SEARCH_MODE_FPR20
+ || desc.mode == KEYDB_SEARCH_MODE_FPR))
+ log_info (_("Warning: value '%s' for %s"
+ " should be a long keyid or a fingerprint.\n"),
+ t->d, option);
+
+ if (! hd)
+ hd = keydb_new ();
+ else
+ keydb_search_reset (hd);
+
+ err = keydb_search (hd, &desc, 1, NULL);
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ {
+ if (error_if_not_found)
+ {
+ if (! rc)
+ rc = err;
+
+ log_error (_("no such key corresponding to '%s'\n"), t->d);
+ if (!opt.quiet)
+ log_info (_("(check argument of option '%s')\n"), option);
+ }
+ continue;
+ }
+ if (err)
+ {
+ if (! rc)
+ rc = err;
+
+ log_error (_("error looking up '%s' in keyring: %s.\n"),
+ t->d, gpg_strerror (err));
+ break;
+ }
+
+ err = keydb_get_keyblock (hd, &kb);
+ if (err)
+ {
+ if (! rc)
+ rc = err;
+
+ log_error (_("error reading key block for '%s': %s\n"),
+ t->d, gpg_strerror (err));
+ continue;
+ }
+
+ pk = kb->pkt->pkt.public_key;
+ fingerprint_from_pk (pk, fingerprint_bin, &fingerprint_bin_len);
+ assert (fingerprint_bin_len == sizeof (fingerprint_bin));
+ bin2hex (fingerprint_bin, MAX_FINGERPRINT_LEN, fingerprint);
+ add_to_strlist (&s2, fingerprint);
+ s2->flags = s->flags;
+
+ release_kbnode (kb);
+
+ /* Continue the search. */
+ err = keydb_search (hd, &desc, 1, NULL);
+ if (! (gpg_err_code (err) == GPG_ERR_NOT_FOUND
+ || gpg_err_code (err) == GPG_ERR_EOF))
+ {
+ char fingerprint_bin2[MAX_FINGERPRINT_LEN];
+ size_t fingerprint_bin2_len = sizeof (fingerprint_bin2);
+ char fingerprint2[2 * MAX_FINGERPRINT_LEN + 1];
+
+ log_error (_("Error: the key specification '%s' is ambiguous.\n"),
+ t->d);
+ if (!opt.quiet)
+ log_info (_("(check argument of option '%s')\n"), option);
+
+ err = keydb_get_keyblock (hd, &kb);
+ if (err)
+ log_error (_("error reading key block for '%s': %s.\n"),
+ t->d, gpg_strerror (err));
+ else
+ {
+ pk = kb->pkt->pkt.public_key;
+ fingerprint_from_pk (pk, fingerprint_bin2, &fingerprint_bin2_len);
+ assert (fingerprint_bin2_len == sizeof (fingerprint_bin2));
+ bin2hex (fingerprint_bin2, MAX_FINGERPRINT_LEN, fingerprint2);
+
+ log_error ("'%s' matches at least: %s and %s.\n",
+ t->d, fingerprint, fingerprint2);
+
+ release_kbnode (kb);
+ }
+ }
+ }
+
+ strlist_rev (&s2);
+
+ if (hd)
+ keydb_release (hd);
+
+ free_strlist (s);
+ *sp = s2;
+ return rc;
+}
int
main (int argc, char **argv)
@@ -2582,7 +2735,8 @@ main (int argc, char **argv)
#endif /*!NO_TRUST_MODELS*/
case oDefaultKey:
- add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+ sl = add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+ sl->flags = (pargs.r_opt << 2);
break;
case oDefRecipient:
if( *pargs.r.ret_str )
@@ -2774,22 +2928,23 @@ main (int argc, char **argv)
case oNoEncryptTo: opt.no_encrypt_to = 1; break;
case oEncryptTo: /* store the recipient in the second list */
sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
- sl->flags = 1;
+ sl->flags = (pargs.r_opt << 2) | 1;
break;
case oHiddenEncryptTo: /* store the recipient in the second list */
sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
- sl->flags = 1|2;
+ sl->flags = (pargs.r_opt << 2) | 1|2;
break;
case oEncryptToDefaultKey:
opt.encrypt_to_default_key = 1;
break;
case oRecipient: /* store the recipient */
- add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+ sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+ sl->flags = (pargs.r_opt << 2);
any_explicit_recipient = 1;
break;
case oHiddenRecipient: /* store the recipient with a flag */
sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
- sl->flags = 2;
+ sl->flags = (pargs.r_opt << 2) | 2;
any_explicit_recipient = 1;
break;
@@ -2832,7 +2987,8 @@ main (int argc, char **argv)
case oAskCertLevel: opt.ask_cert_level = 1; break;
case oNoAskCertLevel: opt.ask_cert_level = 0; break;
case oLocalUser: /* store the local users */
- add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+ sl = add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+ sl->flags = (pargs.r_opt << 2);
break;
case oCompress:
/* this is the -z command line option */
@@ -3740,19 +3896,33 @@ main (int argc, char **argv)
break;
}
- if (opt.encrypt_to_default_key)
- {
- const char *default_key = parse_def_secret_key (ctrl);
- if (default_key)
- {
- sl = add_to_strlist2 (&remusr, default_key, utf8_strings);
- sl->flags = 1;
- }
- else if (opt.def_secret_key)
- log_info (_("--encrypt-to-default-key specified, but no valid default keys specified.\n"));
- else
- log_info (_("--encrypt-to-default-key specified, but --default-key not specified.\n"));
- }
+ {
+ int have_def_secret_key = opt.def_secret_key != NULL;
+
+ rc = check_user_ids (&locusr, 1, 1);
+ if (rc)
+ g10_exit (1);
+ rc = check_user_ids (&remusr, 0, 1);
+ if (rc)
+ g10_exit (1);
+ rc = check_user_ids (&opt.def_secret_key, 1, 0);
+ if (rc)
+ g10_exit (1);
+
+ if (opt.encrypt_to_default_key)
+ {
+ const char *default_key = parse_def_secret_key (ctrl);
+ if (default_key)
+ {
+ sl = add_to_strlist2 (&remusr, default_key, utf8_strings);
+ sl->flags = (oEncryptToDefaultKey << 2) | 1;
+ }
+ else if (have_def_secret_key)
+ log_info (_("--encrypt-to-default-key specified, but no valid default keys specified.\n"));
+ else
+ log_info (_("--encrypt-to-default-key specified, but --default-key not specified.\n"));
+ }
+ }
/* The command dispatcher. */
switch( cmd )