mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-13 00:09:51 +02: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;
|
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
|
/* If the DB is new, initialize it. Otherwise, check the DB's
|
||||||
version.
|
version.
|
||||||
|
@ -727,6 +873,9 @@ initdb (sqlite3 *db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! rc)
|
||||||
|
rc = check_utks (db);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
rc = sqlite3_exec (db, "rollback;", NULL, NULL, &err);
|
rc = sqlite3_exec (db, "rollback;", NULL, NULL, &err);
|
||||||
|
|
|
@ -324,6 +324,13 @@ tdb_keyid_is_utk (u32 *kid)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the list of ultimately trusted keys. */
|
||||||
|
struct key_item *
|
||||||
|
tdb_utks (void)
|
||||||
|
{
|
||||||
|
return utk_list;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
*********** TrustDB stuff *******************
|
*********** TrustDB stuff *******************
|
||||||
|
|
|
@ -117,6 +117,9 @@ void tdb_register_trusted_keyid (u32 *keyid);
|
||||||
void tdb_register_trusted_key (const char *string);
|
void tdb_register_trusted_key (const char *string);
|
||||||
/* Returns whether KID is on the list of ultimately trusted keys. */
|
/* Returns whether KID is on the list of ultimately trusted keys. */
|
||||||
int tdb_keyid_is_utk (u32 *kid);
|
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 check_trustdb (ctrl_t ctrl);
|
||||||
void update_trustdb (ctrl_t ctrl);
|
void update_trustdb (ctrl_t ctrl);
|
||||||
int setup_trustdb( int level, const char *dbname );
|
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
|
;; 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
|
;; Bob adds a new user id, "Alice". TOFU should now detect a
|
||||||
;; conflict, because Alice only signed Bob's "Bob" user id.
|
;; 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")
|
(display "Checking UTK sigs...\n")
|
||||||
(define GPG `(,(tool 'gpg) --no-permission-warning
|
(define GPG `(,(tool 'gpg) --no-permission-warning
|
||||||
|
@ -279,12 +294,18 @@
|
||||||
(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYIDB "-1.gpg"))))
|
(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYIDB "-1.gpg"))))
|
||||||
(display "<\n")
|
(display "<\n")
|
||||||
|
|
||||||
|
(checkpolicy KEYA "auto")
|
||||||
|
(checkpolicy KEYB "auto")
|
||||||
|
|
||||||
;; Import the cross sigs.
|
;; Import the cross sigs.
|
||||||
(display " > Adding cross signatures. ")
|
(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 KEYIDA "-2.gpg"))))
|
||||||
(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYIDB "-2.gpg"))))
|
(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYIDB "-2.gpg"))))
|
||||||
(display "<\n")
|
(display "<\n")
|
||||||
|
|
||||||
|
(checkpolicy KEYA "auto")
|
||||||
|
(checkpolicy KEYB "auto")
|
||||||
|
|
||||||
;; Make KEYA ultimately trusted.
|
;; Make KEYA ultimately trusted.
|
||||||
(display (string-append " > Marking " KEYA " as ultimately trusted. "))
|
(display (string-append " > Marking " KEYA " as ultimately trusted. "))
|
||||||
(pipe:do
|
(pipe:do
|
||||||
|
|
Loading…
Reference in New Issue
Block a user