[Pkg-gnupg-commit] [gnupg2] 17/180: g10: If the set of UTKs changes, invalidate any changed policies.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Sat Dec 24 22:29:03 UTC 2016
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch master
in repository gnupg2.
commit 44c17bcb003a3330f595a6ab144e8439b7b630cb
Author: Neal H. Walfield <neal at g10code.com>
Date: Tue Nov 22 15:05:59 2016 +0100
g10: If the set of UTKs changes, invalidate any changed policies.
* g10/trustdb.c (tdb_utks): New function.
* g10/tofu.c (check_utks): New function.
(initdb): Call it.
* tests/openpgp/tofu.scm: Modify test to check the effective policy of
keys whose effective policy changes when we change the set of UTKs.
--
Signed-off-by: Neal H. Walfield <neal at g10code.com>
If the set of ultimately trusted keys changes, then it is possible
that a binding's effective policy changes. To deal with this, we
detect when the set of ultimately trusted keys changes and invalidate
all cached policies.
---
g10/tofu.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++
g10/trustdb.c | 7 +++
g10/trustdb.h | 3 +
tests/openpgp/tofu.scm | 21 +++++++
4 files changed, 180 insertions(+)
diff --git a/g10/tofu.c b/g10/tofu.c
index 6eb7f5e..d7730a3 100644
--- a/g10/tofu.c
+++ b/g10/tofu.c
@@ -506,6 +506,152 @@ version_check_cb (void *cookie, int argc, char **argv, char **azColName)
return 1;
}
+static int
+check_utks (sqlite3 *db)
+{
+ int rc;
+ char *err = NULL;
+ struct key_item *utks;
+ struct key_item *ki;
+ int utk_count;
+ char *utks_string = NULL;
+ char keyid_str[16+1];
+ long utks_unchanged = 0;
+
+ /* An early version of the v1 format did not include the list of
+ * known ultimately trusted keys.
+ *
+ * This list is used to detect when the set of ultimately trusted
+ * keys changes. We need to detect this to invalidate the effective
+ * policy, which can change if an ultimately trusted key is added or
+ * removed. */
+ rc = sqlite3_exec (db,
+ "create table if not exists ultimately_trusted_keys"
+ " (keyid);\n",
+ NULL, NULL, &err);
+ if (rc)
+ {
+ log_error (_("error creating 'ultimately_trusted_keys' TOFU table: %s\n"),
+ err);
+ sqlite3_free (err);
+ goto out;
+ }
+
+
+ utks = tdb_utks ();
+ for (ki = utks, utk_count = 0; ki; ki = ki->next, utk_count ++)
+ ;
+
+ if (utk_count)
+ {
+ /* Build a list of keyids of the form "XXX","YYY","ZZZ". */
+ int len = (1 + 16 + 1 + 1) * utk_count;
+ int o = 0;
+
+ utks_string = xmalloc (len);
+ *utks_string = 0;
+ for (ki = utks, utk_count = 0; ki; ki = ki->next, utk_count ++)
+ {
+ utks_string[o ++] = '\'';
+ format_keyid (ki->kid, KF_LONG,
+ keyid_str, sizeof (keyid_str));
+ memcpy (&utks_string[o], keyid_str, 16);
+ o += 16;
+ utks_string[o ++] = '\'';
+ utks_string[o ++] = ',';
+ }
+ utks_string[o - 1] = 0;
+ log_assert (o == len);
+ }
+
+ rc = gpgsql_exec_printf
+ (db, get_single_unsigned_long_cb, &utks_unchanged, &err,
+ "select"
+ /* Removed UTKs? (Known UTKs in current UTKs.) */
+ " ((select count(*) from ultimately_trusted_keys"
+ " where (keyid in (%s))) == %d)"
+ " and"
+ /* New UTKs? */
+ " ((select count(*) from ultimately_trusted_keys"
+ " where keyid not in (%s)) == 0);",
+ utks_string ? utks_string : "",
+ utk_count,
+ utks_string ? utks_string : "");
+ xfree (utks_string);
+ if (rc)
+ {
+ log_error (_("TOFU DB error"));
+ print_further_info ("checking if ultimately trusted keys changed: %s",
+ err);
+ sqlite3_free (err);
+ goto out;
+ }
+
+ if (utks_unchanged)
+ goto out;
+
+ if (DBG_TRUST)
+ log_debug ("TOFU: ultimately trusted keys changed.\n");
+
+ /* Given that the set of ultimately trusted keys
+ * changed, clear any cached policies. */
+ rc = gpgsql_exec_printf
+ (db, NULL, NULL, &err,
+ "update bindings set effective_policy = %d;",
+ TOFU_POLICY_NONE);
+ if (rc)
+ {
+ log_error (_("TOFU DB error"));
+ print_further_info ("clearing cached policies: %s", err);
+ sqlite3_free (err);
+ goto out;
+ }
+
+ /* Now, update the UTK table. */
+ rc = sqlite3_exec (db,
+ "drop table ultimately_trusted_keys;",
+ NULL, NULL, &err);
+ if (rc)
+ {
+ log_error (_("TOFU DB error"));
+ print_further_info ("dropping ultimately_trusted_keys: %s", err);
+ sqlite3_free (err);
+ goto out;
+ }
+
+ rc = sqlite3_exec (db,
+ "create table if not exists"
+ " ultimately_trusted_keys (keyid);\n",
+ NULL, NULL, &err);
+ if (rc)
+ {
+ log_error (_("TOFU DB error"));
+ print_further_info ("creating ultimately_trusted_keys: %s", err);
+ sqlite3_free (err);
+ goto out;
+ }
+
+ for (ki = utks; ki; ki = ki->next)
+ {
+ format_keyid (ki->kid, KF_LONG,
+ keyid_str, sizeof (keyid_str));
+ rc = gpgsql_exec_printf
+ (db, NULL, NULL, &err,
+ "insert into ultimately_trusted_keys values ('%s');",
+ keyid_str);
+ if (rc)
+ {
+ log_error (_("TOFU DB error"));
+ print_further_info ("updating ultimately_trusted_keys: %s",
+ err);
+ sqlite3_free (err);
+ goto out;
+ }
+ }
+
+ out:
+ return rc;
+}
/* If the DB is new, initialize it. Otherwise, check the DB's
version.
@@ -727,6 +873,9 @@ initdb (sqlite3 *db)
}
}
+ if (! rc)
+ rc = check_utks (db);
+
if (rc)
{
rc = sqlite3_exec (db, "rollback;", NULL, NULL, &err);
diff --git a/g10/trustdb.c b/g10/trustdb.c
index edae6ef..51a8f22 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -324,6 +324,13 @@ tdb_keyid_is_utk (u32 *kid)
return 0;
}
+
+/* Return the list of ultimately trusted keys. */
+struct key_item *
+tdb_utks (void)
+{
+ return utk_list;
+}
/*********************************************
*********** TrustDB stuff *******************
diff --git a/g10/trustdb.h b/g10/trustdb.h
index 77aa79d..45ecc56 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -117,6 +117,9 @@ void tdb_register_trusted_keyid (u32 *keyid);
void tdb_register_trusted_key (const char *string);
/* Returns whether KID is on the list of ultimately trusted keys. */
int tdb_keyid_is_utk (u32 *kid);
+/* Return the list of ultimately trusted keys. The caller must not
+ * modify this list nor must it free the list. */
+struct key_item *tdb_utks (void);
void check_trustdb (ctrl_t ctrl);
void update_trustdb (ctrl_t ctrl);
int setup_trustdb( int level, const char *dbname );
diff --git a/tests/openpgp/tofu.scm b/tests/openpgp/tofu.scm
index 2a04d13..e1fa001 100755
--- a/tests/openpgp/tofu.scm
+++ b/tests/openpgp/tofu.scm
@@ -248,6 +248,21 @@
;; Alice has an ultimately trusted key and she signs Bob's key. Then
;; Bob adds a new user id, "Alice". TOFU should now detect a
;; conflict, because Alice only signed Bob's "Bob" user id.
+;;
+;;
+;; The Alice key:
+;; pub rsa2048 2016-10-11 [SC]
+;; 1938C3A0E4674B6C217AC0B987DB2814EC38277E
+;; uid [ultimate] Spy Cow <spy at cow.com>
+;; sub rsa2048 2016-10-11 [E]
+;;
+;; The Bob key:
+;;
+;; pub rsa2048 2016-10-11 [SC]
+;; DC463A16E42F03240D76E8BA8B48C6BD871C2247
+;; uid [ full ] Spy R. Cow <spy at cow.com>
+;; uid [ full ] Spy R. Cow <spy at cow.de>
+;; sub rsa2048 2016-10-11 [E]
(display "Checking UTK sigs...\n")
(define GPG `(,(tool 'gpg) --no-permission-warning
@@ -279,12 +294,18 @@
(call-check `(, at GPG --import ,(in-srcdir DIR (string-append KEYIDB "-1.gpg"))))
(display "<\n")
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
;; Import the cross sigs.
(display " > Adding cross signatures. ")
(call-check `(, at GPG --import ,(in-srcdir DIR (string-append KEYIDA "-2.gpg"))))
(call-check `(, at GPG --import ,(in-srcdir DIR (string-append KEYIDB "-2.gpg"))))
(display "<\n")
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
;; Make KEYA ultimately trusted.
(display (string-append " > Marking " KEYA " as ultimately trusted. "))
(pipe:do
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git
More information about the Pkg-gnupg-commit
mailing list