gpg: New option --with-tofu-info.

* g10/gpg.c (oWithTofuInfo): New.
(opts): Add --with-tofu-info.
(main): Set opt.with_tofu_info.
* g10/options.h (struct opt): Add field WITH_TOFU_INFO.
* g10/tofu.c (show_statistics): Add optional arg OUTFP and enter
special mode if not NULL.  Change all callers.
(tofu_write_tfs_record): New.
* g10/keylist.c (list_keyblock_colon): Do not print the tofu policy as
part of the "uid" record.  Print a new "tfs" record if the new option
is set.
* tests/openpgp/tofu.scm (getpolicy): Change from UID to TFS record.
--

A separate option is required to avoid slowing down key listings.
Foer example the current code takes for a keylisting in tofu+pgp mode
17 seconds while it takes more than 5 minutes if the option is used.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-08-25 09:26:36 +02:00
parent 0f1f02acc1
commit 19d12be3ce
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
9 changed files with 107 additions and 38 deletions

View File

@ -52,7 +52,7 @@ described here.
- sub :: Subkey (secondary key) - sub :: Subkey (secondary key)
- sec :: Secret key - sec :: Secret key
- ssb :: Secret subkey (secondary key) - ssb :: Secret subkey (secondary key)
- uid :: User id (only field 10 is used). - uid :: User id
- uat :: User attribute (same as user id except for field 10). - uat :: User attribute (same as user id except for field 10).
- sig :: Signature - sig :: Signature
- rev :: Revocation signature - rev :: Revocation signature
@ -214,10 +214,6 @@ described here.
For pub, sub, sec, and ssb records this field is used for the ECC For pub, sub, sec, and ssb records this field is used for the ECC
curve name. curve name.
*** Field 18 - TOFU Policy
This is the TOFU policy. It is either good, bad, unknown, ask or
auto. This is only shows for uid records.
** Special fields ** Special fields

View File

@ -193,6 +193,11 @@ enum cmd_and_opt_values
oWithKeygrip, oWithKeygrip,
oWithSecret, oWithSecret,
oWithWKDHash, oWithWKDHash,
oWithColons,
oWithKeyData,
oWithTofuInfo,
oWithSigList,
oWithSigCheck,
oAnswerYes, oAnswerYes,
oAnswerNo, oAnswerNo,
oKeyring, oKeyring,
@ -259,10 +264,6 @@ enum cmd_and_opt_values
oNoOptions, oNoOptions,
oNoBatch, oNoBatch,
oHomedir, oHomedir,
oWithColons,
oWithKeyData,
oWithSigList,
oWithSigCheck,
oSkipVerify, oSkipVerify,
oSkipHiddenRecipients, oSkipHiddenRecipients,
oNoSkipHiddenRecipients, oNoSkipHiddenRecipients,
@ -699,6 +700,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oHomedir, "homedir", "@"), ARGPARSE_s_s (oHomedir, "homedir", "@"),
ARGPARSE_s_n (oNoBatch, "no-batch", "@"), ARGPARSE_s_n (oNoBatch, "no-batch", "@"),
ARGPARSE_s_n (oWithColons, "with-colons", "@"), ARGPARSE_s_n (oWithColons, "with-colons", "@"),
ARGPARSE_s_n (oWithTofuInfo,"with-tofu-info", "@"),
ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"), ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"),
ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"), ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"),
ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"), ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"),
@ -2650,6 +2652,8 @@ main (int argc, char **argv)
case oHomedir: break; case oHomedir: break;
case oNoBatch: opt.batch = 0; break; case oNoBatch: opt.batch = 0; break;
case oWithTofuInfo: opt.with_tofu_info = 1; break;
case oWithKeyData: opt.with_key_data=1; /*FALLTHRU*/ case oWithKeyData: opt.with_key_data=1; /*FALLTHRU*/
case oWithColons: opt.with_colons=':'; break; case oWithColons: opt.with_colons=':'; break;

View File

@ -660,6 +660,17 @@ export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
} }
gpg_error_t
tofu_write_tfs_record (ctrl_t ctrl, estream_t fp,
PKT_public_key *pk, const char *user_id)
{
(void)ctrl;
(void)fp;
(void)pk;
(void)user_id;
return gpg_error (GPG_ERR_GENERAL);
}
gpg_error_t gpg_error_t
tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id, tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy) enum tofu_policy *policy)

View File

