/* Return the effective policy for the binding <FINGERPRINT, EMAIL>
- * (email has already been normalized) and any conflict information in
- * *CONFLICT_SETP, if CONFLICT_SETP is not NULL. Returns
- * _tofu_GET_POLICY_ERROR if an error occurs. */
+ * (email has already been normalized). Returns
+ * _tofu_GET_POLICY_ERROR if an error occurs. Returns any conflict
+ * information in *CONFLICT_SETP if CONFLICT_SETP is not NULL and the
+ * returned policy is TOFU_POLICY_ASK (consequently, if there is a
+ * conflict, but the user set the policy to good *CONFLICT_SETP will
+ * empty). Note: as per build_conflict_set, which is used to build
+ * the conflict information, the conflict information includes the
+ * current user id as the first element of the linked list.
+ *
+ * This function registers the binding in the bindings table if it has
+ * not yet been registered.
+ */
static enum tofu_policy
get_policy (tofu_dbs_t dbs, PKT_public_key *pk,
const char *fingerprint, const char *user_id, const char *email,
&& _tofu_GET_TRUST_ERROR != TRUST_FULLY
&& _tofu_GET_TRUST_ERROR != TRUST_ULTIMATE);
+ begin_transaction (ctrl, 0);
+ in_transaction = 1;
+
+ /* We need to call get_policy even if the key is ultimately trusted
+ * to make sure the binding has been registered. */
+ policy = get_policy (dbs, pk, fingerprint, user_id, email,
+ &conflict_set, now);
+
+ if (policy == TOFU_POLICY_ASK)
+ /* The conflict set should always contain at least one element:
+ * the current key. */
+ log_assert (conflict_set);
+ else
+ /* If the policy is not TOFU_POLICY_ASK, then conflict_set will be
+ * NULL. */
+ log_assert (! conflict_set);
+
/* If the key is ultimately trusted, there is nothing to do. */
{
u32 kid[2];
}
}
- begin_transaction (ctrl, 0);
- in_transaction = 1;
-
- policy = get_policy (dbs, pk, fingerprint, user_id, email,
- &conflict_set, now);
if (policy == TOFU_POLICY_AUTO)
{
policy = opt.tofu_default_policy;
" auto (default: %s).\n",
fingerprint, email,
tofu_policy_str (opt.tofu_default_policy));
+
+ if (policy == TOFU_POLICY_ASK)
+ /* The default policy is ASK, but there is no conflict (policy
+ * was 'auto'). In this case, we need to make sure the
+ * conflict set includes at least the current user id. */
+ {
+ add_to_strlist (&conflict_set, fingerprint);
+ }
}
switch (policy)
{
/* Get the signature stats. */
rc = gpgsql_exec_printf
(dbs->db, strings_collect_cb, &strlist, &err,
- "select count (*), min (signatures.time), max (signatures.time)\n"
+ "select count (*), coalesce (min (signatures.time), 0),\n"
+ " coalesce (max (signatures.time), 0)\n"
" from signatures\n"
" left join bindings on signatures.binding = bindings.oid\n"
" where fingerprint = %Q and email = %Q;",
/* Get the encryption stats. */
rc = gpgsql_exec_printf
(dbs->db, strings_collect_cb, &strlist, &err,
- "select count (*), min (encryptions.time), max (encryptions.time)\n"
+ "select count (*), coalesce (min (encryptions.time), 0),\n"
+ " coalesce (max (encryptions.time), 0)\n"
" from encryptions\n"
" left join bindings on encryptions.binding = bindings.oid\n"
" where fingerprint = %Q and email = %Q;",
int bindings = 0;
int bindings_valid = 0;
int need_warning = 0;
+ int had_conflict = 0;
dbs = opendbs (ctrl);
if (! dbs)
* key. */
log_assert (conflict_set);
+ had_conflict = 1;
for (iter = conflict_set; iter; iter = iter->next)
show_statistics (dbs, iter->d, email,
TOFU_POLICY_ASK, NULL, 1, now);
xfree (email);
}
- if (need_warning)
+ if (need_warning && ! had_conflict)
show_warning (fingerprint, user_id_list);
die: