mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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@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.
This commit is contained in:
parent
5c2db9dedf
commit
44c17bcb00
149
g10/tofu.c
149
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);
|
||||
|
@ -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 *******************
|
||||
|
@ -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 );
|
||||
|
@ -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@cow.com>
|
||||
;; sub rsa2048 2016-10-11 [E]
|
||||
;;
|
||||
;; The Bob key:
|
||||
;;
|
||||
;; pub rsa2048 2016-10-11 [SC]
|
||||
;; DC463A16E42F03240D76E8BA8B48C6BD871C2247
|
||||
;; uid [ full ] Spy R. Cow <spy@cow.com>
|
||||
;; uid [ full ] Spy R. Cow <spy@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 `(,@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 `(,@GPG --import ,(in-srcdir DIR (string-append KEYIDA "-2.gpg"))))
|
||||
(call-check `(,@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
|
||||
|
Loading…
x
Reference in New Issue
Block a user