@ -1289,8 +1289,8 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
char *str; char *str;
PKT_user_id *uid = node->pkt->pkt.user_id; PKT_user_id *uid = node->pkt->pkt.user_id;
if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL) if (attrib_fp && uid->attrib_data != NULL)
dump_attribs (node->pkt->pkt.user_id, pk); dump_attribs (uid, pk);
/* /*
* Fixme: We need a valid flag here too * Fixme: We need a valid flag here too
*/ */
@ -1326,18 +1326,16 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len); es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
else else
es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL); es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
es_fprintf (es_stdout, "::::::::");
if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP)
{
#ifdef USE_TOFU
enum tofu_policy policy;
if (! tofu_get_policy (ctrl, pk, uid, &policy)
&& policy != TOFU_POLICY_NONE)
es_fprintf (es_stdout, "%s", tofu_policy_str (policy));
#endif /*USE_TOFU*/
}
es_putc (':', es_stdout); es_putc (':', es_stdout);
es_putc ('\n', es_stdout); es_putc ('\n', es_stdout);
#ifdef USE_TOFU
if (!uid->attrib_data && opt.with_tofu_info
&& (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP))
{
/* Print a "tfs" record. */
tofu_write_tfs_record (ctrl, es_stdout, pk, uid->name);
}
#endif /*USE_TOFU*/
} }
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{ {

View File

@ -81,6 +81,7 @@ struct
int with_fingerprint; /* Option --with-fingerprint active. */ int with_fingerprint; /* Option --with-fingerprint active. */
int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */ int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */
int with_keygrip; /* Option --with-keygrip active. */ int with_keygrip; /* Option --with-keygrip active. */
int with_tofu_info; /* Option --with-tofu_info active. */
int with_secret; /* Option --with-secret active. */ int with_secret; /* Option --with-secret active. */
int with_wkd_hash; /* Option --with-wkd-hash. */ int with_wkd_hash; /* Option --with-wkd-hash. */
int fingerprint; /* list fingerprints */ int fingerprint; /* list fingerprints */

View File

@ -473,6 +473,17 @@ export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
} }
gpg_error_t
tofu_write_tfs_record (ctrl_t ctrl, estream_t fp,
PKT_public_key *pk, const char *user_id)
{
(void)ctrl;
(void)fp;
(void)pk;
(void)user_id;
return gpg_error (GPG_ERR_GENERAL);
}
gpg_error_t gpg_error_t
tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id, tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id,
enum tofu_policy *policy) enum tofu_policy *policy)

View File

@ -1919,10 +1919,13 @@ write_stats_status (estream_t fp, long messages, enum tofu_policy policy,
} }
} }
/* Note: If OUTFP is not NULL, this function merely prints a "tfs" record
* to OUTFP. In this case USER_ID is not required. */
static void static void
show_statistics (tofu_dbs_t dbs, const char *fingerprint, show_statistics (tofu_dbs_t dbs, const char *fingerprint,
const char *email, const char *user_id, const char *email, const char *user_id,
const char *sig_exclude) const char *sig_exclude, estream_t outfp)
{ {
char *fingerprint_pp; char *fingerprint_pp;
int rc; int rc;
@ -1951,15 +1954,16 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
goto out; goto out;
} }
if (!outfp)
write_status_text_and_buffer (STATUS_TOFU_USER, fingerprint, write_status_text_and_buffer (STATUS_TOFU_USER, fingerprint,
email, strlen (email), 0); email, strlen (email), 0);
if (! strlist) if (! strlist)
{ {
log_info (_("Have never verified a message signed by key %s!\n"), if (!outfp)
fingerprint_pp); log_info (_("Have never verified a message signed by key %s!\n"),
write_stats_status (NULL, 0, TOFU_POLICY_NONE, 0, 0); fingerprint_pp);
write_stats_status (outfp, 0, TOFU_POLICY_NONE, 0, 0);
} }
else else
{ {
@ -1999,10 +2003,17 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
if (messages == -1 || !first_seen) if (messages == -1 || !first_seen)
{ {
write_stats_status (NULL, 0, TOFU_POLICY_NONE, 0, 0); write_stats_status (outfp, 0, TOFU_POLICY_NONE, 0, 0);
log_info (_("Failed to collect signature statistics for \"%s\"\n" if (!outfp)
"(key %s)\n"), log_info (_("Failed to collect signature statistics for \"%s\"\n"
user_id, fingerprint_pp); "(key %s)\n"),
user_id, fingerprint_pp);
}
else if (outfp)
{
write_stats_status (outfp, messages,
get_policy (dbs, fingerprint, email, NULL),
first_seen, most_recent_seen);
} }
else else
{ {
@ -2010,7 +2021,8 @@ show_statistics (tofu_dbs_t dbs, const char *fingerprint,
estream_t fp; estream_t fp;
char *msg; char *msg;
write_stats_status (NULL, messages, policy, write_stats_status (NULL, messages,
policy,
first_seen, most_recent_seen); first_seen, most_recent_seen);
fp = es_fopenmem (0, "rw,samethread"); fp = es_fopenmem (0, "rw,samethread");
@ -2313,7 +2325,7 @@ tofu_register (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
/* It's only appropriate to show the statistics in an interactive /* It's only appropriate to show the statistics in an interactive
context. */ context. */
show_statistics (dbs, fingerprint, email, user_id, show_statistics (dbs, fingerprint, email, user_id,
already_verified ? NULL : sig_digest); already_verified ? NULL : sig_digest, NULL);
xfree (email); xfree (email);
xfree (fingerprint); xfree (fingerprint);
@ -2385,6 +2397,38 @@ tofu_wot_trust_combine (int tofu_base, int wot_base)
} }
/* Write a "tfs" record for a --with-colons listing. */
gpg_error_t
tofu_write_tfs_record (ctrl_t ctrl, estream_t fp,
PKT_public_key *pk, const char *user_id)
{
gpg_error_t err;
tofu_dbs_t dbs;
char *fingerprint;
char *email;
if (!*user_id)
return 0; /* No TOFU stats possible for an empty ID. */
dbs = opendbs (ctrl);
if (!dbs)
{
err = gpg_error (GPG_ERR_GENERAL);
log_error (_("error opening TOFU database: %s\n"), gpg_strerror (err));
return err;
}
fingerprint = hexfingerprint (pk, NULL, 0);
email = email_from_user_id (user_id);
show_statistics (dbs, fingerprint, email, user_id, NULL, fp);
xfree (email);
xfree (fingerprint);
return 0;
}
/* Return the validity (TRUST_NEVER, etc.) of the binding /* Return the validity (TRUST_NEVER, etc.) of the binding
<FINGERPRINT, USER_ID>. <FINGERPRINT, USER_ID>.
@ -2429,7 +2473,7 @@ tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
trust_level = TRUST_UNDEFINED; trust_level = TRUST_UNDEFINED;
if (may_ask && trust_level != TRUST_ULTIMATE) if (may_ask && trust_level != TRUST_ULTIMATE)
show_statistics (dbs, fingerprint, email, user_id, NULL); show_statistics (dbs, fingerprint, email, user_id, NULL, NULL);
die: die:
xfree (email); xfree (email);

View File

@ -88,6 +88,10 @@ int tofu_register (ctrl_t ctrl, PKT_public_key *pk, const char *user_id,
interest when the trust model is tofu+pgp (TM_TOFU_PGP). */ interest when the trust model is tofu+pgp (TM_TOFU_PGP). */
int tofu_wot_trust_combine (int tofu, int wot); int tofu_wot_trust_combine (int tofu, int wot);
/* Write a "tfs" record for a --with-colons listing. */
gpg_error_t tofu_write_tfs_record (ctrl_t ctrl, estream_t fp,
PKT_public_key *pk, const char *user_id);
/* Determine the validity (TRUST_NEVER, etc.) of the binding /* Determine the validity (TRUST_NEVER, etc.) of the binding
<PK, USER_ID>. If MAY_ASK is 1, then this function may <PK, USER_ID>. If MAY_ASK is 1, then this function may
interact with the user. If not, TRUST_UNKNOWN is returned. If an interact with the user. If not, TRUST_UNKNOWN is returned. If an

View File

@ -46,11 +46,11 @@
;; This function only supports keys with a single user id. ;; This function only supports keys with a single user id.
(define (getpolicy keyid format . args) (define (getpolicy keyid format . args)
(let ((policy (let ((policy
(list-ref (assoc "uid" (gpg-with-colons (list-ref (assoc "tfs" (gpg-with-colons
`(--tofu-db-format ,format `(--tofu-db-format ,format
--trust-model=tofu --trust-model=tofu --with-tofu-info
,@args ,@args
--list-keys ,keyid))) 17))) --list-keys ,keyid))) 5)))
(unless (member policy '("auto" "good" "unknown" "bad" "ask")) (unless (member policy '("auto" "good" "unknown" "bad" "ask"))
(error "Bad policy:" policy)) (error "Bad policy:" policy))
policy)) policy))